|▽ ̄)ノ なページ再帰 - Ruby BDB

Ruby BDB


ビルドに困難をともなうと思われる Ruby BDB を Windows でビルドするための情報を提供します。

目次

はじめに


Ruby BDB のビルド プロセスは幾つかの困難を抱えています。 Ruby BDB は Berkeley DB の多くのバージョンに対応するために複雑なビルド オプションを用意し、 extconf.rb で有効にするオプションを調査しています。この調査に不備があり、チートすることなくビルドした場合は動きません( windows のみ? todo )。また Ruby の C ヘッダーにも問題があり、状況を複雑にしています。 そうでもないような、複雑なような。

このページでは、 Ubuntu 上で MinGW クロスコンパイルを行う方法と、 Windows 上で vc2010ee を使用してコンパイルを行う方法を説明します。 vc2010ee については遅れます。todo

ついでに Kyoto Cabinet と Kyoto Cabinet - Ruby のビルドも説明します。する予定です。手元ではビルド出来ています。ただしまだテストを全てクリアしていません。todo

環境


ビルドに使用した or 予定の環境は次の通りです。 2011/1/20thu 現在。
  • Windows 7 x64 Ultimate
  • VMware Player 3.1.2 build-301548
  • Ubuntu v10.4 amd64
    • mingw32-binutils 2.20-0.1
    • gcc-mingw32 4.4.2-3
    • mingw32-runtime 3.15.2-0ubuntu1
    • ruby1.8 1.8.7.249-2
    • ruby1.8-dev 1.8.7.249-2
  • Visual C++ 2010 EE
  • Windows SDK v7.1 for Windows 7 and .NET Framework 4
  • Active Script Ruby 1.8.7-p330-1.8.7.35
  • Active Script Ruby 1.9.2-p136-2010-12-25

Ruby BDB の不備


todo

Ruby C ヘッダーの不具合


todo

win32.h に定義され置き換えられているマクロが問題を惹き起こします。ここで行われている置き換えが一般的な名前を使っていること、 fopen のような関数を置き換えていること、 #define と typedef の競合、それらが問題を起こし、また分かりにくくしています。

MinGW Cross Compile


MinGW Cross Compile on Ubuntu に書いた環境で試しています。クロスコンパイルするために Active Script Ruby の rbconfig.rb と mkmf.rb を書き換えています。 rbconfig.rb は変更箇所が多くなっています。

Berkeley DB


Berkeley DB NC (without encryption) を使用します。

xmingw


まだ情報収集が不充分です。 dll を確保するところまで。

dll 名は libdb-5.1.dll です。 Java と C++ まわりは無効になっています。 --disable-test しているのに何故かテストを実行しようとします。

# Berkeley DB | Oracle Embedded Database
# http://www.oracle.com/us/products/database/berkeley-db/db/index.html
# db-5.1.19.NC.tar.gz

tar -zxf db-5.1.19.NC.tar.gz
cd db-5.1.19.NC
cd dist
mkdir target
mkdir build
cd build

${XMINGW}/cross-ppconfigure --prefix=${PWD}/../target --enable-mingw --disable-test --disable-java --disable-jdbc  CFLAGS="-O2 -mtune=pentium3 -msse -mno-sse2 -pipe -fomit-frame-pointer -ffast-math" LDFLAGS="-s"

bash ${XMINGW}/replibtool.sh

${XMINGW}/cross make install > make.log 2>&1
# db_verify でエラーになるが無視する。
# dll は作成されている。 *.exe は単体テストなど。

