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 プロジェクトは、bashHello World を実装しています。この実装には bello シェルスクリプトのみが含まれます。このプログラムの目的は、コマンドラインで Hello World を出力することです。

bello ファイルの構文は以下のようになります。

#!/bin/bash

printf "Hello World\n"

2.1.1.2. Python で書かれた Hello World

pello プロジェクトは、PythonHello 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. 解釈されたコード

bashPython などの一部のプログラミング言語は、マシンのコードにコンパイルしません。代わりに、プログラムのソースコードは、言語インタープリターまたは言語仮想マシンにより、事前の変換なしで順を追って実行されます。

インタープリター型のプログラミング言語でのみ書かれたソフトウェアは、アーキテクチャーに依存しません。そのため、作成される 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 プログラムを手動で構築する場合は、以下の手順を使用します。

手順

  1. GNU コンパイラコレクションから C コンパイラーを起動し、ソースコードをバイナリーにコンパイルします。

    gcc -g -o cello cello.c
  2. 生成された出力バイナリー cello を実行します。

    $ ./cello
    Hello World

2.3.1.2. 自動化ビルド

大規模なソフトウェアは通常、Makefile ファイルを作成し、GNU make ユーティリティーを実行して自動ビルドを使用します。

自動ビルドを使用して cello.c プログラムを構築する場合は、以下の手順を使用します。

手順

  1. 自動ビルドを設定するには、次の内容の Makefile ファイルを cello.cと同じディレクトリーに作成します。

    makefile

    cello:
    	gcc -g -o cello cello.c
    clean:
    	rm cello

    cello: および clean: の行は、タブスペースで始まる必要があります。

  2. ソフトウェアを構築するには、make コマンドを実行します。

    $ make
    make: 'cello' is up to date.
  3. ビルドはすでに利用できるため、make clean コマンドを実行してから、make コマンドを再び実行します。

    $ make clean
    rm cello
    
    $ make
    gcc -g -o cello cello.c
    注記

    別のビルドに影響がなければ、プログラムの構築を試行します。

    $ make
    make: 'cello' is up to date.
  4. プログラムを実行します。

    $ ./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 をバイトコードにコンパイルします。

手順

  1. pello.py ファイルをバイトコンパイルします。

    $ python -m compileall pello.py
    
    $ file pello.pyc
    pello.pyc: python 2.7 byte-compiled
  2. 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 の元のソースコードからパッチを作成する方法を説明します。

手順

  1. 元のソースコードを保持します。

    $ cp -p cello.c cello.c.orig

    -p オプションは、モード、所有権、およびタイムスタンプを保持するために使用されます。

  2. 必要に応じて cello.c を変更します。

    #include <stdio.h>
    
    int main(void) {
        printf("Hello World from my very first patch!\n");
        return 0;
    }
  3. 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 を参照してください。

  4. ファイルにパッチを保存します。

    $ diff -Naur cello.c.orig cello.c > cello-output-first-patch.patch
  5. 元の cello.c を復元します。

    $ cp cello.c.orig cello.c

    RPM を構築するときは変更後のファイルではなく、元のファイルが使用されるため、元の cello.c を保持する必要があります。詳細は「SPEC ファイルでの作業」を参照してください。

以下の手順は、output-first-patch.patch を使用して cello.c にパッチを適用して、パッチプログラムを構築し、これを実行する方法を示しています。

  1. パッチファイルの出力先を patch コマンド変更します。

    $ patch < cello-output-first-patch.patch
    patching file cello.c
  2. cello.c の内容がパッチを反映していることを確認します。

    $ cat cello.c
    #include<stdio.h>
    
    int main(void){
        printf("Hello World from my very first patch!\n");
        return 1;
    }
  3. パッチが適用された 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 ファイルを使用します。

手順

  1. install コマンドを実行して、実行可能スクリプトに共通のパーミッションを持つ /usr/bin ディレクトリーに bello ファイルを配置します。

    $ sudo install -m 0755 bello /usr/bin/bello

    これにより、bello は、$PATH 変数に一覧表示されているディレクトリーに置かれます。

  2. 完全パスを指定せずに、任意のディレクトリーから bello を実行します。

    $ cd ~
    
    $ bello
    Hello World

2.5.2. make install コマンドの使用

make install コマンドを使用することで、ビルドしたソフトウェアをシステムに自動的にインストールできます。この場合、開発者が作成する Makefile 内のシステムにおいて、任意アーティファクトをシステムにインストールする方法を指定する必要があります。

この手順では、システム上の任意の場所にビルドアーティクトをインストールする方法を説明します。

手順

  1. 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 を使用してソフトウェアを構築するだけでなく、ターゲットシステムへのインストールも可能になります。

  2. cello.c プログラムを構築してインストールします。

    $ make
    gcc -g -o cello cello.c
    
    $ sudo make install
    install -m 0755 cello /usr/bin/cello

    これにより、cello 変数に記載されているディレクトリーに cello が置かれます。

  3. 完全パスを指定せずに、任意のディレクトリーから 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 プロジェクトは、bashHello World を実装しています。この実装には bello シェルスクリプトのみが含まれるため、生成される tar.gz アーカイブには LICENSE ファイルとは別のファイルのみが含まれます。

この手順では、配布用に bello を準備する方法を示しています。

前提条件

このプログラムのバージョンが 0.1 であることを考慮してください。

手順

  1. 必要なファイルをすべて 1 つのディレクトリーに追加します。

    $ mkdir /tmp/bello-0.1
    
    $ mv ~/bello /tmp/bello-0.1/
    
    $ cp /tmp/LICENSE /tmp/bello-0.1/
  2. 配布用のアーカイブを作成し、これを ~/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 プロジェクトは、PythonHello World を実装します。この実装には pello.py プログラムのみが含まれるため、生成された tar.gz アーカイブには LICENSE ファイルとは異なる 1 つのファイルのみが含まれます。

この手順では、pello プロジェクトを配布するために準備する方法を示します。

前提条件

このプログラムのバージョンが 0.1.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/
  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. 必要なファイルをすべて 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/
  2. 配布用のアーカイブを作成し、これを ~/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/
  3. パッチを追加します。

    $ mv ~/cello-output-first-patch.patch ~/rpmbuild/SOURCES/

C で書かれたサンプルソースコードの詳細は「C で書かれた Hello World」を参照してください。