5. ビルド済み配布物を作成する

"ビルド済み配布物" とは、おそらく皆さんが通常 "バイナリパッケージ" とか "インストーラ" (背景にしている知識によって違います) と考えているものです。とはいえ、配布物が必然的にバイナリ形式になるわけではありません。配布物には、Python ソースコード、かつ/またはバイトコードが入るからです; また、我々はパッケージという呼び方もしません。すでに Python の用語として使っているからです (また、"インストーラ" という言葉は主流のデスクトップシステム特有の用語です)

ビルド済み配布物は、モジュール配布物をインストール作業者にとってできるだけ簡単な状況にする方法です: ビルド済み配布物は、RPM ベースの Linux システムユーザにとってはバイナリ RPM、Windows ユーザにとっては実行可能なインストーラ、Debian ベースの Linux システムでは Debian パッケージ、などといった具合です。当然のことながら、一人の人間が世の中にある全てのプラットフォーム用にビルド済み配布物を作成できるわけではありません。そこで、Distutils の設計は。開発者が自分の専門分野 — コードを書き、ソース配布物を作成する — に集中できる一方で、パッケージ作成者 (packager) と呼ばれる、開発者とエンドユーザとの中間に位置する人々がソースコード配布物を多くのプラットフォームにおけるビルド済み配布物に変換できるようになっています。

Of course, the module developer could be his own packager; or the packager could be a volunteer "out there" somewhere who has access to a platform which the original developer does not; or it could be software periodically grabbing new source distributions and turning them into built distributions for as many platforms as the software has access to. Regardless of who they are, a packager uses the setup script and the bdist command family to generate built distributions.

単純な例として、Distutils ソースツリーから以下のコマンドを実行したとします:

python setup.py bdist

すると、Distutils はモジュール配布物 (ここでは Distutils 自体) をビルドし、"偽の (fake)" インストールを (build ディレクトリで) 行います。そして現在のプラットフォームにおける標準の形式でビルド済み配布物を生成します。デフォルトのビルド済み形式とは、Unixでは "ダム (dumb)" の tar ファイルで、 Windows ではシンプルな実行形式のインストーラになります。(tar ファイルは、特定の場所に手作業で解凍しないと動作しないので、 "ダム: 賢くない" 形式とみなします。)

従って、 Unix システムで上記のコマンドを実行すると、 Distutils-1.0.plat.tar.gz を作成します; この tarball を正しい場所で解凍すると、ちょうどソース配布物をダウンロードして python setup.py install を実行したのと同じように、正しい場所に Distutils がインストールされます。 ("正しい場所 (right place)" とは、ファイルシステムのルート下か、 Python の prefix ディレクトリ下で、これは bdist_dumb に指定するコマンドで変わります; デフォルトの設定では、 prefix からの相対パスにインストールされるダム配布物が得られます。)

言うまでもなく、pure Python 配布物の場合なら、python setup.py install するのに比べて大して簡単になったとは言えません—しかし、非 pure 配布物で、コンパイルの必要な拡張モジュールを含む場合、拡張モジュールを利用できるか否かという大きな違いになりえます。また、RPM パッケージや Windows 用の実行形式インストーラのような "スマートな" ビルド済み配布物を作成しておけば、たとえ拡張モジュールが一切入っていなくてもユーザにとっては便利になります。

bdist コマンドには、 --formats オプションがあります。これは sdist コマンドの場合に似ていて、生成したいビルド済み配布物の形式を選択できます: 例えば、

python setup.py bdist --format=zip

とすると、Unix システムでは、 Distutils-1.0.plat.zip を作成します— 先にも述べたように、Distutils をインストールするには、このアーカイブ形式をルートディレクトリ下で展開します。

ビルド済み配布物として利用できる形式を以下に示します:

フォーマット 説明 注釈
gztar gzip 圧縮された tar ファイル (.tar.gz) (1)
bztar bzip 圧縮された tar ファイル (.tar.bz2)  
xztar xzip 圧縮された tar ファイル (.tar.xz)  
ztar compress 圧縮された tar ファイル (.tar.Z) (3)
tar tar ファイル (.tar)  
zip zip ファイル (.zip) (2),(4)
rpm RPM 形式 (5)
pkgtool Solaris pkgtool 形式  
sdux HP-UX swinstall 形式  
wininst Windows 用の自己展開形式 ZIP ファイル (4)
msi マイクロソフト・インストーラー。  

