wiki:self-build-creation

self-build パッケージについて

仕組みの概要

  1. 事前にターゲットの rpm パッケージを作成するのに必要な、spec と patch やその他のファイルを用意しておきます。
  2. 上記のファイル類を self-build-%{target} な rpm パッケージに含めておきます。
  3. %post で以下の処理を一括して行います。
    • まず rpm ビルド用のテンポラリディレクトリと作成
    • 次に patch やその他のファイルを /テンポラリ/rpm/SOURCES にコピー
    • 続いて wget を使ってソースをダウンロード
    • 後は、rpmbuild -bb でターゲットのパッケージをビルドし、所定のディレクトリ(/var/cache/self-build)に移動
    • rpm2cpio | cpio を使ってビルドしたパッケージからファイルを事前に展開 (オプショナル)
  • また apt/synaptic を使って self-build-%{target} をインストールした場合には、 所定のディレクトリ(/var/cache/self-build)に置かれたターゲットの rpm ファイル のインストールまでを自動で実行します。
    これは apt の Scripts::PM::Post:: というスロットを使うことで、rpm の DB に 変更がコミットされた(= self-build-%{target} 自体のインストールが完了した)直後 にヘルパースクリプトを呼び出すことで実現されています。

作り方

  1. ターゲット rpm 用のファイル一式の準備
    最初にターゲットのプログラム(以下 lame を例に説明) の rpm パッケージが作成できる spec ファイルを用意します。
    もし patch やその他のファイルが必要な場合は、これも一緒に準備しておきます。
  2. self-build 用の spec ファイルの作成
    上記の spec ファイルを使って rpm のバイナリパッケージが作成できることを確認したら、次に self-build-lame 用の spec を作成します。
    1. ターゲットのプログラム用の spec や patch、その他のファイルを Source? で定義しておきます。
    2. PreReq: にターゲットのプログラムの BuildRequires: と同じものを書いておきます。
      こうすることで、%post でコンパイルする時に必要となるパッケージが一緒にインストールされます。
    3. self-buiild 用の spec とターゲットのプログラム用の spec で、%{version}-%{release} が異なると事前のパッケージ配置に失敗するので、%prep でチェックしておきます。
      %prep
      [ "%{version}-%{release}" != $(rpm -q --queryformat "%%{version}-%%{release}\n" --specfile %{SOURCE0} | tail -1) ] && exit 1
      
    4. %install で Source? で定義した各種ファイルを全て ${RPM_BUILD_ROOT}/%{_datadir}/self-build-lame にインストールします。
      またこれらのファイルを %files でも指定しておきます。
    5. %post で rpm パッケージをビルドするヘルパースクリプトを、以下のように実行します。
      %post
      /usr/lib/rpm/self-build-rpm.sh self-build-lame lame.spec http://...(ソースダウンロード URL) 12345(ログサイズ)
      
      • 1つ目の引数は、self-build パッケージの名前を指定します。
        この名前を使って spec や patch 類が置いてあるディレクトリ (ここでは /usr/share/self-build-lame)を特定します。
      • 2つ目の引数は、rpm のビルドに使用する spec ファイル名を指定します。
      • 3つ目の引数は、ソースファイルをダウンロードするための URL を指定します。
        ヘルパースクリプトはこの URL から wget を使ってソースをダウンロード しようとします。
        3つめ以降~n-1の引数は全てソースの URL と解釈するので、複数のファイルを ダウンロードする必要がある場合は、続けて指定できます。
        また同一の ファイルを複数のミラーサイトからダウロードできる場合は、それらの URL も 複数指定できます。
        この場合、いずれかの URL からファイルがダウンロードできたら2つ目以降の URL から のダウンロードはスキップします。
      • 最後(n番目)の引数は、ターゲット の rpm パッケージをビルドした際に出力される ログファイル(通常であれば /var/tmp/self-build-lame.xxxxx/self-build-lame.log) のサイズを指定します。
        この値が指定されていると、ビルド中に実際に出力されるログファイルのサイズとの 比率でプログレスバーが表示されるようになります。
        (* self-build-setup >= 0.9.5 が必要です)
    6. 作成するターゲットのパッケージ(主に -devel の類)が他の self-build パッケージから依存される可能性がある場合は、更に %post で以下のようにヘルパースクリプトを実行して、作成した rpm パッケージが実際にインストールされるより前に、必要なファイル をファイルシステム上に配置しておきます。(オプショナル)
      %post
      /usr/lib/rpm/pre-allocate-rpm.sh %{pkgname}-%{version}-%{release} \
                                       %{pkgname}-devel-%{version}-%{release}
      
      • 引数には、ターゲットの rpm パッケージ名を指定します。
        対象のファイルが特定できるように Version と Release まで指定する必要があります。
      • ヘルパースクリプトは指定された rpm から 設定ファイル(rpm -qc で表示されるもの)とドキュメント(rpm -qd で表示されるもの)を除いたファイルを rpm2cpio | cpio コマンドで抽出し、ファイルシステム上に配置します。
        (* 尚、この展開したファイルは後の rpm パッケージのインストールにより上書きされるので、 パッケージ管理システム上も不整合をきたすことはありません)
      • これにより依存関係をもつ複数の self-build パッケージが一度の処理(apt-get install hoge fuga ...) で同時にインストールできるようになります。
  3. 作成した self-build パッケージの作成とテスト
    spec ができたら、$ rpm -ba self-build-lame.spec で rpm パッケージを作成し、その後 root になって # rpm -Uvh self-build-lame-3.97-0vl3.i386.rpm のようにしてインストールし、 ターゲットの rpm ファイルが /var/cache/self-build 以下にできあがることを確認します。

