=encoding euc-jp =head1 NAME PAR::Intro - Introduction to Perl Archive Toolkit PAR::Intro - Perl Archive Toolkit の導入 =head1 概要 # これはプレゼンテーションであって、モジュールではない。 Note that a more extensive tutorial is now available online as L and has superceded materials in this introduction. より発展的なチュートリアルはL からオンラインで利用可能だ。これはこのイントロダクションの素材よりも できの良いものになってきている。 =head1 説明 =head2 PAR (Perl Archive Toolkit) とは何か? =over 4 =item * Do what JAR (Java Archive) does for Perl JAR (Java Archive) がやることをPerlで行なう =over 4 =item * Platform-independent, compressed file format (zip) プラットフォームに依存しない、圧縮ファイル形式(zip) =item * Aggregates modules, scripts and other files into one file モジュール、スクリプト、その他のファイルを一つのファイルにまとめる =item * Easy to generate, update and extract 生成、更新、取り出しが容易 =back =item * Benefits of using PAR: PARを利用する利点: =over 4 =item * Reduced download and deployment time ダウンロードと展開の時間を短縮 =item * Saves disk space by compression and selective packaging 圧縮と選択的なパッケージ化によりディスクスペースを節約 =item * Version consistency: solves forward-compatibility problems バージョンによらず一貫性が保たれる:前方互換の問題を解決 =item * Community support: C コミュニティによるサポート:C =back =item * You can also turn a PAR file into a self-contained script PARファイルを自己完結なスクリプトにすることもできる =over 4 =item * Bundles all necessary 3rd-party modules with it 必要な全てのサードパーティモジュールを一緒にバンドル =item * Requires only core Perl to run on the target machine 必要なのは、当該マシン上で実行されるコアなPerlのみ =item * If you use C to compile the script... Cを使ってスクリプトをコンパイルすれば… =item * ...you get an executable not even needing core perl …コアとなるperlさえ必要としない実行ファイルを得る =back =back =head2 Getting Started =over 4 =item * First, generate a PAR file with modules in it: 最初にモジュールの入ったPARファイルを生成する: % zip foo.par Hello.pm % zip -r foo.par lib/ # grab all modules in lib/ =item * Using modules stored inside a PAR file: PARファイルの中に格納されたモジュールを使う: % perl -MPAR=./foo.par -MHello % perl -MPAR=./foo -MHello # the .par part is optional =item * Or put it in @INC and use it just like a directory: あるいは@INC内にファイルを置き、ディレクトリのように利用する: % perl -MPAR -Ifoo.par -MHello % perl -MPAR -Ifoo -MHello # 同上 =back =head2 コマンドラインツール =over 4 =item * Use C to scan scripts and store dependencies as a PAR file: Cを使ってスクリプトを走査し、PARファイルの依存関係にあるものを格納する: % pp -p source.pl # makes 'source.par' % pp -B -p source.pl # bundles core modules too =item * Use C to run files from a Perl Archive: Cを使ってPerlアーカイブからファイルを実行する: % par.pl foo.par # looks for 'main.pl' by default % par.pl foo.par test.pl # runs script/test.pl in foo.par =item * Use C or C to run files from a Perl Archive: CあるいはCを使ってPerlアーカイブからファイルを実行する: % parl foo.par % parl foo.par test.pl =back =head2 バイナリ実行ファイルの作成 Making Binary Executables =over 4 =item * The C utility can also generate binary executables: Cユーティリティはバイナリ形式の実効ファイルも生成できる: % pp -o packed.exe source.pl # self-contained .exe % packed.exe # runs anywhere with the same OS =item * You can also bundle additional modules: 追加のモジュールをバンドルすることもできる: # packs CGI + its dependencies, too % pp -o packed.exe -M CGI source.pl =item * Or pack one-liners: あるいは一行スクリプトのパック: # turns one-liner into executable % pp -o packed.exe -e 'print "Hi!"' =item * Some notes: 諸注意: =over 4 =item * The command-line options of C are almost identical to C's CのコマンドラインオプションはCのものとほぼ同じである =item * Modules are read directly from the PAR file, not extracted モジュールはPARファイルから直接読み込まれるのであって、展開されるのではない =item * Shared object files (aka dll) are extracted with File::Temp 共有オブジェクトファイル(例えばdll)はFile::Tempを使って展開される =item * Tested on Win32, FreeBSD, Linux, AIX, Solaris, Darwin and Cygwin. Win32, FreeBSD, Linux, AIX, Solaris, Darwin そして Cygwinでテストされた =back =back =head2 PARファイル解剖 =over 4 =item * Modules can reside in different directories in a PAR file: モジュールはPARファイル内において様々なディレクトリに属する: /lib/ # standard location /arch/ # for creating from blib/ /i386-freebsd/ # i.e. $Config{archname} /5.8.0/ # i.e. Perl version number /5.8.0/i386-freebsd/ # combination of the two above / # casual packaging only =item * Scripts are stored in one of the two locations: スクリプトは次の二つのロケーションのうちの一つに格納される: /script/ # standard location / # casual packaging only =item * Shared libraries may be architecture- or perl-version-specific: 共有ライブラリはarchitecture-かperl-version-specificに: /shlib/(5.8.0/)?(i386-freebsd/)? =item * PAR files may recursively contain other PAR files: PARファイルは他のPARファイルを再帰的に含む: /par/(5.8.0/)?(i386-freebsd/)? =item * Special files: 特殊なファイル: /MANIFEST # index of the PAR's contents /SIGNATURE # digital signature(s) /META.yml # dependency, license info, etc. /Build.PL # self-contained installer =item * Programs can use C to read file contents inside PAR プログラムはCを使ってPAR内の ファイルコンテンツを読むことが出来る =item * Programs can use C to reload modules within changed PARs プログラムはCを使って、変更されたPAR内のモジュールを 再読み込みすることができる。 =back =head2 派生モジュール =over 4 =item * Apache::PAR =over 4 =item * Nathan Byrd's attempt to make self-contained Perl Handlers Nathan Byrdによる自己完結したPerlハンドラ作成の試み =item * Same as the WAR files for Java Servlets Java ServletにおけるWARファイルと同じもの =item * Includes PerlRun and Registry handlers PerlRunとRegistryハンドラを含む =back =item * App::Packer::Backend::PAR =over 4 =item * Support module of Mattia Barbon's App::Packer suite Mattia BarbonのApp::Packerセットのサポートモジュール =item * Makes it easy to pick-and-choose dependency scanners and packers 依存関係のスキャナとパッカーを選びやすくする =item * Fine-tuned distribution and packaging controls よくチューニングされた配布物とパッケージ制御 =back =item * CPANPLUS::Dist::PAR =over 4 =item * Cross-platform PPM: Auto-generate PAR out of CPAN distributions クロスプラットフォームPPM:CPANディストリビューションから自動生成されたPAR =item * Use the bundled Build.PL to install PAR modules into system バンドルされたBuild.PLを使ってシステムにPARモジュールをインストールする =back =back =head2 Apache::PARのデモ =over 4 =item * In C: C PerlModule Apache::ServerUtil PerlModule Apache::PAR PARDir /opt/myapp PARFile /opt/myapp/myapp.par =item * In C inside C: C内のC: Alias /myapp/static/ ##PARFILE##/ SetHandler perl-script PerlHandler Apache::PAR::Static PerlAddVar PARStaticDirectoryIndex index.html PerlSetVar PARStaticDefaultMIME text/html Alias /myapp/cgi-perl/ ##PARFILE##/ Options +ExecCGI SetHandler perl-script PerlHandler Apache::PAR::Registry =back =head2 今後の開発 =over 4 =item * Polish C's features Cの機能に磨きをかける =over 4 =item * Handles corner dependency cases for LWP, Tk, DBI... LWP, Tk, DBI...に対するcorner dependencyなケースの処理 =item * Optional encryption support (but *not* obscuring) 暗号化オプションのサポート(オブスキュアリングではない) =item * Become a worthy competitor to PerlApp and Perl2Exe PerlAppとPerl2Exeに対抗できるぐらいにする =back =item * Learning from JAR JARから学ぶ =over 4 =item * Making par.pl's command line interface in sync with jar's par.plのコマンドラインインターフェースをjarのものと同期させる =item * Digital signatures for PAR packages using Module::Signature Module::Signatureを使ってPARパッケージ用のデジタル署名 =item * File layout compatibility? ファイルレイアウトの互換性? =back =item * Learning from FreeBSD Bento FreeBSDのBentoから学ぶ =over 4 =item * Smoke test and make PAR automatically for each CPAN upload CPAN uploadのための自動的なスモークテストとPARの作成 =item * Provide binary packages for users without a compiler コンパイラを持っていないユーザーのためにバイナリファイルの提供 =back =back =head2 PAR.pmの実装に関する概観 =over 4 =item * Here begins the scary part ここより危険地帯 =over 4 =item * Grues, Dragons and Jabberwocks abound... グルー、ドラゴン、ジャバウォックがいっぱい… =item * You are going to learn unpleasant things about Perl internals あなたはPerlの内部に関する喜ばしくないものを学ぼうとしている =item * Go home now if you have heart condition or digest problems 心臓に持病があるか胃の調子が悪いなら今すぐお帰りなさい =back =item * PAR invokes five areas of Perl arcana: PARはPerl奥義の5つの領域を召還する =over 4 =item * @INC code references @INCコードリファレンス =item * On-the-fly source filtering オンザフライなソースフィルタリング =item * Faking filehandle with PerlIO::scalar and IO::Scalar PerlIO::scalarとIO::Scalarを使ってファイルハンドリングをだます =item * Overriding DynaLoader::bootstrap to handle XS modules DynaLoader::bootstrapをオーバーライドしてXSモジュールを操作 =item * Making self-bootstrapping binary executables 自己ブートストラップ型バイナリ実行ファイルの生成 =back =item * The first two only works on 5.6 or later 最初の二つは5.6以降でのみ動作する =over 4 =item * PerlIO::scalar is 5.8-specific; IO::scalar only needs 5.005 PerlIO::scalaは5.8の仕様;IO::scalaは5.005を必要とするだけ =item * DynaLoader and %INC are there since Perl 5 was born DynaLoader と %INC は Perl 5 以降存在している =item * PAR currently needs 5.6, but a 5.005 port is possible PARは現在5.6が必要だが、5.005ポートは可能 =back =back =head2 @INC内のコードリファレンス =over 4 =item * On 1999-07-19, Ken Fox submitted a patch to P5P 1999-07-19 に Ken Fox がP5Pにパッチを提起した =over 4 =item * To "enable using remote modules" by putting hooks in @INC @INCにフックを置くことでリモートにあるモジュールを利用できるようにする =item * It's accepted to come in Perl 5.6, but only get documented by 5.8 Perl 5.6で受け入れられたが、5.8になってからドキュメント化された =item * Type 'perldoc -f require' to read the nitty-gritty details 'perldoc -f require'とタイプすれば詳細を読むことができる =back =item * Code references in @INC may return a filehandle, or undef to 'pass': @INC内のコードリファレンスは'pass'に対してファイルハンドルかundefを返す: push @INC, \&my_sub; sub my_sub { my ($coderef, $filename) = @_; # $coderef は \&my_sub open my $fh, "wget http://example.com/$filename |"; return $fh; # リモートホストのモジュールを使う、本当に! } =item * Perl 5.8 let you open a file handle to a string, so we just use that: Perl 5.8では、文字列へのファイルファンドルをオープンできる。 よって次のように: open my $fh, '<', \($zip->memberNamed($filename)->contents); return $fh; =item * But Perl 5.6 does not have that, and I don't want to use temp files... しかしPerl 5.6ではできない。一時ファイルは使いたくないし… =back =head2 Filter::* モジュールを使わないソースフィルタリング =over 4 =item * ... Undocumented features to the rescue! …救済のための機能がドキュメント化されていない! =over 4 =item * It turns out that @INC hooks can return *two* values 結局@INCのフックは*2つ*の値を返すことがわかる =item * The first is still the file handle 一番目はファイルファンドル =item * The second is a code reference for line-by-line source filtering! 二番目は一行毎のソースフィルタリングのためのコードリファレンス! =back =item * This is how C works: これはCの動作の仕方: # 全てのモジュールにstrictとwarningsを使わせる open my $fh, "<", $filename or return; my @lines = ("use strict; use warnings;\n", "#line 1 \"$full\"\n"); return ($fh, sub { return 0 unless @lines; push @lines, $_; $_ = shift @lines; return length $_; }); =item * But we don't really have a filehandle for anything しかし我々は何らかのものに対するファイルハンドルを本当に持っていない =over 4 =item * Another undocumented feature to the rescue もう一つのドキュメント化されていない救済機能 =item * We can actually omit the first return value altogether: 我々は一番目の戻り値を全て捨てることが実際可能だ: # PAR内のファイルから一行毎に内容を全て返す my @lines = split /(?<=\n)/, $zip->memberNamed($filename)->contents; return (sub { $_ = shift(@lines); return length $_ }); =back =back =head2 ハンドルをだます =over 4 =item * The @INC filter stops when it sees C<__END__> or C<__DATA__> @INCフィルタはC<__END__> か C<__DATA__>を見つけるとストップする =over 4 =item * All contents below are lost そこから下の内容は全て失われる =item * Breaks modules that read from the filehandle ファイルハンドルから読み込むモジュールを壊してしまう =item * The same problem appears when we C the main.pl script 同様の問題がmain.plスクリプトをCするときに現れる =back =item * Therefore, we insert a line before the final token to fake *DATA それゆえ、最後のトークンの前に一行挿入して*DATAをごまかす =over 4 =item * It has to be the final line to belong to the correct package 正しいパッケージに属する最終行でなければならない =item * It has to happen in compile time but not inside a BEGIN block コンパイル時に発生しなければならないが、BEGINブロックの中でではない =item * Here is what I came up with (but no longer needed in recent versions): 私が考え出しのはこのような方法だ(だがもはや最近のバージョンでは必要ない): $DATACache{$file} = $1 if ($program =~ s/^__DATA__\n?(.*)//ms); if (eval {require PerlIO::scalar; 1}) { "use PerlIO::scalar". " ( open(*DATA, '<:scalar', \\\$PAR::DATACache{'$key'}) ? () : () )"; } elsif (eval {require IO::Scalar; 1}) { # This will first load IO::Scalar, *then* tie the handles. "use IO::Scalar". " ( tie(*DATA, 'IO::Scalar', \\\$PAR::DATACache{'$key'}) ? () : () )"; } else { # only dies when it's used "use PAR (tie(*DATA, 'PAR::_data') ? () : ())\n"; } sub PAR::_data::TIEHANDLE { return bless({}, shift) } sub PAR::_data::AUTOLOAD { die "Please install IO::Scalar first!\n" } =back =back =head2 DynaLoader::bootstrapのオーバーライド =over 4 =item * XS modules have dynamically loaded libraries (C<.so> or C<.dll>) XSモジュールは動的にライブラリ(C<.so> や C<.dll>)をロードする =over 4 =item * They cannot be loaded as part of a zip file, so we extract them out それらはzipファイルの一部としてロードされない。だから展開すことになる =item * But I don't want to make any temporary C directories だが、一時的なCディレクトリはつくりたくない =item * So we have to intercept DynaLoader's library-finding process そこでDynaLoaderのライブラリ探査処理を横取りしなければならない =back =item * Module names are passed to C for XS loading モジュール名はXSローディングのためにCに渡される =over 4 =item * During the process, it calls C to locate the file この処理の間に、ファイルの位置を把握するためCを呼び出す =item * So we wrap around both functions: そのために両関数をラップする: no strict 'refs'; no warnings 'redefine'; $bootstrap = \&DynaLoader::bootstrap; $dl_findfile = \&DynaLoader::dl_findfile; *{'DynaLoader::bootstrap'} = \&_bootstrap; *{'DynaLoader::dl_findfile'} = \&_dl_findfile; =back =item * Our C<_bootstrap> just checks if the library is in PARs 我々のC<_bootstrap>は、PARの中にライブラリがあるかどうかチェックを行なう =over 4 =item * If yes, extract it to a File::Temp temp file もしあるなら、File::Tempの一時ファイルに展開される =over 4 =item * The file will be automatically cleaned up when the program ends プログラムが終わると、ファイルは自動的にクリンナップされる =back =item * It then pass the arguments to the original C<$bootstrap> それから引数は元のC<$bootstrap>に渡される =item * Finally, our C<_dl_findfile> intercepts known filenames and return it 最後に、我々のC<_dl_findfile>は知ったファイル名を補足し、それを返す =back =back =head2 自己内包型PAR実行ファイルの解剖 =over 4 =item * The par script ($0) itself parスクリプト($0)自身は =over 4 =item * May be in plain-text (par.pl) プレインテキスト(par.pl) =item * Or native executable format (par or par.exe) あるいは実行可能形式(parやpar.exe)である =back =item * Any number of embedded files 任意の数のファイルを埋め込める =over 4 =item * Typically used for bootstrapping PAR's various XS dependencies 典型的にはPARの様々なXSの依存関係物をブートストラップするために利用される =item * Each section begins with the magic string "FILE" 各セクションはマジック文字列"FILE"で始まる =item * Length of filename in pack('N') format and the filename (auto/.../) pack(N)形式のファイル名の長さとファイル名(auto/.../) =item * File length in pack('N') and the file's content(not compressed) pack(N)されたファイルサイズとファイルの内容(圧縮されない) =back =item * One PAR file 一つのPARファイル =over 4 =item * This is just a zip file as usual これは単に普通のzipファイルだ =item * Beginning with the magic string C<"PK\003\004"> マジック文字列C<"PK\003\004">で始まる =back =item * Ending section 終了セクション =over 4 =item * A pack('N') number of the total length of FILE and PAR sections ファイルとPARセクション全体のサイズをpack('N')した数 =item * Finally, there must be a 8-bytes magic string: C<"\012PAR.pm\012"> 最後に、8バイトのマジック文字列がなければならない:C<"\012PAR.pm\012"> =back =back =head2 Self-Bootstrappingのトリック =over 4 =item * All we can expect is a working perl interpreter 期待することはperlインタプリタとして動作することだ =over 4 =item * The self-contained script *must not* use any modules at all 自己完結的スクリプトはどんなモジュールも使っては*ならない* =item * Not even strict.pm or DynaLoader.pm strict.pmやDynaLoader.pmでさえもだめだ =item * But to process PAR files, we need XS modules like Compress::Zlib しかしPARファイルを処理するためにはCompress::ZlibのようなXSモジュールが必要だ =item * A chicken-egg problem 鶏が先か卵が先か =back =item * Solution: bundle all module and object files needed by PAR.pm 解決方法:PAR.pmによって必要とされる 全てのモジュールとオブジェクトファイルをバンドルする =over 4 =item * That's what the C section in the previous slide is for 先のスライドにおけるCセクションはこのためのものであった =item * Load modules to memory, and write object files to disk メモリにモジュールをロードし、オブジェクトファイルをディスクに書き込む =item * Then use a local @INC hook to load them on demand そして必要なときにローカルな@INCフックを使用してそれらをロードする =back =item * We want to minimize the amount of temporary files 一時ファイルの量は最小化したいものだ =over 4 =item * First, try getting PerlIO::scalar loaded まず最初に、PerlIO::scalarのロードを試してみる =over 4 =item * So everything else can be in-memory そうすれば全部メモリ内における =back =item * Next, try getting File::Temp loaded for better C 次に、Cよりも良いFile::Tempをロードするのを試みる =item * Set up an END hook to unlink all temp files up to this point ENDフックをセットアップして、この時点までの一時ファイルを全てunlinkする =item * Load all other bundled files その他の全てのバンドルされているファイルをロードする =item * Finally we are able to look in the compressed PAR section 最終的に、圧縮されたPARセクションを見ることができる =back =item * This can be so much easier if we have a pure-perl C もしピュアPerlのCを持っているなら、もっと簡単にできる =over 4 =item * Patches welcome! パッチ大歓迎! =back =back =head1 SEE ALSO L L (English version) L (Chinese version) L, L, L, L L, L L, L, L, L =head1 AUTHORS Autrijus Tang Eautrijus@autrijus.orgE L is the official PAR website. You can write to the mailing list at Epar@perl.orgE, or send an empty mail to Epar-subscribe@perl.orgE to participate in the discussion. Please submit bug reports to Ebug-par@rt.cpan.orgE. =head1 著作権 Copyright 2002, 2003 by Autrijus Tang Eautrijus@autrijus.orgE. This document is free documentation; you can redistribute it and/or modify it under the same terms as Perl itself. See L