2001/05/05    ROOT-3.01.00-CVS010503 on MacOS X Release

CERNLIB の次は ROOT。現在の CVS 版には MacOS X target が含まれる。正式サポートまで後一歩。ROOT 開発元の Fons Rademakers 氏より、テストの依頼が来ているので今回は CVS 版を使う。ただし、これも含めて今までのものは実は共有ライブラリーになっていなかったので、これにも挑戦する。これがことのほか手こずり非常にに疲れた。
 

[0] 事の顛末

何故疲れたかというと、私が MacOS X の共有ライブラリーというものを全く誤解していたからである。LinuxPPC などのセンスだと、共有ライブラリーは一塊になってロードされる。ところが、MacOS X の dylib はあたかも Archive のようにそこに含まれるモジュールごとにリンクされしかも実行時における実際のローディングはぎりぎり必要になるまで後回しになるようだ。これがディフォールトの振る舞い。従って、dylib に含まれる global や static object が実行時に直ちに存在することあるいは初期化されていることを仮定していると大変痛い目に遭う。LinuxPPC に近い振る舞いをして欲しければリンクのオプションとして "-Xlinker -bind_at_load" を与えてやらねばならない。まずこのことに気づくまでに大変な思いをした。それと、dylib を複数リンクする場合にはこれらに同じ名前のシンボルが含まれてはならない仕様だが、普通に共有ライブラリーを

    c++ -dynamiclib -undefined suppress -install_name libFoo.1.dylib -o libFoo.1.0.dylib hoge1.o hoge2.o .....

のように作ると、libstdc++.a がリンクされ大量の多重定義シンボルがでてしまう。そこで通常は

    c++ -dynamiclib -undefined suppress -nodefaultlibs -install_name libFoo.1.dylib -o libFoo.1.0.dylib hoge1.o hoge2.o ....

とするわけだが、これだと libcc_dynamic.a がリンクされるので場合によって ___builtin_new とか ___builtin_delete とかが多重定義になってしまう。この場合は、

    c++ -dynamiclib -undefined suppress -nostdlib -install_name libFoo.1.dylib -o libFoo.1.0.dylib hoge1.o hoge2.o ....

とするわけだが、こうすると、場合によって

ld: base/src/TApplication.o has external relocation entries in non-writable section (__TEXT,__text) for symbols:
restFP
saveFP
/usr/bin/libtool: internal link edit command failed
などというエラーが出てしまう。これを避ける姑息な手段として、
$ ar -x /usr/lib/libcc_dynamic.a lib/macosx-fpsave.o
などとして、浮動小数点の save、restore を行うアセンブラ関数 restFP、saveFP を含むモジュールを抜き出してこれだけリンクしてやる。

似たような問題ではまったのは、iomanip。共有ライブラリー中で iomanip を使うと、-bind_at_load が指定してあっても、

___ls__H1Zi_R7ostreamRCt6smanip1ZX01_RB0
が、リンクされずに undefined reference になってしまう。これは、iomanip.o が内部で使う private static local のようであるが、これには大変困らされた(リンカーの仕様と言うよりバグだと思われる)。当面は、共有ライブラリーの中で iomanip を使わないようにすることで逃げているが、これは大変情けない事態である。

もう一つの注意点は、インライン関数では local static 変数を使わないこと。さもないとこれは common block に回され、その結果、Mach の仕様に従って、dylib の生成ができなくなる。

これらが、ROOT との共有ライブラリー化に挑んで悶絶した結果得たノウハウである。さらに詳細が知りたければ ROOT 開発者に送ったメモ(英語)を参照のこと。
 

[1] すべてが分かった後でのコンパイルの仕方

コンパイル環境は、

        MacOS X Release 10.0.02 1.3.2 w/o SysV semaphore patch
        gcc-with-g77-2.95.2-1a
        dlcompat-20010123-1a
        freetype-1.3.1-1a
        XFree86 4.0.3 + Aqua0.5

今回は、SysV Semaphore support なしの標準カーネルを使っているので、TMapFile を含む一部の機能が使えないが当面は必要ないので良いこととする。

$ export CVSROOT=:pserver:cvs@root.cern.ch:/user/cvs
$ cvs login
(Logging in to cvs@root.cern.ch)
CVS password: cvs

$ cvs -z3 checkout root
$ tar -zxvf ../orig/ttf_1.1.tar.gz
# mv ttf/fonts /usr/share/fonts/ttf
# pushd /cern/pro/lib
# ln -s libpythia6134.a libPythia.a
$ cd root
$ export ROOTSYS=`pwd`
$ export DYLD_LIBRARY_PATH=$ROOTSYS/lib
$ export PATH=$ROOTSYS/bin:$PATH
$ patch -p1 -s < ../orig/root_v3.01.00-cvs010503-macosx-0.2.patch
$ ./configure macosx
$ make

後はいつものように font path の設定。
 
According to the directory change for ttf fonts, edit
~/.rootrc as:
#Unix.*.Root.TTFontPath:     $(ROOTSYS)/ttf/fonts
Unix.*.Root.TTFontPath:     /usr/share/fonts/ttf
できたバイナリーは
root_v3.01.00-cvs010503-macosx.tar.gz
である。tutorials での benchmarks.C、tset での stress、bench を含むテストには一応全てパス。Tetris も動く。Aclock には問題ありだがこれは以前にもあった問題で、動的ローダブルモジュールに含まれる global constants の初期化の問題。回避の手段はあるがとりあえず先送り。

ところで、バイナリーのサイズは劇的に小さくなった。

$ ls -l bin/root.exe
-rwxr-xr-x  1 fujiik  staff  127816 May  5 16:21 root.exe
実際、otool -L で見てみると
$ otool -L bin/root.exe
        libCore.dylib (compatibility version 0.0.0, current version 0.0.0)
        libCint.dylib (compatibility version 0.0.0, current version 0.0.0)
        libHist.dylib (compatibility version 0.0.0, current version 0.0.0)
        libGraf.dylib (compatibility version 0.0.0, current version 0.0.0)
        libGraf3d.dylib (compatibility version 0.0.0, current version 0.0.0)
        libTree.dylib (compatibility version 0.0.0, current version 0.0.0)
        libMatrix.dylib (compatibility version 0.0.0, current version 0.0.0)
        libRint.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/local/lib/libdl.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 50.0.0)
と、確かに共有ライブラリーを使っている。
 

今までにコンパイルしたMacOS X Release 用の rpm については、 spec ファイル、パッチ、ソース RPM、バイナリー RPM それぞれについて SPECSSOURCESSRPMSRPMS に対応するものが置いてある。バイナリーのみの RPM および Tar Ball のみのパッケージの場合には、ソースおよびパッチは src に、また、Tar Ball は tgz にそれぞれ置いてある。新しいものは ~fujiik/macosx/10.0.X/ 以下にある点に注意(~fujiik/macosx 直下のものは Public Beta 用の古いもの)。  いつものように使う場合は自己責任で。


Back to Keisuke Fujii's MkLinux/LinuxPPC Life