共有ライブラリのコンパイル時に必要な検索パスを追加する方法

依存するsoファイルが見つからない!?

共有ライブラリを作成したら実行時に依存するsoファイルが見つからない的なエラーが発生した。
具体的にはrubymysql apiモジュールライブラリで起きた

gem install mysql

でインストールすると mysql 2.8.1 が入る。
でもコレが実行時にエラー起きる。
エラーの内容は

LoadError: libmysqlclient.so.18: cannot open shared object file:  No such file or directory

と出る。
mysqlモジュールはnative extensionなので内部でmysql_api.soというファイルを生成してそれを利用している。
そこで

ldd /path/to/mysql_api.so

としてみると

libmysqlclient.so.18 => not found

と出て、libmysqlclient.so.18という依存ファイルが見つからないことが原因。

今回はmysqlをソースから入れてるんだけど、yumからインストールするとこの問題は起きない。
なぜかというとyumからインストールすると共有ライブラリの検索パスに/path/to/mysql/libを追加する設定を行なっているから。
詳しくは
/etc/ld.so.conf.d/mysql-x86_64.conf
が追加され、そこにlibmysqlclient.soが置かれている/path/to/mysql/libへのパスが書かれているので

gem install mysql

の時に生成されるmysql_api.soにしっかりと依存ファイルのlibmysqlclient.so.18が関連付けられている。

しかしソースからコンパイルするとそんなこと(/etc/ld.so.conf.d/mysql-x86_64.conf)はされないので自分で何かしらパスを教えてあげる必要がある。

見つからない時の対策

LD_LIBRARY_PATHの設定

対策の1つとして環境変数 LD_LIBRARY_PATH に /path/to/mysql/lib を追記するという方法があるが、これはすべてのコンパイル済みのsoファイルへ影響があるのであまり良くない。

/etc/ld.so.conf.d/以下にconfファイルの設置

二つ目はyumで入れたときにあった/etc/ld.so.conf.d/mysql-x86_64.confみたいに自分でconfファイルを/etc/ld.so.conf.d以下に置く
/etc/ld.so.confには

include ld.so.conf.d/*.conf

と書かれているので*.confという名前なら何でもIncludeしてくれる。
そこに

/path/to/mysql/lib

とだけ書かれたconfファイルを置いとけばいい。
あとは

gem install mysql

とするだけ。
これはコレでいい方法、なのだろうか。

ldconfigで一時的に探索パスを追加

多分一番良い方法としては、ldconfigを利用して /etc/ld.so.cache に一時的に /path/to/mysql/lib を追加すること。

具体的には

ldconfig /path/to/mysql/lib
gem install mysql

とすると

libmysqlclient.so.18 => /path/to/mysql/lib/libmysqlclient.so.18

と、ちゃんと関連付けられたsoファイルが出来上がる。

これと二つ目の方法は、一つ目の方法と何が違うかというと生成されたsoファイルのバイナリにしっかりと依存ライブラリが関連付けられているというところ。
LD_LIBRARY_PATHを設定しただけでは、コンパイル時にはlibmysqlclient.soファイルはnot foundな状態だが、実行時に検索パスの環境変数として見に行くことになる。

無事動いた

ということで、lddでnot foundなものが生成された場合はldconfigで必要なsoファイルの/path/to/libを追加してからコンパイルしなおしましょう。

と書いてみたんだけどあまり詳しくないのでもっといい方法があったり、説明が間違ってたりしたら誰か教えて下さい。

ちなみに

gem install mysql --with-mysql-config=/path/to/mysql/bin/mysql_config

とすると良いという方法がいろんな所に書かれてたんだけど、それをやってみても上手く動かなかった。
生成されたmysql_api.soを確認すると、確かに指定したlibmysqlclient.so.18を登録してるんだけど、バイナリに関連付けられていない。なのでlddするとnot foundになってる。
ちなみに引数に--with-mysql-configを指定しなくてもPATHに/path/to/mysql/binが設定されていればrubyスクリプト側がデフォルトで見てくれるので書く必要がない。

さらにmysqlモジュールの依存ライブラリにlibruby.soがあるんだけど、それはmysql_api.soのLibrary rpathに検索パスが登録されてる。
じゃあLibrary rpathに/path/to/mysql/libも追記すればいいのではと思ったけどこれって複数のパスは追記できないのかな?(無知)
gem installのオプションで指定できない(たぶん)のでどうするのがベストなのか誰かおしえてください。

結局どうするのが一番いい方法なのかわかってないです。