人類が改善した GC の恩恵を受けるために Ruby 2.2.1 を導入してインストールする時の注意点とは……!
最初に言っておきますがインストール手順記事であって GC 要素はありません(がっくり)。
ロケ地:CentOS7 64bit
とりあえずいつものようにインストールしてみる
libyaml は各自インストールしておいてください。
libffi は、libffi.x86_64 は入ってるかもしれませんが、-devel パッケージは入ってないかもしれぬので、以下のように。
( 32bit の人は .i686 パッケージかな )
[root@localhost ~]# yum install libffi.x86_64 libffi-devel.x86_64
[root@localhost ~]# cd /usr/local/src [root@localhost src]# wget http://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.1.tar.gz [root@localhost src]# tar -zxvf ruby-2.2.1.tar.gz [root@localhost src]# cd ruby-2.2.1 [root@localhost ruby-2.2.1]# ./configure --prefix=/usr/local [root@localhost ruby-2.2.1]# make
libffi 周りでエラー出る。
LANG=C の場合
make[2]: Entering directory `/usr/local/src/ruby-2.2.1/ext/fiddle' linking shared-object fiddle.so /usr/bin/ld: ./libffi-3.2.1/.libs/libffi.a(raw_api.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC ./libffi-3.2.1/.libs/libffi.a: could not read symbols: Bad value collect2: error: ld returned 1 exit status make[2]: *** [../../.ext/x86_64-linux/fiddle.so] Error 1 make[2]: Leaving directory `/usr/local/src/ruby-2.2.1/ext/fiddle' make[1]: *** [ext/fiddle/all] Error 2 make[1]: Leaving directory `/usr/local/src/ruby-2.2.1' make: *** [build-ext] Error 2
LANG=ja_JP.UTF-8 の場合
make[2]: ディレクトリ `/usr/local/src/ruby-2.2.1/ext/fiddle' に入ります linking shared-object fiddle.so /usr/bin/ld: ./libffi-3.2.1/.libs/libffi.a(raw_api.o): 再配置 R_X86_64_32S (`.rodata' に対する) は共有オブジェクト作成時には使用できません。-fPIC を付けて再コンパイルしてください。 ./libffi-3.2.1/.libs/libffi.a: シンボルを読み込めませんでした: 不正な値です collect2: エラー: ld はステータス 1 で終了しました make[2]: *** [../../.ext/x86_64-linux/fiddle.so] エラー 1 make[2]: ディレクトリ `/usr/local/src/ruby-2.2.1/ext/fiddle' から出ます make[1]: *** [ext/fiddle/all] エラー 2 make[1]: ディレクトリ `/usr/local/src/ruby-2.2.1' から出ます make: *** [build-ext] エラー 2
何もせずこのまま逃げ切りたい場合
enable-shared オプションを利用することで回避できる、というお告げがあります。
Ruby 2.2.0 Released - Ruby-dev - Ruby-Forum
[root@localhost ruby-2.2.1]# ./configure --prefix=/usr/local --enable-shared [root@localhost ruby-2.2.1]# make [root@localhost ruby-2.2.1]# make install [root@localhost ruby-2.2.1]# ruby -v ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-linux] [root@localhost ruby-2.2.1]# which ruby /usr/local/bin/ruby
やったぜ。
本題: ./configure そのまま通らないの小生きもちわるくてやだ!なんとかしたい!
以下のように、無事バグ認定されたようです。という訳で diff とって patch 作って修正してみましょう!ヘーキヘーキ、簡単だから!
Bug #10960: libffiのビルドの不具合? - Ruby trunk - Ruby Issue Tracking System
- 比較元:修正された時点 ( rev:49957 ) の ext/fiddle/extconf.rb
- 比較先:解凍した ruby-2.2.1/ext/fiddle/extconf.rb
patch つくる
[root@localhost src]# tar -zxvf ruby-2.2.1.tar.gz [root@localhost src]# vi fiddle_extconf.rb -> 上記の URL から rev 49957 の ext/fiddle/extconf.rb をコピペなりでもってきてファイルを保存する [root@localhost src]# diff -u /usr/local/src/ruby-2.2.1/ext/fiddle/extconf.rb /usr/local/src/fiddle_extconf.rb > fiddle_extconf.patch
patch 適用して導入してみる
[root@localhost src]# patch -u /usr/local/src/ruby-2.2.1/ext/fiddle/extconf.rb < /usr/local/src/fiddle_extconf.patch patching file /usr/local/src/ruby-2.2.1/ext/fiddle/extconf.rb [root@localhost src]# cd ruby-2.2.1 [root@localhost ruby-2.2.1]# ./configure --prefix=/usr/local [root@localhost ruby-2.2.1]# make [root@localhost ruby-2.2.1]# make install [root@localhost ruby-2.2.1]# ruby -v ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-linux] [root@localhost ruby-2.2.1]# which ruby /usr/local/bin/ruby
や、やったー!
まとめ
-
- enable-shared オプションつけるか、patch 作って適用するか、来るべき ruby.2.2.2 か 2.2.1 のアップデートを待つと解決できます。
おまけ
うちの環境で作った diff おいとくんで、こいつをパッチファイルとして使ってもなんとかなると思います、使うときは自己責任でね?
--- /usr/local/src/ruby-2.2.1/ext/fiddle/extconf.rb 2015-04-06 18:49:49.000000000 +0900 +++ /usr/local/src/fiddle_extconf.rb 2015-04-06 18:51:33.000000000 +0900 @@ -2,7 +2,8 @@ # :stopdoc: -if ! enable_config('bundled-libffi', false) +bundle = enable_config('bundled-libffi') +if ! bundle dir_config 'libffi' pkg_config("libffi") and @@ -16,7 +17,8 @@ end and (have_library('ffi') || have_library('libffi')) end or begin - ver = Dir.glob("#{$srcdir}/libffi-*/") + ver = bundle != false && + Dir.glob("#{$srcdir}/libffi-*/") .map {|n| File.basename(n)} .max_by {|n| n.scan(/\d+/).map(&:to_i)} unless ver @@ -36,7 +38,7 @@ end libffi.include = "#{libffi.builddir}/include" libffi.lib = "#{libffi.builddir}/.libs" - libffi.a = "#{libffi.lib}/libffi.#{$LIBEXT}" + libffi.a = "#{libffi.lib}/libffi_convenience.#{$LIBEXT}" nowarn = CONFIG.merge("warnflags"=>"") libffi.cflags = RbConfig.expand("$(CFLAGS)", nowarn) ver = ver[/libffi-(.*)/, 1] @@ -46,6 +48,9 @@ libffi.ldflags = RbConfig.expand("$(LDFLAGS) #{libpathflag([relative_from($topdir, "..")])} #{$LIBRUBYARG}") libffi.arch = RbConfig::CONFIG['host'] if $mswin + unless find_executable(as = /x64/ =~ libffi.arch ? "ml64" : "ml") + raise "missing #{as} command." + end $defs << "-DFFI_BUILDING" libffi_config = "#{relative_from($srcdir, '..')}/win32/libffi-config.rb" config = CONFIG.merge("top_srcdir" => $top_srcdir) @@ -64,9 +69,10 @@ ld = RbConfig::CONFIG['LD'] args.concat %W[ --srcdir=#{libffi.srcdir} - --disable-shared --host=#{libffi.arch} + --host=#{libffi.arch} --enable-builddir=#{RUBY_PLATFORM} ] + args << ($enable_shared || !$static ? '--enable-shared' : '--enable-static') args << libffi.opt if libffi.opt args.concat %W[ CC=#{cc} CFLAGS=#{libffi.cflags} @@ -77,8 +83,14 @@ FileUtils.rm_f("#{libffi.include}/ffitarget.h") Logging::open do Logging.message("%p in %p\n", args, opts) - system(*args, **opts) or + unless system(*args, **opts) + begin + IO.copy_stream(libffi.dir + "/config.log", Logging.instance_variable_get(:@logfile)) + rescue SystemCallError => e + Logfile.message("%s\n", e.message) + end raise "failed to configure libffi. Please install libffi." + end end if $mswin && File.file?("#{libffi.include}/ffitarget.h") FileUtils.rm_f("#{libffi.include}/ffitarget.h")