バージョン 3.5 で変更: xztar 形式のサポートが追加されました。

注釈:

  1. Unixでのデフォルト形式です
  2. Windows でのデフォルト形式です
  3. 外部の compress ユーティリティが必要です。
  4. 外部ユーティリティの zip か、 zipfile モジュール (Python 1.6 からは標準 Python ライブラリの一部になっています) が必要です
  5. 外部ユーティリティの rpm 、バージョン 3.0.4 以上が必要です (バージョンを調べるには、 rpm --version とします)

bdist コマンドを使うとき、必ず --formats オプションを使わなければならないわけではありません; 自分の使いたい形式をダイレクトに実装しているコマンドも使えます。こうした bdist "サブコマンド (sub-command)" は、実際には類似のいくつかの形式を生成できます; 例えば、 bdist_dumb コマンドは、全ての "ダム" アーカイブ形式 (tar, gztar, bztar, xztar, ztar, および zip) を作成できますし、 bdist_rpm はバイナリ RPM とソース RPM の両方を生成できます。 bdist サブコマンドと、それぞれが生成する形式を以下に示します:

コマンド Formats
bdist_dumb tar, gztar, bztar, xztar, ztar, zip
bdist_rpm rpm, srpm
bdist_wininst wininst
bdist_msi msi

bdist_* コマンドについては、以下の節で詳しく述べます。

5.1. RPM パッケージを作成する

RPM 形式は、Red Hat, SuSE, Mandrake といった、多くの一般的な Linux ディストリビューションで使われています。普段使っているのがこれらの環境のいずれか (またはその他の RPM ベースの Linux ディストリビューション) なら、同じディストリビューションを使っている他のユーザ用に RPM パッケージを作成するのはとるに足らないことでしょう。一方、モジュール配布物の複雑さや、Linux ディストリビューション間の違いにもよりますが、他の RPM ベースのディストリビューションでも動作するような RPM を作成できるかもしれません。

通常、モジュール配布物の RPM を作成するには、 bdist_rpm コマンドを使います:

python setup.py bdist_rpm

あるいは、 bdist コマンドを --format オプション付きで使います:

python setup.py bdist --formats=rpm

前者の場合、 RPM 特有のオプションを指定できます; 後者の場合、一度の実行で複数の形式を指定できます。両方同時にやりたければ、それぞれの形式について各コマンドごとにオプション付きで bdist_* コマンドを並べます:

python setup.py bdist_rpm --packager="John Doe <jdoe@example.org>" \
                bdist_wininst --target-version="2.0"

Distutils が setup スクリプトで制御されているのとほとんど同じく、 RPM パッケージの作成は、 .spec で制御されています。 RPM の作成を簡便に解決するため、 bdist_rpm コマンドでは通常、 setup スクリプトに与えた情報とコマンドライン、そして Distutils 設定ファイルに基づいて .spec ファイルを作成します。 .spec ファイルの様々なオプションやセクション情報は、以下のようにして setup スクリプトから取り出されます:

RPM .spec ファイルのオプションまたはセクション Distutils setup スクリプト内のオプション
名前 name
Summary (preamble 内) description
Version version
Vendor authorauthor_email, または — & maintainermaintainer_email
Copyright license
Url url
%description (section) long_description

また、 .spec ファイル内の多くのオプションは、 setup スクリプト中に対応するオプションがありません。これらのほとんどは、以下に示す bdist_rpm コマンドのオプションで扱えます:

RPM .spec ファイルのオプションまたはセクション bdist_rpm オプション デフォルト値
リリース release "1"
Group group "Development/Libraries"
Vendor vendor (上記参照)
Packager packager (none)
Provides provides (none)
Requires requires (none)
Conflicts conflicts (none)
Obsoletes obsoletes (none)
Distribution distribution_name (none)
BuildRequires build_requires (none)
Icon icon (none)

明らかに、これらのオプションの中からいくつかだけを提供することでさえ、退屈で間違いを起こしやすいものでしょう。なので通常は、それらを setup 設定ファイル setup.cfg に収めるのが最適な方法です — setup 設定ファイル (setup configuration file) を書く を参照してください。多くの Python モジュールの配布物を頒布したりパッケージングする場合は、それら全てに適用するオプションをあなた専用の Distutils 設定ファイル (~/.pydistutils.cfg) に収めたいと思うかもしれません。このファイルを一時的に無効にしたければ、 --no-user-cfgsetup.py に渡せます。

