rabbit-shockers で追求されたので記憶をたどりながら調べてみた。
MacPorts の +universal
TN2137 にあるように、CFLAGS と LDFLAGS に作成するアーキテクチャを -arch オプションで列挙していけばよい。これによって、それぞれのアーキテクチャをビルドして、lipo でファットバイナリ化するという手続きをコンパイラがやってくれる。
MacPorts では、configure && make && make install スタイルのソフトウェアには、あらかじめ universal バリアントが用意されている。universal バリアントを追加したときは、configure オプションが設定される。くわしくは、portconfigure.tcl やportmain.tcl を参照のこと。
universal ruby はどこで失敗するか
簡単に実験。ターゲットは素の ruby-1.8.6-p111
% CFLAGS="-arch ppc -arch i386" LDFLAGS="-arch ppc -arch i386" \
./configure --enable-shared && make
:
:
making ruby
gcc -arch ppc -arch i386 -fno-common -pipe -fno-common -DRUBY_EXPORT -L.
-arch ppc -arch i386 main.o -lruby -ldl -lobjc -o ruby
ld: warning in ./libruby.dylib, file is not of required architecture
Undefined symbols for architecture ppc:
"_ruby_options", referenced from:
_main in main.o
"_ruby_run", referenced from:
_main in main.o
"_ruby_init", referenced from:
_main in main.o
"_ruby_init_stack", referenced from:
_main in main.o
ld: symbol(s) not found for architecture ppc
collect2: ld returned 1 exit status
lipo: can't open input file: /var/folders/5T/5TkNBDNhGRyDkhxmhrRcOU+++TM/-T
mp-//cca2jxgL.out (No such file or directory)
make[1]: *** [ruby] Error 1
make: *** [all] Error 2
となりました。libruby に ppc アーキテクチャのコードがないために ruby (コマンド)のビルドに失敗する。
原因は libruby.dylib のビルドに利用されるコンパイラフラグの LDSHARED に適切な値が設定されないため。
configure.in
1055 darwin*) : ${LDSHARED='cc -dynamic -bundle -undefined suppre ss -flat_namespace'}
ちなみに --enable-shared しなければ、libruby.a および ruby はユニバーサルバイナリで正常にビルドできる。
じゃ Apple はどうしているのか
原因は LDSHARED にリンカオプションを渡せないことはわかった。じゃ、MacOSX に含まれる ruby ではどうしているのって話になるよな。
簡単なこと、configure を変更しているのだ patch-configure。
ここでは、RC_CFLAGS という値を追加して LDSHARED および LIBRUBY_LDSHARED で利用するようになっている。この RC_CFLAGS が -arch オプションを含んでいる。RC_CFLAGS はMakefile(rubyソースの上階層のほう)の
22 include $(MAKEFILEPATH)/CoreOS/ReleaseControl/GNUSource.make
で、/Developer/Makefiles/CoreOS/ReleaseControl/Common.make
48 RC_ARCHS = $(shell for i in `file /usr/lib/libSystem.B.dylib | grep 'share
d library ' | sed 's|.*shared library ||'`; do $(CC) -arch $$i -E -x c /dev/
null > /dev/null 2>&1 && echo $$i; done)
から来ているっぽいのだけど、RC_ARCHS -> RC_CFLAGS の経路が見つけられず。
(2008/1/30 追記:Tiger 10.4.11 についてもざっと確認。同じように RC_CFLAGS を追加している)
けつろん
LDSHARED をどうにかすれば、ユニバーサルバイナリの ruby を configure のオプションだけで作ることができるようになるはず。じゃ、どう解決するかがこれから考えるところ。
darwin のとき、LDFLAGS を追加するようにするだけでよいかなあ。
最近のコメント