読者です 読者をやめる 読者になる 読者になる

clock-up-blog

go-mi-tech

Berkeley DB 4.8.30 を MinGW, MSYS 環境でビルドする(要修正パッチ)

MinGW

Berkeley DB 4.8 について

現時点で利用できる最新の Oracle Berkeley DB は 6.2 系列ですが、Bitcoin Core 等が Berkeley DB 4.8 に依存している等の事情があり、いまだに Berkeley DB 4.8 を使うことは割とあったりします。

Berkeley DB 4.8 の MinGW, MSYS でのビルドエラーについて

実のところ Berkeley DB 4.8.30 はパッケージを入手して MinGW, MSYS 環境でビルドしようとしてもおそらくビルドは通りません。(この問題がいまだに残っているのはおそらく MinGW, MSYS 環境への Berkeley DB 4.8 導入実績が少なく気づかれなかった、または 4.8 リリース当時の MinGW, MSYS では問題なかったのかもしれません。)

大抵の場合は make の段階で以下のようなエラーに遭遇するでしょう。

libtool: compile:  gcc -c -I. -I../dist/.. -O3 ../dist/../mutex/mut_failchk.c  -DDLL_EXPORT -DPIC -o .libs/mut_failchk.o
../dist/../mutex/mut_failchk.c: In function '__mut_failchk':
../dist/../mutex/mut_failchk.c:53:27: error: incompatible type for argument 3 of 'dbenv->is_alive'
       dbenv, mutexp->pid, 0, DB_MUTEX_PROCESS_ONLY))
                           ^

ビルドエラーの根本的な原因

どこに問題があるのかというと、configure により生成される db.h 内では

typedef pthread_t db_threadid_t;

と定義されている db_threadid_t 型に対し、この変数型に対して無効値として「0」を代入しようとしていることがビルドエラーの原因となっています。

元の pthread_t は大抵の環境では数値型 (unsigned long int 等) に過ぎないのですが、全ての環境において数値型であるとは限りません。
例えば MinGW 環境下では C:\MinGW\include\pthread.h 内にて以下のように pthread_t が定義されています。

typedef struct
{ void * p;                   /* Pointer to actual object */
#if __PTW32_VERSION_MAJOR > 2
  size_t x;                   /* Extra information - reuse count etc */
#else
  unsigned int x;             /* Extra information - reuse count etc */
#endif
} ptw32_handle_t;

typedef ptw32_handle_t pthread_t;

このヘッダ内では pthread_t は構造体として定義されているわけです。これでは「0」の代入は当然ながらコンパイルエラーになります。

ビルドエラーへの対策

上記のような状況に遭遇した場合、もうこれは環境をどうにか調整することでエラー対策を行おうとすることは悪手で、pthread_t に「0」を代入しようとしている Berkeley DB コード側に原因があることは明らかなのでそちらを修正する必要があります。

とりあえず以下に修正パッチを上げました。
https://gist.github.com/kobake/2761506fc958f8bf07601d00dea01470

修正内容としては、db_threadid_t 型に対して 0 を指定するようなコードを排除し、0 指定の代わりに db_threadid_t unused; memset(&unused, 0, sizeof(unused)); とした変数 unused を指定することでエラー対処を行っています。(あと GetCurrentThreadId のところもエラってたので対応を行っていたりする)

この修正内容は基本的に Berkeley DB 6.2.23 のソースコードを参考に、6.2.23 とほぼ同じ対処を行いました。つまり最新版ではこの修正対応は行われているのですが 4.8 系については該当の対応は適用されていません。バージョンが古いので仕方ないかと思います。4.8.30 のリリースは2010年です。

パッチを適用した上でのビルドの流れ

MinGW, MSYS が導入されていて PATH も通っている前提。

コマンドプロンプトにて。

> bash.exe … MSYS Bash を起動
$ wget http://download.oracle.com/berkeley-db/db-4.8.30.tar.gz
$ tar xzvf db-4.8.30.tar.gz
$ cd db-4.8.30
$ wget --no-check-certificate https://gist.githubusercontent.com/kobake/2761506fc958f8bf07601d00dea01470/raw/805e58ee669c9d3f7214091c816c1a6257d5407d/db-4.8.30-fix-for-mingw.patch … 今回のパッチ入手
$ patch -p1 < db-4.8.30-fix-for-mingw.patch … パッチ適用
$ cd build_unix
$ ../dist/configure --prefix=/usr/local --enable-cxx --enable-mingw --disable-replication
$ make
$ make install
$ ls -l /usr/local/lib
total 9526
-rw-r--r-- 1 kobake Administrators 1839830 Feb  5 02:52 libdb-4.8.a
-rw-r--r-- 1 kobake Administrators  826274 Feb  5 02:50 libdb-4.8.dll.a
-rw-r--r-- 1 kobake Administrators     918 Feb  5 02:50 libdb-4.8.la
-rw-r--r-- 1 kobake Administrators 1839830 Feb  5 02:52 libdb.a
-rw-r--r-- 1 kobake Administrators 2001662 Feb  5 02:52 libdb_cxx-4.8.a
-rw-r--r-- 1 kobake Administrators 1241124 Feb  5 02:50 libdb_cxx-4.8.dll.a
-rw-r--r-- 1 kobake Administrators     938 Feb  5 02:50 libdb_cxx-4.8.la
-rw-r--r-- 1 kobake Administrators 2001662 Feb  5 02:52 libdb_cxx.a

というわけでパッチ(自前)を適用することでビルドが通るようになりました。

});