(2007/04/24)
LinuxSampler の CVS 最新版をそのままビルドして Universal Binary ができるようにしてみた。当然 CVS 最新版は開発途中の版なので、不安定であることは承知しておくこと。
ディレクトリ構成を決めておく。ここでは、後述の libsndfile のビルドも含めて1つのディレクトリ(以下 $PROJDIR とする。例えば PROJDIR=$HOME/Development/LinuxSampler)の中で全部済ませることにする。
LinuxSampler の公式サイトから libgig と linuxsampler の最新版をとってくる。
libsndfile もソースをとってきて、同じディレクトリ中で展開しておく。
libgig, linuxsampler の CVS 版は、最初に make -f Makefile.cvs として configure, Makefile.in などを作る。ここが最初の難関。
Apple の "Porting UNIX/Linux Applications to Mac OS X" の Dynamic Libraries and Plug-ins の章に書かれている通り、 Mac OS X では GNU libtool, libtoolize はそれぞれ /usr/bin/glibtool, /usr/bin/glibtoolize としてインストールされている。このままでは、次のようにつまづいてしまう。
ちょっと強引だが、/usr/bin/glibtoolize へのシンボリックリンクを /usr/local/bin/libtoolize として作成し、パスに /usr/local/bin を入れる。これで一応 make -f Makefile.cvs は通るようになる。
こういう変更は他の部分に影響を及ぼす可能性があるので要注意である。ただ、libtool は NeXTSTEP 由来の同名のツールが /usr/bin にあるので厄介だが、libtoolize は名前はぶつからないので一応大丈夫みたい。
ところが、これで作成した configure を走らせると、途中で止まってしまう。
これは Mac OS 10.4 に pkg-config が無いため。最新版をダウンロードして、./configure && make && sudo make install でインストールする。/usr/local 以下にインストールされる。
さらに、このままでは Makefile.cvs から呼び出される aclocal が /usr/local/share/aclocal/pkg.m4 を認識してくれない。そこで、libgig のトップレベルディレクトリにある aclocal を /usr/local/bin にコピーし、実行許可をつけておく。
ちなみに、このファイルの中身は次の2行。同じことで悩んだ人が他にもいたのだろうか。
ここまで準備してしまえば、あとは libgig, linuxsampler それぞれのディレクトリで make -f Makefile.cvs とすれば、configure および関連ファイルが作成される。
libsndfile, libgig はライブラリで、linuxsampler はこれらにリンクする実行ファイルになる。UNIX の流儀なら、ライブラリは /usr/local/lib あたりにインストールしてもらうことになるのだろうが、Mac OS X の場合はそうはいかない。ユーザーは当然「linuxsampler のバイナリをダウンロードしてきて適当な位置にコピーして、それをダブルクリックすれば linuxsampler が走る」ことを期待している。まあ、JackOSX のインストールぐらいはやってもらってもよいだろうが、それ以上のことをユーザーに要求する訳にはいかない。というわけで、今回はこれらのライブラリはスタティックリンクとする。
また、Universal Binary を作成する時、i386 版と ppc 版は別々に configure && make することになる。エンディアンやアーキテクチャ依存の最適化が重要なプログラムではこれは必須である。最後に linuxsampler の実行ファイルができてから、lipo コマンドで結合して Universal Binary を作る。
このため、i386 版と ppc 版のビルドは $PROJDIR の中にそれぞれ独立したディレクトリを切って、その中で行うことにする。また、libsndfile, libgig はいったん make install した方がスムーズだが、これも $PROJDIR の中に一時的なインストールディレクトリを作って、そこにインストールする。こうすれば、make install に sudo がいちいち必要ないので好都合である。
具体的には、次のようなディレクトリ構成にする。
$PROJDIR/
libsndfile-1.0.17/
libgig/
linuxsampler/
build/
ppc/
libsndfile-1.0.17/
libgig/
linuxsampler/
local/ # 一時インストール用
i386/
libsndfile-1.0.17/
libgig/
linuxsampler/
local/ # 一時インストール用
UB/
linuxsampler # 実行ファイル(ディレクトリではない)
$PROJDIR/build/i386/libgig は $PROJDIR/libgig を(autoconf したあと)ディレクトリツリーごとコピーしたもの。他のディレクトリも同様。下の例ではソースファイルを全部 cp -r でコピーしているが、本当はシンボリックリンクにするべきである。
ADC の TN2137: Building Universal Binaries from "configure"-based Open Source Projects に "configure" ベースのプロジェクトから Universal Binary を作る方法が記述されている。「単純な」プロジェクトなら、CFLAGS に "-arch i386 -arch ppc" を同時に指定することで一気に UB を作れる場合もあるのだが、上にも書いた通り今回は i386 のバイナリと ppc のバイナリを別々に作成する。
上記 Technical Note では、intel マシンと ppc マシンそれぞれでビルドして、あとで結合するように書いてある。しかし、ppc マシンだけしかなくても、次のようにすれば2種類のバイナリを作ることはできるようだ。
ppc バイナリ(全部1行で):
i386 バイナリ(全部1行で):
--host=.... を(configure を走らせているマシンと)違うものに指定すると、クロスコンパイルと見なされ、configure 中に作成したプログラムの実行がスキップされる。また、コンパイラフラグの -msse, -msse2 は、CarbonCore.h をインクルードした時に起きるエラーを回避するためのもの。
なお、PPC Mac ではクロスコンパイルのために MacOSX10.4u.sdk が必要。これは ADC のサイトからダウンロードすることができる。Intel Mac では、システムのライブラリがすでに UB 化されているため -isysroot ... は必要ないはず(Intel Mac を持っていないので確かめられないが)。
それではまず PPC 版をビルドしてみる。
configure の時に、インストール場所として $PROJDIR/build/ppc/local を --prefix オプションで指定しておく。
$PROJDIR/build/ppc/local/lib に libsndfile.a, pkgconfig/sndfile.pc ができていれば成功。
configure に先と同じ --prefix オプションに加えて、環境変数として PKG_CONFIG_PATH=$PROJDIR/build/ppc/local/lib/pkgconfig を指定する。こうしないと、さきほどインストールした libsndfile.a を見つけられず、失敗する。
$PROJDIR/build/ppc/local/lib に libgig.a, pkgconfig/gig.pc ができていれば成功。
configure に先と同じ --prefix, PKG_CONFIG_PATH=... 指定に加えて、次の指定が必要。
HAVE_UNIX98=1 を指定する。これは、Mutex::Mutex() 中にある pthread_mutexattr_settype() コールを生かすためのもので、指定しないとデッドロックが起きてしまう。ただしこれは 10.4 での話で、10.3 では実装方法が違うみたい。CFLAGS, CXXFLAGS に -I$PROJDIR/build/ppc/local/include が必要。これがないと、giglib のヘッダファイルを見つけてくれない。configure が生成した Makefile を見ると GIG_CFLAGS = -I/.../local/include という1行が確かにあるのだが、これがどこにも使われていない。ちょっと変。
$PROJDIR/build/ppc/local/bin/linuxsampler ができていれば成功。
ppc 版の時と同様。CFLAGS/CXXFLAGS に -arch i386 -msse -msse2 を指定することと、configure に --host=... を指定するのがポイント。
$PROJDIR/build/i386/local/lib に libsndfile.a, pkgconfig/sndfile.pc ができていれば成功。
$PROJDIR/build/i386/local/lib に libgig.a, pkgconfig/gig.pc ができていれば成功。
ppc マシン上で i386 版をビルドするときは、--enable-signed-triang-algo=intmathabs --enable-unsigned-triang-algo=intmathabs というオプションが必要。linuxsampler の configure では、LFO の処理アルゴリズムを決めるためにベンチマークをやるのだが、ppc マシン上では i386 の実行ファイルを走らせることはできないので、手動でアルゴリズムを決めてやる。ただし、2007/4/11 現在の CVS に含まれる configure.in はこの点の処理が完全でなく、これらのオプションを与えても config.h に正しい定義が書き込まれない。従って、configure が正常に終了した後、config.h を開いて、CONFIG_SIGNED_TRIANG_ALGO と CONFIG_UNSIGNED_TRIANG_ALGO を 5 に #define するよう手で書き換える。
$PROJDIR/build/i386/local/bin/linuxsampler ができていれば成功。
2つの linuxsampler バイナリを lipo で結合する。
Universal Binary になっていることは file コマンドで確かめることができる。