Catalystにはデフォルトでcatalyst_parというディレクティブが備え付けられていて、Makefile.PLで
... catalyst_par; ... WriteAll;
とすると後のmake時にPAR形式のファイルを作れるようになる機能があります。このPARファイルを作成するには
make catalyst_par
とするわけですが、アプリケーションができあがって、「さあPARでも作るか!」と言った皆さんはおおむね以下のような意味の分からないエラーに悩まされてきたのではないでしょうか:
Writing PAR "wifigadgets-control.par" make: *** [catalyst_par] Error 25
この訳の分からない動作不具合、根本的な問題は二つあります。一つにはこのcatalyst_parでPARファイルを作成するモジュールがどういう理由かかなり意図的にエラーをユーザーに見せないように操作しているのです。該当モジュールはModule::Install::Catalystのこのあたり:
local $SIG{__WARN__} = sub { }; open my $olderr, '>&STDERR'; open STDERR, '>', File::Spec->devnull; my %opt = ( 'x' => 1, 'n' => 0, 'o' => $par, 'a' => [ grep( !/par.pl/, glob '.' ) ], 'p' => 1, 'B' => $CORE, 'm' => $MULTIARCH ); App::Packer::PAR->new( frontend => 'Module::ScanDeps', backend => 'PAR::Packer', frontopts => \%opt, backopts => \%opt, args => ['par.pl'], )->go; open STDERR, '>&', $olderr;
うひゃ、STDERRを完全にブロックしてやがる><

さて、これを取り除いてやるとエラーの内容がだんだんわかってきます。最初はmmap_cache.cでassert()が落ちてるとか、なんかようわからんエラーだったわけですが。これをよくよく考えてみたら、どうもMyApp->setup()がPARファイルを作成するときに呼ばれ、アプリケーション内で使われているモジュールの初期化ルーチンが実行されているみたい。

つまり、PARを作るときにrequire MyApp;が一度走るわけです。その時にMyApp.pmに、Catalystの一般的な作法である以下のコードがおいてあると、setup()が実行されちゃうわけですな

ということはこのコードをとにかく実行させなければよろしい。色んな方法があると思いますが、とりあえずあまり妙な事はしたくないので、環境変数に頼ることにしました:
package MyApp; ... if ($ENV{ CATALYST_DEPLOY }) { __PACKAGE__->config( ... ); __PACKAGE__->setup( qw( ... ) ); }
こうすると、script/内のスクリプトを実行する時もenv CATALYST_DEPLOY=1 とかしないといけないので、その辺りはもう少し頭良くできるかとは思いますが、とりあえず動きます。これでPARも期待通り動くようになります。

あと、もしPARにCatalyst::Plugin系のモジュールも見つけて欲しいのであれば(つまり、違うホストで実行した時にこのファイルをインストールする必要がないようにしたい場合)、setup()で呼ぶだけでなくてuseしてやる必要がありますので注意。
package MyApp; .... use Catalyst::Plugin::ConfigLoader; use Catalyst::Plugin::Static::Simple; ...
これはニーズに合わせて調整してください。