実際にはパッケージ名やターゲットのプログラムの名前、ソースのダウンロード URL 等は %define でマクロとして最初に宣言しておいた方が管理しやすくなります。 self-build-lame.spec がサンプルとして使えると思いますので、初めて作成する方は apt-get source self-build-lame を実行して ~/rpm/SPECS に展開された spec ファイルを参考してみてください。

self-build 同士が依存する場合の注意点

ある self-build なパッケージが、他の self-build なパッケージが提供する rpm に依存する場合、以下の点に注意する必要があります。

  • 他の self-build パッケージから依存されそうな場合は、pre-allocate-rpm.sh を %post で実行
    たとえば self-build-lame からは lame, lame-mp3x, lame-devel の3つの rpm が出来上がります。これらは(たとえば) mplayer を mp3 対応でビルドする為には、 予めインストールされている必要があります。
    このような場合、self-build-lame.spec の %post で pre-allocate-rpm.sh を実行しておくと、事前に必要なバイナリやヘッダファイル等がファイルシステム上に 展開されるので、apt-get install self-build-mplayer を実行した結果、依存により self-build-mplayer と self-build-lame が一緒に一回でインストールされても、 mplayer を mp3 対応でビルドできるようになります。
  • self-build 同士の依存情報は、self-build-*.spec 内の PreReq にのみ記述
    上記のケースで、mplayer のビルドに lame, lame-devel が必要となる場合、各 spec には以下のように記述します。
    これは self-build の仕組み上、先にすべての rpm パッケージを作成して、 その後にできた rpm パッケージをまとめてインストールするので、 後からインストールされる rpm パッケージをその前の段階で要求すると、 依存が満たせずにエラーとなるのを防ぐためです。
    • self-build-mplayer.spec
      PreReq: self-build-lame, *-devel
    • mplayer.spec
      BuildRequires: *-devel 等 (※ self-build-lame、lame-devel は書かない)

self-build パッケージに依存するパッケージのカテゴリ

self-build パッケージは、non-free カテゴリに属しております。 そのため、self-build パッケージに依存するパッケージのカテゴリは、 non-free カテゴリになります。

現時点で、例外のあるパッケージは以下の通りです。

  • amarok

self-build パッケージの %{arch}

