web-dev-qa-db-ja.com

Mac OS Xでdylibを検索するための実行可能ファイルを更新するinstall_name_tool

/PATH/libにインストールされている動的ライブラリーlibtest.dylibと、/PATH/binにインストールされているdylibを使用する実行バイナリmyappがあります。

次のようにmyappを実行してdylibを見つけることができます( Mac OS XでDYLD_LIBRARY_PATHを使用しても大丈夫ですか?また、動的ライブラリ検索アルゴリズムは何ですか? ):

DYLD_LIBRARY_PATH="/PATH/lib" myapp 

ライブラリがrpathで見つかるように、install_name_toolを使用してライブラリと実行可能ファイルを更新できると思います。この投稿でヒントを使用しました- dylibでrpathを指定するにはどうすればよいですか?

Libでは、このコマンドを実行してrpathを追加しました。

install_name_tool -id "@rpath/libtest.dylib" libtest.dylib
install_name_tool -add_rpath "@executable_path/../lib/" libtest.dylib

ビンで、install_name_tool -add_rpath "@executable_path/../lib/" myappを実行しました。

ただし、myappディレクトリでbinを実行すると、エラーメッセージが表示されます。

dyld: Library not loaded: libtest.dylib
  Referenced from: /PATH/bin/./myapp
  Reason: image not found
Trace/BPT trap: 5

otool -l myappは、myappでrpathが正しく更新されたことを示します。

Load command 16
          cmd LC_RPATH
      cmdsize 40
         path @executable_path/../lib/ (offset 12)

Libtest.dylibでも同様です

Load command 13
          cmd LC_RPATH
      cmdsize 40
         path @executable_path/../lib/ (offset 12)

何が悪いのでしょうか?

追加されました

もちろん、コンパイル時とリンク時にcc -install_nameを使用できますが、generatd dylibと実行バイナリを変更して同じことを行う方法を知りたいと思いました。

ライブラリから:

cc -install_name "@loader_path/../lib/libtest.dylib" -dynamiclib -o libtest.dylib test.c

または、install_nameは@rpathを使用できます。

cc -install_name "@rpath/libtest.dylib" -dynamiclib -o libtest.dylib test.c

ビンから:

cc -I../lib -c main.c
cc -o main main.o ../lib/libtest.dylib -Wl,-rpath -Wl,@loader_path/../lib

または1行だけ:

cc -I../lib -L../lib -o main main.c -ltest -Wl,-rpath -Wl,@loader_path/../lib
35
prosseek

otool -lから、元のライブラリとバイナリに追加または変更する必要があるものを分析しました。

ダイリブ

変更はidにあります:

Load command 2 <-- OLD
          cmd LC_ID_DYLIB
      cmdsize 40
         name libtest.dylib (offset 24)
   time stamp 1 Wed Dec 31 18:00:01 1969

Load command 2 <-- NEW
          cmd LC_ID_DYLIB
      cmdsize 64
         name @loader_path/../lib/libtest.dylib (offset 24)

これは、変更を行うためのコマンドです。

install_name_tool -id "@loader_path/../lib/libtest.dylib" libtest.dylib 

または、rpathを使用します。

install_name_tool -id "@rpath/libtest.dylib" libtest.dylib

実行可能ファイル

2つの変更点があります:rpathとload_dylib

Load command 12 <-- OLD
          cmd LC_LOAD_DYLIB
      cmdsize 40
         name libtest.dylib (offset 24)

Load command 12 <-- NEW
          cmd LC_LOAD_DYLIB
      cmdsize 64
         name @loader_path/../lib/libtest.dylib (offset 24)

これは、変更を達成するためのコマンドです

install_name_tool -change libtest.dylib @loader_path/../lib/libtest.dylib myapp 

また、rpathを追加する必要がありました

Load command 14
          cmd LC_RPATH
      cmdsize 32
         path @loader_path/../lib (offset 12)

これは、追加を実行するコマンドです。

 install_name_tool -add_rpath "@loader_path/../lib" myapp

アイデア

バイナリはライブラリを見つけようとし、install_name_tool -add_rpath "@loader_path/../lib" myappからどこにあるかを認識します。ライブラリをロードし、ライブラリのIDは@rpath/libtest.dylibです。@rpathは、実行可能バイナリで@loader_path/../libに設定され、一致します。

参照

Cmake

CMakeを使用する場合、CMakeLists.txtファイルに以下を追加することでプロセスを自動化できます。

IDを追加する必要があります。

# https://cmake.org/pipermail/cmake/2006-October/011530.html
SET_TARGET_PROPERTIES (test
  PROPERTIES BUILD_WITH_INSTALL_RPATH 1
             INSTALL_NAME_DIR "@rpath"
  )

Rpathを指定する必要があります。

SET(CMAKE_INSTALL_RPATH "@loader_path/../lib/libtest.dylib")
37
prosseek