Image::Magickモジュールを含むWindows用EXEが生成できる pp 環境の構築。
Strawberry Perlのサイトから、ダウンロードしました。執筆時点で最新は「5.28.0.1」ですが、Image::Magickが入らないので、5.26.2.1を選択。
形式はどれでも構わないと思いますが、個人的にPortableを選びました。
Image::Magickはppmから入れるので簡単でした。
c:\> ppm
ppm> install Image::Magick
Install package 'Image-Magick?' (y/N): y
ppm> quit
続いてPAR::Packerです。PARは普通にインストールするとよくエラーが出るので、force installしました。
c:\> cpan
cpan> force install PAR::Packer
コンパイル&テストが長いのでそこそこ待たされます。
Image::Magickをパッケージに含めるためには、Image::MagickのDLLを一緒に含める必要があります。
pp は -l オプションや -a オプションを使うと、DLLや他のファイルを一緒にパッケージ化することができます。できますが、それではImage::Magickのロードに失敗します。Image::MagickのDLLは通常と違う場所に置かれているのでDLLがロードできませんし、DLL以外の必要ファイルを参照するための情報も不足します。
これを修正するために、perl/vendor/lib/PAR.pm にパッチを充ててください。
sub import {
my $class = shift;
PAR::SetupProgname::set_progname();
PAR::SetupTemp::set_par_temp_env();
# patch for sitelib by nabe@abk ---------
if ($ENV{PAR_TEMP} && $^O eq 'MSWin32') {
my %conf;
foreach(keys(%Config)) {
$conf{$_} = $Config{$_};
}
*Config::Config = \%conf; # replace read-only object
my $base = "$ENV{PAR_TEMP}\\inc";
$Config::Config{sitelib} = "$base\\site\\lib";
$Config::Config{sitelibexp} = "$base\\site\\lib";
}
# patch end -----------------------------
Image::Magickは環境変数を参照しながら、.dllや.xmlファイルをその都度ロードするようになっているのですが、それらのファイルは指定しないとパッケージ化されませんし、パッケージ化しても $Config{sitelib} が適切に設定されていないため、Magick.pm で正しく環境変数を設定できません。
これを解決するためのパッチになります。
pp コマンドの -a オプションで、Image::Magickのライブラリ類(*.dll, *.xml)を一緒にパッケージ化します。
Strawberry Perlインストールディレクトの「perl\site\lib\Image」以下にあるすべてのファイルをパッケージに収録します。面倒なのでファイルに記述してそれをコマンドラインで与えることにします。
以下は例になります。パスは適当に読み替えてください。
pp -a "C:/strawberry-perl-5.26.2.1/perl/site/lib/Image;site/lib/Image"
-o test.exe test.pl
オプションが長くなり入力が面倒なので、pp-option というファイルを用意してその中にオプションを書きました。
pp @pp-option
スクリプト内で、スレッド生成やforkをしている場合は、スクリプト最初の方で「use Image::Magick」してください。生成されたスレッドやプロセスから「require Image::Magick」しても必要な環境変数が設定されず、Image::Magickが動作しません。
Image::Magickモジュールごと、PerlスクリプトをEXE化できるようになりました。
ActivePerlでも同じ方法で解決できると思います。