Module::Buildにアクションを追加する
./Build時に Parse::Yappの文法ファイルを yappコマンドを通して、
モジュールを生成するということがしたかったのでその方法を調べ
ました。
アクションを追加する方法
Module::Buildのサブクラスを作り、Action_hookpointの関数を
作ることで actionを追加できます。プロパティは $self->{properties}から
読み出すことができます。サブクラス作成には以下の 2つの方法があります。
Module::Buildを継承して、サブクラスを作る
'use parent qw/Module::Build/'等でサブクラスを作成します。
他のケースでも利用できる場合があるということであればこちらの
方法が良いかと思います。需要がたくさんあれば CPANに上げると
なお良いかもしれません。
'Module::Build::'というネームスペースのモジュールがだいだいそう
なので、metacpan等で探すと参考にできるものが見つかると思います。
Module::Build->subclassを使う
今回は大したことない処理だったので、こちらの方法を利用しました。
(Module::Build::Cookbookの "Adding an action"セクションに短い
ですが記載されています)
コード
以下のようになりました。
Build.PLの書き方は Nanaを Actionについては Config::Irssi::Parserを参考にしました。
Module::Buildの各種 APIについては Module::Build::APIを参照してください。
use strict; use warnings; use Module::Build; use File::Spec; my $class = Module::Build->subclass( class => 'My::Builder', code => <<'...' sub ACTION_code { my $self = shift; my $yapp_files = $self->{properties}->{yapp_file}; if (defined $yapp_files) { unless (ref $yapp_files eq "ARRAY") { $yapp_files = [$yapp_files]; } for my $yapp_file (@{$yapp_files}) { my $relpath = _to_relative_path($yapp_file); (my $output_module = $relpath) =~ s{\.yp\z}{\.pm}; my $parser_package = do { local $_ = $yapp_file; s{\Alib/}{}; s{/}{::}g; s{\.yp\z}{}; $_; }; unless ($self->up_to_date($yapp_file, $output_module)) { my @args = ("-s", # Output stand alone module "-m", $parser_package, "-o", $output_module, $yapp_file); $self->do_system("yapp", @args); $self->add_to_cleanup($output_module); } } } $self->SUPER::ACTION_code(@_); } sub _to_relative_path { my $file = shift; my $cpath = File::Spec->canonpath($file); if (File::Spec->file_name_is_absolute($cpath)) { return File::Spec->abs2rel($file); } return $file; } ... ); my $build = My::Builder->new( license => 'perl', dynamic_config => 0, build_requires => { 'Test::More' => '0.98', }, configure_requires => { 'Module::Build' => '0.38', 'Parse::Yapp' => '1.05', }, requires => { 'parent' => 0, }, no_index => { 'directory' => [ 'inc' ] }, name => 'Awesome', module_name => 'Awesome', test_files => (-d '.git' || $ENV{RELEASE_TESTING}) ? 't/ xt/' : 't/', recursive_test_files => 1, yapp_file => ['lib/Awesome/Parser.yp'], create_readme => 0, create_license => 0, ); $build->create_build_script();
おわりに
文字列をサブクラスのコードとして渡すというやり方がいけてないと
思うのですが、公式がこのやり方を提示しているのでこうやるのが
普通なのでしょう。コードリファレンスだけ渡してとかできないもの
なのだろうか・・・?
スマートな方法がある、問題がある等あれば教えていただければと
思います。