読者です 読者をやめる 読者になる 読者になる

おがさわらなるひこのオープンソースとかプログラミングとか印刷技術とか

おがさわらなるひこ @naru0ga が技術系で興味を持ったりなんだりしたことをたまーに書くブログです。最近はてなダイアリー放置しすぎて記事書くたびにはてな記法忘れるのではてなブログに移行しました。

クリエイティブ・コモンズ・ライセンス
特に断りがない場合は、本ブログの筆者によるコンテンツは クリエイティブ・コモンズ 表示 - 継承 4.0 国際 ライセンスの下に提供されています。

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/ に置かれた PPD を インストール時に %set_ppd_links でリンクし、削除時に %remove_ppd_links で削除すればいいだけです。

%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/ に置くと決めてますので、specs には %install_opt_files を書くことになります。したがってこの if 文は常に実行されるということになります。

一段下がった 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 対応とそうでない奴を両方作りたいひととか、そういう用途には使えるかもしれませんね。ええ。

しっかしこの一連のエントリ、何人が読んでるんだろ?