以下、環境によっては違うかも。
(ExtUtils::MakeMaker 5.4302)
サイトインストール(INSTALLDIRS=site)の場合
アーキテクチャ依存ファイル | INSTALLSITEARCH | $(LIB)/$arcname |
pm 等 | INSTALLSITELIB | $(LIB) |
実行可能ファイル | INSTALLBIN | $(PREFIX)/bin |
スクリプト | INSTALLSCRIPT | $(PREFIX)/bin |
man1 | INSTALLMAN1DIR | |
man3 | INSTALLMAN3DIR | |
perllocal.pod | $(INSTALLARCHLIB) |
Makefile.PL の PREFIXパラメータだけでは bin 以下のものしか変更されない。 ユーザ権限でホームディレクトリ等にインストールする場合は、PREFIX, LIB, INSTALLMAN1DIR, INSTALLMAN3DIR を指定しておく。
perllocal.pod は $(INSTALLARCHLIB)の下へ追記される。 perllocal.pod への追記の必要がなければ、make install のかわりに、make pure_install する。
サイトインストール(INSTALLDIRS=site)の場合
アーキテクチャ依存ファイル | INSTALLSITEARCH | $(SITEPREFIX)/lib/perl/5.6.1 または $(LIB)/arcname |
pm 等 | INSTALLSITELIB | $(SITEPREFIX)/share/perl/5.6.1 または $(LIB)/$ |
HTML | INSTALLHTMLSITELIBDIR | ? |
HTMLスクリプト | INSTALLHTMLSCRIPTDIR | ? |
実行可能ファイル | INSTALLBIN | $(PREFIX)/bin |
スクリプト | INSTALLSCRIPT | $(PREFIX)/bin |
man1 | INSTALLMAN1DIR | $(PREFIX)/share/man/man1 |
man3 | INSTALLMAN3DIR | $(PREFIX)/share/man/man3 |
(man1) | INSTALLSITEMAN1DIR | $(SITEPREFIX)/man/man1 |
(man3) | INSTALLSITEMAN3DIR | $(SITEPREFIX)/man/man3 |
perllocal.pod | $(INSTALLARCHLIB) |
Makefile.PL の SITEPREFIX と PREFIX を指定する。モジュールのディレクトリを直接指定するなら LIB も使用する。
perllocal.pod は $(INSTALLARCHLIB)の下へ追記される。
サイトインストール(INSTALLDIRS=site)の場合
アーキテクチャ依存ファイル | INSTALLSITEARCH | $(SITEPREFIX)/lib/perl/5.8.0 または $(LIB) |
pm 等 | INSTALLSITELIB | $(SITEPREFIX)/share/perl/5.8.0 または $(LIB)/$arcname |
実行可能ファイル | INSTALLSITEBIN | $(SITEPREFIX)/bin |
スクリプト | INSTALLSCRIPT | $(PREFIX)/bin |
man1 | INSTALLSITEMAN1DIR | $(SITEPREFIX)/man/man3 |
man3 | INSTALLSITEMAN3DIR | $(SITEPREFIX)/man/man3 |
perllocal.pod | $(INSTALLARCHLIB) |
Makefile.PL の SITEPREFIX でほとんどまとめて指定できる。 INSTALLSCRIPT だけは PREFIX を使用するので、必要があれば指定する。
モジュールのディレクトリを直接指定するなら LIB も使用する。
perllocal.pod は $(INSTALLARCHLIB)の下へ追記される。 perllocal.pod への追記の必要がなければ、make install のかわりに、make pure_install する。
CGI.pm 等はデフォルトで 'perl' が指定してある。 ホーム以下にインストールするには INSTALLDIRS=site を指定する。
例えば File::Spec の最新版をローカルにインストール。 ここで最新の File::Spec を使う File::Temp をインストールするのに PERL5LIB にローカルディレクトリを指定しても、make test では標準ライブラリのディレクトリが -Iオプションで指定されるので、古い版が優先的に使用されテストに失敗してしまう。
この場合 PERL_LIB をでローカルのディレクトリを指定すればとりあえずだませる。
Devel::Size、Devel::Cycle を埋め込むもののメモリを喰ってそうなところがなかなか見つからず。
デバッグ用コードを書いたり消したりも面倒なので、ビルド時に WIKICKER_DEBUG=1 を指定しておいた時だけ、ExtUtils::MakeMaker の PM_FILTER を使ってソース中の、
#IFDEBUG: <デバッグコード>
が有効になるようにしておく。
でメモリ消費の方だが以前より攻撃的に eval "use ..." で必要な時だけモジュールをロードするように修正。 常にロードしてあった Jcode も必要な時だけに。 これで少しは減ってくれるかな?
真実32 充分テストをしたとプログラマが自信を持つソフトウェアでも、全パスの50〜60%程度しか網羅していない。 パス・カバレージ・アナライザのような自動化ツールを使うと、網羅率が85〜90%に上がる。しかし、100%のパスを網羅するのは不可能だ。
真実34 ツールを使わないと、不良除去はうまくいかない。デバッガはみんな使うが、カバレージ・アナライザは、ほとんど使わない。
ということで、Perl 用のカバレッジ分析ツールを探してみる。 CPAN にある Devel::Cover が良さそげ。
apt-get install libtest-differences-perl \ libpod-coverage-perl \ libtemplate-perl
してから Devel::Cover をインストール
dh-make-perl --cpan Devel::Cover --build dpkg --install libdevel-cover-perl_0.45-1_i386.deb
WiKicker はExtUtils::MakeMaker を使ってパッケージ化しており、テストは t/*.t を使用するようになっているので、そのまま分析をする事ができる。
perl Makefile.PL make cover -delete HARNESS_PERL_SWITCHES=-MDevel::Cover make test cover
出力はこんな感じ
Reading database from /path/WiKicker/source/cover_db ---------------------------- ------ ------ ------ ------ ------ ------ ------ File stmt branch cond sub pod time total ---------------------------- ------ ------ ------ ------ ------ ------ ------ blib/lib/WiKicker.pm 100.0 n/a n/a 100.0 n/a 0.0 100.0 ...cker/App/Configuration.pm 44.1 0.0 n/a 62.5 n/a 0.0 41.7 ...icker/App/MarkUpAsHtml.pm 38.1 0.0 0.0 66.7 n/a 0.0 34.8 ...CGI/AbstractController.pm 24.8 0.0 n/a 47.4 n/a 0.0 23.6 [snip] ...ageHtmlFragmentVisitor.pm 100.0 n/a n/a 100.0 n/a 0.0 100.0 ...icker/WikiPage/WriNode.pm 96.4 83.3 n/a 88.9 n/a 0.9 93.0 .../tDiaryFragmentVisitor.pm 32.3 0.0 n/a 33.3 n/a 0.0 29.8 Total 59.2 41.3 31.4 67.5 100.0 100.0 56.7 ---------------------------- ------ ------ ------ ------ ------ ------ ------ Writing HTML output to /path/WiKicker/source/cover_db/coverage.html ... done.
cover_db/coverage.html に各モジュール毎のコードカバレッジが表示される。 また、各モジュールファイル毎のレポートもHTMLで作成され、プログラムの各行毎のカバレッジがプログラムとともに表示される。
なかなかいい感じ。さすがにパスカバレッジはサポートしていない。
コードカバレッジを上げてもバグ0にはなるとは全然言えないのは承知しているが、テスト漏れを減らすための情報として結構使えそうだ。
[ Perl ]
コードカバレッジをチェックするDevel::Coverであるが、AutoSplit / AutoLoader を使っていると分割されたサブルーチンが対象にならない。WiKicker では AutoLoader を多用しているので、ここがチェックされないと意味がない。
ということで Devel::Cover下でテストする時は AutoLoader を使わないようしてみる。
perl Makefile.PL WIKICKER_NO_AUTOLOAD=1
とした時はExtUtils::MakeMaker::WriteMakefile に PM_FILTER として
q($(PERL) -e "while (<>) {s!^\\\\s*use\\\\s+AutoLoader.*!!g; s!^__END__!!g; print} print qq(\\n1;\\n); ")
を渡すように Makefile.PL を修正。これで
perl Makefile.PL WIKICKER_NO_AUTOLOAD=1 make cover -delete HARNESS_PERL_SWITCHES=-MDevel::Cover make test cover
とすると AutoLoader を使わないバージョンでチェックができる。
EXE_FILES でインストールするスクリプトを指定してある Makefile.PL を ActivePerl 上で実行して nmake をかける。 また nmake する。
するとソースを書き換えてないにもかかわらず、EXE_FILES指定ファイルの blib/script へのコピーと pl2bat の実行が行われる。 嫌な感じ。
追いかけてみると
というわけ。コピーした後 touch するようにすればよい。
perl -MExtUtils::Command -e touch %1 pl2bat %1
という内容の touchpl2bat.bat を作って
nmake FIXIN=touchpl2bat
とすればきちんと更新時刻が反映されビルドは1回だけになる。 毎回指定するのは面倒なので、MSWin32 なら自動的にそうするようにパッケージングしたいのだが nmake で他にうまく FIXIN を上書きする方法がみつからず (MY::postamble で書き出しても、WriteMakefile(macro => {FIXIN => 'touchpl2bat'}, ...) しても駄目)。
NSIS のサイトによるとビルドに「SCons」を使うようしたらしい。
と興味深いツールになっているようだ。
現在プロジェクトLaTeXベースのドキュメント生成には GNU Make を使っているのだが、UNIX、Windows の両方でビルドできるようにするには ComSpec 環境変数の有無で使用するコマンドを切り換えたり等いろいろ面倒なので、代替ツールとして使えないかなと。
基本的な機能は Make に対する改良がなされているようであるし、コピー等ファイル操作も SCons 自体がもっているのでクロスプラットフォームでビルドできるようにするのも楽そうだ。
一方 Autoconf 系の機能については、インストール済みのライブラリの検出や実装レベルのチェック等を実装しているようである。 make check や make dist、make install 等にあたるターゲットに関する機能(あるいは規約)のようなものは無い。これは非常に残念。 結局自分が Ant を使わなくなったのも GNU Autotools にあるこれらの機能に欠けているからであるし。
実は私がPerl が好きな理由の一つとして、これらサポートが充実しているという点がある。Perl では ExtUtils::MakeMaker (あるいは Module::Build)があり、ビルドからテスト、ソースパッケージのパッケージングまでフレームワークが整っている。
SCons は Python ベースで、Makefile にあたるファイルも Python スクリプトである。 SCons が影響を受けた Cons は Perl ベースであったのだが、既に2001年5月ごろから開発が止まってしまっている。残念。
ということで Make の代替には使えそうであるが、GNU Autotools と同じようなことをするにはいろいろ手をかけないといけないといった印象。
私が Perl が好きな理由の一つに、標準でExtUtils::MakeMakerという Makefile ジェネレータがついているところである。これを使って Makefile.PL を書くと
perl Makefile.PL make manifest make make test make dist
で <pacakge>-<versionno>.tar.gz というソースパッケージを作ることができ、
tar zxvf <pacakge>-<versionno>.tar.gz cd <pacakge>-<versionno> perl Makefile.PL make make test make install
という手順でインストールする事ができるようになる。 パッケージの作り方が確立されているので、容易に新しいパッケージを開発しはじめられる。
逆に Java でプログラムを書くのが億劫なのは、このあたりの準備が面倒だからである。 Ant を使っても結局ここら辺自分でやらなければならないし。
ちょっとしたパッケージを作りたいと思うことは良くある。 例えばいくつかのデータファイルと、READMEファイルなんかをひとまとめにしてアーカイブにするとか。
本当にちょっとしたであれば、手動でアーカイブすれば良いのだが、
あたりを考慮しなければならない時は面倒くさくなってくる。
自動化としては
あたりがぱっと思い浮かぶ。 しかし、最初の2つは毎回同じようなものを書くのが面倒だし保守もしにくい。 GNU Autotools はちょっとごっつすぎだし、Windows での環境構築も面倒。
ということで最初は ExtUtils::MakeMaker を使うという線で考えてみた。 もともと Perl モジュール用で汎用用途にはちょっと邪魔な振舞いもあるが、使えないことはないと思う。 しかし make (GNU Make あるいは nmake など) に依存しているという欠点がある。
ということで ExtUtils::MakeMaker の代替である Module::Build ベースで汎用用途に使えないか検討してみた。こちらは pure Perl で make を必要としない。
Module::Build も Perl モジュールビルドにあわせた振舞いがあるものの、ちょっとカスタマイズすれば使えそうだ。 で、いろいろいじった結果、次のような感じにすると使いやすそうだ。
use Module::Build; my $class = Module::Build ->subclass(class => 'NonmoduleBuilder', code => q{ # Don't make blib sub ACTION_code {}; # Don't make blib sub ACTION_docs {}; # Don't make META.yml sub ACTION_distmeta { # no warning on ACTION_distdir $_[0]->{metafile} = 'MANIFEST'; }; # Don't add MEATA.yml to MANIFEST sub ACTION_manifest { $_[0]->{metafile} = 'MANIFEST', $_[0]->SUPER::ACTION_manifest(@_); }; }); # Set your archive name and version. $class->new(dist_name => 'mypackage', dist_version => '1.0.2', )->create_build_script;
カスタマイズした部分は以下(Module::Build 0.26 で動作確認)。
上記のようなファイルを Build.PL という名前で作っておけば
perl Build.PL ./Build manifest ./Build ./Build test ./Build dist
等として、アーカイブ作成が容易にできるようになる。
しばらくこの方法でいろいろ試してみることにしてみよう。
WiKicker には依存している Perl モジュールとして、必須なものとオプションなものがある。 必須なものは例えば Log::Log4perl など。 一方 Cache::Memcached や HTML::Scrubber などは、追加機能を使用したい場合のみ必要である。
一般的な Perl モジュールパッケージと同様、WiKicker では Makefile.PL に ExtUtils::MakeMaker を使っている。 必須な依存 Perl モジュールは PREREQ_PM に指定してあるが、オプションのものについては独自にチェックして警告をするにとどめていた。 しかしこれだと、オプションのものは CPAN.pm を使って自動的にインストールすることができない。
ということで検討した結果、Module::Install を用いることにした。 Module::Install を用いて Makefile.PL を作成すると、
などの機能が使えるようになる。
Module::Install の実行に必要なファイルはパッケージの inc ディレクトリ以下に自動的にコピーされ配布パッケージに含められるので、インストールする側はそのために余分なインストールを強いられることもない。
最終的に内部で ExtUtils::MakeMaker を使っているので、それの機能はほぼ全て使える。
Perl のバージョンも 5.004 から使えるとのことで、Perl 5.005_03 以上を対象としている WiKicker で使っても問題なし。
ということで、Makefile.PL をさらっと書き換え。
合わせて WiKicker に含まれていた実験的な機能を削除して、(オプションな)依存モジュールも減らすことにした。
次回のリリース版から、Module::Install ベースだ。
ゴールデンウィークに突入。 9連休を利用して、一気に WiKicker コーディングを企んでいる。
さっそくちょこちょこ修正してパッケージングし、www.naney.org へインストール。 …… Perl Makefile.PL でコケる。
どうも use inc::Module::Install; でエラーを起してしまっているようだ。 Makefile.PL は変更していないので、そうすると Module::Install の問題っぽい。
tarball をパッケージングするホスト側の Module::Install を 0.57 まで落としたところ、Perl 5.005_03 でも通るようになった。
Module::Install is a package for writing installers for CPAN (or CPAN-like) distributions that are clean, simple, minimalist, act in a strictly correct manner with both the ExtUtils::MakeMaker and Module::Build build systems, and will run on any Perl installation version 5.004 or newer. (Module::Install 0.61 より)
とあるように古い Perl もサポートにも気を払っているのが気にいって ExtUtils::MakeMaker から移行しただけにちょっと残念。
今後また 5.005_03 でも動くようになるのか、それとも捨てられるのか要チェック。
GNU Autotools や ExtUtils::MakeMaker (とその仲間たち)で make dist するのがあたり前になっている自分には、気持ち悪い。
Module::Build 0.26 には ExtUtils::MakeMaker のように zipdist ターゲットがないので ACTION を追加してみた。
use Module::Build my $class Module::Build->subclass( class => 'Packager', code => q { sub ACTION_zipdist { my ($self) = @_; my $dist_dir = $self->dist_dir; $self->depends_on('distdir'); print "Creating $dist_dir.zip\n"; system("zip -r $dist_dir.zip $dist_dir") == 0 or die $?; $self->delete_filetree($dist_dir); } });
これで ./Build zipdist できるようになる。
Naney (なにい) です。株式会社MIXIで SNS 事業の部長をしています。
※本サイトの内容は個人的見解であり所属組織とは関係ありません。