Home > まめ知識 | 開発裏話 > 自作RPMの作成とレポジトリ3〜specファイルの書き方〜

自作RPMの作成とレポジトリ3〜specファイルの書き方〜

specファイルの書き方は、一種のプログラムか、と思うぐらい複雑でした。今回は、specファイルの書き方を基本から書いてみます。

(独学ですので、間違いがあったらごめんなさい。ぜひ、御指摘お願いします。)

基本構造

基本構造は、次の通りです。(例としてphp5.2を使用・・デフォルトのものではありません。ご注意ください。)

Summary: PHP 5 - A powerful scripting language
Name: php5
Version: 5.2.13
Release: 5
Group: System Environment/Daemons
Source: php-%{version}.tar.gz
Vendor: PHP
BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot
BuildPrereq: libjpeg-devel
BuildPrereq: libpng-devel
BuildPrereq: MySQL-shared
Requires: webserver
Requires: MySQL-shared
Requires: libmcrypt
Requires:libmcrypt-devel
Provides: php = 5.2.13
Provides: php-gd php-xml php-mbstring php-mysql php-bcmath

%description
korehatesutodesu

%prep
%setup -q -n php-%{version}

%build
# つくるくん。
./configure --with-apxs2=/usr/local/apache2/bin/apxs \
--enable-mbstring \
--enable-mbregex \
--with-gd \
--with-zlib \

make

%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/usr/local/apache2/conf
mkdir $RPM_BUILD_ROOT/usr/local/apache2/bin
mkdir $RPM_BUILD_ROOT/usr/local/apache2/modules
cp /usr/local/apache2/conf/httpd.conf $RPM_BUILD_ROOT/usr/local/apache2/conf/httpd.conf

make install INSTALL_ROOT=$RPM_BUILD_ROOT 

rm -rf $RPM_BUILD_ROOT/usr/local/apache2/conf/httpd.conf
rm -rf $RPM_BUILD_ROOT/usr/local/apache2/conf/httpd.conf.bak

rm -rf $RPM_BUILD_ROOT/.channels
rm -rf $RPM_BUILD_ROOT/.registry
rm -rf $RPM_BUILD_ROOT/.depdb
rm -rf $RPM_BUILD_ROOT/.depdblock
rm -rf $RPM_BUILD_ROOT/.filemap
rm -rf $RPM_BUILD_ROOT/.lock

