RPM を使ってソフトウェアをパッケージ化する: 第 1 回 パッケージのビルドと配布

この記事では、RPM Package Manager に関する 3 回連載の記事の第 1 回として、RPM を使ってソフトウェアとその関連ファイルをインストールする方法に加え、システム・スクリプトからソース・コードやドキュメントに至るまで、ありとあらゆるものを RPM でパッケージ化する方法を説明します。(この連載記事は Dan Poirier が以前 RPM に関して書いた連載記事を置き換えるものです。)

専門知識をお持ちの方へ:  RPM に関してどんなテクニックをよく使いますか?記事の終わりにあるコメント欄にコメントをお寄せください。

Martin Streicher, Software Developer, Pixel, Byte, and Comma

author photo - martin streicherMartin Streicher はフリーランスの Ruby on Rails 開発者であり、以前は Linux Magazine の編集責任者でした。彼は Purdue University でコンピューター・サイエンスの修士号を取得しており、1986年以来 UNIX ライクなシステムのプログラミングをしてきました。彼は美術品やおもちゃを収集しています。


developerWorks 貢献著者レベル

2010年 1月 12日

オープンソース・ソフトウェアを使用する主なメリットは、その名前が示すように、アプリケーションの内部動作をいじれることです。ソースを入手できると、アプリケーションの動作を調べることができ、その動作の変更、改善、拡張が可能になります。また、コードを借用して他の用途に使用することや (ただし、そのアプリケーションのライセンス制限に従う必要があります)、新たに登場したプラットフォームにそのアプリケーションを移植することができます。

しかし、必ずしもそのように自由に利用できることが望まれているわけではありません。例えば、ユーザーはソース・コードからビルドする面倒を望んでおらず、むしろ従来の「パッケージ化された」アプリケーションのように、メディアを挿入して setup を実行し、画面の表示に従って手順を進めればインストールが完了するようなものを望んでいるかもしれません。実際、ビルド済みのコードの方がシステムによる違いの影響を受けにくく、動作が安定して予測が可能なため、大半のコンピューター・ユーザーは、そうしたビルド済みのソフトウェアを好んで利用しています。

一般的に、ビルド済みのオープンソース・アプリケーションはパッケージと呼ばれ、パッケージにはそのアプリケーションの実行に必要なすべてのバイナリー・ファイル、データ・ファイル、構成ファイルがバンドルされています。パッケージにはさらに、そのアプリケーションをシステムにデプロイするために必要なすべてのステップが、通常はスクリプトの形で含まれています。アプリケーションによってはスクリプトを使って、データの生成や、システム・サービスの起動/停止、ファイルやディレクトリーの操作などを行う場合があり、既存のソフトウェアを新しいバージョンにアップグレードするための操作を行う場合もあります。

各オペレーティング・システムには独特の違いがあるため、パッケージは通常、特定のシステム用にチューニングされています。また各オペレーティング・システムには、システムに対してパッケージの追加/削除を行うための特別なユーティリティーとして、独自のパッケージ・マネージャーが用意されています。例えば、Debian Linux® ベースのシステムには APT (Advanced Package Tool) が使われており、Fedora Linux システムには RPM Package Manager が使われています。パッケージ・マネージャーを利用することで、不完全なインストールや誤ったインストールを防ぐことができ、また、パッケージ内のファイルをアトミックに追加/削除することによる「アンイストール」が可能になります。またパッケージ・マネージャーはシステムにインストールされたすべてのパッケージのマニフェストを保持しており、前提となるパッケージやファイル、そのパッケージと同時に必要なパッケージやファイルなどの存在を事前に検証することもできます。

