PARでPerlスクリプトをexe化 @ ActivePerl 5.10.1 build 1007


久々に環境を作り直したら、PARの導入が恐ろしく簡単になってた。

まずは、PAR::Packerのインストールの前に、必要モジュールをPPMでインストールしておく1。必要なのは以下の6つだ。

  • Module::ScanDeps
  • Win32::Exe
  • Parse::Binary
  • Getopt::Argvfile
  • PAR
  • PAR::Dist

cpanコマンドでPAR::Packerをインストール

以前はここからが厄介だった。別のリポジトリからインストールしようとしてバージョン違いに泣いたり、以下のリンクなどを参考にしてMinGWやnmakeと格闘したりした。

BdP – PPM Repository
http://www.bribes.org/perl/ppmdir.html

Vista/XPのActivePerl 5.10.0でPAR::Packerをビルド ハードなソフトの話/ウェブリブログ
http://hardsoft.at.webry.info/200801/article_4.html

ところが今や、やることはこれだけである2

C:\>cpan -fi PAR::Packer

これだけでcpanコマンドが勝手にMinGWをダウンロードしてきてPAR::Packerのコンパイル&インストールをやってくれる。

実際にexe化してみる

試しにテストスクリプトをexe化してみよう。

#!/usr/bin/perl -l
use utf8;
use strict;
use warnings;
print "Hello, World!";

-oオプションでexeファイル名を指定する

C:\>pp -o test.exe test.pl

C:\>test
Hello, World!

C:\>

Mooseなパッケージをexe化

Mooseを使ってても大丈夫。

#!/usr/bin/perl
{
    package MyApp;
    use Moose;
    use Perl6::Say;
    has param_a => ( is => "rw", isa => "Num", required => 1 );

    sub add_to_a { my $self = shift;
        $self->param_a( $self->param_a + shift );
    }

    sub say_a { my $self = shift;
        say $self->param_a;
    }
}

my $app = MyApp->new( param_a => 20 );
$app->say_a;
$app->add_to_a( 500 );
$app->say_a;
C:\>pp -o test_moose.exe test_moose.pl

C:\>test_moose
20
520

C:\>

複雑なスクリプトのexe化

しかし、ちょっと複雑なスクリプトだと依存関係が解決できず、うまくいかない。

#!/usr/bin/perl
{
    package MyApp;
    use Moose;
    use MooseX::AttributeHelpers;
    use Perl6::Say;
    has param_a => ( metaclass => "Number",
        is => "ro", isa => "Num", required => 1,
        provides => {
            add => "add_to_a",
        } );

    sub say_a { my $self = shift;
        say $self->param_a;
    }
}

my $app = MyApp->new( param_a => 20 );
$app->say_a;
$app->add_to_a( 500 );
$app->say_a;

ハイライトした部分でMooseX::AttributeHelpersを使っている。このスクリプトをexe化して実行しようとすると……

C:\>pp -o test_moose2.exe test_moose2.pl

C:\>test_moose2
Can't locate MooseX/AttributeHelpers/Trait/Base.pm in @INC (@INC contains: CODE(0x13f44b4) C:\DOCUME~1\delphinus\LOCALS~1\Temp\par-delphinus\cache-b1b75156f11447ac0b31ee7c267d96d75110c96d\inc\lib C:\DOCUME~1\delphinus\LOCALS~1\Temp\par-delphinus\cache-b1b75156f11447ac0b31ee7c267d96d75110c96d\inc CODE(0x126de64) CODE(0x126e164)). at Class/MOP.pm line 116
        Class::MOP::load_first_existing_class('MooseX::AttributeHelpers::Trait::Base') called at Class/MOP.pm line 121
        Class::MOP::load_class('MooseX::AttributeHelpers::Trait::Base') called at Moose/Util.pm line 108
        Moose::Util::_apply_all_roles('Moose::Meta::Role=HASH(0x1ad1e54)', undef, 'MooseX::AttributeHelpers::Trait::Base

~以下略~

ものすごい量のエラーが出る。こういう時は-Mオプションを使って、足りないモジュールを追加してあげないといけない。

C:\>pp -M MooseX::AttributeHelpers::Trait::Base -M MooseX::AttributeHelpers::Trait::Collection -o test_moose2.exe test_moose2.pl

C:\>test_moose2
20
520

C:\>

この“足りないモジュール”はTry&Errorで一つずつ見付けていくしかないのが辛いところ。まあ、exe化するつもりなら、元から妙なモジュールを使わないように気をつければいいだけなのかもしれない。


  1. 別に、後でPAR::Packerと纏めてcpanコマンドでインストールしてもいいのだが、そうするとものすごい時間がかかる。PPMで出来るものはPPMで済ませておこう。 
  2. テストでエラーが出まくるので-f(force)オプションを付けている。 

One thought on “PARでPerlスクリプトをexe化 @ ActivePerl 5.10.1 build 1007

  1. Pingback: 【Perl】Win32::GUI::LoftでGUIプログラミング | blog.remora.cx

コメントを残す