Momonga Linux は FHS-2.1 に準拠した環境を提供する。よって
man page は %{_mandir}
info ファイルは %{_infodir}
ドキュメントファイルは %{_docdir}
起動スクリプトを置くべき場所は、/etc/init.d へ移行した。 %{_initscriptdir}というマクロを定義してあるので、そこに置くようにする。
既に commit されている既存バージョンのパッケージを見ておくこと。 そうでないとMomonga独自の patch を取りこぼしたり、 spec ファイルでの変更が無効になっていたり、 命名規則等にずれが生じるからである。
commit 前に必ず cvs diff を使って自分の変更した部分を確認すること。
tcsh% cvs diff |& less bash$ cvs diff 2>&1 | less
などとして標準エラー出力までチェックすれば、 cvs add すべきファイルを add し忘れたりすることもなくなるので、 問題なくなるまで何度も cvs diff をチェックすることを推奨する。
同じ名前の tar ball や patch でも中身が変わっている事が有り、 このため rebuild が通らなくなる事が有る。
これは md5sum 値などを明示することによりある程度は防ぐ事が可能であるが、 根本的な解決は難しいので気をつけること。
バイナリパッケージを作成する場合(-ba、-bb、--rebuild)は 一般ユーザで行うこと。 ただし root でなければ作成できない場合はこの限りではない。 (see OmoiKondara-HOWTO)
現在の所 root でなければ作成できないパッケージは、suidperl を作る perl、 su を作る sh-utils などと MAKEDEV(mknod) を使う dev などである。
これ以外で Makefile などで install -o root などしているパッケージは spec file 中で sed を用いたり、 patch を作成して修正する。 配付されている Makefile で useradd を使っている場合は patch を作成して変更する。
spec file で useradd を使用している場合は %post に移動する。
また当然ではあるが spec fileで chown -R root.root . などとしてはいけない。
使わない。 /usr/local 以下にファイルが install されないようにすること。 確認は rpm -qpl hogehoge.`arch`.rpm | grep local などで行う。
また、/usr/local/bin/perl や /usr/local/bin/ruby が Require されないようにすること。 こちらの確認は rpm -qp --requires buroro.`arch`.rpm | grep local などで行う。
rebuild 時などに log を取り、それを確認することにより defattr 拳や /usr/local が使われていないかを確認する。 rpm -vv --rebuild --target i586 hogehoge.nosrc.rpm 2>&1 | tee /var/tmp/hogehoge-rebuild-log.txt などで行う。
rpm --eval %configure を実行してみれば、意味と使い方がわかるハズ。 rpm --define '_bindir /bin' --eval %configure も、ちゃんと _bindir を変更した %configure の内容を表示してくれる。 これで、%make や %configure に影響するマクロを変更する際に、 いちいち /usr/lib/rpm/macros を表示して 頭の中で変換したり、何度もビルドして確かめたりする必要はなくなるだろう。
パッケージを作成する人は unset LINGUAS して行うこと。
export LINGUAS="" と似ているが、こちらはダメである。 これではあらゆるメッセージカタログが生成されなくなってしまう。
spec ファイル内で unset LINGUAS するのは禁止とする。 ある言語のメッセージカタログだけを含むバイナリパッケージを 生成したい場合には、 LINGUAS=ja rpm --rebuild hoge などと外部から制御する余地を残すこと。 また、すでにこの拳が入っているパッケージは修正する事。
info は、黙っていると %{_infodir}/dir がぶちあたる。 そのため、
Prereq: install-info
したうえで
%post /sbin/install-info %{_infodir}/hogehoge.info %{_infodir}/dir %preun if [ $1 = 0 ]; then /sbin/install-info --delete %{_infodir}/hogehoge.info %{_infodir}/dir fi %files %{_infodir}/hogehoge.info*
といった感じでサバくこと。
最近の install-info は、 hogehoge.info というファイルが見付からない時には hogehoge.info.gz や hogehoge.info.bz2 をさがすようになっているので、 .gz や .bz2 などの suffix をつけないこと。
ファイルリストに
files -f <ファイル名>
と書いて、<ファイル名> を自動生成させるようにすれば、 ファイルリストを手で書く必要がなくて楽になる。が、 この手法にたより過ぎてしまうと、filesystem パッケージや basesystem パッケージをはじめとして、 ディレクトリのコンフリクトが起こる確率が高い。
そこで、 ファイルリストを生成させるときは、 ファイル及びシンボリックリンクのみを抽出して、 ディレクトリをニギりたければ そのディレクトリが作っているパッケージ (と作っているパッケージに依存するように出来ているパッケージ) 以外がそのディレクトリをニギっていないことを確認すべきである。 以下のようにすると確認するのは簡単である。 rpm -qf ディレクトリのフルパス このとき、フルパスの最後に / が付かないようにすること。
自動的にそのあたりを判別しながらファイルリストでディレクトリをニギるのは はっきり言って無理に等しいので、dir は手で書くのが無難であろう。
また、ファイルリストでニギるのは /usr 以下にしておいた方がよい。 /etc 配下のファイルには様々なマクロを付けたくなることが普通だからであり、 どんなファイルが出来ているかきちんと把握する意味でも手動リストアップを 推奨する。
なお
(find RPM_BUILD_ROOT/usr \ -type f -o -type l | sort ) > {name}.files mv {name}.files {name}.files.in sed "s|.*/usr|/usr|" < {name}.files.in | while read file; do if [ -d RPM_BUILD_ROOT/file ]; then echo -n 'dir ' fi echo file done > {name}.files
としておくと、RPM_BUILD_ROOT/usr 以下 (パッケージがインストールされると /usr 以下となる) の type -f (つまり普通のファイル) と -l (つまりシンボリックリンク)のみを抜き出してリストアップし、 ファイルリストに収めるようになる。 このスクリプトでニギりきれないファイル、およびニギってもよいディレクトリ は手動でニギるべし、と覚えておこう。
daemon 系のものは、あらゆる
Prereq: chkconfig
したうえで
%post /sbin/chkconfig --add hoge if test -r /var/run/hoge.pid then %{_initscriptdir}/hoge restart fi %preun if [ "$1" = 0 ] then if test -r /var/run/hoge.pid then %{_initscriptdir}/hoge stop fi /sbin/chkconfig --del hoge fi
といった感じでサバくこと。
%files には /etc/rc3.d/S15hoge などは書かない。
また、FHS 準拠により /etc/init.d、/etc/rc?.d となったことに注意すること。
perl モジュールを RPM にしようとする時、 .packlist というファイルを含めると、何らアーキテクチャ依存ファイルが含まれていないパッケージでも /usr/lib/perl5/site_perl/5.6.0/i586-linux/auto/*/.packlist のようなディレクトリが含まれてしまうので、あらゆるモジュールにおいて .packlist およびそれが含まれるだけのディレクトリは含めないこと。
tetex-dvips で使用する font package では, %install などで map ファイル を /usr/share/texmf/dvips/config/extmap ディレクトリに置き, %post で /usr/share/texmf/dvips/config/updmap すること. %postun で /usr/share/texmf/dvips/config/updmap すれば font map 情報は自動的に削 除される.
あ!! それから, tetex-dvips を
tetex-dvips >= 1.0.7-13kとして Require するのを忘れ ないこと (11k 以前には extmap がない).
txfonts や pxfonts パケジの spec file を雛型にすると良い鴨.
modutils からみて/etc/conf.modulesは今や obsolete であり、 今後ユーザは/etc/modules.confを使うことが推奨される。 しかし、パッケージ側では/etc/conf.modulesを使っている場合にも 対応出来るようにすべきであり、 そこで、%post で/etc/conf.modulesや/etc/modules.confにエントリを 書き加える場合は
if [ "$1" = 1 ] ; then hogehoge if [ -f /etc/modules.conf ] ; then MODULES_CONF=/etc/modules.conf else MODULES_CONF=/etc/conf.modules fi if [ -f $MODULES_CONF ] ; then if ! grep -q fugahoge $MODULES_CONF > /dev/null; then echo -n 'Add a fugafuga entry to '$MODULES_CONF'...' echo "alias fuga-hoge-0 fugahoge" >> $MODULES_CONF echo "OK" fi fi fiのようにして、/etc/modules.confが存在する場合にはそちらを優先して 使うようにする。
また、%postun で/etc/conf.modulesや/etc/modules.confからエントリを 削除する場合は、
if [ "$1" = 0 ] ; then hogehoge for i in /etc/modules.conf /etc/conf.modules do if ( test -f $i grep -q fugahoge $i ) > /dev/null; then echo -n 'Removing a fugafuga entry from '$i'...' ( cd /etc; \ mv $i $i.bak ; \ sed -e 's:alias fuga-hoge-0 fugahoge::' $i.bak > $i ; \ ) echo "OK" fi done fiのようにして、両方のファイルを確認することを忘れないこと。
backport のしやすさを考えて、マクロをなるべく使うようにする。 つまり
%configure
%makeinstall
%{buildroot}
%{optflags}
%{_mandir}
%{_infodir}
%{_initscriptdir}
man や info ファイルは基本的には rpm の生成において自動で圧縮されるので、 spec 中に故意に圧縮させるのはむだである。また strip に関しても同様である。
これに関し、
%files ... %{_mandir}/man3/hoge.3.gz
のように書いてはいけない。
正しくは、
%{_mandir}/man3/hoge.3*
となる。
例えば、
%define hoge 1
という行をコメントアウトしようとして、
# %define hoge 1
と書いてもコメントアウトしたことにはならない(hoge が define される)。 rpm ではコメントよりも先にマクロが解釈されるからである。 正しくコメントアウトするためには、
# %%define hoge 1
と書けばよい。
同じような話として、%changelog の中で
- modify %post section
と書いてはいけない。%post が解釈されるからである。正しくは
- modify %%post section
と書く。
specファイルの%prep、%build、%installセクションは、 --short-circuit付きでrpmが起動されてどのセクションから実行されても、 きちんとパッケージをビルドできるように 工夫しておくのが好ましい。
具体的には、 %{_builddir} 以下のディレクトリ構造は、 %prep 以外では変更しないようにする、 などの注意が必要である。
%setup に付けるオプションについて。
まず -q はあらゆるオプションの前に付けること。
%setup の基本動作は次の通り。まず %_builddir に cd し、Source0 の展開予定場所 [4] を rm -fr し、それから Source0 を展開し、そこに cd する。 以下で紹介するオプションは、それをどう変形するかに関わってくる。
-a 1 は、 Source0 を展開し、その展開場所に cd した「後 (after)」に Source1 を展開するという意味。 そこには cd しない。
-b 1 は、Source0 の展開予定場所に cd する「前 (before)」に Source1 を展開するという意味。 [5] そこには cd しない。
-c は、Source0 の展開予定場所を mkdir してから、 そこに cd して Source0 を展開するという意味。 カレントディレクトリにファイルをぶちまけてしまうような tar 玉に有効。
-D は展開前に rm -fr しないという意味。
-n foo は、Source0 の展開場所として foo を指定するという意味。 普段は -n %{name}-%{version} が暗示されているが、 これに合わないディレクトリを展開するパケジに有用。
-T は Source0 の展開 をしないという意味。 rm -fr と cd はする。 複数の %setup を使うことは可能なので、%setup -q したあとに %setup -q -T -D -a 1 するというような使い方で %setup -q -a 1 と同じことができる。
%attr 等の標準的な説明は省略して、 よくわからないで使ってしまいがちなものだけを取り上げる。
%config(missingok) は、そのファイルが存在しなくても問題ない という意味。 [6] インストール後に消されても verify 時に missing と表示しない。
%config(noreplace) は、既存のファイルが既に編集されている場合に 新しいもので上書きしないという意味。新しいファイルは .rpmnew というサフィクスを付けて保存される。
%dir はディレクトリを指定する。そのディレクトリだけを指定するので、 ディレクトリ内のファイルは含まれない。これを使う必要があるのは パケジに含めたくないファイルがそのディレクトリにある場合のみである。 [7]
%doc はおなじみだが、カレントディレクトリからの相対パス以外に %buildroot を除いたフルパスで指定する [8] こともできるので、覚えておこう。
%docdir は、そのディレクトリ内のファイルを %doc とみなす宣言である。 注意すべきなのは、%dir と違って、そのディレクトリをニギらないということ。 %docdir /usr/doc/foo として /usr/doc/foo/README だけを %files に入れると、アンインストール時に /usr/doc/foo が消されずに残ってしまう。 %docdir したディレクトリは、もう一度 %files に書くこと。
%ghost は、インストールはしないが verify やアンインストールはする、 という意味。だから、 %attr や %verify と組み合わせないと意味がないかもしれない。
%files を処理する際には存在している必要があるので、 %install の中で %makeinstall 等によって生成されないのであれば、 touch しておくこと。 また、%files で %attr を指定しないのであれば %install 中で chmod しておくこと。
これは、%post で作成されるファイルや、 利用しているうちに作成されるようなファイル [9] に有用であろう。 後者の場合は、インストールしても利用しなければ存在しないのだから %config(missingok) にするのが適当であろう。 このようなファイルを %ghost で指定しておくことで、 アンインストール時にファイルが残ってディレクトリが消されない、 というような問題を回避できる。
%verify(owner group mode md5 size maj min symlink mtime) は、検査対象を明示するためのものだ。(not ……) と書くと、検査の対象に 「しない」ものを明示することになる。どちらかというと not の方がパケジャの意図に合うことが多いと思われる。
%post 等で使う $1 の値は、最初のインストールでは 1, アップグレイドでは 2, アンインストール時には 0 というようになる。アップグレイドの時は実行せず、 最初のインストールの時だけ実行したいときには %post (または %pre) で $1 が 1 かどうかを確かめれば良いというわけだ。
--install の方の最後の引数は優先度である。大きい方が優先される。 既に install されているものを再度 install しても、優先度等が更新されるだけで二重登録にはならない。 基本的には以下のようにすれば良い。
%post min %{_sbindir}alternatives --install %{_bindir}/foomin foo %{_bindir}/foo 10 %post max %{_sbindir}alternatives --install %{_bindir}/foomax foo %{_bindir}/foo 20 %postun min %{_sbindir}alternatives --remove foo %{_bindir}/foomin %postun max %{_sbindir}alternatives --remove foo %{_bindir}/foomax
%pre, %post, %trigger 等に使えるものとして、 "-p" というオプションがある。よく %post -p /sbin/ldconfig として使われるが、これは実は、普段の %post が %post -p /bin/sh と同等である、というようなものである。 つまり %post -p /usr/bin/ruby というような使い方もできるはずなのだ。 ただ、 [Momonga-devel.ja:02464]によると LSB に違反するそうなので、 使用しないことが望ましい。
なお、rpm の CHANGES ファイルを見ると %post -p "/sbin/ldconfig -n /lib" という書式に対応しているように見えるのだが、試してみたところ、 引数がうまく処理されないようだった。 実際に意図した通りの動作をするかどうか、 また、使用しないで済む方法がないのか、 よく確認してから使った方が良いだろう。
なお、
# インストール時に実行する %post -p /sbin/ldconfig # アンインストール時に実行する %postun -p /sbin/ldconfigのような書き方をすると、「アンインストール時に実行する」というコメント行が ldconfig に渡されることになって困るかもしれない [10] ので注意が必要である。コメントを付けただけだからと言って テストせずにコミットすることのないように。