皆さんがソフトウェア開発者またはシステム管理者である場合、作成したアプリケーションをパッケージとして提供すると、インストールやアップグレード、保守などがはるかに容易になります。この連載では、よく使われる RPM Package Manager を使ってユーティリティーをバンドルする方法について学びます。ここでは例として、インターネットからファイルをダウンロードするための wget というネットワーク・ユーティリティーをバンドルします。wget ユーティリティーは便利なものですが、ディストリビューションに標準で含まれているわけではありません (wget に似た、curl がディストリビューションに含まれていることはよくあります)。RPM を使用することで、ほとんどすべてのもの (スクリプト、ドキュメント、データ) を配布することができ、ほぼどんな保守作業でも行えることを覚えておいてください。

手動で wget をビルドする

wget ユーティリティーは、他の多くのオープンソース・アプリケーションと同様、手動でビルドすることができます。そのプロセスを理解することが、wget をパッケージにバンドルするための出発点です。通常のビルドと同じように、wget をビルドするためには以下の 4 つのステップが必要です。

  1. ソースをダウンロードして解凍します。
  2. ビルドの構成を行います。
  3. コードをビルドします。
  4. ソフトウェアをインストールします。

最新バージョンの wget のソース・コードは ftp.gnu.org からダウンロードすることができます (「参考文献」にリンクがあります。2009年 9月末の時点で、wget の最新バージョンは 1.12 でした)。残りのステップはコマンドラインから行う必要があります (リスト 1)。

リスト 1. wget をインストールする
$ tar xzf wget-latest.tar.gz
$ cd wget-1.12
$ ./configure
configure: configuring for GNU Wget 1.12
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... build-aux/install-sh -c -d
checking for gawk... no
checking for mawk... no
checking for nawk... no
...
$ make
$ sudo make install

./configure はシステムの構成を調べ、検出されたハードウェアとソフトウェアに適したコンパイル・オプションを設定します。make はコードをコンパイルし、sudo make install はシステム・ディレクトリーにコードをインストールします。デフォルトで、ディレクトリーのルートは /usr/local ですが、何らかの完全パス名が指定されている --prefix= オプションの値を ./configure に変更することで、ターゲット・ルートを変更することができます。

このプロセスを RPM に変換するためには、ソースをリポジトリーに配置し、コンパイル対象のソースの場所、そしてコードのビルド方法とインストール方法を記述した構成ファイルを作成します。この構成ファイル (spec ファイルと呼ばれます) が、rpmbuild というユーティリティーに読み込まれます。spec ファイルとバイナリー・ファイルは rpmbuild によって RPM の中にパッケージ化されます。その RPM を別のユーザーがダウンロードすると、rpm ユーティリティーは spec ファイルを読み取り、事前に作成された命令に従ってそのパッケージをインストールします。


初めての RPM のビルド

先に進む前に一言注意しておきます。従来、パッケージは、root、つまりスーパーユーザーによってビルドされていました。その理由は、システムのソース・コード・リポジトリーにアクセスできるユーザーが root のみであったためです。しかし、この方法は危険をはらんでいます。root はシステム上の任意のファイルを変更できるため、RPM のビルドの途中で余分なファイルを追加したり、あるいは重要なファイルを削除したりすることによって、実行中のシステムを誤って変更してしまいがちでした。最近の RPM システムでは、すべてのユーザーがホーム・ディレクトリーで RPM をビルドできるようになっています。root 権限なしに RPM をビルドできることで、コアとなるシステム・ファイルへの変更を防ぐことができます。最近の方法を以下に示します。

RPM をビルドするためには、以下の作業を行う必要があります。

  • rpmbuild の仕様に従ってディレクトリーの階層構造を設定します。
  • その階層構造の適切な場所にソース・コードと補助ファイルを配置します。
  • spec ファイルを作成します。
  • RPM をビルドします。オプションとして、ソース RPM をビルドし、他の人達とソース・コードを共有することもできます。

