I hope that there is an alternative

Carton を使った Perl モジュールのインストール時に、困ったことがまたあったので、記しておきたいと思います。概要を先に述べますと、 Makefile.PL 実行時にオプションを渡したいのだけれども、現在の Carton では渡せないので、代替手段があればそれを使う、なければ… 残念。ということです。

バッド・ノウハウという言い方は好ましく思わないのですが、時間的・発生場所いずれにも局所的な問題をワークアラウンド(その場凌ぎ的)に回避するアイデアをひとくちにバッド・ノウハウと言うのならば、ほかにいい言い方も無いので観念するとして、またひとつ、バッド・ノウハウを披露することになるかと思います。

経緯はこうです。

carton install するべく、あるプロダクトに cpanfile を用意して、いざ実行しました。

その中には、 Imager::File::PNG が含まれていたのですが、それは libpng を要求します。そして libpng がシステムに入っていないことじぶんは知っていたので、システムデフォルトの lib 以外の場所にインストールはしておきました。ただし、そうした場合、 Makefile.PL 実行時に --incpath--libpath を指定しなければなりません。

なので、 carton install の実行中に Imager::File::PNG のインストールが失敗するのを見て、見込みどおりであることを確認し、安心して「さて、どうしたものか」と改めて思いました。

carton install のとき、 requires しているうちの任意のモジュールのビルドにオプション渡したいのだけれど… 。

そのつぶやきは @miyagawa 氏が拾ってくださって、折り返しに “that’s a known issue” とコメントを頂きました。このことから、将来的には、このような問題は何らかの形で解消されるものと期待されます。たぶん、 requires 行に、モジュール名、バージョンに続けてオプションが書けるようになるんじゃないでしょうか。当てずっぽうですが、そこにしか、モジュールとの関連を設定できる所がないからです。

さて、失敗した Imager::File::PNG については、別途手動でビルドしてしまえば用は済むのですが、必要なモジュールを全自動でインストールしたいというのが Carton の意義でもあるわけです?から、なんとかして、全自動をかなえたい。 Carton (または cpanm ? ) が対応していないからには、ほかのアプローチを模索しなければなりません。

そこでまずは Imager::File::PNG の Makefile.PL を注意深く覗いてみることにします。 libpng の在処を探す場面があるはずです。それは中で require している Imager::Probe にありました。それに従い Imager::Probe のソースを覗いてみると、見つけました。 pkg-config コマンドを呼び出しているようです。

pkg-config も、その機能を用いるために、システム標準の位置に無いライブラリについては、それを教えてやる必要があります。それは PKG_CONFIG_PATH 環境変数で渡すことが出来ます。そして、別途インストールしておいた libpng にはそのPKG_CONFIG_PATH に相応しいディレクトリがありました。

$ export PKG_CONFIG_PATH=/path/to/libpng/lib/pkgconfig:$PKG_CONFIG_PATH
$ carton install
...

まとめると、 Imager::File::PNG のビルド時には、 Makefile.PL 実行時に --incpath--libpath を渡すことの替わりに PKG_CONFIG_PATH をセットしておけばよいということでした。

通常、 Carton を使わないビルド時や、そもそもシステムの lib に libpng がインストールされていれば、このような状況には出遭いません。実際 Imager::File::PNG の README には libpng の dev パッケージをインストールしなさいと書いてありましたから、それに従えばいいのです。 pkg-config のことはドキュメントにはありませんし、バージョンが変われば、その手は使えなくなるかもしれません。それがゆえに、 PKG_CONFIG_PATH を使う手がバッド・ノウハウと言える性質を備えています。

けれども、ここで得る教訓があります。デベロッパは、自身のプロダクトを提供する場合、ユーザにカスタマイズする方法を複数用意しておくことが望ましいということです。コマンドライン・オプションだけからしかオプションを指定できないツールでは、コマンドラインが無い環境からはそれを実行できません。

例に挙げた Imager::File::PNG の場合を見直してみますと、これは、たまたま pkg-config を使用していたがために、ユーザがコマンドライン・オプションを使わないことを選択できたわけであって、それ自身がコマンドライン・オプション以外の設定方法を提供しているわけではないので、いまいちと言えます。望むべくは、コマンドライン・オプション同等の設定を行う環境変数などを用意しておくべきなのだと、思います。 libpng をシステムの lib にインストールしたくない(または、できない!)状況も十分あり得るのですから。