Carton
Cartonもcpanmと同様に、
carton is a command line tool to track the Perl module dependencies for your Perl application.
「Cartonとは、
また、
Carton - Perl module dependency manager (aka Bundler for Perl)
Rubyでお馴染みのBundlerという単語が出てきました。Rubyを使う人にはこちらのほうがピンとくるのではないでしょうか。BundlerはRubyのモジュール管理ツールとして有名で、
どのように動くのか
それでは、
そもそもPerlモジュールのインストールにはメタデータが必要です。メタデータとは、
Cartonはここで定義された依存関係を解決し、
次のセクションで解説しますが、
なお、
cpanfile
cpanfileとは、
前述のとおり、
- CPANにアップロードしないプロダクトの考慮
- たとえばアプリケーションプロジェクトでは、
依存関係の定義だけが欲しいので、 Makefile. PLやBuild. PLをあえて作成する必要はない - より正確な依存関係の解析
- モジュールのビルドそのものに必要となるconfigureフェーズも、
正確に定義・ 解析できるようになる (後述) - CPAN Meta Spec v2のサブセットとなるDSL
(Do main Specific Language、 ドメイン特化言語) のサポート - Module::InstallライクなDSLに加えて、
CPAN Meta Spec v2の機能であるバージョンの範囲指定などもサポートされる
既存のMakefile.
cpanfileの書き方
cpanfileは前述のとおりModule::Installによく似たDSLで依存関係を定義します。PODからcpanfileの例を引用します。
requires 'Catalyst', '5.8000'; # 5.8000 or newer
requires 'Catalyst::View::JSON', '>= 0.30, < 0.40';
recommends 'JSON::XS', '2.0';
conflicts 'JSON', '< 1.0';
on 'test' => sub {
requires 'Test::More', '>= 0.96, < 2.0';
recommends 'Test::TCP', '1.12';
};
on 'develop' => sub {
recommends 'Devel::NYTProf';
};requiresやrecommendsはModule::Installでも使われており、conflictsやsuggestsもありますので、requiresのみです。
これらの引数は以下のように指定でき、
requires 'Module::Name';
requires 'Module::Name', 'MINIMUM VERSION';
requires 'Module::Name', '>= MINIMUM, < MAXIMUM';
requires 'Module::Name', '== SPECIFIC VERSION';フェーズ
on 'PHASE'という記法で、configure、build、test、runtime、developの5つがあります。上記例のようにフェーズ指定がない場合は、runtimeフェーズとして扱われます。
テストのみで必要なモジュールはtestフェーズで、developフェーズで、configureフェーズで、
on 'confgure' => sub {
requires 'Module::Build', '0.40';
requires 'Module::CPANfile', '0.9031';
};
on 'test' => sub {
requires 'Test::More', '>= 0.96, < 2.0';
};
on 'develop' => sub {
recommends 'Devel::NYTProf';
};既存ツールチェインとの連携
ところで、
Module::Installの場合
Module::Install の場合は、
on 'configure' => sub {
requires 'Module::Install';
requires 'Module::Install::CPANfile';
};
requires 'Some::Module';use inc::Module::Install;
(省略)
cpanfile;
WriteAll;Module::Buildの場合
Module::Buildの場合は、
on 'configure' => sub {
requires 'Module::Build', '0.40';
requires 'Module::Build::Pluggable::CPANfle', '0.04';
};
requires 'Some::Module';use Module::Build::Pluggable qw(
CPANfile
);
my $builder = Module::Build::Pluggable->new(
(省略)
);
$builder->create_build_script();Cartonの導入
ここまでCartonを動かすためのしくみを見てきたので、
$ cpanm Cartonインストールされたことを確認します。
$ carton -v
carton v0.9.15旧バージョンの導入
前述のように、
$ cpanm Carton@v0.9.4
# or
$ cpanm MIYAGAWA/carton-v0.9.4.tar.gz
(省略)
$ carton -v
carton v0.9.4一括インストール
Cartonで現在できることは、
Cartonのメイン機能である一括インストールを行うには、installサブコマンドを使います。ここではサンプルとして次の内容のcpanfileを使います。
requires 'Plack';この状態でCartonを実行すると、
$ carton install
Installing modules using cpanfile
Successfully installed File-ShareDir-Install-0.04
Successfully installed Try-Tiny-0.12
(省略)
Successfully installed Plack-1.0024
34 distributions installed
Complete! Modules were installed into localこのとき、
$ tree local
local
├─ bin
│ ├─ instmodsh
(省略)
└─ lib
└─ perl5
├─ Apache
│ └─ LogFormat
│ └─ Compiler.pm
(省略)
125 directories, 301 filescarton installを実行すると、carton.というファイルが生成されます。このファイルにはインストールされたモジュールのメタデータが入っており、
インストールの挙動を変更するオプションが3つあるので、
インストール先の変更── --path、PERL_CARTON_PATH
インストール先を変更したい場合は、--pathオプション、PERL_環境変数で指定できます。
$ carton install --path=vendor/modules
# or
$ PERL_CARTON_PATH=vendor/modules carton install
Installing modules using cpanfile
(省略)
34 distributions installed
Complete! Modules were installed into vendor/modules場所が変わっただけで、
$ tree vendor/modules
(省略)
125 directories, 301 filesデプロイモード ── --deployment
--deploymentオプションを指定するとcarton.の更新を行わなくなります。利用シーンとしては、
$ carton install --deployment
Installing modules using cpanfile (deployment mode)
(省略)
34 distributions installed
Complete! Modules were installed into localbundleしたモジュールをインストール── --cached
後述するbundleサブコマンドを使うと、--cachedオプションは、
$ carton install --cached
(省略)
34 distributions installed
Complete! Modules were installed into locallocal環境での実行
execサブコマンドを使うと、localディレクトリにインストールしたモジュールを使ってプログラムを起動できます。
$ carton exec -- plackup -v
Plack 1.0024execのあとに--を挟んで実行したいコマンドラインを指定しないと、-vオプションがplackupではなくcartonのオプションとして解釈されてしまうので、
$ carton exec plackup -v
carton v0.9.15local/以外のディレクトリを独自に@INCに差し込みたい場合は、-Iオプションで指定できます。
$ carton exec -Iextlib -- perl -le 'print join "\n", @INC'
extlib
local/lib/perl5/darwin-2level
local/lib/perl5
.
(省略)また、PERL_環境変数でディレクトリを指定して実行します
$ PERL_CARTON_PATH=vendor/modules carton exec -- plackup -v
Plack 1.0024依存モジュールのダウンロード
bundleサブコマンドで依存モジュールのtarballを一括ダウンロードできます。
$ carton bundle
Bundling modules using cpanfile
File-ShareDir-Install-0.04
Plack-1.0024
\_ Try-Tiny-0.12
(省略)
Complete! Modules were bundled into /Users/ikasam_a/myapp/
local/cacheデフォルトでlocal/ディレクトリ以下にCPANミラーと同様の構造で保存します。
$ tree local/cache
local/cache
└─ authors
└─ id
├─ A
│ └─ AD
│ └─ ADAMK
│ ├─ Class-Inspector-1.28.tar.gz
(省略)
41 directories, 34 filesただし、modulesディレクトリと02packagesファイルが存在しない
ダウンロード先の変更── --path、PERL_CARTON_PATH
インストールと同様に、--pathオプションあるいはPERL_環境変数で保存先を指定できます。ただし、/cacheが自動で付与されることに注意が必要です。
$ carton bundle --path=vendor/bundle
Bundling modules using cpanfile
(省略)
Complete! Modules were bundled into /Users/ikasam_a/myapp/
vendor/bundle/cache
$ tree vendor/bundle/cache
(省略)
41 directories, 34 filesbundleであらかじめモジュールを取得しておくと、install --cachedを利用してローカルでインストールを完結させることができるので、
依存モジュールの確認
モジュールの表示をするサブコマンドにはlist、tree、showがあります。名前から予想できるように、
listサブコマンドを実行すると次のように、
$ carton list
Test-NoWarnings-1.04
IO-HTML-1.00
(省略)list --treeとすると整形して簡易ツリー表示になります。treeサブコマンドもまったく同じで、list --treeのショートカットなだけです。
$ carton list --tree
# or
$ carton tree
Plack-1.0024
Test-Requires-0.06
ExtUtils-MakeMaker-6.66
(省略)show Module::Nameで指定したモジュールの情報がJSONでダンプされます。省略していますが、
$ carton show File::ShareDir::Install
{
"dist" : "File-ShareDir-Install-0.04",
(省略)
"provides" : {
"File::ShareDir::Install" : {
"file" : "File/ShareDir/Install.pm",
"version" : "0.04"
}
},
"target" : "File::ShareDir::Install",
"version" : "0.04"
}なお、carton.ファイルが存在しないとエラーになるので、carton installあるいはcarton bundleを実行しておく必要があります。
Carton今後の課題
Cartonは1.
たとえばサブコマンドによってオプションの一貫性が取れていない部分もありますし、bundleやinstall時のcarton.ファイルの扱いがあまり考慮されていない、
今回紹介した機能で基本的なモジュール管理はできるようになりますが、
なお、
まとめ
今回は、
さて、