Menu Close
Red Hat Training
A Red Hat training course is available for Red Hat Enterprise Linux
第2章 RPM パッケージ化を行うためのソフトウェアの準備
本セクションでは、RPM パッケージ化のソフトウェアを準備する方法を説明します。この準備には、プログラミングの知識は必要ありません。ただし、「ソースコードとは」、「プログラムが作られる仕組み」など、基本的な概念を理解しておく必要があります。
2.1. ソースコードとは
ここでは、ソースコードの概要を説明し、3 種類のプログラミング言語で書かれたプログラムのソースコード例を紹介します。
ソースコードとは、人間が読むことのできるコンピューターへの命令で、計算の実行方法を記述しています。ソースコードは、プログラミング言語で書かれています。
2.1.1. ソースコードの例
本書では、3 つのプログラミング言語で書かれた Hello World
プログラムが紹介されています。
各言語で、パッケージ化が異なります。
各言語の Hello World
プログラムは、RPM パッケージャーの主要な 3 つのユースケースをカバーしています。
2.1.1.1. bash で書かれた Hello World
bello プロジェクトは、bash で Hello World
を実装しています。この実装には bello
シェルスクリプトのみが含まれます。このプログラムの目的は、コマンドラインで Hello World
を出力することです。
bello
ファイルの構文は以下のようになります。
#!/bin/bash printf "Hello World\n"
2.1.1.2. Python で書かれた Hello World
pello プロジェクトは、Python に Hello World
を実装します。この実装には、pello.py
プログラムのみが含まれます。このプログラムの目的は、コマンドラインで Hello World
を出力することです。
pello.py
ファイルの構文は以下のようになります。
#!/usr/bin/python3 print("Hello World")
2.1.1.3. C で書かれた Hello World
cello プロジェクトは、C の Hello World
を実装します。この実装には、cello.c
および Makefile
ファイルだけが含まれます。そのため、生成される tar.gz
アーカイブには、LICENSE
ファイル以外にファイルが 2 つ含まれます。
このプログラムの目的は、コマンドラインで Hello World
を出力することです。
cello.c
ファイルの構文は以下のようになります。
#include <stdio.h> int main(void) { printf("Hello World\n"); return 0; }
2.2. プログラムが作られる仕組み
人間が判読できるソースコードからマシンコード (コンピューターがプログラムを実行するために従う命令) に変換する方法は、以下のとおりです。
- プログラムがネイティブにコンパイルされる。
- プログラムがマシンコードの解釈により、解釈される。
- プログラムがバイトコンパイルによって解釈される。
2.2.1. ネイティブにコンパイルされたコード
ネイティブにコンパイルされたソフトウェアは、生成されたバイナリーの実行ファイルでマシンコードにコンパイルされるプログラミング言語で書かれたソフトウェアです。このようなソフトウェアは、スタンドアロンで実行できます。
この方法でビルドした RPM パッケージは、アーキテクチャー固有のパッケージです。
64 ビット (x86_64) AMD または Intel のプロセッサーを使用するコンピューターでこのようなソフトウェアをコンパイルすると、32 ビット (x86) AMD または Intel プロセッサーでは実行できません。生成されるパッケージには、名前でアーキテクチャーが指定されています。
2.2.2. 解釈されたコード
bash や Python などの一部のプログラミング言語は、マシンのコードにコンパイルしません。代わりに、プログラムのソースコードは、言語インタープリターまたは言語仮想マシンにより、事前の変換なしで順を追って実行されます。
インタープリター型のプログラミング言語でのみ書かれたソフトウェアは、アーキテクチャーに依存しません。そのため、作成される RPM パッケージの名前には noarch
文字列が付きます。
インタープリター言語は、raw インタープリタープログラム または バイトコンパイル言語です。この 2 つは、パッケージ化作業のプログラムビルドプロセスにおいて異なります。
2.2.2.1. raw インタープリタープログラム
raw インタープリター言語プログラムはコンパイルする必要はなく、インタープリターにより直接実行されます。
2.2.2.2. バイトコンパイルプログラム
バイトコンパイル言語は、バイトコードにコンパイルして、その言語の仮想マシンにより実行される必要があります。
一部の言語では、raw インタープリターとバイトコンパイルを選ぶことができます。
2.3. ソースからのソフトウェア構築
このセクションでは、ソースコードからソフトウェアを構築する方法を説明します。
コンパイル言語で書かれたソフトウェアの場合、ソースコードはビルドプロセスを経て、マシンコードを生成します。このプロセスは、コンパイルまたはトランスレートと呼ばれ、言語によって異なります。その結果構築されるソフトウェアは実行できるようになります。これにより、プログラマーが指定したタスクをコンピューターが実行するようになります。
raw インタープリター言語で書かれたソフトウェアの場合、ソースコードは構築されず、直接実行します。
バイトコンパイル型のインタープリター言語で書かれたソフトウェアの場合、ソースコードがバイトコードにコンパイルされ、その言語の仮想マシンによって実行されます。
2.3.1. ネイティブにコンパイルされたコード
本セクションでは、C 言語で書かれた cello.c
プログラムの実行可能なファイルへの構築方法を紹介します。
cello.c
#include <stdio.h> int main(void) { printf("Hello World\n"); return 0; }
2.3.1.1. 手動による構築
cello.c
プログラムを手動で構築する場合は、以下の手順を使用します。
手順
GNU コンパイラコレクションから C コンパイラーを起動し、ソースコードをバイナリーにコンパイルします。
gcc -g -o cello cello.c
生成された出力バイナリー
cello
を実行します。$ ./cello Hello World
2.3.1.2. 自動化ビルド
大規模なソフトウェアは通常、Makefile
ファイルを作成し、GNU make
ユーティリティーを実行して自動ビルドを使用します。
自動ビルドを使用して cello.c
プログラムを構築する場合は、以下の手順を使用します。
手順
自動ビルドを設定するには、次の内容の
Makefile
ファイルをcello.c
と同じディレクトリーに作成します。makefile
cello: gcc -g -o cello cello.c clean: rm cello
cello:
およびclean:
の行は、タブスペースで始まる必要があります。ソフトウェアを構築するには、
make
コマンドを実行します。$ make make: 'cello' is up to date.
ビルドはすでに利用できるため、
make clean
コマンドを実行してから、make
コマンドを再び実行します。$ make clean rm cello $ make gcc -g -o cello cello.c
注記別のビルドに影響がなければ、プログラムの構築を試行します。
$ make make: 'cello' is up to date.
プログラムを実行します。
$ ./cello Hello World
これで、ビルドツールを使用した手動によるプログラムのコンパイルが完了しました。
2.3.2. コードの解釈
本セクションでは、Python で書かれたプログラムをバイトコンパイルして、bash で書かれたプログラムをそのまま解釈する方法を示しています。
以下の 2 つの例では、ファイルの一番上の #!
行は、シバン (shebang) と呼ばれるもので、プログラミング言語ソースコードの一部ではありません。
シバン により、実行ファイルとしてテキストファイルを使用できるようになります。システムプログラムローダーは、シバンを含む行を解析して、バイナリーの実行ファイルへのパスを取得します。これは、プログラミング言語インタープリターとして使用されます。この場合は、テキストファイルを実行ファイルとしてマークする必要があります。
2.3.2.1. コードのバイトコンパイル
本セクションでは、Python で書かれた pello.py
プログラムをバイトコードにコンパイルし、Python 言語の仮想マシンで実行する方法を説明します。
Python のソースコードは、そのまま解釈することもできすが、バイトにコンパイルした方が高速です。したがって、RPM パッケージャーは、エンドユーザーが配布するバージョンにはバイトコンパイルのパッケージ化を推奨しています。
pello.py
#!/usr/bin/python3 print("Hello World")
プログラムのバイトコンパイル手順は、以下の要素によって異なります。
- プログラミング言語
- 言語の仮想マシン
- その言語で使用するツールおよびプロセス
Python は、多くの場合バイトコンパイルが行われますが、ここでは説明しません。以下の手順は、コミュニティーの標準に準拠するのではなく、簡潔さを重視しています。実際の Python ガイドラインは「Software Packaging and Distribution」を参照してください。
この手順に従って pello.py
をバイトコードにコンパイルします。
手順
pello.py
ファイルをバイトコンパイルします。$ python -m compileall pello.py $ file pello.pyc pello.pyc: python 2.7 byte-compiled
pello.pyc
のバイトコードを実行します。$ python pello.pyc Hello World
2.3.2.2. raw-interpreting code
本セクションでは、bash シェルの組み込み言語で書かれた bello
プログラムをそのまま解釈する方法を示しています。
bello
#!/bin/bash printf "Hello World\n"
bashなどのシェルスクリプト言語で書かれたプログラムはそのまま解釈されます。
手順
ソースコードの実行ファイルでファイルを作成して実行します。
$ chmod +x bello $ ./bello Hello World
2.4. ソフトウェアへのパッチの適用
本セクションでは、ソフトウェアにパッチを適用する方法を説明します。
RPM のパッケージ化では、元のソースコードを変更するのではなく、コードを維持し、コードにパッチを使用します。
パッチは、ソースコードを更新するソースコードです。これは、2 つのバージョンのテキストの差を示すため、diff としてフォーマットされます。diff は、diff
ユーティリティーを使用して作成されます。これは、パッチ ユーティリティーを使用してソースコードに適用されます。
ソフトウェア開発者は多くの場合、git などのバージョン管理システムを使用してコードベースを管理します。このようなツールでは、diff やパッチソフトウェアを独自の方法で作成できます。
以下の例は、diff
を使用して元のソースコードからパッチを作成する方法と、パッチ
でパッチを適用する方法を示しています。後続のセクションで RPM を作成するときにパッチを適用します。「SPEC ファイルでの作業」を参照してください。
この手順では、cello.c
の元のソースコードからパッチを作成する方法を説明します。
手順
元のソースコードを保持します。
$ cp -p cello.c cello.c.orig
-p
オプションは、モード、所有権、およびタイムスタンプを保持するために使用されます。必要に応じて
cello.c
を変更します。#include <stdio.h> int main(void) { printf("Hello World from my very first patch!\n"); return 0; }
diff
ユーティリティーを使用してパッチを生成します。$ diff -Naur cello.c.orig cello.c --- cello.c.orig 2016-05-26 17:21:30.478523360 -0500 + cello.c 2016-05-27 14:53:20.668588245 -0500 @@ -1,6 +1,6 @@ #include<stdio.h> int main(void){ - printf("Hello World!\n"); + printf("Hello World from my very first patch!\n"); return 0; } \ No newline at end of file
-
で始まる行は、元のソースコードから削除され、+
で始まる行に置き換えられます。通常のユースケースの多くに適切なため、
diff
コマンドにNaur
オプションを指定することが推奨されます。ただし、この場合は、-u
オプションのみが必要になります。特定のオプションにより、以下が確保されます。-
-N
(または--new-file
) - 存在しないファイルを、空のファイルであるかのように処理します。 -
-a
(または--text
) - すべてのファイルをテキストとして処理します。そのため、diff
がバイナリーとして分類するファイルは無視されません。 -
-u
(もしくは-U NUM
または--unified[=NUM]
) - 統一されたコンテキストの出力の NUM (デフォルトは 3) 行の形式で、出力を返します。これは、変更したソースツリーにパッチを適用する際に、あいまい一致を可能にする読みやすい形式です。 -r
(または--recursive
) - 検出されたサブディレクトリーを再帰的に比較します。diff
ユーティリティーの一般的な引数は、man ページのdiff
を参照してください。
-
ファイルにパッチを保存します。
$ diff -Naur cello.c.orig cello.c > cello-output-first-patch.patch
元の
cello.c
を復元します。$ cp cello.c.orig cello.c
RPM を構築するときは変更後のファイルではなく、元のファイルが使用されるため、元の
cello.c
を保持する必要があります。詳細は「SPEC ファイルでの作業」を参照してください。
以下の手順は、output-first-patch.patch
を使用して cello.c
にパッチを適用して、パッチプログラムを構築し、これを実行する方法を示しています。
パッチファイルの出力先を
patch
コマンド変更します。$ patch < cello-output-first-patch.patch patching file cello.c
cello.c
の内容がパッチを反映していることを確認します。$ cat cello.c #include<stdio.h> int main(void){ printf("Hello World from my very first patch!\n"); return 1; }
パッチが適用された
cello.c
を構築して実行します。$ make clean rm cello $ make gcc -g -o cello cello.c $ ./cello Hello World from my very first patch!
2.5. 任意のアーティファクトのインストール
UNIX のようなシステムでは、ファイルシステム階層標準 (FHS) を使用して、特定のファイルに適したディレクトリーを指定します。
RPM パッケージからインストールしたファイルは、FHS に従って配置されます。たとえば、実行ファイルは、システム $PATH
変数のディレクトリーに置く必要があります。
このドキュメントのコンテキストでは、任意アーティファクト は RPM からシステムにインストールされたものを意味します。RPM およびシステムの場合は、スクリプト、パッケージのソースコードからコンパイルしたバイナリー、事前にコンパイルしたバイナリー、またはその他のファイルを意味します。
本セクションでは、システムに 任意アーティファクト を配置する一般的な 2 つの方法を説明します。
2.5.1. install コマンドの使用
パッケージャーは、GNU make などのビルド自動化ツールが最適ではない場合に install
コマンドを使用することがよくあります。たとえば、パッケージ化したプログラムに余分なオーバーヘッドが必要ない場合などが考えられます。
coreutils により、install
コマンドをシステムで利用できます。このコマンドは、指定のパーミッションセットで、ファイルシステム内の指定したディレクトリーにアーティファクトを配置します。
以下の手順では、このインストール方法に、任意アーティファクトとして以前に作成された bello
ファイルを使用します。
手順
install
コマンドを実行して、実行可能スクリプトに共通のパーミッションを持つ/usr/bin
ディレクトリーにbello
ファイルを配置します。$ sudo install -m 0755 bello /usr/bin/bello
これにより、
bello
は、$PATH
変数に一覧表示されているディレクトリーに置かれます。完全パスを指定せずに、任意のディレクトリーから
bello
を実行します。$ cd ~ $ bello Hello World
2.5.2. make install コマンドの使用
make install
コマンドを使用することで、ビルドしたソフトウェアをシステムに自動的にインストールできます。この場合、開発者が作成する Makefile
内のシステムにおいて、任意アーティファクトをシステムにインストールする方法を指定する必要があります。
この手順では、システム上の任意の場所にビルドアーティクトをインストールする方法を説明します。
手順
Makefile
にインストール
セクションを追加します。makefile
cello: gcc -g -o cello cello.c clean: rm cello install: mkdir -p $(DESTDIR)/usr/bin install -m 0755 cello $(DESTDIR)/usr/bin/cello
cello:
、clean:
、およびinstall:
の行は、行頭にタブスペースを追加する必要があります。注記$(DESTDIR) 変数は GNU make の組み込みで、一般的には、root ディレクトリーとは異なるディレクトリーへのインストールを指定するために使用されます。
これで、
Makefile
を使用してソフトウェアを構築するだけでなく、ターゲットシステムへのインストールも可能になります。cello.c
プログラムを構築してインストールします。$ make gcc -g -o cello cello.c $ sudo make install install -m 0755 cello /usr/bin/cello
これにより、
cello
変数に記載されているディレクトリーにcello
が置かれます。完全パスを指定せずに、任意のディレクトリーから
cello
を実行します。$ cd ~ $ cello Hello World
2.6. パッケージ化を行うためのソースコードの準備
開発者は、ソースコードの圧縮アーカイブとしてソフトウェアを配布するため、パッケージの作成に使用されます。RPM パッケージャーは、準備の整ったソースコードアーカイブと連携します。
ソフトウェアは、ソフトウェアライセンスとともに配布する必要があります。
この手順では、LICENSE
ファイルのサンプルコンテンツとして GPLv3 ライセンステキストを使用します。
手順
LICENSE
ファイルを作成し、以下の内容が含まれることを確認します。$ cat /tmp/LICENSE This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.
関連情報
- このセクションで作成したコードは、こちら にあります。
2.7. ソースコードを tarball へ追加
本セクションでは、「ソースコードの例」で紹介されている 3 つの Hello World
プログラムをそれぞれ gzip で圧縮した tarball にまとめる方法を説明します。これは、後で配布用にパッケージ化するソフトウェアをリリースする一般的な方法です。
2.7.1. bello プロジェクトを tarball へ追加
bello プロジェクトは、bash で Hello World
を実装しています。この実装には bello
シェルスクリプトのみが含まれるため、生成される tar.gz
アーカイブには LICENSE
ファイルとは別のファイルのみが含まれます。
この手順では、配布用に bello を準備する方法を示しています。
前提条件
このプログラムのバージョンが 0.1
であることを考慮してください。
手順
必要なファイルをすべて 1 つのディレクトリーに追加します。
$ mkdir /tmp/bello-0.1 $ mv ~/bello /tmp/bello-0.1/ $ cp /tmp/LICENSE /tmp/bello-0.1/
配布用のアーカイブを作成し、これを
~/rpmbuild/SOURCES/
ディレクトリーに移動します。このディレクトリーは、rpmbuild
コマンドがパッケージを構築するファイルを保存するデフォルトディレクトリーです。$ cd /tmp/ $ tar -cvzf bello-0.1.tar.gz bello-0.1 bello-0.1/ bello-0.1/LICENSE bello-0.1/bello $ mv /tmp/bello-0.1.tar.gz ~/rpmbuild/SOURCES/
bash で書かれたサンプルソースコードの詳細は「bash で書かれた Hello World」を参照してください。
2.7.2. pello プロジェクトを tarball へ追加
pello プロジェクトは、Python に Hello World
を実装します。この実装には pello.py
プログラムのみが含まれるため、生成された tar.gz
アーカイブには LICENSE
ファイルとは異なる 1 つのファイルのみが含まれます。
この手順では、pello プロジェクトを配布するために準備する方法を示します。
前提条件
このプログラムのバージョンが 0.1.1
であることを考慮する。
手順
必要なファイルをすべて 1 つのディレクトリーに追加します。
$ mkdir /tmp/pello-0.1.2 $ mv ~/pello.py /tmp/pello-0.1.2/ $ cp /tmp/LICENSE /tmp/pello-0.1.2/
配布用のアーカイブを作成し、これを
~/rpmbuild/SOURCES/
ディレクトリーに移動します。このディレクトリーは、rpmbuild
コマンドがパッケージを構築するファイルを保存するデフォルトディレクトリーです。$ cd /tmp/ $ tar -cvzf pello-0.1.2.tar.gz pello-0.1.2 pello-0.1.2/ pello-0.1.2/LICENSE pello-0.1.2/pello.py $ mv /tmp/pello-0.1.2.tar.gz ~/rpmbuild/SOURCES/
Python で書かれたサンプルソースコードの詳細は「Python で書かれた Hello World」を参照してください。
2.7.3. cello プロジェクトを tarball へ追加
cello プロジェクトは、C の Hello World
を実装します。この実装には、cello.c
および Makefile
ファイルだけが含まれます。そのため、生成される tar.gz
アーカイブには、LICENSE
ファイル以外にファイルが 2 つ含まれます。
パッチ
ファイルは、プログラムとともにアーカイブで配布されません。RPM Packager は、RPM を構築する際にパッチを適用します。パッチは、.tar.gz
アーカイブとともに、~/rpmbuild/SOURCES/
ディレクトリーに配置されます。
この手順では、cello プロジェクトを配布するために準備する方法を示します。
前提条件
このプログラムのバージョンが 1.0
であることを考慮してください。
手順
必要なファイルをすべて 1 つのディレクトリーに追加します。
$ mkdir /tmp/cello-1.0 $ mv ~/cello.c /tmp/cello-1.0/ $ mv ~/Makefile /tmp/cello-1.0/ $ cp /tmp/LICENSE /tmp/cello-1.0/
配布用のアーカイブを作成し、これを
~/rpmbuild/SOURCES/
ディレクトリーに移動します。このディレクトリーは、rpmbuild
コマンドがパッケージを構築するファイルを保存するデフォルトディレクトリーです。$ cd /tmp/ $ tar -cvzf cello-1.0.tar.gz cello-1.0 cello-1.0/ cello-1.0/Makefile cello-1.0/cello.c cello-1.0/LICENSE $ mv /tmp/cello-1.0.tar.gz ~/rpmbuild/SOURCES/
パッチを追加します。
$ mv ~/cello-output-first-patch.patch ~/rpmbuild/SOURCES/
C で書かれたサンプルソースコードの詳細は「C で書かれた Hello World」を参照してください。