パッケージング

フリーソフトウェアを配布する標準的なやり方は、ソースコードを配布することです。 これはソフトウェアがソースコードをそのまま実行できる(i.e. Perl, Python, PHP などのように、 インタプリタによって解釈できるもの)か、 はじめに(C, C++, Javaなどによって)コンパイルする必要があるかどうかに関わらず当てはまります。 コンパイルする必要があるソフトウェアの場合、 ほとんどのユーザーが多分自分でソースをコンパイルせず、 あらかじめビルドされたバイナリパッケージをインストールするでしょう。 (この章の後半にある 「バイナリパッケージ」 を参照してください) しかしながら、バイナリパッケージはオリジナルのソースコードを元にして作られています。 ソースパッケージで重要なのは、曖昧でない形でリリースを定義していることです。 プロジェクトが "Scanley 2.5.0" を配布する場合、それが特に意味するところは "コンパイルして(必要であれば)インストールすると、Scanley 2.5.0 を生成するソースファイルのツリーである" ということです。

どういう形でソースファイルをリリースすべきかについては、かなり厳格な基準があります。 基準から外れた部分も時折見つかるでしょうが、それはルールではなく例外です。 やむを得ない理由がなければ、あなたのプロジェクトでもこの基準に従うべきです。

パッケージのフォーマット

ソースコードはディレクトリツリーを保存してくれる標準的なフォーマットでリリースすべきです。 Unix または Unixライクなオペレーティングシステムでは、 compress コマンドや、gzipbzip または bzip2 コマンドを使って圧縮した TAR フォーマットを使うという決まりがあります。Microsoft Windows では、 ディレクトリツリーを保存した状態で配布する標準的なやり方として zip フォーマットを使う方法があります。これはたまたま圧縮もしてくれるので、 アーカイブを作った後に圧縮を行う必要がありません。

パッケージ名とレイアウト

パッケージの名前は、ソフトウェアの名前とリリース番号の後で、 アーカイブのやり方に合った適切なフォーマットの拡張子を最後につけるようにしましょう。 たとえば、Scanley 2.5.0 を Unix向けにパッケージングし、 GNU Zip(gzip) フォーマットで圧縮したときの名前は次のようになるでしょう。

scanley-2.5.0.tar.gz

また、Windows 向けに zip フォーマットで圧縮した場合の名前は次のようになるでしょう。

scanley-2.5.0.zip

どちらのアーカイブを展開しても、 カレントディレクトリに scanley-2.5.0 という名前の単一のディレクトリツリーが生成されるはずです。 このディレクトリには、ソースコードを(必要なら)コンパイルし、 インストールできる状態でソースコードを配置すべきでしょう。 ディレクトリツリーの最上部には、このソフトウェアが何をするもので、 今回のリリース内容がどういうものか、 そしてプロジェクトのWebサイトやその他面白いファイルなどのリソースについて説明した README ファイルをプレーンテキストで配置します。 他の面白いファイルとしては、README ファイルの兄弟分にあたり、 サポートする全てのオペレーティングシステム上でソフトウェアをビルドし、 インストールする方法を説明した INSTALL ファイルがあげられます。 2章さあ始めましょう 「ライセンスを適用する方法」 でも説明していますが、 ソフトウェアの配付条件を示した COPYINGLICENSEファイルもツリーの最上部に配置します。

今回のリリースで新しくなったことを説明する CHANGES (NEWS と呼ばれることもあります) ファイルもツリーの最上部に配置します。 この CHANGES ファイルは、 これまで行われたリリース全ての変更点を集めたもので、 今回のリリースの変更点の一覧が一番最初になるように、 リリースされた順番とは逆順に記されています。 この変更点一覧を完成させるのは、 リリースブランチをリリースできる状態にする作業の最後に行うのが普通です。 開発している間に少しずつ変更点を書き足していくプロジェクトもあれば、 バージョン管理システムのログを組み合わせることで情報を集め、 最後にひとりの人間がまとめるまで作業を保留するのを好むプロジェクトもあります。 変更点の一覧は、次のようになるでしょう。

