Introduction
備忘録。
自作の dylib を簡単なコンソールプログラムにリンクしたところ、下記のようなライブラリが読み込めないというエラーを吐いてしまった。
1 | $ ./program |
単純な疑問として、Linux のように同じディレクトリにライブラリを置くだけではダメなの?って思った。
How to resolve?
対処手段は幾つかある。
1. DYLD_LIBRARY_PATH を指定する
実行時に dylib を読み込む場所を指定する。
1 | $ DYLD_LIBRARY_PATH=$PWD ./program |
上記ではカレントディレクトリから dylib を読み込むように指示して実行するので、program
と同じディレクトリに dylib を配置すれば解決。
2. 実行ファイルを書き換える
DYLD_LIBRARY_PATH
で指定するのは一時的な方法だが、恒久的に対処する方法がある。
まず、otool
をつかって動的ライブラリの読込先を確認する。
1 | $ otool -l ./program |
または
1 | $ otool -L program |
でもよい。
とにかく、目的の動的ライブラリの読込み先が @rpath/libSample.dylib
であることがわかる。
では、この @rpath
は何かというと、実行時に動的ライブラリを探索するパスのリストを示している。
問題の出力メッセージにもあったように、
- ‘/System/Volumes/Preboot/Cryptexes/OS@rpath/libSample.dylib’ (no such file)
- ‘/usr/local/lib/libSample.dylib’ (no such file)
- ‘/usr/lib/libSample.dylib’ (no such file, not in dyld cache)
というように、システムパスを見に行っている。
ここに、カレントディレクトリのような任意のディレクトリを追加できればいい。
ちなみに rpath
は RPATH (Runpath Search Paths) であって Reference ではない。
具多的な対処は下記。
- executable_path を指定
1 | $ install_name_tool -add_rpath "@executable_path/." program |
otool -l
の結果が変化する。
1 | $ otool -l ./program |
- loader_path を指定
1 | $ install_name_tool -add_rpath "@loader_path/." program |
otool -l
の結果が変化する。
1 | $ otool -l ./program |
どちらも、最後に追加のセクションが現れる。otool -L
の結果は変化しないので注意。
@executable_path
と @loader_path
の違いは
@executable_path
は、実行時にローダーが実際のパスに置換するもので、上記の場合は 実行ファイルから見て同一のディレクトリ になる- 実行可能ファイルがディスク上に存在する場所である。
@executable_path/..
なら一つ上のディレクトリになる。
@loader_path
は、実行時にローダーが実際のパスに置換するもので、上記の場合は 現在読み込まれているバイナリ (実行可能ファイルやライブラリ自体) から見て同一のディレクトリ になる- 現在読み込んでいるバイナリ (それがアプリケーション、ライブラリ、フレームワークなどであるかに関係なく) がディスク上に存在する場所である。
@loader_path/..
なら一つ上のディレクトリになる。
3. ビルド時に対処する
CMake で対処するとしたら下記のようにする。
1 | if (APPLE) |
ビルド後に生成されたプログラムに対する、otool -l
の結果が変化する。
1 | $ otool -l ./program |
INSTALL_RPATH
は複数指定可能で、上記なら、実行ファイルと同じディレクトリまたは実行ファイルと同じディレクトリにある lib ディレクトリからライブラリを探しに行く。