Perl 5.8.8でfatpacked cartonを頑張って作った

carton bundleを実行すると、App::FatPackerを用いて、cartonを1ファイルのスクリプトにまとめてくれます。
このfatpacked cartonをCentOS5のsystem perl(5.8.8)で使用したかったのですが、carton bundleで生成されたfatpacked cartonを実行すると、エラーが発生して動きませんでした。
何とか動作させる方法を調べたので、エラーの原因と解消方法をまとめておこうと思います。

なお、carton bundleでのfatpacked carton生成は、"experimental feature"のようです。
https://github.com/miyagawa/carton/issues/141

また、fatpacked cartonが原因の課題が多いため、carton bundleではデフォルトで作成させず、別コマンドに切り離すIssueが作成されてます。
https://github.com/miyagawa/carton/issues/156

Cartonのバージョン

v1.0.12

App::FatPackerがfatpackする条件

CHECKブロックで%INCからfatpackするモジュール一覧を取り出すので、それまでにrequireされたモジュール(のはず)

エラー内容と解決方法

1. Can't locate Algorithm/C3.pm in @INC

Algorithm::C3がfatpackされていないという理由で怒られます。
この問題の原因はClass::C3です。

CartonとAlgrorithm::C3の関係は以下の通り。

Carton
 \- Moo
     \- MRO::Compat
         \- Class::C3
             \- Algorithm::C3

Class::C3はClass::C3::XSが存在する場合は、Algorithm::C3がrequireされません。
Class::C3::XSはPerlのバージョンが5.9.5より下であれば自動でインストールされるので、fatpackする時にXSが対象となり、Algorithm::C3はfatpackされません。
しかし、fatpacked cartonではXSモジュールのロードに失敗するので、Algrorithm::C3をrequireしようとしてエラーとなります。
(詳細はClass::C3のBEGINブロック参照)

対処法は、Class::C3::XSをuninstallすることです。

cpanm -U Class::C3::XS
carton bunlde

因みに、Perl 5.10.0以上だとMRO::Compatのかわりにmroが使用されるので、この問題は発生しません。
(詳細はMoo/_mro.pmを参照)

2. List::Util version 1.33 required--this is only version 1.18

List::Utilのバージョンが古いという理由で怒られます。
これは、CPAN::Metaの2.133380以降がList::Utilの1.33以上に依存していることが原因です。

CartonはCPAN::Metaの2.120921に依存していますが、Perl 5.8.8のコアモジュールにCPAN::Metaが入っていないため、CPANからインストールされます。
この時インストールされるバージョンは2.140640(2014/03/11時点)です。
このバージョンではList::Util 1.33以上に依存しているので、併せてList::Util 1.38(2014/03/11時点)がインストールされ、carton bundle時にfatpackされます。
しかし、List::UtilはXSモジュールなので、fatpacked cartonではロードに失敗します。
なので、コアのList::Utilが使われるのですが、バージョンが1.18と古いため、エラーが発生します。

対処法は、CPAN::MetaをuninstallしてCPAN::Metaの2.120921を入れ直せば良いです。

cpanm -U CPAN::Meta
cpanm CPAN:Meta@2.120921
carton bundle

因みに、Perl 5.17.1以上だとコアモジュールにCPAN::Metaの2.120921が入っているので、この問題は発生しません。

まとめ

以下のどれかを採用しましょう。

  1. End of lifeとなったPerl 5.8.8とか使ってないで、Perl 5.18.2(or later)を使おう
  2. サーバセットアップ時にPerlと一緒にCartonをインストールしよう
  3. cpan-module-bootstrapを使おう

どうしてもPerl 5.8.8でfatpacked cartonを作りたければ、上記の方法で頑張ってつくろう。