$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

cpanmとインストールするモジュールの走査

 今回はcpanmがモジュールの依存の何をインストールしようとするのか分からなくて、それを調べたのでメモ。現状の仕様のみ書いてるのと、全然読めてないので勘違いがあるかもしれない。

どのへんを見ると分かるか

 基本的にwant_phasesとか、install_typeとかいう文字列を追っかけてくと良い。具体的には

 あと関係しそうなオプションは

  • installdeps
  • notest
  • with-develop
  • with-feature, with-all-features
  • with-recommends, with-suggests

あたり。

フェーズとインストールタイプ

http://perldoc.jp/docs/modules/CPAN-Meta-2.132140/lib/CPAN/Meta/Spec.pod#Phases を見ると分かりやすい。

あと実際の実装は https://github.com/Perl-Toolchain-Gang/CPAN-Meta/blob/5f96f40032e21e10d7e4adfaf2b3b3b476c278b4/lib/CPAN/Meta/Prereqs.pm とか、そのあたりっぽい。

フェーズとインストールタイプの組み合わせで入れるものが決まるっぽい。特定のフェーズ(configure, build, testとか)で、どのような要求がされているか(requires, recommends, suggests)というので、入れるモジュールが決まる。

例) installdeps + notestのとき

 cartonがインストールするときのデフォルトはinstalldeps + notestでcpanmに渡される。この時

  • cpanfileに記録されたモジュールはbuild, runtime, testがインストールされる
  • cpanfileに書かれた依存のさらに依存はbuild, runtimeがインストールされる

という挙動になりそう。

 それは https://github.com/miyagawa/cpanminus/blob/452beb8583340780fe547e00501bf3d7619c5d71/lib/App/cpanminus/script.pm#L2135-L2137 を見ると分かる。

 cpanmはインストールするときに、依存を探して更にその依存を見つけたら再帰的にインストールして...という処理を繰り返している。その時$depthというのは今どの深さを辿ってるかを表していて、installdepsでcpanfileの依存を入れる時は0になるけど、依存の依存を見る時は1、依存の依存の依存を見る時は2とかになりそう。

 上のことからintalldepsでcpanfileに書かれている物を見ている時はdepthが0、installdepsがtrueとなるので、testまでインストールされる。こうしている理由は https://twitter.com/hide_o_55/statuses/315073204966277122 に書かれている。

 依存の依存はdepthが1以上になるので、buildとruntimeのみがインストールされる。

 あとはデフォルトはrequiresのインストールタイプを入れようとするように見える。https://github.com/miyagawa/cpanminus/blob/452beb8583340780fe547e00501bf3d7619c5d71/lib/App/cpanminus/script.pm#L97

まとめ

もうだめだ。