self-build パッケージは、基本的には noarch で作成します。

ただし、BuildArch?: noarch を使うと、%ifarch が使えないので、 arch に依存するパッケージでは BuildArch? タグを使えません。

現時点で、arch に依存するのは、以下のパッケージです。

self-build 系パッケージ arch に依存する理由
self-build-ffmpeg %{ix86} x86_64: Requires(post): yasm
self-build-x264 %{ix86} x86_64: Requires(post): yasm
self-build-vlc %{ix86} x86_64: Requires(post): svgalib-devel libXvMC-devel
self-build-xvidcore %{ix86}: Requires(post): nasm; x86_64: Requires(post): yasm
self-build-mplayer-codecs %{ix86} ppc x86_64: arch により source0path が異なる
self-build-lame %{ix86} x86_64: Requires(post): nasm

ファイルダウンロード時のプロトコル (http or ftp)

ソースアーカイブのダウンロード時に http と ftp が選べる場合は、 http を選ぶことを推奨します。

ftp は Active/Passive? いずれにおいても firewall や router の 設定によってはアクセスできない場合がある為、これを極力避ける 必要があります。
(<VineLinux:wishes:0191> と [VineSeed:18681] 以降のスレッド参照)

self-build パッケージ更新

リリースバージョンの場合、原則として、 so name の変更を伴う self-build パッケージの更新をしないで下さい。

詳しくは、Package Maintenance Policy を参照。

例えば、faad2-2.6.1 を faad2-2.7 へ更新すると仮定します。

faad2-2.6.1 は libfaad.so.0.0.0 を提供しますが、 faad2-2.7 は libfaad.so-2.0.0 を提供しますので、 self-build-faad2-2.7 だけ put すると、 以下のように libfaad.so.0 の欠如により、 faad2-2.7 をインストールすることができません。

$ sudo apt-get install self-build-faad2-2.7-1vl6.noarch.rpm 
パッケージリストを読みこんでいます... 完了
依存情報ツリーを作成しています... 完了        
'self-build-faad2-2.7-1vl6.noarch.rpm' として self-build-faad2 を選択しました
アップグレード: 0 個, 新規インストール: 0 個, 再インストール: 1 個, 削除: 0 個, 保留: 0 個
0B/7698B のアーカイブを取得する必要があります。
展開後に 0B のディスク容量が追加消費されます。
続行しますか? [Y/n]Y
変更を適用しています...
準備中                                ############################## [100%]
更新/インストール中
  self-build-faad2-2.7-1vl6.noarch       ############################## [100%]
     rpm パッケージの作成を開始します。(self-build-faad2)
     ソースファイルのダウンロード中...
(snip)
     ソースファイルのダウンロードが完了しました。
     rpm パッケージをビルド中...
      (詳細は /var/tmp/self-build-faad2.log を参照してください。)
     rpm パッケージのビルドが完了しました。
     作成した rpm パッケージから必要なファイルを事前に配置しました。
完了
作成/ダウンロードした rpm パッケージをインストール中...
エラー: 依存性の欠如:
	libfaad.so.0()(64bit) は (インストール済み)ffmpeg-libs-0.5-6vl5.x86_64 に必要とされています
	libfaad.so.0()(64bit) は (インストール済み)gpac-libs-0.4.5-6vl5.x86_64 に必要とされています
	libfaad.so.0()(64bit) は (インストール済み)libquicktime-1.1.2-1vl5.x86_64 に必要とされています
	libfaad.so.0()(64bit) は (インストール済み)avidemux-cli-2.4.4-1vl5.x86_64 に必要とされています
	libfaad.so.0()(64bit) は (インストール済み)avidemux-qt-2.4.4-1vl5.x86_64 に必要とされています
	libfaad.so.0()(64bit) は (インストール済み)gstreamer-plugins-bad-0.10.12-1vl5.x86_64 に必要とされています
	libfaad.so.0()(64bit) は (インストール済み)avidemux-gtk-2.4.4-1vl5.x86_64 に必要とされています
	libfaad.so.0()(64bit) は (インストール済み)ffmpeg-mh-0.33-10vl5.x86_64 に必要とされています
	libfaad.so.0()(64bit) は (インストール済み)xine-lib-faad-1.1.16.3-2vl5.x86_64 に必要とされています
	libfaad.so.0()(64bit) は (インストール済み)vlc-1.0.1-1vl5.x86_64 に必要とされています
	libfaad.so.0()(64bit) は (インストール済み)mplayer-1.0-23.20090821vl5.x86_64 に必要とされています
