空の RPM パッケージで依存関係の問題を解決する (2)

昨日は「新設された -devel パッケージへの依存に困ったときは -devel を捏造すればいい」と力説したわけで、今日は、このために必要な空の RPM パッケージの作り方をメモしておこう。
作り方といっても大したことではなく、こんな感じの SPEC ファイルを書けばいい:

Name:           perl-devel
Summary:        This is a dummy package just for resolving dependency problems.
Version:        5.8.8
Release:        dummy.0
Group:          Development/Languages
License:        public domain
Packager:       masugata_k <masugata_k@example.com>
Source0:        %{name}-%{version}.tar.gz
Source1:        README
BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)

%description
No files but README are installed by this package because all necessary
files are installed by "perl" package.

%prep
%setup

%build

%install

%clean
[ "${RPM_BUILD_ROOT}" != "/" ] && rm -rf ${RPM_BUILD_ROOT}

%files
%defattr(-,root,root)
%doc $RPM_SOURCE_DIR/README

昨日は「popt-devel がなくて困るんだよ」的な話をしたが、今日は偶々 perl-devel がなくて困った((subversionrpmbuild --rebuild していた。))ので perl-devel を題材に取ることにした。
続いて、SPEC ファイル中で Source0, Source1 としている perl-devel-5.8.8.tar.gz*1 と README を用意する。perl-devel-5.8.8.tar.gz は、perl-devel-5.8.8 という空のディレクトリが入っているだけの TAR ボールだ。README の方には何でも好きなことを書けばよい。インストールされた暁には /usr/share/doc/perl-devel-5.8.8/README になるので、このニセモノパッケージを作るに至った経緯などを書いておくといいと思う。ちなみに、TAR ボールと README を分けたのは、README を簡単に編集できるようにするためだ。
たったこれだけ。あとは、rpmbuild -ba --clean SPEC/perl-devel.spec するだけで、perl-devel-5.8.8-dummy.0.i386.rpm がめでたく出来上がる。

CentOS 本来のパッケージに Provides を追加するのとどちらが簡単か?

昨日は Provides を書いて再ビルドする方がいい気がしていたが、やはり、空の -devel の方がいいと思う。perl の再ビルドなんてやりたくない。BuildRequires なのを入れまくるのも避けたいところだ。

*1:perl-5.8.8.tar.gz ではない点に注意。

空の RPM パッケージで依存関係の問題を解決する (1)

CentOS を使っていてちょっと困るのは、パッケージの少なさと古さだ。安定性が売りなのだから仕方がないが、欲しいパッケージやバージョンが Fedora にあると、「安定性」とやらを多少犠牲にしても手を出さずにはいられない*1
もちろん、取ってくるのは SRPM で、rpmbuild --rebuild してインストールする。別のディストロのバイナリ RPM をブチ込むなんていう恐ろしいことはゴメンだ*2。大概、rpmbuild --rebuild は問題なく完了する。別に何をしたわけでもないのにターミナルに流れる大量のメッセージが“ビルドしたぜ!!”という意味不明な満足感と達成感を与えてくれる一種の魔境で、疲れたときの気分転換などによい。
だがしかし、ここに1つの罠がある。BuildRequires されているパッケージが CentOS には存在しないことがあるのだ。
パッケージがない、というのにも2つのパターンがある。1つは、当該のパッケージが“本当に”ない場合だ。これは大した問題ではない。そのパッケージの SRPMFedora から取ってきて rpmbuild --rebuild すればいいだけの話だ。そこでもまた BuildRequires が見つからないかもしれないが、再帰すればいい。
困るのは、「ちょっとパッケージ構成見直しちゃったよ」系の“見つからない”だ。ありがちなのは、ライブラリの -devel を別パッケージに分けたよ、というやつ。たとえば、CentOS 5 では popt という1つのパッケージなのが Fedora 9 では poptpopt-devel に分けられている。この場合、「Fedora 9 の SRPMpopt-develBuildRequires するが、そんなパッケージは CentOS 5 には存在しない」という事態に陥る。
このパターンだと、Fedora 9 から popt-devel を持ってくるわけにはいかない。この popt-devel は、CentOS 5 の popt とは競合する。popt の方も Fedora 9 のものに置き換えるという手もあるが、別に popt の最新版が使いたいわけではないのだから、“安定性”が期待できる CentOS のパッケージを使い続けたい。
「ビルドしようとしている SRPM の SPEC ファイルを書き直す」というのは、正攻法ではあるが面倒くさい。特に、popt-devel のように多くのパッケージから BuildRequires されているパッケージの場合、大量の依存元に個別対処していくのは精神衛生上よろしくない。
では、どうすればいいのか。答えは簡単で、popt-devel という名前の空の RPM を作ってインストールすればいい。必要なファイルは全部インストール済みで、足りないのは popt-devel という名前だけなのだから。「うちの poptpopt-develProvides してるんですよ、実は。」という表明だと捉えることもできる((「じゃあ、CentOS 5 の poptSRPM を取ってきて、SPEC に Provides popt-devel って書いて rpmbuild -bb すればいいじゃん」と思われるかもしれない。確かにそうですね。今これを書いていて気付きました……。))。

