LSB 3.2 準拠じゃないディストリでも動く LSB 準拠っぽいプリンタドライバのパッケージを作ってみた
d:id:naruoga:20090706:1246868439 の続き。
LSB 3.2 の要件って決して厳しくないんだけど、実際取ってない、けど市場だとまだ使われてるディストリビューションって多いのですよね。
だからそういう奴らでも動く RPM を作ろうと頑張ってみた。
設計方針 (おおげさ)
まずは方針を決めましょう。、
- 基本的にファイルは /opt/
の下に置くという原則を崩さない - ファイル名の原則も互換を保つ
- しかし古いディストリ君のツールや CUPS は ppd.gz を難しい場所に置くと認識してくれないので、なるべく固い場所にリンクを置く
- リンクを置く場所はなるべくハードコードしないで、調べられるようにする
とまあこんな感じ。
リンクを置く場所の決定
Debian 系
決めうちはしないと言った舌の根も乾かぬうちになんですが、Debian 系は /usr/share/ppd に置くのが固いようなので (/usr/share/cups/model というフォルダもあるんだけど見てくれないっぽい)、
/usr/share/ppd がある場合はここで決めうち
としちゃいました。
Red Hat 系
こいつの場合は /usr/share/cups/model の下に置くのが確実なようなのですが (一段ぐらいディレクトリを掘っても大丈夫っぽいが、直置きが確実)、だから決めうちは止そうっての。
cups 君には可愛いことに cups-config というツールがついてきます。
$ cups-config Usage: cups-config --api-version cups-config --cflags cups-config --datadir cups-config --help cups-config --ldflags cups-config [--image] [--static] --libs cups-config --serverbin cups-config --serverroot cups-config --version
なんてことを答えてくれます。
いえ、厳密に言えば cups-devel についてくるみたいですが。
ので、今のディストリは大抵 cups が入っていると cups-devel も入れてくれるのですが (つかデフォルトだと cups も cups-devel も入ってる)、古い子だと入っていない場合があるので要注意。
まずは cups-config がない場合は泣きながら /usr/share/cups/model 決めうちです。
cups-config がある場合は --modeldir というオプションがある奴とない奴があるようですが、これはたぶん古い奴なんだと思われます。
のでこれで取れる場合はそのディレクトリをそのまま採用し、取れない場合は --datadir でとったディレクトリ名 (大抵は /usr/share/cups) に model を付けたもの (大抵は /usr/share/cups/model になる) を選びましょう。
以下を RPM スクリプト (/etc/rpm/macro) にするとこんな感じになります。
if [ -d '/usr/share/ppd' ]; then \ ppddir=/usr/share/ppd \ else \ if cups-config --version >/dev/null 2>/dev/null; then \ ppddir=`cups-config --modeldir 2>/dev/null` || \\\ ppddir=`cups-config --datadir`/model \ else \ ppddir=/usr/share/cups/model \ fi \ fi \
ここまで分かればあとは /opt/
%set_ppd_links
とゆことでまずは %set_ppd_links から。
細かいこと抜きで結論だけ書きましょう。
%set_ppd_links \ if [ "%{?optinstall}" = "1" ]; then \ if [ -d '/usr/share/ppd' ]; then \ ppddir=/usr/share/ppd \ else \ if cups-config --version >/dev/null 2>/dev/null; then \ ppddir=`cups-config --modeldir 2>/dev/null` || \\\ ppddir=`cups-config --datadir`/model \ else \ ppddir=/usr/share/cups/model \ fi \ fi \ # Remove old links to PPD file directory \ find $ppddir -name "*.ppd.gz" -type l -print | xargs rm -f - \ # Make PPD files available to CUPS \ ln -sf %{_cupsppd}/%{supplier}/* $ppddir 2>/dev/null || true \ fi \ %{nil}
全体を囲っている大きな if 文は opt に ppd.gz を置くかどうかという設定をチェックするものですが、これは先に述べたとおり /opt/
一段下がった if 文の固まりはさっきのコピペでございます。DRY 原則には思い切り反してますがめんどくさいのでこのまんま。
これで $ppddir という変数に ppd の格納場所が決まりました。
次の find 文は *.ppd.gz というファイル名のシンボリックリンクをぜんぶ消しちゃうというちょっと大胆な内容です。まあ、わざわざシンボリックリンクでファイルを置く人はあんまりいなかろうということで、自分が配置したものかどうか判断せずにえいやで消してます。
お次の ln は /opt/
%remove_ppd_links
まあ普通のおつむをお持ちの方は %remove_ppd_links がどんなふうになるかお分かりでしょうからこれもぱっと書いてしまいます。
%remove_ppd_links \ if [ "%{?optinstall}" = "1" ]; then \ if [ -d '/usr/share/ppd' ]; then \ ppddir=/usr/share/ppd \ else \ if cups-config --version >/dev/null 2>/dev/null; then \ ppddir=`cups-config --modeldir 2>/dev/null` || \\\ ppddir=`cups-config --datadir`/model \ else \ ppddir=/usr/share/cups/model \ fi \ fi \ # Remove old links to PPD file directory \ find $ppddir -name "*.ppd.gz" -type l -print | xargs rm -f - \ fi \ %{nil}
ええ、%set_ppd_links の末尾二行を取っただけです。
まさに DRY 違反。気にしない気にしない。
あたりまえですがこの macro ファイルは LSB 3.2 の環境と共存できないので (できるように書き直した人がいたらください ^^)、LSB 3.2 じゃない環境 (たとえば CentOS 5.3 とか) で使うようにしてくださいです。
specs
specs は前回のネタとあんまり変わりません。
強いて言えば
- LSB との Require を外す
- BuildRequire に Foomatic を追加し、ついでに cupsddk -> cups-devel に変えておく
- バージョン番号から LSB という文字列を外す
てな感じなので、まあサンプルを乗せるまでもないでしょう。
終わりに
ま、もちろん素で RPM 書ける人はわざわざこんな作り方をする必要はないとは思いますが、LSB 対応とそうでない奴を両方作りたいひととか、そういう用途には使えるかもしれませんね。ええ。
しっかしこの一連のエントリ、何人が読んでるんだろ?