まず、階層構造を作成します。ホーム・ディレクトリーの中の 1 つのディレクトリー (例えば $HOME/mywget) に以下の 5 つのサブディレクトリーを作成します。

  • BUILD: BUILD は実際にソフトウェアをコンパイルするためのスクラッチ・スペースとして使われます。
  • RPMS: RPMS には、rpmbuild によってビルドされるバイナリーの RPM が含まれます。
  • SOURCES: SOURCES はソース・コード用です。
  • SPECS: SPECS には spec ファイルが含まれます (ビルド対象の RPM ごとに 1 つの spec ファイルが必要です)。
  • SRPMS: SRPMS には、このプロセス中にビルドされるソース RPM が含まれます。

少なくとも、SOURCES にソース・コードが、そして SPECS に spec ファイルが必要です。

ソース (理想的には tarball としてバンドルされたもの) を SOURCES ディレクトリーにコピーします (リスト 2)。必要な場合には、tarball をリネームしてアプリケーションのバージョン番号を含め、他のバージョンと区別できるようにします。命名規則は、[パッケージ名]-[バージョン番号].tar.gz です。wget の場合には以下を使います。

リスト 2. ソースをコピーする
$ cd ~
$ mkdir mywget
$ cd mywget 
$ mkdir BUILD RPMS SOURCES SPECS SRPMS
$ cd SOURCES
$ cp wget-latest.tar.gz .
$ mv wget-latest.tar.gz wget-1.12.tar.gz
$ cd ..

次に、spec ファイルを作成します。spec ファイルは特別な構文を持つテキスト・ファイルにすぎません。リスト 3 は spec ファイルの例を示しています。

リスト 3. spec ファイルの例
# This is a sample spec file for wget

%define _topdir	 	/home/strike/mywget
%define name			wget 
%define release		1
%define version 	1.12
%define buildroot %{_topdir}/%{name}-%{version}-root

BuildRoot:	%{buildroot}
Summary: 		GNU wget
License: 		GPL
Name: 			%{name}
Version: 		%{version}
Release: 		%{release}
Source: 		%{name}-%{version}.tar.gz
Prefix: 		/usr
Group: 			Development/Tools

%description
The GNU wget program downloads files from the Internet using the command-line.

%prep
%setup -q

%build
./configure
make

%install
make install prefix=$RPM_BUILD_ROOT/usr

%files
%defattr(-,root,root)
/usr/local/bin/wget

%doc %attr(0444,root,root) /usr/local/share/man/man1/wget.1

この spec ファイルを先頭から最後まで順に見ていきましょう。1 行目から 5 行目は、このファイルの他の部分全体で使用されるコンビニエンス変数を定義しています。7 行目から 15 行目は、「パラメーター: 値」という形式で必要とされるパラメーターを設定しています。7 行目や他の部分を見るとわかるように、変数を評価して組み合わせることで設定の値を生成しています。

パラメーターの名前の大半は自明ですが、BuildRoot は先ほど作成した BUILD ディレクトリーと区別するために少し説明した方がよいでしょう。BuildRoot は最終的なインストール・ディレクトリーの代わりの役目を果たすディレクトリーです。つまり、例えば wget が最終的に /usr/local/bin/wget にインストールされ、他のサブディレクトリーが /usr/local にインストールされる場合 (例えばドキュメントは /usr/local/man にインストールされる、など)、BuildRoot は RPM のビルド・プロセス中に /usr/local の代わりとなります。BuildRoot を設定すると、RPM_BUILD_ROOT 環境変数を使って BuildRoot の値にアクセスすることができます。spec ファイルには必ず BuildRoot を設定する必要があり、また BuildRoot ディレクトリーの内容を調べ、そのパッケージによって何がインストールされるのかを検証する必要があります。