というわけで、漸く本題で「空の RPM パッケージの作り方」なわけですが、今日はもう疲れたので明日にします。ごめんなさい。

*1:後で悔しい思いをしないよう、EPEL と RPMforge はチェックしておく。

*2:どうせ、ライブラリバージョンへの依存関係とかで入れられないと思うが。

『Google C++ Style Guide』だってさ

はてなブックマークの「最近の人気エントリー」に『Google C++スタイルガイド日本語訳』というのがあったので、『Google C++ Style Guide』の存在を知ることができた。
日頃は「Google の開発者っていいよなー」と羨ましがることしきりだが、今日は初めて「Google 勤めじゃなくて本当によかったよ」と思えました。

冠詞は形容詞みたいなもの

【コラム】エンジニアのための英語術 (53) 重要なのは受け手を混乱させないこと - 定冠詞"the"再考 | エンタープライズ | マイコミジャーナル』より:


ネイティブスピーカ向けの文法の解説書には「articlesはnouns(名詞)を形容するadjective(形容詞)のうちのひとつ」という位置付けになっているものもあります。私が日本で勉強してきた英語は、冠詞は冠詞であって形容詞ではなかったので、当初、この分類には違和感を持ちましたが、たしかにarticlesの用法を考慮すると、形容詞のひとつ、というのはうなずけます。
すごく納得した。文法的にどうのこうのっていうのもあるんだけど、意味としてどうなのかが大事なんだろう。日頃、「こういうときは付けるのか?」じゃなくて「付けるとどういう感じになるんだ?」という感覚で考えるようにしている。
冠詞の有無は、シンタックスじゃなくてセマンティクスの領域なんだろう。“正しくない使い方”は、「そこに付けるとこういう意味にあるけど、そんな状況ってあんまりないよね。」という意味で正しくなくわけだ。
で、これを「コンパイル時エラーじゃなくて実行時エラー*1なのか」と捉えるのは職業病か?

*1:“エラー”というほどじゃなくて“奇妙な振る舞い”ぐらいだけど、まあいい。

MacPorts と Universal Binary

Universal Binary をビルドしたい場合、ライブラリも Universal Binary でないといけない、……らしい*1。なので、MacPorts でインストールするライブラリも Universal Binary のやつにしたい。
まず分かったのは、「univeral」バリアントを入れればいいということ。で、sudo port install のたびに +universal を付けるのは面倒なので /opt/local/etc/macports/variants.conf にこう書いておく、というのも分かった:

+universal