バイナリ形式の RPM パッケージを作成する際には三つの段階があり、Distutils はこれら全ての段階を自動的に処理します:

  1. RPM パッケージの内容を記述する .spec ファイルを作成します (.spec ファイルは setup スクリプトに似たファイルです; 実際、 setup スクリプトのほとんどの情報が .spec ファイルから引き揚げられます)
  2. ソース RPM を作成します
  3. "バイナリ (binary)" RPM を生成します (モジュール配布物に Python 拡張モジュールが入っているか否かで、バイナリコードが含まれることも含まれないこともあります)

通常、RPM は最後の二つのステップをまとめて行います; Distutils を使うと、普通は三つのステップ全てをまとめて行います。

望むなら、これらの三つのステップを分割できます。 bdist_rpm コマンドに --spec-only を指定すれば、単に .spec を作成して終了します; この場合、 .spec ファイルは "配布物ディレクトリ (distribution directory)"— 通常は dist/ に作成されますが、 --dist-dir オプションで変更することもできます。(通常、 .spec ファイルは "ビルドツリー (build tree)"、すなわち bdist_rpm が作成する一時ディレクトリの中から引き揚げられます。)

5.2. Windows インストーラを作成する

実行可能なインストーラは、Windows 環境ではごく自然なバイナリ配布形式です。インストーラは結構なグラフィカルユーザインタフェースを表示して、モジュール配布物に関するいくつかの情報を setup スクリプト内のメタデータから取り出して示し、ユーザがいくつかのオプションを選んだり、インストールを決行するか取りやめるか選んだりできるようにします。

メタデータは setup スクリプトから取り出されるので、Windows インストーラの作成は至って簡単で、以下を実行するだけです:

python setup.py bdist_wininst

あるいは、 bdist コマンドを --formats オプション付きで実行します:

python setup.py bdist --formats=wininst

(pure Python モジュールとパッケージだけの入った) pure モジュール配布物の場合、作成されるインストーラは実行バージョンに依存しない形式になり、 foo-1.0.win32.exe のような名前になります。 pure モジュールの Windows インストーラは Unix や Mac OS X でも作成できます。

非 pure 配布物の場合、拡張モジュールは Windows プラットフォーム上だけで作成でき、Python のバージョンに依存したインストーラになります。インストーラのファイル名もバージョン依存性を反映して、 foo-1.0.win32-py2.0.exe のような形式になります。従って、サポートしたい全てのバージョンの Python に対して、別々のインストーラを作成しなければなりません。

インストーラは、ターゲットとなるシステムにインストールを実行した後、 pure モジュールを通常 (normal) モードと最適化 (optimizing) モードでバイトコード(bytecode)にコンパイルしようと試みます。何らかの理由があってコンパイルさせたくなければ、 bdist_wininst コマンドを --no-target-compile かつ/または --no-target-optimize オプション付きで実行します。

デフォルトでは、インストーラは実行時にクールな "Python Powered" ロゴを表示しますが、自作の152x261ビットマップ画像も指定できます。画像は Windows の .bmp ファイル形式でなくてはならず、 --bitmap オプションで指定します。

インストーラを起動すると、デスクトップの背景ウィンドウ上にでっかいタイトルも表示します。タイトルは配布物の名前とバージョン番号から作成します。 --title オプションを使えば、タイトルを別のテキストに変更できます。

インストーラファイルは "配布物ディレクトリ (distribution directory)" — 通常は dist/ に作成されますが、 --dist-dir オプションで指定することもできます。

5.3. Windows でのクロスコンパイル

Python 2.6 から、distutils は Windows プラットフォーム間でのクロスコンパイルに対応しました。これによって、必要なツールがインストールされていれば、32bit 版の Windows で 64bit 版の拡張を作成したり、その逆が可能になりました。

別のプラットフォーム用にビルドするには、 build コマンドの --plat-name オプションを指定します。有効な値は、現在のところ、 'win32', 'win-amd64', 'win-ia64' です。例えば、次のようにして 32bit 版の Windows で 64bit 版の拡張をビルドできます:

python setup.py build --plat-name=win-amd64

Windows インストーラもこのオプションをサポートしています。なので次のコマンドを実行すると:

python setup.py build --plat-name=win-amd64 bdist_wininst

64bit のインストーラを32bitのWindowsで作成できます。

クロスコンパイルするためには、Python のソースコードをダウンロードして Python 自体をターゲットのプラットフォーム用にクロスコンパイルしなければなりません。 Python のバイナリインストールからではクロスコンパイルできません。(他のプラットフォーム用の .lib などのファイルが含まれないからです。) 具体的に言えば、拡張のクロスコンパイルができるようになるには、 32bit OS のユーザーは Visual Studio 2008 を使って Python ソースツリー内の PCBuild/PCbuild.sln ソリューションファイルを開き、 "x64" コンフィギュレーションで 'pythoncore' プロジェクトをビルドしなければなりません。

デフォルトでは、Visual Studio 2008 は 64bit のコンパイラーなどのツールをインストールしないことに注意してください。Visual Studio セットアッププロセスを再実行して、それらのツールを選択する必要があるでしょう。(コントロールパネル -> [追加と削除] から簡単に既存のインストールをチェック、修正できます。)

5.3.1. インストール後実行スクリプト (postinstallation script)

Python 2.3 からは、インストール実行後スクリプトを --install-script オプションで指定できるようになりました。スクリプトはディレクトリを含まないベースネーム (basename) で指定しなければならず、スクリプトファイル名は setup 関数の scripts 引数中に挙げられていなければなりません。

指定したスクリプトは、インストール時、ターゲットとなるシステム上で全てのファイルがコピーされた後に実行されます。このとき argv[1]-install に設定します。また、アンインストール時には、ファイルを削除する前に argv[1]-remove に設定して実行します。

Windows インストーラでは、インストールスクリプトは埋め込みで実行され、全ての出力 (sys.stdoutsys.stderr) はバッファにリダイレクトされ、スクリプトの終了後に GUI 上に表示されます。

インストールスクリプトでは、インストール/アンインストールのコンテキストで特に有用ないくつかの機能を、追加の組み込み関数として利用することができます。

directory_created(path)
file_created(path)

これらの関数は、インストール後実行スクリプトがディレクトリやファイルを作成した際に呼び出さなければなりません。この関数はアンインストーラに作成された path を登録し、配布物をアンインストールする際にファイルが消されるようにします。安全を期すために、ディレクトリは空の時にのみ削除されます。

get_special_folder_path(csidl_string)

この関数は、「スタートメニュー」や「デスクトップ」といった、Windows における特殊なフォルダ位置を取得する際に使えます。この関数はフォルダのフルパスを返します。csidl_string は以下の文字列のいずれかでなければなりません:

"CSIDL_APPDATA"

"CSIDL_COMMON_STARTMENU"
"CSIDL_STARTMENU"

"CSIDL_COMMON_DESKTOPDIRECTORY"
"CSIDL_DESKTOPDIRECTORY"

"CSIDL_COMMON_STARTUP"
"CSIDL_STARTUP"

"CSIDL_COMMON_PROGRAMS"
"CSIDL_PROGRAMS"

"CSIDL_FONTS"

該当するフォルダを取得できなかった場合、 OSError が送出されます。

どの種類のフォルダを取得できるかは、特定の Windows のバージョンごとに異なります。また、おそらく設定によっても異なるでしょう。詳細については、 SHGetSpecialFolderPath() 関数に関する Microsoft のドキュメントを参照してください。

create_shortcut(target, description, filename[, arguments[, workdir[, iconpath[, iconindex]]]])

この関数はショートカットを作成します。 target はショートカットによって起動されるプログラムへのパスです。 description はショートカットに対する説明です。 filename はユーザから見えるショートカットの名前です。コマンドライン引数があれば、 arguments に指定します。 workdir はプログラムの作業ディレクトリです。 iconpath はショートカットのためのアイコンが入ったファイルで、 iconindex はファイル iconpath 中のアイコンへのインデクスです。これについても、詳しくは IShellLink インタフェースに関する Microsoft のドキュメントを参照してください。

5.4. Vista のユーザアカウント制御 (UAC)

Python 2.6 から、 bdist_wininst は --user-access-control オプションをサポートしています。デフォルトは 'none' (UAC制御をしないことを意味します) で、それ以外の有効な値は 'auto' (Python が全ユーザー用にインストールされていれば UAC 昇格を行う)、 'force' (常に昇格を行う) です。