試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

ebuildの作成メモ(後半)

ebuildの作成メモ(前半)」の続き。

基本的な流れ

ebuild内で定義する関数とその処理について。
必要のあるものだけを記述し、処理順に上から書くのが一般的。関数の継承(後述)により、省略が可能な場合がある。

  1. src_unpack(): ダウンロードしたソースを展開(unpack)し、必要に応じてパッチを当てる(epatch)処理など
  2. src_compile(): 設定(econf)、ビルド(emake)、もしくはそれに相当する「変換」処理
  3. src_install(): 仮インストール先(${D})へインストールする操作をして、システムへ組み込んだ後のディレクトリ構成を作る

必要に応じて

  • pkg_setup(): パッケージビルド前にチェックしておく必要のある状態がある場合はここで確認し、条件に合わなければメッセージを出しつつ(eerror)エラーを出して終了(die)する
  • pkg_postinst()pkg_postrm(): パッケージがシステムにインストールされた後とシステムから削除された後に実行される処理を記述(これらは.tbz2パッケージ化したものをインストール/アンインストールしたときにも実行される)

などの処理を追加する。
このような、段階に応じて処理を記述する方式は、RPMというパッケージ管理システムが使用するパッケージの作成に使用する「.specファイル」という、ebuildと機能的に似ているファイルでも使用されている。ただ、.specファイルよりはebuildのほうが後発であることもあり、後述のeclassなどを含めて、色々と洗練されている。幾つかの自作ebuildを.specファイルへ移植するテストをしてみたが、.specファイルは構造が見づらく、ずらずらと長くなってしまうのに比べて、ebuildはシンプルで分かりやすい気がした。

eclass

あるパッケージグループ(デスクトップ環境など)に属する一連のパッケージ群において、一部の処理*1が共通している場合がある。このとき、その共通している部分を別ファイルに記述しておいて各ファイルから参照させる方式をとることで、それぞれのebuildの記述量を大きく減らすことができる。
この「別ファイル」が.eclassファイルで、特定の用途でのみ使われる関数群を提供するためのeclassも存在する。
ebuildの先頭に

inherit [eclass名...]

を記述することで、PortageツリーやOverlayのeclassディレクトリにあるファイルの名前で取り込むことができる。

eclassによる関数の継承

例として、「distutils」というeclassには
[引用]ファイル名: ${PORTDIR}/eclass/distutils.eclass

EXPORT_FUNCTIONS src_unpack src_compile src_install pkg_postinst pkg_postrm

という記述があるのだが、これが意味するのは、このeclassを「inherit」することによって、ebuild内の上記5つの関数が、省略時に「distutils_[関数名]」の関数に置き換わるということ。もちろん、継承された関数を用いずに

src_unpack() {
	distutils_src_unpack  # 手動で呼んでいる
	(何かの追加処理...)
}

のようにして関数を上書きすることもできる。

追加の関数

例として、GCCのある最適化オプションがアプリケーションの動作に明らかに悪い影響を与えると分かっているとき、ユーザが変数CFLAGSやCXXFLAGSをいじっていても、その中から自動的にオプションをフィルタすることができ、このときには、「flag-o-matic」というeclassを用いてreplace-flags()filter-flags()などの関数を呼ぶこととなる。
行いたい処理によって、その処理を行う関数が定義されているeclassが異なるため、他のebuildを参考にするなどして、適切なeclassを「inherit」するようにする。

ダイジェスト作成

Gentoo Linuxにおけるパッケージ管理について(Overlay)」にも書いているように、パッケージとしてemergeでインストールするためには、ebuildコマンドでebuildとその関連ファイルのダイジェストを作成する必要がある。

ACCESS VIOLATIONとその回避

パッケージをインストールするときの流れは「Gentoo Linuxにおけるパッケージ管理について(パッケージ、バージョンとその識別子)」に書いているが、このときのビルド用一時ディレクトリ(${S})の中でビルド作業を行って、仮インストール先(${D})へインストールするまでの間にその外(システム上の実行ファイルやライブラリなどの入っている場所)へ書き込みを行おうとすると、それをブロックして「ACCESS VIOLATION」が発生したことを示すエラーを出してインストールに失敗する。
多くは、ビルドのルールを記述するファイル(Makefileなど)に、インストール時に直接システム上の具体的な場所に対してディレクトリを作成したりファイルをコピーしたりするように書かれているのが原因。
ebuild内では、${D}以下へ仮インストールするようにするために

emake DESTDIR="${D}" install || die "emake install failed"
もしくは
einstall || die "einstall failed"

のように記述することが多い*2が、そのときにビルドシステムへ渡される引数だけではうまくインストール先が動かせない場合には、Makefileのようなファイルの一部を、${D}以下に書き込みがされるように(パッチやsedコマンドなどで)編集するような処理を別途追加しておかなくてはならない。
なお、einstallについては
http://www.atzm.org/gentoo/ebuilds2.html#einstall
を参照。DESTDIR指定でうまくいかないときに試すとよい。

*1:ビルドシステムに対する操作やインストール後の操作など

*2:configureスクリプトなどでは、インストール先を(システム上に実際に配置される場所である)/usrなどに指定する(configureスクリプトではeconfがやってくれる)のだが、仮インストール時にはインストール先を${D}の下へ一時的にずらしている