PerlのDBD::mysqlをlibmysqlclient.aとstatic linkしたい話

static linkするにあたっての動機、諸注意(ハメがあるので必読)は [twitter:@sonots] さんの

を参照してください。

ここではDBD::mysqlをビルドする際のオプションのみ記します。

http://dev.mysql.com/downloads/mysql/ からダウンロードできるrpm

の場合、

$ ldconfig -p | grep libmysqlclient
        libmysqlclient.so.18 (libc6,x86-64) => /usr/lib64/libmysqlclient.so.18
        libmysqlclient.so (libc6,x86-64) => /usr/lib64/libmysqlclient.so

$ rpm -ql MySQL-devel | grep libmysqlclient.a
/usr/lib64/mysql/libmysqlclient.a

$ mysql_config --libs
-L/usr/lib64 -lmysqlclient -lpthread -lm -lrt -ldl

こういう感じの構成になっているので、

  • /usr/lib64の代わりにlibmysqlclient.aがある/usr/lib64/mysqlにライブラリパスを通す
  • libstdc++もリンクする

するように、このように

$ mysql_config --libs | sed -e 's@-L/usr/lib64@-L/usr/lib64/mysql@' -e 's@$@ -lstdc++@'
-L/usr/lib64/mysql -lmysqlclient -lpthread -lm -lrt -ldl -lstdc++

します。


ソースを展開してMakefile.PLを使ってビルドする場合は、--libsにこれを指定すればよいです。

$ perl Makefile.PL --libs="$(mysql_config --libs | sed -e 's@-L/usr/lib64@-L/usr/lib64/mysql@' -e 's@$@ -lstdc++@')"
$ make

$ ldd blib/arch/auto/DBD/mysql/mysql.so
        linux-vdso.so.1 =>  (0x00007fff9a52a000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f3434572000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f34342ee000)
        librt.so.1 => /lib64/librt.so.1 (0x00007f34340e5000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f3433ee1000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f3433ccb000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f3433936000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3434d84000)
# ↑libmysqlclient.so を dynamic linkしていない

$ perl -Iblib/lib -Iblib/arch -MDBD::mysql -e 1
# ↑ちゃんとモジュールをロードできる

$ sudo make install

ちなみに -lstdc++ していない場合はこのようにモジュールのロードで失敗します。

$ perl -Iblib/lib -Iblib/arch -MDBD::mysql -e 1
Can't load 'blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: __cxa_pure_virtual at /usr/lib64/perl5/DynaLoader.pm line 200.
 at - line 0
Compilation failed in require.
BEGIN failed--compilation aborted.


cpanmでインストールする場合は、--configure-args="--libs=..." に指定すればよいです。

$ mylib=$(mysql_config --libs | sed -e 's@-L/usr/lib64@-L/usr/lib64/mysql@' -e 's@$@ -lstdc++@')
$ cpanm -n DBD::mysql --configure-args="--libs='${mylib}'"


Oracle謹製のrpmには先程書いた http://dev.mysql.com/downloads/mysql/ で配布しているものの他に、yumレポジトリで配布しているものもあります。

なぜか両者ではライブラリファイルの配置が異なっているので気をつけてください。

このように、

$ ldconfig -p | grep libmysqlclient
        libmysqlclient.so.18 (libc6,x86-64) => /usr/lib64/mysql/libmysqlclient.so.18
        libmysqlclient.so (libc6,x86-64) => /usr/lib64/mysql/libmysqlclient.so

$ rpm -ql mysql-community-devel |  grep libmysqlclient.a
/usr/lib64/mysql/libmysqlclient.a

$ mysql_config --libs
-L/usr/lib64/mysql -lmysqlclient -lpthread -lm -lrt -ldl

yumで配布しているrpmのはlibmysqlclient.soも.aも同じディレクトリ/usr/lib64/mysqlにあります。

このままではstatic linkできないので、*.aを別のディレクトリにコピーして、そこにライブラリパスを通してビルドしないといけません。

$ mkdir /tmp/oreno-lib
$ cp /usr/lib64/mysql/*.a /tmp/oreno-lib/

$ mysql_config --libs
-L/usr/lib64/mysql -lmysqlclient -lpthread -lm -lrt -ldl
$ mylib="-L/tmp/oreno-lib -lmysqlclient -lpthread -lm -lrt -ldl -lstdc++"

$ perl Makefile.PL --libs="${mylib}"
  OR
$ cpanm -n DBD::mysql --configure-args="--libs='${mylib}'"