Version 2.5.0
(2004年12月20日に /branches/2.5.x からリリース)
http://svn.scanley.org/repos/svn/tags/2.5.0/

 新機能、改良点:
    * 正規表現による問い合わせを追加 (問題 #53)
    * UTF-8 と UTF-16 で書かれたドキュメントのサポートを追加
    * ドキュメントが ポーランド語、ロシア語、マダガスカル語に翻訳された。
    * ...

 バグ修正:
    * 再インデックス時のバグを修正 (問題 #945)
    * 問い合わせに関するバグをいくつか修正 (問題 #815, #1007, #1008)
    * ...

変更点の一覧は、必要であればどれだけ長くても構いませんが、 小さなバグ修正や機能追加を全て含めてしまうことで、内容が退屈にならないようにしましょう。 このファイルの目的は、新しいリリースにアップグレードすることで得られるものの概要をユーザーに示すだけです。 実際、変更点の一覧はリリースアナウンスの電子メールに書くことが普通なので、 それを見る人のことを考えて書くようにしましょう。

ツリーにあるソースコードのレイアウトは、 バージョン管理システムのリポジトリから直接プロジェクトをチェックアウトしたときに得られるものと同じか、 できるだけ似たものにすべきです。 これらの間には少し違いがあるのが普通です。 たとえば、リリースされるパッケージには設定やコンパイルに必要な自動生成されたファイル(この章の後半の「コンパイルとインストール」 を参照してください) が含まれていたり、 プロジェクトが管理していないが、必須のものであったり、 ユーザーがまだインストールしていないかもしれないサードパーティーのソフトウェアが含まれているからです。 しかしながら、たとえ配布されたディレクトリツリーが、 バージョン管理システムのリポジトリにある開発ツリーと全く同じだったとしても、 その配布物は作業コピーと同じであってはいけません(作業コピー を参照してください)。 あるリリースは、開発ツリーへの静的な参照ポイントです。 — これは特に、ある時点の固定されたソースファイルの設定 を表したものです。 もし配布物が作業コピーと同じだと、ユーザーがそれを変更するかもしれません。 また、実際に変更した後でリリースがあることを考えると危険です。

パッケージの中身は、パッケージングのやり方に関わらず同じであることを忘れないでください。 リリース—つまり、"Scanley 2.5.0" と呼ぶ場合に参照する正確なものは、 zipやtarボールを展開したときに生成されるディレクトリツリーと同じです。 よって、プロジェクトはこれら全てのフォーマットをダウンロード用に提供しても構いません。

scanley-2.5.0.tar.bz2
scanley-2.5.0.tar.gz
scanley-2.5.0.zip

しかし、パッケージを展開して生成されるソースツリーは全て同じでなければなりません。 このソースツリーは配布物です。つまり、ダウンロードするパッケージのフォーマットは、 ユーザーの便宜のためだけに存在します。 ソースパッケージにちょっとした違いがあっても許される場合があります。 たとえば、Windows用のパッケージでは、 テキストファイルの行はCRLF(キャリッジリターンとラインフィード)コードで終わるべきです。 一方でUnix用のパッケージでは、LFで終了します。 仮に異なったオペレーティングシステム間で違うコンパイル用のレイアウトが必要なら、 異なったオペレーティングシステム用のソースパッケージでは、 ソースツリーが少し異なっていても構いません。 しかし、こうした違いは基本的にちょっとした変換で済ませるものです。 基本的なソースファイルは、同じリリースのパッケージの範囲では同じにしておくべきです。

大文字にするか、小文字のままにするか

プロジェクトの名前を引用する場合、普通は適当な名詞を大文字にし、 もし頭文字だけを大文字にする単語があれば、そのようにします。 たとえば "MySQL 5.0", "Scanley 2.5.0" などです。 大文字の表現をパッケージ名でも使うかどうかは、プロジェクトによって異なります。 たとえば、Scanley-2.5.0.tar.gzscanley-2.5.0.tar.gz のどちらがよいか、ということです。(私は後者が好きです。 なぜなら、シフトキーを人に打たせるのが嫌だからではなく、 大文字を使うパッケージをたくさんのプロジェクトに出荷させることになるからです) 重要なのは、tarボールを展開したときに作られるディレクトリが同じ名前を使っているかどうかです。 ユーザーを驚かせないようにすべきです。つまり、配布物を展開して生成されるディレクトリ名は、 ユーザーが正確に予測できるようにしておかなければなりません。

プレリリース版

プレリリース版またはリリース候補のパッケージをリリースする場合は、 その識別子はリリース番号の一部になります。 よって、パッケージ名にその識別子を含めるようにしましょう。 たとえば、「リリース番号の構成要素」 で説明したアルファ版やベータ版のリリースの順番は、パッケージ名では以下のように表現します。

scanley-2.3.0-alpha1.tar.gz
scanley-2.3.0-alpha2.tar.gz
scanley-2.3.0-beta1.tar.gz
scanley-2.3.0-beta2.tar.gz
scanley-2.3.0-beta3.tar.gz
scanley-2.3.0.tar.gz

はじめのパッケージは、scanley-2.3.0-alpha1というディレクトリに展開され、ふたつめは scanley-2.3.0-alpha2 に展開される ... などです。

コンパイルとインストール

ソースコードをコンパイルし、インストールを行う必要があるソフトウェアは、 経験豊富なユーザーが従う標準的な手順があります。 たとえば、C, C++, その他のコンパイル言語で書かれたプログラムでは、 Unixライクなシステムでユーザーがタイプする標準的な手順は次のようなものです。

   $ ./configure
   $ make
   # make install

はじめのコマンドは、自動的に実行環境をできるだけ把握し、ビルドの準備を行います。 ふたつめのコマンドはソフトウェアをビルドします。(しかしインストールは行いません) 最後のコマンドはシステムにソフトウェアをインストールします。 最初のふたつのコマンドは通常のユーザーで実行し、最後はrootユーザーで実行します。 このシステムをセットアップする作業の詳細は、Vaughan, Elliston, Tromey, Taylor が書いた GNU Autoconf, Automake, and Libtool という優れた本があるので、それを参照してください。 この本は 出版社 New Riders によってツリーウェア[27]として公開されており、 http://sources.redhat.com/autobook/ でもオンラインで利用可能です。

この手順が唯一の標準というわけではありませんが、 もっとも普及しているもののひとつです。 Ant (http://ant.apache.org/) ビルドシステムが特にJavaで書かれたプロジェクトで人気を得つつありますが、Antもビルドとインストールの標準的な手順を持っています。 同様に、PerlやPythonのようなプログラミング言語では、 その言語で書かれた殆どのプログラムで同じ手順を使うことを勧めています(たとえば、Perlモジュールは次のようなコマンドを使います。 perl Makefile.PL) 自分のプロジェクトにどの標準を使うかがわからない場合は、 経験豊富な開発者に尋ねてみましょう[28]。 たとえどの標準を使うかがはじめわからなくても、 適用できる標準が 存在する と思っても大丈夫です。

自分のプロジェクトに適した標準が何であれ、 やむを得ない場合以外はそれを破ってはいけません。 標準的なインストール手順は、たくさんのシステム管理者が反射的に実践しているものです。 プロジェクトの INSTALLファイル に自分が馴染んだ手順が書かれているのがわかれば、 このプロジェクトは標準的な規約を守っているという信頼をすぐに得られます。 標準的な手順をドキュメントに記すことで、他のことも理解しやすくなるでしょう。 また、2章さあ始めましょう 「ダウンロード」 でも議論していますが、 標準的なビルド手順があると、開発者になる可能性がある人も喜んでくれます。

Windows では、ビルドとインストールの標準的な手順がUnixライクなシステムほど決まっているわけではありません。 コンパイルする必要があるプロジェクトでは、 Microsoft の標準的な開発環境(Developer Studio, Visual Studio, VS.NET, MSVC++, など)の ワークスペース/プロジェクトモデルに合った形でソースツリーをリリースすることが標準的な規約のようです。 ソフトウェアの性質にもよりますが、Cygwin環境(http://www.cygwin.com/)経由でUnixライクなビルドオプションを提供することもできるでしょう。 もちろん、自前のビルドとインストール手順があるプログラミング言語やフレームワーク—e.g Perl や Python のような— があるときは、 環境が Windows, Unix, Mac OS X, あるいは他のオペレーティングシステム上であっても、 それが提供している標準的な手順を採用すべきです。

標準的なビルド、インストール手順にプロジェクトを合わせる努力を惜しまないようにしましょう。 ビルドとインストールはソフトウェアを使う入口となる作業です。 それを終えたら、やむを得ないならソフトウェアが扱いにくくてもよいのです。 しかし、ユーザーや開発者がソフトウェアに触れる最初の段階で、 予想外の手順を踏む必要があるなら、それは恥ずかしいことなのです。

バイナリパッケージ

ソースコードをパッケージングしてリリースするのが正式なやり方ですが、 ほとんどのユーザーは、オペレーティングシステムのソフトウェア配布システムや、 プロジェクト自体や、サードパーティーから取得したバイナリパッケージをインストールします。 ここでいう "バイナリ" というのは必ずしも "コンパイルして生成したもの" という意味ではありません。 ここでは単に、ソースコードをビルドしてインストールする手順を経ずに、 コンピューターにインストールすることができる設定済みのパッケージのことをいいます。 RedHat GNU/Linux では、その仕組みはRPMシステムと呼ばれ、Debian GNU/Linux では、 APT (.deb) システムといいます。Microsoft Windows では、 .MSI ファイル や、実行すればインストールを行ってくれる .exe ファイルであることが普通です。

バイナリパッケージを作る人がプロジェクトに深く関わっている人であれ、 サードパーティーであれ、 ユーザーはそれらをプロジェクトの公式なリリースとして扱い、 バイナリパッケージの振る舞いをベースにしてバグ報告システムに問題を登録してきます。 よって、パッケージャーに明確なガイドラインを提供し、 彼らが提供するパッケージが、 プロジェクトのソフトウェアを適切に表現してくれるように、 彼らと緊密に連携することがプロジェクトの関心事になります。

パッケージャーが主に知っておくべきことは、生成するバイナリパッケージは、 プロジェクトからリリースされたオフィシャルなソースコードを元にすべきだということです。 ユーザーにバグ修正や機能追加を提供するために、 パッケージャーはソースコードリポジトリのコピーや、 リリース後にコミットされた修正を選んでバイナリパッケージに取り込むことがあります。 しかしこうした習慣は、実際には多くの混乱を引きおこします。 プロジェクトはリリース済みのバージョンで見つかったバグ報告や、 最近の trunk や主要なブランチのソースコードのバグ報告(つまり、 注意深く最先端のコードを実行している人が見つけたバグ)を受け付ける準備をしています。 バグ報告があがってくると、 応答する人はそのバグがある時点のスナップショットで発生したということや、 修正済みであること、そしてユーザーがアップグレードすべきか、 次のリリースを待つべきかを確認することができます。 仮にまだ報告されていないバグの場合は、 リリースの時点が明確であれば、 それの再現やバグ報告システム上でのバグの分類もやりやすくなります。

しかしながら、ユーザーが改造を加えたものや、 バージョンが決まっていない中間的なコードに対するバグ報告は、 プロジェクトは受け付ける準備ができていません。こうした報告は再現させるのが難しく、 後の開発で加えられる別の変更に予想外の影響を与える可能性もあります。 このため、開発者が責任を取る必要がない不正な振舞いをソフトウェアが起こしてしまうのです。 過去に発生していたはずのバグが 発生しなくなってしまった ために、 多くの時間を浪費してしまってげんなりしたことがあります。 これはユーザーが公式のリリース(全く同じではない)にちょっと改造を加えたバージョンを使っていたためです。 バグが発生しなかったのが予想外だったので、 開発者全員がその理由を調べるために詳細な調査をしなければなりませんでした。

さらに、リリースされたソースコードには変更が必要だとパッケージャーが主張することもあります。 パッケージャーは、プロジェクトの開発者にこうした変更を報告し、変更の計画を説明すべきです。 パッケージャーが加えた変更は、開発者が受け入れてくれるかもしれませんが、 受け入れてもらえなくても、自分がソースコードに変更を加える理由をプロジェクトに知らせておくべきです。 これは、プロジェクトが予想外のバグ報告を見張ることができるようにするためです。 開発者はプロジェクトのウェブサイトに免責事項を記載することで、 こうしたバグ報告に対応してもよいでしょう。また、バイナリパッケージのユーザーに、 自分たちが使っているパッケージがプロジェクトが公式にリリースしたものとは正確に同じものではないことを知らせるために、 適切な場所で作業をするようにパッケージャーに求めることもできます。 こういう状況で、パッケージャーと開発者がいがみ合う必要はありませんが、 残念なことに対立してしまうこともあります。 パッケージャーは、目指すものが開発者と少し違うだけなのです。 パッケージャーはユーザーがインストールすればすぐに使えるものを主に求めています。 開発者ももちろんそれを追求してはいますが、彼らは一貫したバグ報告を受付け、 互換性を保証するためにパッケージャーが使っているバージョンを知らなればいけません。 このふたつの目標はたびたび対立します。対立が起きたときには、 プロジェクトはパッケージャーを拘束していないし、パッケージャーと開発者は、 持ちつ持たれつの関係にあることを思い出すとよいでしょう。 プロジェクトは、ソフトウェアを作るだけであっても、 パッケージャーにとって良いことをしているのは事実です。 しかし、パッケージャーもユーザーにソフトウェアを広めるために地道な作業のほとんどをこなすことで、 開発者にとってよいことをしているのです。この作業は、とてつもない数のユーザーを対象にすることもあります。パッケージャーに反対の意思を示すのはよいことですが、喧嘩をしてはいけません。 開発者は自分が出せる最良のソフトウェアを世に送り出すことのみに注力すればよいのです。



[27] ドキュメントやその他の印刷物を指すハッカー用語

[28] Python では python setup.py install という、Distutils を使った標準的なコマンドがあります。Ruby の場合は Rubygems 経由で gem install [パッケージ名] というコマンドを使います。