最近の MacPorts 版 GCC はなんだか怪しく感じる。最近のバージョンでは /opt/local/lib/libstdc++.6.dylib
が依存関係に追加されるようになったらしい。チケットを見てみるとなんだかごたごたしているような雰囲気ではあるが英語なのでよくわからない。
Mac OS X 10.6 で g++-mp-4.7 -arch x86_64
なんてやるとコンパイルは通るものの、実行時に /usr/lib/libSystem.B.dylib
が /usr/lib/libstdc++.6.dylib
を呼び出すためクラッシュしてしまう。これを回避するために色々試行錯誤しているんだけどなかなかうまくいかない。
一番簡単なのは DYLD_LIBRARY_PATH=/opt/local/lib/gcc47
と指定すること。こうすればとりあえず /usr/lib/libstdc++.6.dylib
を読まなくなる。ただし実行ファイルから直接起動ができないので事前に DYLD_LIBRARY_PATH
を設定しなくてはいけない。
$ DYLD_LIBRARY_PATH=/opt/local/lib/gcc47 ./application
次に簡単なのはコンパイル時に /usr/lib/libstdc++.6.dylib
を最優先でリンクしてしまうこと。これは LDFLAGS=/usr/lib/libstdc++.6.dylib
のようにフルパスで直接指定すればいい(-L
とか lstdc++
とかは要らない)。こうすれば /opt/local/lib/libstdc++.6.dylib
が後から読み込まれて上書きしてくれる。otool
で見た時に一番上に出てるのがなんだか微妙だけど。
$ cmake -DCMAKE_EXE_LINKER_FLAGS="/usr/lib/libstdc++.6.dylib" ..
最後に DYLD_INSERT_LIBRARIES
を使う方法。これは LD_PRELOAD
の Mac 版かな?実行ファイルを起動するときに最初に読み込むライブラリを指定できる。ただし、普通にコンパイルした場合は DYLD_FORCE_FLAT_NAMESPACE=1
も一緒に指定する必要がある。これがちょっと面倒だけど、コンパイラフラグに -flat_namespace
をつけてコンパイルしてあげると設定しなくてもいい。DYLD_LIBRARY_PATH
だとディレクトリまるごとになってしまうけどこれは単体で指定できるので使い易い。
ビルド時
$ cmake -DCMAKE_EXE_LINKER_FLAGS="-Wl,-flat_namespace" ..
起動時
$ DYLD_INSERT_LIBRARIES=/usr/lib/libstdc++.6.dylib ./application
自分が使っているのが MacBook Air3,1 Snow Leopard なので CPU は x86_64 なのに uname
とかが i386
だったり困惑する。arch
とかの結果を永続的に書き換える方法ってないんだろうか?
自分でビルドした LLVM/CLANG-3.3 は /usr/lib/libstdc++.6.dylib
を使っているのでこの作業は必要ないけど、まだ対応していないものが多いので GCC を使うしかない。時間があるときに自分でビルドしよう。依存関係多くて面倒だけど。
man ld
を色々読んで見て、オプションに -weak-library
なんてのがあったので設定してみたらライブラリをフルパスで指定したときと同じように一番最初に読み込むようにリンクしてくれるようになった。
(最近 tcsh にしました)
setenv CC "/opt/local/bin/gcc-mp-4.7" setenv CXX "/opt/local/bin/g++-mp-4.7" setenv LDFLAGS "-flat_namespace -pie -Wl,-lazy_library,/usr/lib/libstdc++.6.dylib"
/usr/lib/libstdc++.6.dylib
は後から /opt/local/lib/libstdc++.6.dylib
で上書きされる。
/usr/local/src/rawtherapee/RELWITHDEBINFO/rawtherapee: /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0) (中略) /opt/local/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.17.0) /opt/local/lib/gcc47/libgomp.1.dylib (compatibility version 2.0.0, current version 2.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0) /opt/local/lib/gcc47/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
otool -l -v
で確認してみると -weak-library
で指定すると LC_LOAD_DYLIB
ではなく LC_LOAD_WEAK_DYLIB
として設定されている。
Load command 11 cmd LC_LOAD_WEAK_DYLIB cmdsize 56 name /usr/lib/libstdc++.6.dylib (offset 24) time stamp 2 Thu Jan 1 09:00:02 1970 current version 7.9.0 compatibility version 7.0.0 (中略) Load command 54 cmd LC_LOAD_DYLIB cmdsize 64 name /opt/local/lib/libstdc++.6.dylib (offset 24) time stamp 2 Thu Jan 1 09:00:02 1970 current version 7.17.0 compatibility version 7.0.0
ウィークリンクについてまだ勉強不足でどのような結果になるかはわからないけどとりあえず今回はここまで。