いくつかのヒントを以下に挙げます。

  • ./configure --prefix=$RPM_BUILD_ROOT という記述をしてはいけません。このコマンドを使うと、ファイル群の最終的な場所がビルド・ルートだと見なされ、パッケージ全体がビルドされてしまいます。すると、インストール済みファイルを実行時に見つける必要があるプログラムの場合、そのプログラムはおそらく失敗します。なぜなら、その RPM が最終的にユーザーのシステムにインストールされた時には、もはやファイル群はビルド・ルートの下にないからです。ビルド・ルートはビルド・システム上の一時ディレクトリーにすぎません。
  • Source の定義にパスを含めてはいけません。
  • Version と Release は特に重要です。アプリケーションのコードやデータを変更して新しい RPM を用意するごとに、必ず Version と Release の値を進め、それぞれメジャーな変更とマイナーな変更を反映させます。皆さんも (たとえ自分自身で使う場合でも) 試した内容を区別できるように、RPM をビルドするごとにリリース番号を上げた方が便利であると思うことでしょう。

次のセクションは %description で始まります。このセクションに、そのソフトウェアに関する簡潔で明確な説明を記述します。この行は、ユーザーが rpm -qi を実行して RPM パッケージに関する情報を照会すると表示されます。このパッケージが何をするものなのか、あるいは何らかの警告、構成に関する追加の指示内容などをこのセクションで説明することができます。

次に、%prep%build%install セクションが続いています。各セクションによって、シェル・スクリプトが生成され、そのスクリプトが RPM に組み込まれ、インストール作業の一環としてインストールに続いて実行されます。%prep はソース・コードを準備します (例えば tarball を解凍するなど)。ここで、%setup -q は Source で名前を指定された tarball を自動解凍するための %prep のマクロです。

%build セクションの命令は、どこかで見たことがあるはずです。これらのステップは、ビルドを手動で構成して起動する際に使用したステップと同じです。%install セクションも同じです。ただし、手動でビルドしたときのターゲットはシステムの実際の /usr/local ディレクトリーでしたが、%install 命令のターゲットは ~/mywget/BUILD ディレクトリーです。

%files は RPM にバンドルする対象のファイルを一覧表示し、またオプションでアクセス権やその他の情報を設定します。%files の中で %defattr マクロを使用すると、その RPM でのデフォルトのアクセス権、所有者、ファイル・グループを定義することができます。この例では、%defattr(-,root,root) によって、root が所有するすべてのファイルがインストールされます。その際、RPM がビルド・システムからバンドルする際に検出されたあらゆるアクセス権が使われます。

%files には複数のファイルを含めることができ、1 行に 1 つのファイルを指定します。これらの行には %doc または %config を追加することで、そのファイルをタグ付けすることができます。%doc は RPM に対し、そのファイルが文書ファイルであることを伝えます。そのため、ユーザーがそのパッケージを --excludedocs を使ってインストールすると、%doc が付いたファイルはインストールされません。%config は RPM に対し、そのファイルが構成ファイルであることを伝えます。アップグレードの際、RPM は、RPM によってパッケージ化されたデフォルトの構成ファイルが、ユーザーによって注意深く変更された構成を上書きしないようにします。

%files の下にディレクトリー名を記述すると、RPM はそのディレクトリーの下にあるすべてのファイルを含めてしまうことに注意してください。


RPM を完成させる

これでファイルの用意ができ、spec ファイルを定義できたので、実際に RPM ファイルをビルドする準備が整ったことになります。RPM ファイルをビルドするためには、その名のとおりの rpmbuild ユーティリティーを使います。

$ rpmbuild -v -bb --clean SPECS/wget.spec

このコマンドは指定された spec ファイルを使用し、詳細を出力する指定をして (-v)、バイナリー・パッケージをビルドします (-bb)。(-bb は「build binary」を意味します)。このビルド・ユーティリティーは、パッケージが作成された後でビルド・ツリーを削除します (--clean)。ソースの RPM もビルドしたい場合には、-bb ではなく -ba (「build all」) を指定します。(オプションの完全な一覧は rpmbuild の man ページを参照してください。)

