=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