ところが、これだけだと、"-arch ppc -arch i386" な*2 Universal Binary になってしまう。どうせなら*3、"-arch ppc -arch i386 -arch ppc64 -arch x86_64" な Universal Binary にしたい。
『MacPorts Guide』には、macports.conf の「universal_archs」で「ppc i386 ppc64 x86_64」を指定しなさい、みたく書いてあるが、やってみたところ効果なし。どうやら割と最近入った機能らしく1.6.0 にはまだ入っていないっぽい
途方に暮れて*4grep -FR -- '-arch' /opt/local」としたところ、/opt/local/share/macports/Tcl/port1.0/portconfigure.tcl なるものを発見。で、恐る恐る修正:

--- portconfigure.tcl.bak
+++ portconfigure.tcl
@@ -87,10 +87,10 @@
 }
 options configure.universal_args        configure.universal_cflags configure.universal_cppflags configure.universal_cxxflags configure.universal_ldflags configure.universal_env
 default configure.universal_args        --disable-dependency-tracking
-default configure.universal_cflags      {"-isysroot $sysroot -arch i386 -arch ppc"}
+default configure.universal_cflags      {"-isysroot $sysroot -arch i386 -arch ppc -arch x86_64 -arch ppc64"}
 default configure.universal_cppflags    {}
-default configure.universal_cxxflags    {"-isysroot $sysroot -arch i386 -arch ppc"}
-default configure.universal_ldflags     {"-arch i386 -arch ppc"}
+default configure.universal_cxxflags    {"-isysroot $sysroot -arch i386 -arch ppc -arch x86_64 -arch ppc64"}
+default configure.universal_ldflags     {"-arch i386 -arch ppc -arch x86_64 -arch ppc64"}

 # Select a distinct compiler (C, C preprocessor, C++)
 options configure.ccache configure.distcc configure.cc configure.cxx configure.cpp configure.objc configure.f77 configure.f90 configure.fc configure.javac configure.compiler

こんなんでいいのかなぁ、と自分でも疑問に思いつつ、どうやら問題ない様子。

*1:Mac には日が浅いので自信がない。

*2:なんて呼ぶのがいいんだろう?

*3:貧乏性か?

*4:ムシャクシャしてやった。今は反省している

ファイアウォール内で MacPorts を使う

MacPorts は非常に便利で嬉しい存在なんだが、ポーツをリポジトリに同期させるのに rsync を使うため、ファイアウォールに閉じこめられている……、いやいや匿って頂いている身としてはちょっと使いづらい。いろいろと工夫したら何とか使えるようになったので、備忘のためにメモしておく。

インストール

インストールは、.dmg で .pkg な普通のインストールで大丈夫だ。インストーラport selfupdate しようとしてくれてエラーになって終わるが、環境変数の設定を自分でやらないといけないこと以外には、別に問題はないようだ。

ポーツリポジトリSubversion で持ってくる

rsync が使えないので、port selfupdateport sync ができない。そこで、/opt/local/etc/macports/sources.conf をこんな風に設定する:

#rsync://rsync.macports.org/release/ports/
file:///opt/dports/

これで、rsync など止めて /opt/dports を見に行くようになる。
問題は /opt/dports をどうやって取ってくるかだが、これは http://svn.macosforge.org/repository/macports/trunk/dports/ から Subversion でチェックアウトできる。
trunk なんかから持って来ちゃって大丈夫かよ、とも思ったが、こんなことが書いてあるので別によさそう:


Though a distinction is made between pre-release and release versions of MacPorts base, the ports collection supports no such distinction or versioning. The selfupdate command installs the latest port revisions from subversion (at a slight delay), and updates MacPorts base to the latest released version.

sudo環境変数 http_proxy を引き継がせる

そのままだと、sudo port install としたときに HTTP プロクシを見つけられなくてエラーになってしまう。これは、sudo環境変数 http_proxy をクリアしてしまうためだ。visudo で以下の設定を加え、http_proxy が保存されるようにしておく:

Defaults        env_keep += "http_proxy"

ポーツリポジトリの更新

sudo port sync((sudo port selfupdate はうまく動作しない。多分、ポーツリポジトリしかないからだろう。)) は /opt/dports に同期するだけなので、/opt/dports 自体を svn update しないといけないことに注意。