%clean
rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root)
/usr/local/apache2/modules/libphp5.so
/usr/local/bin/pear
/usr/local/bin/peardev
/usr/local/bin/pecl
/usr/local/bin/php
/usr/local/bin/php-config
/usr/local/bin/phpize
%config /usr/local/etc/pear.conf
/usr/local/include/php/*
/usr/local/lib/php/*
/usr/local/lib/php/.channels/*
/usr/local/lib/php/.channels/.alias/*
/usr/local/lib/php/.registry/*
/usr/local/lib/php/.depdb
/usr/local/lib/php/.depdblock
/usr/local/lib/php/.filemap
/usr/local/lib/php/.lock
/usr/local/man/man1/php*

%changelog
* Thu Oct 28 2010 tesutosakusei tekitou@tekitou.tek
- tesutodesu

個々の部位の説明1(はじめの部分・・パッケージ情報)

まず、はじめの部分は、非常に重要な値がてんこもりです。

Summary: PHP 5 - A powerful scripting language
Name: php5
Version: 5.2.13
Release: 5
Group: System Environment/Daemons
Source: php-%{version}.tar.gz
Vendor: PHP
License: PHP License

Summary :パッケージの簡単な説明(必ず一行で。)

Name:パッケージの名前(スペースやタブは不可)

Version:パッケージのバージョン(*.*.*の形式で書くのが普通。)

Release:パッケージのリリース番号(バージョンは変化しないが、コンフィグを変えてコンパイルしなおした場合等はここをインクリメント。1からスタート)

License:ライセンス情報(必須項目。わからなければ大抵はGPL。)

Group:適当でもいいが、yumのグループインストールをするならば、一意のグループ名が必要。

Source:Sourceのtarballの名称を書きます。rpmmacrosで設定しているので、標準ではSOURCESディレクトリ内のファイル名となります。http://~等でも構いません。(この場合は、インターネット接続が必須ですが・・)また、本来はSource0となります。0は省略可能です。さらに、Sourceが複数ある場合は、Source1、Source2・・と増やしていきます。下は例です。

Source0: php-%{version}.tar.gz
Source1: php.ini
Source2: php.conf

Vender:ベンダ名です。任意ですので、書かなくてもrpm作成できます。

※ほかのところでversion番号とかを使うときは、%{Version}で変数みたいに呼び出せます。(マクロ展開されます)%{Name}と%{Version}は良く使います。

個々の部位の説明1(はじめの部分・・パッケージ情報の続き)

はじめの部分の続きです。

BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot
BuildPrereq: libjpeg-devel
BuildPrereq: libpng-devel
BuildPrereq: MySQL-shared
Requires: webserver
Requires: MySQL-shared
Requires: libmcrypt
Requires:libmcrypt-devel
Provides: php = 5.2.13
Provides: php-gd php-xml php-mbstring php-mysql php-bcmath

BuildRoot:RPM化するために仮想的にインストールするルートディレクトリです。特に問題無ければ、どのSPECファイルでも、「%{_tmppath}/%{name}-%{version}-buildroot」でいいかと思います。ちなみに%{_tmppath}はデフォルトで/var/tmpとなります。

BuildPrereq:コンパイルするのに必要なパッケージ名(機能名)を書きます。特に書かなくても問題ないですが、忘れないように書いておくといいです。注意するべき点は「このディレクティブは、rpmを作成するサーバーに必要なものを書くのであって、インストールする先のサーバーに必要なものでは無い」ということです。

Requires:こっちは、rpmをインストールするサーバーに必要なパッケージ名(機能名)を書きます。これを書くことで、依存関係を構築してくれます。バージョン**以上が必要等の書き方は、「Requires: httpd >= 2.2」のように書きます。

Provides:このパッケージが供給する機能名です。パッケージ名はデフォルトで機能名として登録されるので、パッケージ名だけでいい場合は、不要です。ただし、phpのように、コンパイルインストールすると、いろんな機能が一緒にインストールされる場合は、名前を追加する必要があります。この名前が、RequireとかBuildPrereqとかで使われる名前ともなります。また、バージョン番号を付ける場合は、「 php = 5.2.13」のように、=の前後に半角スペースを入れて書いてください。

個々の部位の説明2(description・prepセクション)

次から、各セクションの説明です。セクションは、大抵はじまりが%~~~で、終わりは次のセクション名か、ファイル終了です。(大抵と書いたのは、%setupのようにセクション名でないものもあるためです。)

%description
korehatesutodesu

%prep
%setup -q -n php-%{version}

%descriptionセクションは、パッケージの詳細情報を書くのに使います。yumコマンドで、閲覧できます(僕はあまり使わないですが・・)。また、ここは、次のセクションまで何行でも書くことができます。

%prepセクションは、コンパイル前の準備作業を書くセクションです。この場所には、%setupや%patch等が入ります。

%setupは、セクションではありません。これは、自動的にtarballをBUILDディレクトリに展開するコマンドです。-qで、展開時の情報を表示しないという設定、-n以降は、不要な場合も多いのですが、setupコマンドは、何も指定しないと、tarballを展開してできるディレクトリ名を%{Name}-%{Version}であると判断してコピーを行います。展開後のディレクトリ名がデフォルトと異なる場合は、-n以降で指定する必要があります。今回は、わざとNameをphp5としたので、展開した後の名前「php-5.2.13」と異なりますので、設定が必要です。

patchを当てるときは、ここで行いますが、次回まわしにします。また、%prepセクションでは、必要なソースを追加コピーしたり等も行うことがあります。

個々の部位の説明3(buildセクション)

このセクションは、コンパイルを行うセクションです。

%build
# つくるくん。
./configure --with-apxs2=/usr/local/apache2/bin/apxs \
--enable-mbstring \
--enable-mbregex \
--with-gd \
--with-zlib \

make

普通のコンパイルインストールとほとんど同じです。実は、%setupを行うと、カレントディレクトリが展開されてコピーされたディレクトリに移っているようなので、%buildセクションでは、パスの指定は通常不要です。また、make installはこの場所では行いません。(今回のせたのは、適当ですので、コンフィグ内容は適宜書き加えてください。)

個々の部位の説明4(installセクション)

このセクションは、仮想ルートに対してインストールを行うセクションです。

%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/usr/local/apache2/conf
mkdir $RPM_BUILD_ROOT/usr/local/apache2/bin
mkdir $RPM_BUILD_ROOT/usr/local/apache2/modules
cp /usr/local/apache2/conf/httpd.conf $RPM_BUILD_ROOT/usr/local/apache2/conf/httpd.conf

make install INSTALL_ROOT=$RPM_BUILD_ROOT 

rm -rf $RPM_BUILD_ROOT/usr/local/apache2/conf/httpd.conf
rm -rf $RPM_BUILD_ROOT/usr/local/apache2/conf/httpd.conf.bak

rm -rf $RPM_BUILD_ROOT/.channels
rm -rf $RPM_BUILD_ROOT/.registry
rm -rf $RPM_BUILD_ROOT/.depdb
rm -rf $RPM_BUILD_ROOT/.depdblock
rm -rf $RPM_BUILD_ROOT/.filemap
rm -rf $RPM_BUILD_ROOT/.lock

一行目の「rm -rf $RPM_BUILD_ROOT」はBuildRootで指定したフォルダを消す処理です。$RPM_BUILD_ROOTは%{BuildRoot}と同一ですが、こう書くのが普通のようです。

また、残りの部分でやっている内容は、php専用の特殊処理です。phpは、make installの際、apacheのconfigに追記しようと試みるので、無理矢理仮想インストール環境に、configを追加しました。あと、moduleのインストールを行ってもらうために、フォルダを作っています。

注意するのは「make install」です。普通にmake installを行うと、実環境の方にインストールされてしまいます。(不要なアプリがyum経由でなくインストールされてしまう。非常に問題。)このミスを防ぐためにも、「rootでコンパイルしない」というのが定石です。仮想環境にインストールするために、phpでは、「make install INSTALL_ROOT=$RPM_BUILD_ROOT」と書きます。大抵のものは、「make DESTDIR=$RPM_BUILD_ROOT install」と書くのですが、何故かphpは書き方が異なります。気を付けてください。

make installが終わった後の処理は、単純に不要なディレクトリとかのパッケージに入れないものを消しています。

(phpは結構いろいろしなければならなかったので、apacheの%installセクションの例をのせておきます。普通はこんな感じです。)

%install
#いつも書く。
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/usr/local
#DESTDIRを入れないと、勝手にこの機体にインストールする。危険。 
make DESTDIR=$RPM_BUILD_ROOT install

個々の部位の説明5(cleanセクション)

このセクションは、パッケージングが終わったあとの処理を書くセクションです。

%clean
rm -rf $RPM_BUILD_ROOT

大抵これですが、ミスを防止するために、

%clean
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT

と書いた方がいいかもしれません。

個々の部位の説明6(filesセクション)

このセクションは、最も面倒臭いセクションであり、必ず書かなければならないセクションです。

%files
%defattr(-,root,root)
/usr/local/apache2/modules/libphp5.so
/usr/local/bin/pear
/usr/local/bin/peardev
/usr/local/bin/pecl
/usr/local/bin/php
/usr/local/bin/php-config
/usr/local/bin/phpize
%config /usr/local/etc/pear.conf
/usr/local/include/php/*
/usr/local/lib/php/*
/usr/local/lib/php/.channels/*
/usr/local/lib/php/.channels/.alias/*
/usr/local/lib/php/.registry/*
/usr/local/lib/php/.depdb
/usr/local/lib/php/.depdblock
/usr/local/lib/php/.filemap
/usr/local/lib/php/.lock
/usr/local/man/man1/php*

rpm化する場合は、ここに書かれたファイルがパッケージ化されます。注意するべき点は、「仮想ディレクトリにインストールされた(buildセクションで最後に残った)ファイルは全て書かなければならない」という点(この点は後述)と、「仮想ルートを基準としたパスで書くこと(実際にインストールされるパス)」です。

%defattr(-,root,root)は、デフォルト属性を設定します。特定のファイルだけパーミッションを変更したい場合は、%attr(755,apache,apache)みたいなものを、ファイルパスの前につけます。

また、%configを前に付けると、インストール時にもしファイルがある場合は、.rpmsaveを名前の後ろにつけてバックアップとして保存します。また、%config(noreplace)をつけると、インストール時にもしファイルがある場合は上書きもバックアップもせず、元のファイルを残します。

個々の部位の説明7(changelogセクション)

このセクションは、変更履歴を残すのに使います。

%changelog
* Thu Oct 28 2010 tesutosakusei tekitou@tekitou.tek
- tesutodesu

通常、タイトル行は「* (日時) (作成者) (メールアドレス) 」で、その下に「-メッセージ」と書きます。メッセージは何行でもいけるようです。 (たくさんある場合の例)

%changelog
* Thu Oct 28 2010 tesutosakusei tekitou@tekitou.tek
- tesutodesu
- tesutodesune
* Thu Oct 10 2010 tesutosakusei tekitou@tekitou.tek
- tesutodesuyo
- tesutodesuka
- tesutodesusi

最も問題になり得る「files」セクションのうまい方法について

実は、最初のころ、ひたすらはまりました。当然ですが、プログラムが何をどこにインストールしているかなんて、全て知っているわけないので・・。現在、僕は次のようにして対処しています。

1. とりあえずfilesセクションには何も書かずにspecファイルを編集して「rpmbuild -ba ***.spec」で、パッケージングしてみる。

2. 当然エラーするが、最後のパッケージングまでたどり着くと、エラー内容が、「未伸張のファイルが見つかりました」というエラーとともに、インストールされるべきファイルの一覧が表示される。

3. この一覧を元に、specファイルのfilesセクションを書いて、再度ビルド。

ミスなくいけるのですが、問題はコンパイルに時間のかかるものだと、二回コンパイルするので余計に時間を食います。他にいい方法があったら、ぜひ教えてください。

エラー内容の例をのせておきます。(a52decのコンパイル)

RPM ビルドエラー:
    インストール済み(ただし未伸張)ファイルが見つかりました:
   /usr/bin/a52dec
   /usr/bin/extract_a52
   /usr/include/a52dec/a52.h
   /usr/include/a52dec/attributes.h
   /usr/include/a52dec/audio_out.h
   /usr/include/a52dec/mm_accel.h
   /usr/lib64/liba52.a
   /usr/lib64/liba52.la
   /usr/man/man1/a52dec.1.gz
   /usr/man/man1/extract_a52.1.gz

次回は、インストール時にユーザーをつくるやり方とか、chkconfigに登録する方法とかをかけるといいな、と思っています。

Comments:0

Comment Form

Trackbacks:0

Trackback URL for this entry
http://dev.tapweb.co.jp/2010/12/273/trackback
Listed below are links to weblogs that reference
自作RPMの作成とレポジトリ3〜specファイルの書き方〜 from tap dev blog

Home > まめ知識 | 開発裏話 > 自作RPMの作成とレポジトリ3〜specファイルの書き方〜

Search
Feeds

Return to page top