rpmbuild は以下のステップを実行します。

  • wget.spec ファイルを読み取り、構文解析します。
  • %prep セクションを実行し、ソース・コードを一時ディレクトリーに解凍します。この場合の一時ディレクトリーは BUILD です。
  • %build セクションを実行してコードをコンパイルします。
  • %install セクションを実行し、ビルド・マシンのディレクトリーにコードをインストールします。
  • %files セクションからファイルのリストを読み取り、それらを集めてバイナリー RPM を作成します (また、指定された場合にはソースの RPM ファイルも作成します)。

$HOME/mywget ディレクトリーを調べてみると、wget-1.12-root という名前の新しいディレクトリーが見つかるはずですが、このディレクトリーはターゲットとなるディレクトリーの代わりとなります。また、RPMS/i386 という名前の新しいディレクトリーも見つかるはずで、このディレクトリーには RPM が wget-1.12-1.i386.rpm という名前で含まれているはずです。この RPM の名前は、これが wget のバージョン 1.12 であり、i386 プロセッサー用であることを示しています。

この RPM に適切なファイルが含まれていることを検証するためには、rpm コマンドを使います (リスト 4)。

リスト 4. RPM の内容を検証する
$ rpm -Vp RPMS/i386/wget-1.12-1.i386.rpm
missing     /usr/local/bin/wget
.M....G.    /usr/local/etc
missing   c /usr/local/etc/wgetrc
.M....G.    /usr/local/share
missing     /usr/local/share/info
missing   d /usr/local/share/info/wget.info
missing     /usr/local/share/locale
missing     /usr/local/share/locale/be
missing     /usr/local/share/locale/be/LC_MESSAGES
missing   d /usr/local/share/locale/be/LC_MESSAGES/wget.mo
.
.
.

rpm -Vp RPMS/i386/wget-1.12-1.i386.rpm というコマンドは、システム上のファイル群に対してこのパッケージの検証をします。一見多くのエラーがあるように見えますが、それぞれのエラーは RPM ファイルの内容が適切であることを示す手掛かりになります。あるファイルがインストールされているはずでありながら出力に現れていない場合には、そのファイルはパッケージに含まれていなかったことになります。その場合には、spec ファイルを見直し、そのファイルが %files セクションに列挙されているかどうかを確認します。

RPM の検証が終わると、このファイルを共同作業者に配布することができます。共同作業者はそのファイルを受け取ると、下記のように rpm を実行することで、自分のシステムに wget をインストールできるはずです。

$ sudo rpm -i wget-1.12-1.i386.rpm

他の用途に RPM を使用する

この簡単な紹介の記事では、RPM で行えることの表面的な部分しか説明できませんでした。RPM はソフトウェアやそれに関連するファイルのインストールに使われることが最も多いのですが、システム・スクリプトからソース・コードやドキュメントに至るまで、ほとんどすべてのものをパッケージ化することができます。また、この連載の次回の記事で説明するように、RPM を使ってソース・コードにパッチを当てることもでき、ソフトウェアの再ビルドと再インストールもすることができます。RPM によるディストリビューションのフォーマットは多くの Linux システムに使用されており、特に Red Hat と Fedora のシステムでは、バイナリー・ソフトウェアをインストールするための推奨の方法となっています。

RPM を使ってビルドとパッケージ化を行うと、必ず期待どおりの結果を得ることができます。

参考文献

学ぶために

製品や技術を入手するために

  • ftp.gnu.org から最新バージョンの wget のソース・コードをダウンロードしてください。
  • rpmlint について学び、また rpmlint をダウンロードしてください。
  • Easy RPM Builder について学び、また Easy RPM Builder をダウンロードしてください。
  • developerWorks から直接ダウンロードできる IBM ソフトウェアの試用版を使用して、皆さんの次期 Linux プロジェクトを革新してください。

議論するために

  • My developerWorks コミュニティーに参加してください。開発者向けのブログ、フォーラム、グループ、ウィキなどを利用しながら、他の developerWorks ユーザーとつながりを持ってください。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux
ArticleID=230479
ArticleTitle=RPM を使ってソフトウェアをパッケージ化する: 第 1 回 パッケージのビルドと配布
publish-date=01122010