cp .libs/libdb-5.1.dll.def ../target/lib/.
# cp *.exe ../target/bin/.
cd ../target
7z a berkeleydb-5.1.19.NC-bin.7z bin/*.dll
7z a berkeleydb-dev-5.1.19.NC.7z include lib/*.{a,def}
# 7z a berkeleydb-5.1.19.NC-tools.7z bin/*.exe

vc2010ee


db-5.1.19.NC パッケージに不備があります。

db.vcxproj を書き換えます。 db.vcxproj の ..\src\crypto\* を全てコメントアウトし、..\src\common\crypto_stub.c を追加します。

また db.h に記述されながらエクスポートされない関数が存在します。 dist/win_exports.in に関数を追加し、 dist ディレクトリーで bash s_windows を実行します。実行には MSys のコマンドが必要です。

tar -zxf db-5.1.19.NC.tar.gz
cd db-5.1.19.NC

REM 下記パッチを適用する。 patch は MSys コマンド
patch -i patch -p 1

cd dist
bash s_windows
cd ..

cd build_windows

msbuild /maxcpucount /fileLogger Berkeley_DB_vs2010.sln /target:db /property:OutDir=vc2010win32/;Configuration=Release;Platform=Win32
REM OutDir の値は ./%s に置き換えられる。値の最後にスラッシュ(/)が必要。
REM     %CD% ではエラーになる。
REM /target:Build でもいい。

cd vc2010win32
mkdir bin
mkdir include
mkdir lib
copy ..\db.h include\.
copy ..\db_cxx.h include\.
copy *.dll bin\.
copy *.lib lib\.
copy *.exp lib\.
copy *.pdb lib\.

7z a berkeleydb-5.1.19.NC-bin.7z bin/*.dll
7z a berkeleydb-dev-5.1.19.NC.7z include lib
patch

--- db-5.1.19.NC.orig/build_windows/db.vcxproj
+++ db-5.1.19.NC/build_windows/db.vcxproj
@@ -216,7 +216,7 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
-    <ClCompile Include="..\src\crypto\aes_method.c" />
+<!--    <ClCompile Include="..\src\crypto\aes_method.c" /> -->
     <ClCompile Include="..\src\btree\bt_compact.c" />
     <ClCompile Include="..\src\btree\bt_compare.c" />
     <ClCompile Include="..\src\btree\bt_compress.c" />
@@ -239,7 +239,7 @@
     <ClCompile Include="..\src\btree\btree_auto.c" />
     <ClCompile Include="..\src\db\crdel_auto.c" />
     <ClCompile Include="..\src\db\crdel_rec.c" />
-    <ClCompile Include="..\src\crypto\crypto.c" />
+<!--    <ClCompile Include="..\src\crypto\crypto.c" /> -->
     <ClCompile Include="..\lang\cxx\cxx_db.cpp" />
     <ClCompile Include="..\lang\cxx\cxx_dbc.cpp" />
     <ClCompile Include="..\lang\cxx\cxx_dbt.cpp" />
@@ -255,6 +255,7 @@
     <ClCompile Include="..\src\db\db_am.c" />
     <ClCompile Include="..\src\db\db_auto.c" />
     <ClCompile Include="..\src\common\clock.c" />
+    <ClCompile Include="..\src\common\crypto_stub.c" />
     <ClCompile Include="..\src\common\db_byteorder.c" />
     <ClCompile Include="..\src\db\db_cam.c" />
     <ClCompile Include="..\src\db\db_cds.c" />
@@ -372,7 +373,7 @@
     <ClCompile Include="..\src\mp\mp_stat.c" />
     <ClCompile Include="..\src\mp\mp_sync.c" />
     <ClCompile Include="..\src\mp\mp_trickle.c" />
-    <ClCompile Include="..\src\crypto\mersenne\mt19937db.c" />
+<!--    <ClCompile Include="..\src\crypto\mersenne\mt19937db.c" /> -->
     <ClCompile Include="..\src\mutex\mut_alloc.c" />
     <ClCompile Include="..\src\mutex\mut_failchk.c" />
     <ClCompile Include="..\src\mutex\mut_method.c" />
@@ -443,8 +444,8 @@
     <ClCompile Include="..\src\repmgr\repmgr_stat.c" />
     <ClCompile Include="..\src\repmgr\repmgr_util.c" />
     <ClCompile Include="..\src\repmgr\repmgr_windows.c" />
-    <ClCompile Include="..\src\crypto\rijndael\rijndael-alg-fst.c" />
-    <ClCompile Include="..\src\crypto\rijndael\rijndael-api-fst.c" />
+<!--    <ClCompile Include="..\src\crypto\rijndael\rijndael-alg-fst.c" /> -->
+<!--    <ClCompile Include="..\src\crypto\rijndael\rijndael-api-fst.c" /> -->
     <ClCompile Include="..\src\sequence\seq_stat.c" />
     <ClCompile Include="..\src\sequence\sequence.c" />
     <ClCompile Include="..\src\hmac\sha1.c" />

--- db-5.1.19.NC.orig/dist/win_exports.in
+++ db-5.1.19.NC/dist/win_exports.in
@@ -3,9 +3,27 @@
 # Standard interfaces.
 	db_create
 	db_env_create
-	db_env_set_func_free
-	db_env_set_func_malloc
-	db_env_set_func_realloc
+    db_env_set_func_close
+    db_env_set_func_dirfree
+    db_env_set_func_dirlist
+    db_env_set_func_exists
+    db_env_set_func_free
+    db_env_set_func_fsync
+    db_env_set_func_ftruncate
+    db_env_set_func_ioinfo
+    db_env_set_func_malloc
+    db_env_set_func_file_map
+    db_env_set_func_region_map
+    db_env_set_func_pread
+    db_env_set_func_pwrite
+    db_env_set_func_open
+    db_env_set_func_read
+    db_env_set_func_realloc
+    db_env_set_func_rename
+    db_env_set_func_seek
+    db_env_set_func_unlink
+    db_env_set_func_write
+    db_env_set_func_yield
 	db_sequence_create
 	db_strerror
 	db_version

Ruby BDB


ビルドが正常に終了すると src の下に bdb.so が出来ます。

ディレクトリー トップにある extconf.rb を実行すると src/extconf.rb を実行します。 mkmf.log は src ディレクトリーの下に作成されます。 src/extconf.rb は src/features.rb を require します。 src/features.rb は src/bdb_features.h を作成します。

ビルド ログはこちらに置きました。Ruby BDB.log

xmingw


1.9.2 でもビルドできます。ただしまだ tests を実行していません。 今のところ動きません。

cross compile の問題で有効にされないオプションがあります。 features.rb で try_db_run 関数を呼び、実行ファイルを生成しそのご実行しようとするのですが、実行できない環境のため無効にされてしまいます。生成された bdb_features.h の HAVE_DB_ENV_ERRCALL_3, HAVE_DB_OPEN_7_DB_CREATE および HAVE_DB_KEY_DBT_MALLOC を有効(1)にしてからビルドしてください。

# RubyForge: Ruby/BDB: Project Info
# http://rubyforge.org/projects/bdb/
# bdb-0.6.5.tar.gz

tar -zxf bdb-0.6.5.tar.gz
cd bdb-0.6.5

# Berkeley DB は ${PWD}/bdb に置いている。
${XMINGW}/cross ruby extconf.rb --ruby="`which ruby`" --with-db-dir="${PWD}/bdb" --with-db-version=-5.1 --ruby="`which ruby`"

# src/bdb_features.h を書き換える。
# xcompile の問題。
# HAVE_DB_ENV_ERRCALL_3 の値を 0 から 1 にする。
# HAVE_DB_OPEN_7_DB_CREATE の値を 0 から 1 にする。
# HAVE_DB_KEY_DBT_MALLOC の値を 0 から 1 にする。

${XMINGW}/cross make > make.log 2>&1

vc2010ee


Berkeley DB のインポート ライブラリー名を db-5.1.lib にしています。 bdb-0.6.5/bdb にヘッダー等を置いています。ディレクトリー構成は MinGW に準じています。

asr192 に同梱されている rbconfig.rb の cflags またはテスト コンパイルに使用するフラグを確認してください。 -we4020 がなければ追加します( Ruby/BDB の src/features.rb ファイルの try_compile 関数呼び出しの引数にオプションを与えてもいい。こちらのほうが影響範囲が小さい。 rbconfig.rb を書き換える利点は、同様の問題に遭遇した場合に煩わされずに済むこと)。これは” C4020: 'ポインターによる関数の呼び出し' : 実引数が多すぎます。”をエラーにするコンパイル オプションです。 vc2010ee のコンパイラーの既定では C4020 は警告を表示するだけでエラーになりません。 feature.rb は C4020 がエラーになることを期待して検査しており、エラーにならなければ bdb_features.h が正しく作成されません。

src の下かパスが通った場所に Berkeley DB の dll を置いてから extconf.rb を実行します。

asr192 & Berkeley DB 5.1.19(25) でビルド&テストが成功することを確認しています。

asr187 でビルドできますが、 test で SEGV します。調査中です。

tar -zxf bdb-0.6.5.tar.gz
cd bdb-0.6.5

patch -i ../knu.20110325fri.patch -p1
patch -i ../niloufar.20110325fri.patch -p1

ruby extconf.rb --with-db-dir="%CD%\bdb" --with-db-version=-5.1

cd src
nmake > make.log 2>&1
knu.20110325fri.patch

ruby bdb 0.6.5 と下記サイトの差分です。

https://github.com/knu/ruby-bdb/

--- bdb-0.6.5/bdbxml2/extconf.rb
+++ ruby-bdb/bdbxml2/extconf.rb
@@ -76,7 +76,7 @@
 
 have_func("rb_block_call")
 
-require 'features.rb'
+require './features'
 create_makefile('bdbxml')
 
 begin

--- bdb-0.6.5/src/bdb.h
+++ ruby-bdb/src/bdb.h
@@ -1,9 +1,13 @@
+#include <db.h>
+#include <errno.h>
+
 #include <ruby.h>
+#ifdef HAVE_RUBY_IO_H
+#include <ruby/io.h>
+#else
 #include <rubysig.h>
 #include <rubyio.h>
-
-#include <db.h>
-#include <errno.h>
+#endif
 
 #include "bdb_features.h"
 

--- bdb-0.6.5/src/common.c
+++ ruby-bdb/src/common.c
@@ -941,7 +941,7 @@
 		}
 	    }
 	    if (!(dbst->options & BDB_NOT_OPEN)) {
-		bdb_test_error(dbst->dbp->close(dbst->dbp, flags));
+		dbst->dbp->close(dbst->dbp, flags);
 	    }
 	}
 	else {
@@ -950,7 +950,7 @@
 		bdb_ary_delete(&envst->db_ary, dbst->ori_val);
 	    }
 	    if (!(dbst->options & BDB_NOT_OPEN)) {
-		bdb_test_error(dbst->dbp->close(dbst->dbp, flags));
+		dbst->dbp->close(dbst->dbp, flags);
 	    }
 	}
     }

--- bdb-0.6.5/src/env.c
+++ ruby-bdb/src/env.c
@@ -364,8 +364,8 @@
     if (TYPE(res) != T_ARRAY || RARRAY_LEN(res) != 2) {
 	rb_raise(bdb_eFatal, "expected [pid, threadid]");
     }
-    *pid = NUM2INT(RARRAY_PTR(res)[0]);
-    *tid = NUM2INT(RARRAY_PTR(res)[0]);
+    *pid = NUM2LONG(RARRAY_PTR(res)[0]);
+    *tid = (db_threadid_t)NUM2LONG(RARRAY_PTR(res)[0]);
     return;
 }
 
@@ -384,11 +384,11 @@
 
     GetIdEnv(obj, envst);
     if (NIL_P(envst->thread_id_string)) {
-	snprintf(buf, DB_THREADID_STRLEN, "%d/%d", pid, (int)tid);
+	snprintf(buf, DB_THREADID_STRLEN, "%d/%ld", pid, (long)tid);
 	return buf;
     }
-    a = INT2NUM(pid);
-    b = INT2NUM(tid);
+    a = LONG2NUM(pid);
+    b = LONG2NUM((long)tid);
     if (envst->thread_id_string == 0) {
 	res = rb_funcall(obj, id_thread_id_string, 2, a, b);
     }
@@ -418,8 +418,8 @@
     if (NIL_P(envst->isalive)) {
 	return 0;
     }
-    a = INT2NUM(pid);
-    b = INT2NUM(tid);
+    a = LONG2NUM(pid);
+    b = LONG2NUM((long)tid);
     c = INT2NUM(flags);
     if (envst->isalive == 0) {
 	res = rb_funcall(obj, id_isalive, 3, a, b, c);
@@ -1903,9 +1903,9 @@
 #endif
 #if HAVE_ST_DB_ENV_GET_MP_MMAPSIZE
     if (strcmp(str, "mp_mmapsize") == 0) {
-	u_int32_t size;
+	size_t size;
 	bdb_test_error(envst->envp->get_mp_mmapsize(envst->envp, &size));
-	return INT2NUM(size);
+	return LONG2NUM(size);
     }
 #endif
 #if HAVE_ST_DB_ENV_GET_OPEN_FLAGS
@@ -1981,7 +1981,7 @@
 #endif
 #if    HAVE_ST_DB_ENV_REP_GET_PRIORITY
     if (strcmp(str, "rep_priority") == 0) {
-	size_t size = 0;
+	int size = 0;
 	bdb_test_error(envst->envp->rep_get_priority(envst->envp, &size));
 	return INT2NUM(size);
     }
@@ -2448,7 +2448,7 @@
 bdb_env_rep_get_nsites(VALUE obj, VALUE a)
 {
     bdb_ENV *envst;
-    u_int32_t offon;
+    int offon;
 
     GetEnvDB(obj, envst);
     bdb_test_error(envst->envp->rep_get_nsites(envst->envp, &offon));
@@ -2473,7 +2473,7 @@
 bdb_env_rep_get_priority(VALUE obj, VALUE a)
 {
     bdb_ENV *envst;
-    u_int32_t offon;
+    int offon;
 
     GetEnvDB(obj, envst);
     bdb_test_error(envst->envp->rep_get_priority(envst->envp, &offon));

--- bdb-0.6.5/src/extconf.rb
+++ ruby-bdb/src/extconf.rb
@@ -90,6 +90,12 @@
    raise "libdb#{version[-1]} not found"
 end
 
+headers = ["ruby.h"]
+if have_header("ruby/io.h")
+   headers << "ruby/io.h"
+else
+   headers << "rubyio.h"
+end
 ["rb_frame_this_func", "rb_block_proc", "rb_io_stdio_file", "rb_block_call"].each do |f|
    have_func(f, "ruby.h")
 end
@@ -103,8 +109,7 @@
       puts "no"
    end
 end
-
-have_type('rb_io_t', ['ruby.h', 'rubyio.h'])
+have_type('rb_io_t', headers)
 
 if enable_config('db-xml')
    $defs << '-DHAVE_DBXML_INTERFACE'
@@ -112,7 +117,7 @@
    $defs << '-DNOT_HAVE_DBXML_INTERFACE'
 end
 
-require 'features'
+require './features'
 
 create_makefile("bdb")
 if unknown

niloufar.20110325fri.patch

上記パッチを適用後にこちらを当ててください。

--- ruby-bdb/src/bdb_ruby.h
+++ bdb-0.6.5/src/bdb_ruby.h
@@ -0,0 +1,27 @@
+#include <ruby.h>
+#ifdef HAVE_RUBY_IO_H
+#include <ruby/io.h>
+#else
+#include <rubysig.h>
+#include <rubyio.h>
+#endif
+
+#ifdef close
+#undef close
+#endif
+
+#ifdef open
+#undef open
+#endif
+
+#ifdef rename
+#undef rename
+#endif
+
+#ifdef stat
+#undef stat
+#endif
+
+#ifdef truncate
+#undef truncate
+#endif

--- ruby-bdb/src/bdb.h
+++ bdb-0.6.5/src/bdb.h
@@ -1,13 +1,7 @@
 #include <db.h>
 #include <errno.h>
 
-#include <ruby.h>
-#ifdef HAVE_RUBY_IO_H
-#include <ruby/io.h>
-#else
-#include <rubysig.h>
-#include <rubyio.h>
-#endif
+#include "bdb_ruby.h"
 
 #include "bdb_features.h"
 
@@ -39,18 +33,6 @@
 #define RCLASS_SUPER(c) (RCLASS(c)->super)
 #endif
 
-#ifdef close
-#undef close
-#endif
-
-#ifdef stat
-#undef stat
-#endif
-
-#ifdef rename
-#undef rename
-#endif
-
 #if defined(__cplusplus)
 extern "C" {
 #endif

--- ruby-bdb/src/common.c
+++ bdb-0.6.5/src/common.c
@@ -573,9 +573,9 @@
 #endif
 
 static VALUE
-compar_func(VALUE value)
+compar_func(VALUE value_)
 {
-    value = rb_obj_as_string(value);
+    VALUE value = rb_obj_as_string(value_);
     char *compar = StringValuePtr(value);
 
     if (strcmp(compar, "int_compare") == 0) {
@@ -1229,7 +1229,7 @@
     if (argc && TYPE(argv[argc - 1]) == T_HASH) {
 	VALUE v, f = argv[argc - 1];
 
-	if ((v = rb_hash_aref(f, rb_str_new2("txn"))) != RHASH(f)->ifnone) {
+	if ((v = rb_hash_aref(f, rb_str_new2("txn"))) != RHASH_IFNONE(f)) {
 	    if (!rb_obj_is_kind_of(v, bdb_cTxn)) {
 		rb_raise(bdb_eFatal, "argument of txn must be a transaction");
 	    }
@@ -1241,7 +1241,7 @@
 	    dbst->options |= envst->options & BDB_NO_THREAD;
 	    dbst->marshal = txnst->marshal;
 	}
-	else if ((v = rb_hash_aref(f, rb_str_new2("env"))) != RHASH(f)->ifnone) {
+	else if ((v = rb_hash_aref(f, rb_str_new2("env"))) != RHASH_IFNONE(f)) {
 	    if (!rb_obj_is_kind_of(v, bdb_cEnv)) {
 		rb_raise(bdb_eFatal, "argument of env must be an environnement");
 	    }
@@ -1254,11 +1254,11 @@
 #if HAVE_CONST_DB_ENCRYPT 
 	if (envst && (envst->options & BDB_ENV_ENCRYPT)) {
 	    VALUE tmp = rb_str_new2("set_flags");
-	    if ((v = rb_hash_aref(f, rb_intern("set_flags"))) != RHASH(f)->ifnone) {
+	    if ((v = rb_hash_aref(f, rb_intern("set_flags"))) != RHASH_IFNONE(f)) {
 		rb_hash_aset(f, rb_intern("set_flags"), 
 			     INT2NUM(NUM2INT(v) | DB_ENCRYPT));
 	    }
-	    else if ((v = rb_hash_aref(f, tmp)) != RHASH(f)->ifnone) {
+	    else if ((v = rb_hash_aref(f, tmp)) != RHASH_IFNONE(f)) {
 		rb_hash_aset(f, tmp, INT2NUM(NUM2INT(v) | DB_ENCRYPT));
 	    }
 	    else {
@@ -1277,16 +1277,16 @@
 	dbst->marshal = obj;
 	dbst->options |= BDB_MARSHAL;
     }
-    if (rb_method_boundp(obj, rb_intern("bdb_store_key"), 0) == Qtrue) {
+    if (rb_method_boundp(obj, rb_intern("bdb_store_key"), 0)) {
 	dbst->filter[FILTER_KEY] = INT2FIX(rb_intern("bdb_store_key"));
     }
-    if (rb_method_boundp(obj, rb_intern("bdb_fetch_key"), 0) == Qtrue) {
+    if (rb_method_boundp(obj, rb_intern("bdb_fetch_key"), 0)) {
 	dbst->filter[2 + FILTER_KEY] = INT2FIX(rb_intern("bdb_fetch_key"));
     }
-    if (rb_method_boundp(obj, rb_intern("bdb_store_value"), 0) == Qtrue) {
+    if (rb_method_boundp(obj, rb_intern("bdb_store_value"), 0)) {
 	dbst->filter[FILTER_VALUE] = INT2FIX(rb_intern("bdb_store_value"));
     }
-    if (rb_method_boundp(obj, rb_intern("bdb_fetch_value"), 0) == Qtrue) {
+    if (rb_method_boundp(obj, rb_intern("bdb_fetch_value"), 0)) {
 	dbst->filter[2 + FILTER_VALUE] = INT2FIX(rb_intern("bdb_fetch_value"));
     }
     rb_obj_call_init(res, argc, argv);
@@ -3004,8 +3004,8 @@
 
     if (argc && TYPE(argv[argc - 1]) == T_HASH) {
 	VALUE g, f = argv[argc - 1];
-	if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH(f)->ifnone ||
-	    (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH(f)->ifnone) {
+	if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH_IFNONE(f) ||
+	    (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH_IFNONE(f)) {
 	    flags = NUM2INT(g);
 	}
 	argc--;
@@ -3323,8 +3323,8 @@
     flags = 0;
     if (argc && TYPE(argv[argc - 1]) == T_HASH) {
 	VALUE g, f = argv[argc - 1];
-	if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH(f)->ifnone ||
-	    (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH(f)->ifnone) {
+	if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH_IFNONE(f) ||
+	    (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH_IFNONE(f)) {
 	    flags = NUM2INT(g);
 	}
 	argc--;
@@ -3348,8 +3348,8 @@
     flags = 0;
     if (TYPE(argv[argc - 1]) == T_HASH) {
 	VALUE f = argv[argc - 1];
-	if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH(f)->ifnone ||
-	    (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH(f)->ifnone) {
+	if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH_IFNONE(f) ||
+	    (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH_IFNONE(f)) {
 	    flags = NUM2INT(g);
 	}
 	argc--;

--- ruby-bdb\ruby-bdb/src/cursor.c
+++ bdb-0.6.5/src/cursor.c
@@ -29,8 +29,8 @@
     flags = 0;
     if (argc && TYPE(argv[argc - 1]) == T_HASH) {
 	VALUE g, f = argv[argc - 1];
-	if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH(f)->ifnone ||
-	    (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH(f)->ifnone) {
+	if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH_IFNONE(f) ||
+	    (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH_IFNONE(f)) {
 	    flags = NUM2INT(g);
 	}
 	argc--;

--- ruby-bdb/src/features.rb
+++ bdb-0.6.5/src/features.rb
@@ -33,7 +33,11 @@
 
 def try_db_compile(func, src, mess = nil)
    print "checking for #{func}... " unless mess
-   if try_compile(src)
+   ud = <<EOS
+#include "bdb_ruby.h"
+
+EOS
+   if try_compile(ud + src)
       $defs << "-DHAVE_#{func}"
       puts "yes"
       true

--- ruby-bdb/src/recnum.c
+++ bdb-0.6.5/src/recnum.c
@@ -17,7 +17,7 @@
 	argc++;
     }
     rb_hash_aset(argv[argc - 1], array, INT2FIX(0));
-    if (rb_hash_aref(argv[argc - 1], sarray) != RHASH(argv[argc - 1])->ifnone) {
+    if (rb_hash_aref(argv[argc - 1], sarray) != RHASH_IFNONE(argv[argc - 1])) {
 	rb_hash_aset(argv[argc - 1], sarray, INT2FIX(0));
     }
     rb_hash_aset(argv[argc - 1], rb_str_new2("set_flags"), INT2FIX(DB_RENUMBER));
@@ -697,8 +697,8 @@
 
     if (argc && TYPE(argv[argc - 1]) == T_HASH) {
 	VALUE f = argv[argc - 1];
-	if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH(f)->ifnone ||
-	    (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH(f)->ifnone) {
+	if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH_IFNONE(f) ||
+	    (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH_IFNONE(f)) {
 	    flags = NUM2INT(g);
 	}
 	argc--;

--- ruby-bdb/tests/btree.rb
+++ bdb-0.6.5/tests/btree.rb
@@ -29,6 +29,14 @@
 end
 
 def clean
+   unless $bdb.nil?
+      $bdb.close
+      $bdb = nil
+   end
+   unless $env.nil?
+      $env.close
+      $env = nil
+   end
    Dir.foreach('tmp') do |x|
       if FileTest.file?("tmp/#{x}")
 	 File.unlink("tmp/#{x}")

--- ruby-bdb/tests/lock.rb
+++ bdb-0.6.5/tests/lock.rb
@@ -115,7 +115,7 @@
       assert_equal(1, inc = db1.push("record1")[0], "<set db>")
       assert_kind_of(BDB::Txn, txn2 = $env.begin("flags" => BDB::TXN_NOWAIT))
       assert_kind_of(BDB::Queue, db2 = txn2.assoc($db))
-      if BDB::VERSION_MAJOR >= 4 && BDB::VERSION_MINOR >= 2
+      if BDB::VERSION_MAJOR >= 4 || ( BDB::VERSION_MAJOR >= 4 && BDB::VERSION_MINOR >= 2 )
 	 assert_raises(BDB::LockDead) { db2[inc] }
       else
 	 assert_raises(BDB::LockGranted) { db2[inc] }
@@ -130,7 +130,7 @@
       end
    end
 
-   def test_forward(meth1, meth2)
+   def _test_forward(meth1, meth2)
       assert_kind_of(BDB::Txn, txn1 = $env.begin("flags" => BDB::TXN_NOWAIT))
       assert_kind_of(BDB::Queue, db1 = txn1.assoc($db))
       ind1, = db1.push("record1")
@@ -178,12 +178,12 @@
       end
       ["commit", "abort"].each do |t1|
 	 ["commit", "abort"].each do |t2|
-	    test_forward(t1, t2)
+	    _test_forward(t1, t2)
 	 end
       end
    end
 
-   def test_reverse(meth1, meth2)
+   def _test_reverse(meth1, meth2)
       assert_kind_of(BDB::Txn, txn1 = $env.begin("flags" => BDB::TXN_NOWAIT))
       assert_kind_of(BDB::Queue, db1 = txn1.assoc($db))
       ind1, = db1.push("record1")
@@ -231,7 +231,7 @@
       end
       ["commit", "abort"].each do |t1|
 	 ["commit", "abort"].each do |t2|
-	    test_reverse(t1, t2)
+	    _test_reverse(t1, t2)
 	 end
       end
    end

tests


tests 以下のテスト スクリプトに不備があります。上記パッチを当てていれば、最後の一つを除いて不要です。

btree.rb の clean 関数の始めに次の行を挿入します。

   unless $bdb.nil?
      $bdb.close
      $bdb = nil
   end
   unless $env.nil?
      $env.close
      $env = nil
   end

tests/lock.rb の "BDB::VERSION_MAJOR >= 4 && BDB::VERSION_MINOR >= 2" を "BDB::VERSION_MAJOR > 4 || ( BDB::VERSION_MAJOR = 4 && BDB::VERSION_MINOR >= 2 )" に置き換えます。

あと、ファイル パスのセパレーターの違いでテストに失敗している所があります。

鬼車


鬼車は正規表現ライブラリーです。 kyotocabinet のビルドに使用します。

xmingw


dll 名は libonig-2.dll になります。

# Oniguruma
# http://www.geocities.jp/kosako3/oniguruma/
# onig-5.9.2.tar.gz

tar -zxf onig-5.9.2.tar.gz
cd onig-5.9.2
mkdir target
mkdir build
cd build

${XMINGW}/cross-ppconfigure --prefix=${PWD}/../target CFLAGS="-O2 -mtune=pentium3 -msse -mno-sse2 -pipe -fomit-frame-pointer -ffast-math" LDFLAGS="-s"

bash ${XMINGW}/replibtool.sh

${XMINGW}/cross make > make.log 2>&1

${XMINGW}/cross make install > install.log 2>&1

cd ../target
7z a onig-5.9.2-bin.7z bin/*.dll
7z a onig-dev-5.9.2.7z bin/*-config include lib/*.a

Kyoto Cabinet


regex (正規表現)ライブラリーが必要です。ここでは鬼車を使用しています。 pthread は使ってないのですが、面倒な予感がするので変えてません。

xmingw


dll 名は libkyotocabinet-10.dll になります。

# Kyoto Cabinet: a straightforward implementation of DBM
# http://fallabs.com/kyotocabinet/
# kyotocabinet-1.2.57.tar.gz

# deps: pthread, regex

tar -zxf kyotocabinet-1.2.57.tar.gz
cd kyotocabinet-1.2.57
mkdir target

mkdir regex_include
mkdir regex_lib
# oniggnu.h ではない。
ln -s `${XMINGW}/cross onig-config --prefix`/include/onigposix.h regex_include/regex.h
ln -s `${XMINGW}/cross onig-config --prefix`/lib/libonig.dll.a regex_lib/libregex.a

${XMINGW}/cross-configure --prefix=${PWD}/target CPPFLAGS="`${XMINGW}/cross onig-config --cflags` -I${PWD}/regex_include -O2 -mtune=pentium4 -msse -msse2 -pipe -fomit-frame-pointer -ffast-math -D _WIN32_WINNT=0x0500" LDFLAGS="-s `${XMINGW}/cross onig-config --libs` `${XMINGW}/cross --cflags`" --enable-static --enable-shared --disable-atomic
# --disable-atomic は win64 では不要?

# soname 関係の修正。
sed -i.orig -e 's/libkyotocabinet\.so\.\$(LIBVER)/libkyotocabinet-\$(LIBVER).dll/g' -e 's/\(LIBRARYFILES = libkyotocabinet\.a libkyotocabinet\).\+$/\1-\$(LIBVER).dll/' -e 's/^\(kc\w\+\) :/\1 :/' Makefile
# 上記修正のつじつま合わせ。
sed -i -e 's/^\(libkyotocabinet-\$(LIBVER)\.dll\|libkyotocabinet\.so\) /# \1 /' -e 's/^\s\+ln -f -s libkyotocabinet-\$(LIBVER)\.dll\./# \0/' Makefile
# 上記修正のつじつま合わせ。それと libkyotocabinet.dll.a を作るための修正。
sed -i -e 's/^libkyotocabinet-\$(LIBVER)\.dll\.\$(LIBREV)\.0 /libkyotocabinet-\$(LIBVER)\.dll /' -e 's/\(-soname,libkyotocabinet-$(LIBVER).dll \)/\1 -Wl,--out-implib -Wl,libkyotocabinet.dll.a -Wl,--output-def -Wl,libkyotocabinet.def /' -e 's/\( -lkyotocabinet\)/\1.dll /' Makefile
# コマンドに .exe を足す。
sed -i -e '/^COMMANDFILES = /{' -e 's/kc\w\+/\0.exe/g' -e '}' -e 's/^\(kc\w\+\) :/\1.exe :/' Makefile

${XMINGW}/cross make CMDLIBS="-lonig `grep '^CMDLIBS' Makefile | sed -e 's/^.\+=\s*\(.*\)/\1/'`" LIBS="-lonig `grep '^LIBS' Makefile | sed -e 's/^.\+=\s*\(.*\)/\1/'`" > make.log 2>&1

${XMINGW}/cross make install > install.log 2>&1

cp *.dll.a target/lib/.
cd target
mv ../libkyotocabinet-*.dll bin/.
7z a kyotocabinet-1.2.57-bin.7z bin/*.dll
7z a kyotocabinet-dev-1.2.57.7z include lib/*.a lib/pkgconfig
7z a kyotocabinet-1.2.57-tools.7z bin/*.exe share/{doc,man}

Kyoto Cabinet - Ruby


充分に情報収集できていません。

xmingw


正常に終了すると kyotocabinet.so ができます。

asr187

いまのところ wicked + スレッド絡みで期待通りに動きません。

# Kyoto Cabinet: a straightforward implementation of DBM
# http://fallabs.com/kyotocabinet/
# kyotocabinet-ruby-1.26.tar.gz

# deps: kyotocabinet

tar -zxf kyotocabinet-ruby-1.26.tar.gz
cd kyotocabinet-ruby-1.26

patch -i ../kyotocabinet-ruby-1.26.patch -p 0

XLIBRARY_SET="${XLIBRARY}/asr187_set"

# kyotocabinet は ${PWD}/kc に配置している。
${XMINGW}/cross ${XLIBRARY}/asr187/ruby extconf.rb --with-opt-dir="${PWD}/kc"

# -lrt って何だろう。
sed -i.orig -e '/^LIBS = /{' -e 's/ -l\(rt\|c\)//g' -e '}' Makefile

${XMINGW}/cross make DESTDIR="${PWD}/target" prefix="${XLIBRARY}/asr187" CFLAGS="-O2 -mtune=pentium4 -msse -msse2 -pipe -fomit-frame-pointer -ffast-math `${XMINGW}/cross --cflags`" LDFLAGS="-s `${XMINGW}/cross --ldflags`" RUBY="`which ruby`" > make.log 2>&1

7z a kyotocabinet-ruby-1.26-so.7z kyotocabinet.so
asr192

test.rb はひとつを除き通っています。このひとつは単体で実行すると通ります。いまのところ原因不明です。

tar -zxf kyotocabinet-ruby-1.26.tar.gz
cd kyotocabinet-ruby-1.26

patch -i ../kyotocabinet-ruby-1.26.patch -p 0

# -lrt って何だろう。
sed -i.orig -e '/^kclibs = /{' -e 's/ -l\(rt\|c\)//g' -e '}' extconf.rb
# 1.9.2 の mkmf.rb が have_header で try compile してしまうので細工する。
sed -i -e 's/^\$CFLAGS = "/\0-xc++ /' extconf.rb

# 必要ないかも。
XLIBRARY_SET="${XLIBRARY}/asr192_set"

# kyotocabinet は ${PWD}/kc に配置している。
${XMINGW}/cross ${XLIBRARY}/asr192/ruby extconf.rb --with-kyotocabinet-dir="${PWD}/kc" --with-opt-dir=${XLIBRARY}/lib

${XMINGW}/cross make DESTDIR="${PWD}/target" prefix="${XLIBRARY}/asr192" CFLAGS="-O2 -mtune=pentium4 -msse -msse2 -pipe -fomit-frame-pointer -ffast-math `${XMINGW}/cross --cflags`" LDFLAGS="-s `${XMINGW}/cross --ldflags`" RUBY="`which ruby`" > make.log 2>&1

7z a kyotocabinet-ruby-1.26-asr192-so.7z kyotocabinet.so

kyotocabinet-ruby-1.26.patch


win32/win32.h の問題に対応するパッチです。

--- kyotocabinet.cc.orig
+++ kyotocabinet.cc
@@ -21,6 +21,14 @@
 
 #include <ruby.h>
 
+#ifdef accept
+#undef accept
+#endif
+
+#ifdef close
+#undef close
+#endif
+
 #if RUBY_VM >= 1
 #define _KC_YARV_
 #endif

tests


ログはこちらに置きました。Ruby BDB.log

asr187 ( xmingw ) では wicked + スレッドのテストに失敗しています。


そのままでは問題があるのでパッチをあてます。

--- test.rb.orig
+++ test.rb
@@ -30,7 +30,7 @@
            ]
 
 system("rm -rf casket*")
-rubycmd = Config::CONFIG["bindir"] + "/" + RbConfig::CONFIG['ruby_install_name']
+rubycmd = "ruby"
 all = confs.size * formats.size
 cnt = 0
 oknum = 0
@@ -41,7 +41,7 @@
     cnt += 1
     command = sprintf(format, path, rnum)
     printf("%03d/%03d: %s: ", cnt, all, command)
-    rv = system("#{rubycmd} -I. #{command} >/dev/null")
+    rv = system("#{rubycmd} -I. #{command} > nul")
     if rv
       oknum += 1
       printf("ok\n")

memo

extconf.rb

  • extconf.rb の経過出力を保存する。
  • mkmf.log

extconf.rb で使用している関数
dir_config(target, inc_dir, lib_dir)
--with-<target>-dir, --with-<target>-include, --with-<target>-lib を取得する。
with_config(target, default_value)
--with<target> で指定される値を取得する。

todo

  • vc2010ee でビルド
    • berkeley db v5.1.19 nc (without encryption)
    • ruby bdb 0.6.5
    • kyotocabinet 1.2.33
    • kyotocabinet-ruby 1.2.33
  • Ruby Library を MinGW Cross Compile する方法
  • extconf.rb メモ
  • 1.9.2 で tests を動かす
  • kyotocabinet-ruby の調査

更新履歴



2011/5/23mon kyotocabinet-ruby を更新。 asr192 の場合を書き加えた。
2011/5/22sun kyotocabinet を 1.2.57 に、 kyotocabinet-ruby を 1.26 に差し替えた。
2011/4/13wed Ruby BDB/xmingw の不備を修正した。
2011/3/25fri asr192 & vc2010ee での ruby bdb のビルド方法を書いた。
2011/1/27thu 書き忘れを書き足した。
2011/1/26wed vc2010ee まわりを記述。もろもろ修正。
2011/1/20thu ページ作成。