Clangでruby-1.8.7をコンパイルしてみる (3) サヨウナラ、gcc
たぶん対応できた。っていうかMacPortsはもう使用可能にしちゃった。r95753
http://d.hatena.ne.jp/kimuraw/20120628/p1 http://d.hatena.ne.jp/kimuraw/20120712/p1 のつづき。bignumの問題は解決したけど、クラッシュするケースがあるというのが宿題でした。
作業記録
まずはクラッシュするケースを絞り込みしたところ、
- OK: ふつうにconfigure && makeしたもの
- OK: MacPortsでuniversalでないもの
- OK: MacPortsで+universalで"i386" (32bit)
- NG: MacPortsで+universalで"x86_64" (64bit)
ということになった。NGってのは
./lib/fileutils.rb:1428: [BUG] unexpected local variable ruby 1.8.7 (2012-02-08 patchlevel 358) [x86_64-darwin11]
になる件。
2番目と4番目で結果がちがうのは、ちょっとおかしい。こういうときはとりあえず、Makefileとかconfig.hを比較してみるのがとっかかり。
--- config.h-i686 2012-07-21 13:50:29.000000000 +0900 +++ config.h-universal-x86_64 2012-07-21 13:45:50.000000000 +0900 @@ -5,7 +5,6 @@ #define PACKAGE_STRING "" #define PACKAGE_BUGREPORT "" #define PACKAGE_URL "" -#define USE_BUILTIN_FRAME_ADDRESS 1 #define STDC_HEADERS 1 #define HAVE_SYS_TYPES_H 1 #define HAVE_SYS_STAT_H 1 @@ -214,7 +213,7 @@ #define RUBY_SITE_LIB2 "/opt/local/lib/ruby/site_ruby/1.8" #define RUBY_VENDOR_LIB "/opt/local/lib/ruby/vendor_ruby" #define RUBY_VENDOR_LIB2 "/opt/local/lib/ruby/vendor_ruby/1.8" -#define RUBY_PLATFORM "i686-darwin11" -#define RUBY_ARCHLIB "/opt/local/lib/ruby/1.8/i686-darwin11" -#define RUBY_SITE_ARCHLIB "/opt/local/lib/ruby/site_ruby/1.8/i686-darwin11" -#define RUBY_VENDOR_ARCHLIB "/opt/local/lib/ruby/vendor_ruby/1.8/i686-darwin11" +#define RUBY_PLATFORM "x86_64-darwin11" +#define RUBY_ARCHLIB "/opt/local/lib/ruby/1.8/x86_64-darwin11" +#define RUBY_SITE_ARCHLIB "/opt/local/lib/ruby/site_ruby/1.8/x86_64-darwin11" +#define RUBY_VENDOR_ARCHLIB "/opt/local/lib/ruby/vendor_ruby/1.8/x86_64-darwin11"
i686とx86_64がちがってるのは良いとして、USE_BUILTIN_FRAME_ADDRESSがuniversalのほうにない。
configureを見てみると、このあたりでUSE_BUILTIN_FRAME_ADDRESSを処理してるね。
2723 case $target_cpu in 2724 i?86) frame_address=yes;; 2725 *) frame_address=no;; 2726 esac 2727 # Check whether --enable-frame-address was given. 2728 if test "${enable_frame_address+set}" = set; then : 2729 enableval=$enable_frame_address; frame_address=$enableval 2730 fi 2731 2732 if test $frame_address = yes; then 2733 $as_echo "#define USE_BUILTIN_FRAME_ADDRESS 1" >>confdefs.h
うん。+universalのときac_cv_buildでx86_64渡してるのが原因ですね。--enable_frame_addressをconfigureに渡すようにしてもよかったんだけど、いつ渡すべきかをPortfile側で制御するのがけっこうめんどうだったので、configure側にパッチいれることに。
今度は別のシステムでSEGVが起きた。同様にconfig.hを比べてみる(これは32/64での比較)。
--- config.h-i386@u 2012-07-21 15:51:31.000000000 +0900 +++ config.h-x86_64@u 2012-07-21 15:51:00.000000000 +0900 @@ -25,14 +25,14 @@ #define HAVE_OFF_T 1 #define SIZEOF_INT 4 #define SIZEOF_SHORT 2 -#define SIZEOF_LONG 4 +#define SIZEOF_LONG 8 #define SIZEOF_LONG_LONG 8 : #define rb_uid_t uid_t @@ -198,9 +198,8 @@ #define FILE_COUNT _r #define FILE_READPTR _p #define NEED_IO_SEEK_BETWEEN_RW 1 -#define HUGE_ST_INO 1 #define HAVE__SC_CLK_TCK 1 -#define STACK_GROW_DIRECTION -1 +#define STACK_GROW_DIRECTION +1 #define _REENTRANT 1 :
STACK_GROW_DIRECTION +1はおかしいような。同じように$target_cpuかな?
9845 case "$target_cpu" in 9846 m68*|i?86|ia64|sparc*|alpha*) rb_cv_stack_grow_dir=-1;; 9847 hppa*) rb_cv_stack_grow_dir=+1;; 9848 esac 9849 { $as_echo "$as_me:${as_lineno-$LINENO}: checking stack growing direction" >&5 9850 $as_echo_n "checking stack growing direction... " >&6; } 9851 if test "${rb_cv_stack_grow_dir+set}" = set; then : 9852 $as_echo_n "(cached) " >&6 9853 else 9854 if test "$cross_compiling" = yes; then : 9855 rb_cv_stack_grow_dir=0 9856 else
ビンゴ!
他に$target_cpuが/i.86/的な処理をしているところがないか、ざっと見たところはなさそう。で、結果的にconfigureに以下のパッチを当てることに。
--- configure.orig 2012-06-29 22:18:24.000000000 +0900 +++ configure 2012-07-21 16:32:51.000000000 +0900 @@ -2722,6 +2722,7 @@ case $target_cpu in i?86) frame_address=yes;; + x86_64) frame_address=yes;; *) frame_address=no;; esac # Check whether --enable-frame-address was given. @@ -9843,7 +9844,7 @@ fi case "$target_cpu" in -m68*|i?86|ia64|sparc*|alpha*) rb_cv_stack_grow_dir=-1;; +m68*|i?86|x86_64|ia64|sparc*|alpha*) rb_cv_stack_grow_dir=-1;; hppa*) rb_cv_stack_grow_dir=+1;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking stack growing direction" >&5
今回の成果
という対処をすることで、clangでtest-allが(gccの時と同程度に)通るようになったよ!テストしたのは以下のパターン。
- Mac OS 10.8GM, Xcode 4.4GM
- Mac OS 10.7.4, Xcode 4.3.3
- Mac OS 10.7.4, Xcode 4.2.1
- Mac OS 10.6.8, Xcode 3.2.6 (これはgccを使うケース)
これで自分持ちのMacPortsはMountain Lionの準備ができた、はず。apple-gcc42とか、いつ使えなくなってもおかしくないしね。それによって「ビルドできない」とかのレポートに対応するのはイヤなのです。
長かった…ようやくRubyCocoaに取りかかれる。