CPAN モジュールの rpm 化ノウハウ
Wassr で ZIGOROu さん や hidek さん とやりとりした内容をまとめてみます。
CPAN モジュールの rpm パッケージ作成なんですが、自分はRPM::Specfile に付属している、cpanflute2 を基本的に使ってます。
cpan2rpm の方がメジャーだとは思うんですが、オリジナルのダウンロード用FTPサイトが接続できないのと、吐き出す SPEC ファイルが微妙な感じがするので、なんとなくイヤで使ってないんですが、それ以外はそんなに明確な理由もなく、cpanflute2 の方を使ってます。
ただ、cpanflute2 には以下の問題点があります。
- 依存関係を自動的に解決してくれない(これは cpan2rpm も同じ)
- モジュールの tar ball を自分で取得しないといけない(cpan2rpm はsearch.cpan.org から取得してくれる)
なので、cpanflute2_wrapper.pl といったラッパースクリプトを書いて使ってます。これを使うと、
$ cpanflute2_wrapper.pl --buildall Catalyst::Runtime
みたいに実行すると、Catalyt::Runtime とそれに依存するモジュールの srpm と rpm を「半自動」で全部作ってくれます。--buildall とかのオプションは、中で呼び出される cpanflute2 にそのまま渡されます。
「半自動」と言ってるのは、スクリプトがいろいろとイケてなくて、場合によっては途中でこけてるのを目視で確認して、依存関係を自分で解決しないといけない時があったりするからです。あと、エラー処理やエラーメッセージもイケてなくてわかりにくかったり、ということもあって、今まで公開してなかったんですが、Wassr の流れで gist にスクリプト貼り付けちゃったので、ここでまとめてみることにしました。
他にも注意点があって、まずは rpmbuild の問題。rpmbuild でパッケージを作る際に、use/require してるモジュールがすべて勝手に SPEC ファイルのRequires に含まれてしまう、という問題があります。eval しているモジュールは依存関係の対象とはならないが、以下のように複数行にまたがっていると、依存関係の対象になってしまう。
eval {
require 'Hoge';
}
そのせいで、Linux 上でビルドしてるのに、Requires に Win32::*** が含まれる、ということがあったりします。で、Requires に含まれないようにするためには、/usr/lib/rpm/perl.req を以下のように修正します。(cpanflute2 が Makefile.PL を見て Requires に加えてくれるので、rpmbuild で Requires の処理してる部分はコメントアウトしちゃう。)
-
/usr/lib/rpm/perl.req
old new 221 221 222 222 ($module =~ m/\.ph$/) && next; 223 223 224 $require{$module}=$version;225 $line{$module}=$_;224 #$require{$module}=$version; 225 #$line{$module}=$_; 226 226 } 227 227 228 228 }
それから、cpanflute2自体に問題があって、以下のパッチをあてておく必要がある。
-
cpanflute2
old new 159 159 my $yaml = Load($contents); 160 160 161 161 while (my ($mod, $ver) = each %{$yaml->{build_requires}}) { 162 push @build_requires, [ "perl($mod)", $ver ]; 162 $mod = "perl($mod)" if $mod ne 'perl'; 163 push @build_requires, [ "$mod", $ver ]; 163 164 } 164 165 while (my ($mod, $ver) = each %{$yaml->{requires}}) { 165 push @requires, [ "perl($mod)", $ver ]; 166 $mod = "perl($mod)" if $mod ne 'perl'; 167 push @requires, [ "$mod", $ver ]; 166 168 } 167 169 } 168 170 … … 289 291 my $makefile_pl = qq{CFLAGS="\$RPM_OPT_FLAGS" %{__perl} Makefile.PL < /dev/null}; 290 292 my $make_install = qq{make pure_install PERL_INSTALL_ROOT=\$RPM_BUILD_ROOT}; 291 293 292 if ($use_module_build) { 293 $makefile_pl = qq{CFLAGS="\$RPM_OPT_FLAGS" %{__perl} Makefile.PL destdir=\$RPM_BUILD_ROOT $installdirs < /dev/null}; 294 } 295 else { 296 $makefile_pl = qq{CFLAGS="\$RPM_OPT_FLAGS" %{__perl} Makefile.PL $installdirs}; 297 } 294 $makefile_pl = qq{CFLAGS="\$RPM_OPT_FLAGS" %{__perl} Makefile.PL $installdirs}; 298 295 299 296 $spec->build(<<EOB); 300 297 $makefile_pl
前半の修正は、Makefile.PL の PREREQ_PM とか requires とかに perl が含まれていると、SPEC ファイルの Requires に perl(perl) とか入っちゃっておかしなことになるので、そうならないように修正。
後半の修正は、なんで修正したかあまり覚えてないんだけど、時々 RPM_BUILD_ROOT がおかしくなることがあって、それに対する修正だったと思う。
そういえば、まっさらなサーバを30分で本番投入できるようにする で stanaka さんが「CPANの依存関係を解析してrpm化する手製スクリプトで、CPANモジュールのrpm化が、ほぼ自動化されています」と書いてるんだけど、これって公開してくれないのかなー。
