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

注釈

このドキュメントは、 https://setuptools.readthedocs.io/en/latest/setuptools.html にある `setuptools` のドキュメントが現時点でここにある関連情報を全て網羅するまで、単独でここに載せておかれます。

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

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

もちろん、モジュール開発者自身がパッケージ作成者かもしれません; また、パッケージを作成するのはオリジナルの作成者が利用できないプラットフォームにアクセスできるような "外部の" ボランティアかもしれませんし、ソース配布物を定期的に取り込んで、アクセスできるかぎりのプラットフォーム向けにビルド済み配布物を生成するソフトウェアかもしれません。作業を行うのが誰であれ、パッケージ作成者は setup スクリプトを利用し、 bdist コマンドファミリを使ってビルド済み配布物を作成します。

単純な例として、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 形式 |
`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_msi | msi

注釈

bdist_msi は Python 3.9 で非推奨になりました。

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>"

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

RPM `.spec` ファイルのオプションまたはセクション | Distutils setup スクリプト内のオプション
--- | ---
名前 | `name`
Summary (preamble 内) | `description`
Version | `version`
Vendor | `author` と `author_email`, または --- & `maintainer` と `maintainer_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-cfg` を `setup.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 でのクロスコンパイル

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

別のプラットフォーム向けのビルドを行うには、 `--plat-name` オプションを指定します。現在のところ、有効な値は 'win32' と 'win-amd64' です。たとえば、 32bit 版の Windows 上で、 以下のようにして 64bit版 Windows 向けのビルドを行うことができます:

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

to build a 64bit version of your extension.

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

クロスコンパイルを行うためには、 Python のソースコードをダウンロードして Python 自身をターゲットのプラットフォーム向けにクロスコンパイルしなければなりません。 Python のバイナリインストールではクロスコンパイルできません (ターゲットのプラットフォーム用の .lib などのファイルが存在しないためです)。実際問題として、拡張モジュールのクロスコンパイルを可能にするためには、32ビットOS のユーザーは Python ソースツリーの `PCbuild/PCbuild.sln` ソリューションファイルを開き、 'pythoncore' プロジェクトの "x64" コンフィグレーションをビルドするために Visual Studio 2008 を使う必要があるということを意味しています。

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

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

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

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

Windows インストーラでは、インストールスクリプトは埋め込みで実行され、全ての出力 (`sys.stdout`、`sys.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 のドキュメントを参照してください。