ruby2.2でkyotocabinet-rubyがインストールできない問題の対処法
通常の流れとしては、
ruby extconf.rb
make
make install
で良いはずなのだが、ruby2.2で試したところエラーが発生した。
具体的なエラーはこのようなもの。
$ wget http://fallabs.com/kyotocabinet/rubypkg/kyotocabinet-ruby-1.32.tar.gz $ tar xvzf kyotocabinet-ruby-1.32.tar.gz $ cd kyotocabinet-ruby-1.32 $ ruby extconf.rb *** extconf.rb failed *** Could not create Makefile due to some reason, probably lack of necessary libraries and/or headers. Check the mkmf.log file for more details. You may need configuration options. Provided configuration options: --with-opt-dir --without-opt-dir --with-opt-include --without-opt-include=${opt-dir}/include --with-opt-lib --without-opt-lib=${opt-dir}/lib --with-make-prog --without-make-prog --srcdir=. --curdir --ruby=/home/watanabe/.rbenv/versions/2.2.2/bin/$(RUBY_BASE_NAME) --with-kyotocabinet-dir --without-kyotocabinet-dir --with-kyotocabinet-include --without-kyotocabinet-include=${kyotocabinet-dir}/include --with-kyotocabinet-lib --without-kyotocabinet-lib=${kyotocabinet-dir}/lib extconf.rb:18:in `<main>': uninitialized constant Config (NameError)
exitconf.rbのConfigという定数というかクラスが未定義という事でエラーになっている。
Configが使われている場所を調べる。
$ grep Config extconf.rb Config::CONFIG["CPP"] = "g++ -E"
ruby2.2ではConfigがRbConfigに変わっているので、ここを書き換えれば良いはず。
$ cp -a extconf.rb extconf.rb.bak $ sed -i 's/Config/RbConfig/g' extconf.rb $ diff extconf.rb extconf.rb.bak 18c18 < RbConfig::CONFIG["CPP"] = "g++ -E" --- > Config::CONFIG["CPP"] = "g++ -E"
再度、extconf.rbを実行すると無事成功!
$ ruby extconf.rb setting variables ... $CFLAGS = -I. -I/usr/local/include -Wall $(cflags) -O2 $LDFLAGS = -L. -L/home/watanabe/.rbenv/versions/2.2.2/lib -fstack-protector -rdynamic -Wl,-export-dynamic -L. -L/usr/local/lib $libs = -lkyotocabinet -lz -lstdc++ -lrt -lpthread -lm -lc checking for kccommon.h... yes creating Makefile
次にmakeを実行すると、またしてもエラー・・・。
$ make compiling kyotocabinet.cc kyotocabinet.cc: In static member function ‘static void NativeFunction::execute(NativeFunction*)’: kyotocabinet.cc:602: error: ‘rb_thread_blocking_region’ was not declared in this scope make: *** [kyotocabinet.o] Error 1
ネットで調べたところ、rb_thread_blocking_regionという関数がなくなったから起きているらしい。
kyotocabinet.ccの該当行は以下のようになっている。
600 static void execute(NativeFunction* func) { 601 #if defined(_KC_YARV_) 602 rb_thread_blocking_region(execute_impl, func, RUBY_UBF_IO, NULL); 603 #else 604 func->operate(); 605 #endif 606 }
_KC_YARV_が定義されていたらrb_thread_blocking_regionを使用するという事になっているが、
代替手段としてfunc->operate()が用意されている。
という事は、常にfunc->operate()を使うようにしてやれば良いはず。
調べたところ、_KC_YARV_ は601~605行目の処理のみで利用されているので影響範囲が小さい。
24 #if RUBY_VM >= 1 25 #define _KC_YARV_ 26 #endif
とりあえず、25行目を空にしてやれば良いだろう。
$ cp -a kyotocabinet.cc kyotocabinet.cc.bak $ sed -i 's/define _KC_YARV_//g' kyotocabinet.cc $ diff kyotocabinet.cc kyotocabinet.cc.bak 25c25 < # --- > #define _KC_YARV_
再度、makeを実行するとエラーが起きずにコンパイルが成功した。
$ make compiling kyotocabinet.cc linking shared-object kyotocabinet.so
とりあえず、インストールする。
$ make install
テストを実行して問題がないか確認するが、やっぱりエラー。
$ ruby test.rb test.rb:33:in `<main>': uninitialized constant Config (NameError)
例によってConfigをRbConfigにしてやれば良い。
影響範囲を調べる。なぜかRbConfigに直ってるやつもある・・・ $ grep Config test.rb rubycmd = Config::CONFIG["bindir"] + "/" + RbConfig::CONFIG['ruby_install_name'] $ cp -a test.rb test.rb.bak $ sed -i 's/rubycmd = Config/rubycmd = RbConfig/' test.rb $ diff test.rb test.rb.bak 33c33 < rubycmd = RbConfig::CONFIG["bindir"] + "/" + RbConfig::CONFIG['ruby_install_name'] --- > rubycmd = Config::CONFIG["bindir"] + "/" + RbConfig::CONFIG['ruby_install_name']
再度、テストを実行(少し時間かかる)すると、無事に全てのテストが成功。
$ ruby test.rb 001/105: kctest.rb order ':' '10000': ok 002/105: kctest.rb order -rnd ':' '10000': ok 003/105: kctest.rb order -etc ':' '10000': ok ... 105/105: kctest.rb misc 'casket.kcf': ok 105 tests were all ok
これで安心してruby2.2でもkyotocabinetを使う事が出来る。