koba::blog

小林聡: プログラマです

Minillaでbuild時に .pmファイルを変更する

Minillaを使ってモジュールのひな形を作る - koba::blog の続き。

モジュール作成時にインストールされる環境に合わせてソースを書き換えたい場合がある。具体的には内部で実行するコマンドのパス名の変更とか。C だと configure が Makefile を生成するときにやっていること。

Minilla ではどうすればいいのか調べていたのだが、Module::Build 由来の“PL_files”を使えばいいらしい。例えば Foo::Bar::Env に環境依存の部分がある場合、lib/Foo/Bar/Env.pm.PL というPerlスクリプトで lib/Foo/Bar/Env.pm を生成するようにする(書き換えるのではない)。

具体的には、lib/Foo/Bar/Env.pm が以下のような内容で、git のパス名を環境に合わせて設定したいとする。*1

package Foo::Bar::Env;

use strict;
use warnings;

our $GIT = '/usr/bin/git';

1;

この場合、以下のような lib/Foo/Bar/Env.pm.PL を用意する。

my $pm_file = shift;
open my $fh, '>', $pm_file      or die "$pm_file: $!";

chomp( my $git = `which git` );

while (<DATA>) {
    s/^(our \$GIT);/$1 = '$git';/     if $git;
    print $fh $_;
}

close $fh;

__DATA__
package Foo::Bar::Env;

use strict;
use warnings;

our $GIT;

1;

で、minil.toml に以下の設定を追加すればよい。

[PL_files]
lib/Foo/Bar/Env.pm.PL="lib/Foo/Bar/Env.pm"

こうしておけば、minil build 実行時に、

$ perl lib/Foo/Bar/Env.pm.PL lib/Foo/Bar/Env.pm

が実行されて、lib/Foo/Bar/Env.pm が生成される。

…… はずだったのであるが、2つ問題が発生した。

1. minil.toml の解析でエラーが発生する

minil.toml の lib/Foo/Bar/Env.pm.PL="lib/Foo/Bar/Env.pm" の部分がシンタックス・エラーになる。キーに '.' が含まれているのがよろしくないらしい。TOML形式の仕様かもしれないし、TOML のバグかもしれない。TOML-0.92 以前ではこの問題は発生しないので、ダウングレードして対処した。*2

$ cpanm -S http://search.cpan.org/CPAN/authors/id/D/DA/DARREN/TOML-0.92.tar.gz
2. PL_files のパラメータが正しく渡らない

これで、minil.toml は読込まれるようになったのだが、今度は lib/Foo/Bar/Env.pm.PL の実行時にパラメータであるはずの“lib/Foo/Bar/Env.pm”が渡ってこない。これはおそらく Minilla のバグじゃないかな。しかたがないので、lib/Foo/Bar/Env.pm.PL を以下に書き換えた。

diff --git a/lib/Foo/Bar/Env.pm.PL b/lib/Foo/Bar/Env.pm.PL
index 9b2f27c..50242cf 100644
--- a/lib/Foo/Bar/Env.pm.PL
+++ b/lib/Foo/Bar/Env.pm.PL
@@ -1,5 +1,5 @@
-my $pm_file = shift;
+my $pm_file = 'lib/Foo/Bar/Env.pm';
 open my $fh, '>', $pm_file      or die "$pm_file: $!";
 
 chomp( my $git = `which git` );

ありがたみが減ったけどしかたがない。バグレポートはしたので、修正されることに期待しよう。

追記 (2014-10-09)

1.の問題についてはTOML-0.95で修正されました。素早い対応に感謝! ですが、2.の問題は私のつたない英語のせいか、解決されないままcloseされてしまった。とほほ...

追記 (2014-10-10)

2.の問題については、Minilla-v2.1.3 で Module::Build::Tiny を使用する場合は PL_files をサポートしないという結論になったもようです*3。minil.toml の module_maker を ModuleBuild に変更する必要があります。

module_maker="ModuleBuild"

追記 (2014-10-12)

2.の問題について、Module::Build::Tiny が修正されました。Module-Build-Tiny-0.039 以降なら対応済みです。ですが、Minilla側はサポートをやめてしまったので、それより前のMinilla-v2.1.1 を使わねばならぬ。ややこしいことになった。

追記 (2014-10-13)

2.の問題ですが、Module::Build::Tiny は 0.039 で PL_files を指定しなくても *.PL の処理をするようになったとのことです*4。なので、minil.toml への記述自体が不要というオチのようです。関係各所をお騒がせして申し訳ない!

*1:/usr/bin/git なのか /usr/local/bin/git なのかとかです

*2:TOML-0.93 からTOMLファイルの解析に TOML::Perser を使っているらしいので、この影響と思われる

*3:元々 Module::Build::Tiny が PL_files をサポートしていないため

*4:ただし変換後のファイル名は .PL を取り除いた名前固定