とある事情があって古いcpanmに固定して使っている場所があったのだけれど、それによってハマったことがあったのでメモ。詳しいわけではないので、間違ったことを書くかもしれないです。何か間違っていたら指摘していただけると。
cpanmのバージョン1.5くらいを使っていて、Net::Twitter::Liteをインストールしようとしたら、以下の様な状況が起こった。
- 何もインストールされていないところにcpanm -L local Net::Twitter::Lite するとインストールが成功する
- Net::HTTPがインストールされているところに、cpanm -L local Net::Twitter::Lite すると、Invalid version format (non-numeric data) と言われて死ぬ
上のようになった理由としては、cpanにおけるversion rangeというものが、Net::Twitter::LiteのBuild.PLでNet::HTTPの依存の記述に使われていたためだった。
まずVersion Rangeだが、これはCPAN::Meta::SpecのVersion Rangeに仕様が書かれている。これに従うと、Build.PL以下のように指定することが出来る。
"Net::HTTP" => ">= 0, != 6.04, != 6.05",
この仕様がcpanmでも使えるようになったのが、1.59_01だと思われる。このため、これより前のversionではBuild.PLなどにこの仕様を使っていた場合、うまくインストールできない(この辺りちょっと怪しい)。
1.59_01 Thu Jan 31 09:54:50 PST 2013 [New Features] - Added a proper support for version range in MYMETA files using CPAN::Meta::Requirements - Skip installing modules when found versions from CPAN doesn't satisfy the requirement, rather than proceeding as if it is ok. For instance, if a ditribution X requires Y >= 1.1 and Y on CPAN (or your CPAN mirror) has 1.0, cpanm will just complain and stop installing it. - Better cpanfile end-to-end support - Upgraded fatpacked modules to the latest
以上の理由から、Net::Twitter::Liteをインストールするときに、Build.PLのversion rangeの記述をparseできずインストール出来なかったとおもわれる。
しかし、ここで一番最初の状況をみてみると、インストール出来ないはずなのに、何も入っていない状況だと、問題なくインストールできてしまう。
これはcpanmの、入れたいモジュールが入っているかどうかをチェックする部分が関係している。cpanmは、インストール先に入れたいモジュールが入っていなければモジュールのversionをチェックせずそのまま入れ、入れたいモジュールが入っている場合はversionをチェックする。このため、何も入っていなければversionをチェックしないため、parse出来なかったとしてもインストールができていた。
上に書いたように、cpanmでモジュールが入ったり入らなかったりする事例が起こり、非常にハマった。モジュールのインストールといった、基礎を構築している部分のモジュールは出来るだけ最新を使わないと大変な事になるという教訓になった。