*エラー: rpm パッケージをインストールできません。
rpm ファイルは /var/cache/self-build に残っています。

この問題を解決する方法は、

  • libfaad.0.0.0 を提供する compatibility パッケージを用意
  • faad2 に依存するパッケージを rel + 1 する
    • faad2-devel-2.7 でリビルド

で対処可能です。

しかしながら、非常にリポジトリの依存関係の壊れの元になりかねません。 原則として self-build 系のパッケージで lib 系のパッケージの更新においては、 so name の変更を伴う version up をしない方が懸命です。

[資料]ビルドログのファイルサイズ

$ date
2010年  2月 17日 水曜日 17:20:27 JST
$ sudo vbuilder --version 5.0 --clean --install-rpm self-build-vlc --install-rpm self-build-mplayer
$ du -b /var/local/vbootstrap/5.0/var/tmp/self-build-*
26148	/var/local/vbootstrap/5.0/var/tmp/self-build-a52dec.log
25711	/var/local/vbootstrap/5.0/var/tmp/self-build-faac.log
66762	/var/local/vbootstrap/5.0/var/tmp/self-build-faad2.log
609432	/var/local/vbootstrap/5.0/var/tmp/self-build-ffmpeg.log
373437	/var/local/vbootstrap/5.0/var/tmp/self-build-gpac.log
64384	/var/local/vbootstrap/5.0/var/tmp/self-build-lame.log
32482	/var/local/vbootstrap/5.0/var/tmp/self-build-libdca.log
78717	/var/local/vbootstrap/5.0/var/tmp/self-build-libdvbpsi.log
16699	/var/local/vbootstrap/5.0/var/tmp/self-build-libdvdnav.log
24200	/var/local/vbootstrap/5.0/var/tmp/self-build-libmad.log
56955	/var/local/vbootstrap/5.0/var/tmp/self-build-libmp4v2.log
63615	/var/local/vbootstrap/5.0/var/tmp/self-build-libmpeg2.log
2119	/var/local/vbootstrap/5.0/var/tmp/self-build-mplayer-codecs.log
1378555	/var/local/vbootstrap/5.0/var/tmp/self-build-mplayer.log
2586749	/var/local/vbootstrap/5.0/var/tmp/self-build-vlc.log
18876	/var/local/vbootstrap/5.0/var/tmp/self-build-x264.log
10053	/var/local/vbootstrap/5.0/var/tmp/self-build-xvidcore.log

提案

ばっちりのバイト数を指定すると、98%, 99% などになる場合がしばしばある。そこで、1000バイト単位で指定しても良いのでは?

例:$ du -b /var/tmp/self-build-a52dec.log 
27240	/var/tmp/self-build-a52dec.log
このとき、
/usr/lib/rpm/self-build-rpm.sh %{name} %{pkgname}.spec "%{sourceurl}" 27000

公式:self-build-hoge.log
$ echo $(($(du -b self-build-hoge.log | cut -f 1)/1000*1000))

TODO

  • synaptic で self-build 系パッケージをインストールしたときに、 止まっているように感じるそうなので、ビルドログを表示する。
  • 他の環境でビルドしたself-build 系パッケージの rpm を、 別の環境でインストールできる仕組みを作る。
    • vbuilder の利用
  • ビルドした self-build 系パッケージの src.rpm を保存する・しない、 ダウンロードした tarball などのソースを保持する・しないを設定できるようにする。
  • self-build に特化したツールの整備