Carmel を読む

5/20 に 吉祥寺.pmミニ Carton/Carmelのコードリーディング が行われるので事前にCarmelを読んどく。

結論

読むなら Carmel::Setup/Runtime あたり!

Carmel の基本的な使い方

ほとんど Carton と同じにように使える。つまり cpanfile に依存を書いて、carmel install でインストールし、carmel exec で実行。

$ echo "requires 'Plack';" > cpanfile

$ carmel install
---> Installing new dependencies: Plack
...
---> Complete! 1 cpanfile dependencies. 20 modules installed.

$ carmel exec perl -V
...
  @INC:
    Carmel::Runtime::FastINC=HASH(0x7fbe120a45a8)
    /Users/skaji/.carmel/5.20.2-darwin-2level/builds/Apache-LogFormat-Compiler-0.32/blib/lib
    /Users/skaji/.carmel/5.20.2-darwin-2level/builds/POSIX-strftime-Compiler-0.41/blib/lib
    ...

$ carmel exec plackup --version
Plack 1.0034

実際のところ

Carmel と Carton は module の保持の仕方、それをどのように使わせるかにおいてかなり違う。

Caton は local/ 以下に module をインストールし、実行時は単に PERL5LIB に local/ を追加していた。

一方 Carmel は中央 repository (~/.carmel/perl-version/builds) に module を "個別" に保持し、実行時に @INC を巧みにいじり、require させている。

Carmel は @INC をどのように扱っているのか

中央 repository に個別にmodule を保持しているためたくさんの依存があった場合は、その数だけ @INC に追加しなくてはいけない。

初期の Carmel は環境変数 PERL5LIB にこれを追加していた。 PERL5LIBは相当な長さになり、これはちょっと、という感じがあった。

現在の Carmel は .carmel/MySetup.pm という設定ファイルに @INC をはじめとする依存moduleの情報を保存し、実行時はそれを require するようになった。

そして、ここからが興味深いところで Carmel は その設定ファイル .carmel/MySetup.pm の情報を単に @INC に追加するのではなく、Carmel::Runtime::FastINC クラスのインスタンスを作り、それを @INC に差し込んでいる。

名前の通り、Carmel::Runtime::FastINC は素早くmoduleを読み込むための仕掛けである。 実装詳細はコードを見てもらえばわかるが、とにかくこのあたりがかっこいい!

その他

  • 依存モジュールを recursive に解決するコードがかっこいい。
  • binstub の意味は?
  • my($self, $arg) = @_my( の間にスペースを書かない流儀 は誰が発祥か知りたい。
  • carmel package で configure deps などがコピーされない。
  • https://github.com/miyagawa/Carmel/blob/master/lib/Carmel/Runner.pm#L31
    ここは PERL5OPT ではなくて PERL5LIB=local/lib/perl5 だと思うが自信がない。-> やはりそのままであってた。
  • 開発環境での使い方は?
    perl -MCarmel::Setup ... がいい?
  • 本番環境での使い方は?
    carmel rollout してPERL5LIB に local を設定する、がいい?
  • 会社で HTML::Tidy module を使っているのだが、これは先にAlien::Tidyp module を入れておかないとインストールに失敗する。 このようなmoduleをcpanfileで管理するのに苦労している。 何かいい解決法はないか。