web-dev-qa-db-ja.com

Mac OS X(C ++)でdylibを使用する方法

Dylibを正常に呼び出すアプリケーション(実行可能ファイル)を作成しましたが、dylibファイルと実行可能ファイルは別のディレクトリにあります。 dylibファイルを含むディレクトリを$ PATH環境変数に追加しましたが、それでもロードされません。すべてのdylibファイルを実行可能ファイルにコピーすると、プログラムが最終的に実行されます。これにより、dylibファイルに問題がないことが確認されます。ただし、OSにそれを見つけるように指示するにはどうすればよいですか? Windowsでは、dllファイルを含むディレクトリパスを$ PATHに追加するだけです。 Mac OS Xで何をする必要がありますか?どうもありがとう!

34
Alfred Zhong

Justinが提供したリンクを読んだ後、@executable_pathトークンを使用して、dylib install_nameを実行可能ファイルのある同じディレクトリを指すように変更することに成功しました。

@ executable_path絶対パスは迷惑です。フレームワークを/ Libraryまたは同様の場所にインストールする代わりに、フレームワークをアプリケーションに埋め込む場合があります。

これに対するMacのソリューションは@executable_pathです。これは、ライブラリのインストール名の先頭に配置されると、それをロードする実行可能ファイルのパスから最後のコンポーネントを除いて展開されるマジックトークンです。たとえば、Bar.appがFoo.frameworkにリンクしているとします。 Bar.appが/ Applicationsにインストールされている場合、@ executable_pathは/Applications/Bar.app/Contents/MacOSに展開されます。フレームワークをContents/Frameworksに埋め込む場合は、Foo.frameworkのインストール名を@executable_path /../ Frameworks/Foo.framework/Versions/A/Fooに設定するだけです。動的リンカーはそれを/Applications/Bar.app/Contents/MacOS/../Frameworks/Foo.framework/Versions/A/Fooに展開し、そこでフレームワークを見つけます。

http://www.mikeash.com/pyblog/friday-qa-2009-11-06-linking-and-install-names.html

例を使って説明します。

次の実行可能ファイル/ opt/local/bin/convertがあり、そのdylibが/ opt/local/libにあるとします。別のディレクトリにコピーして、実行可能ファイルをコピーしたディレクトリと同じディレクトリからdylibをロードするようにします。

> mkdir ~/tmp/bin
> cp /opt/local/bin/convert ~/tmp/bin

実行可能ファイルdylibのリストを取得します

> otool -L ~/tmp/bin/convert
~/tmp/bin/convert:
    /opt/local/lib/libtiff.3.dylib (compatibility version 13.0.0, current version 13.5.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
    /opt/local/lib/libjpeg.8.dylib (compatibility version 12.0.0, current version 12.0.0)
    /opt/local/lib/libfontconfig.1.dylib (compatibility version 6.0.0, current version 6.4.0)
    /opt/local/lib/libiconv.2.dylib (compatibility version 8.0.0, current version 8.1.0)
    /opt/local/lib/libfreetype.6.dylib (compatibility version 15.0.0, current version 15.0.0)
    /opt/local/lib/libexpat.1.dylib (compatibility version 7.0.0, current version 7.2.0)
    /opt/local/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.6)
    /opt/local/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.6)
    ...

/ opt/local/libディレクトリー内のdylibのみが重要なので、/ opt内のdylibのみを引き出します。特に/ usr/lib/libSystemを参照して、他のすべてのdylib参照をそのまま保持したいと思います。

> DYLIBS=`otool -L ~/tmp/bin/convert | grep "/opt" | awk -F' ' '{ print $1 }'`

実行可能ファイルが参照するすべてのdylibを、実行可能ファイルがコピーされたのと同じディレクトリにコピーします。

> for dylib in $DYLIBS; do cp $dylib ~/tmp/bin/; done;

install_name_toolを使用して、上記の手順で取り出したすべてのdylibのインストール名を変更し、@executable_pathをdylib名の前に追加して置き換えます。これにより、動的リンカーは、実行可能ファイルが存在するディレクトリと同じディレクトリでdylibを検索します。

> for dylib in $DYLIBS; do install_name_tool -change $dylib @executable_path/`basename $dylib` ~/tmp/bin/convert; done;

インストール名が変更されていること、およびlibSystemがまだ/ usr/lib/libSystemを指していることを確認します。

> otool -L ~/tmp/bin/convert
~/tmp/bin/convert:
    @executable_path/libtiff.3.dylib (compatibility version 13.0.0, current version 13.5.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
    @executable_path/libjpeg.8.dylib (compatibility version 12.0.0, current version 12.0.0)
    @executable_path/libfontconfig.1.dylib (compatibility version 6.0.0, current version 6.4.0)
    @executable_path/libiconv.2.dylib (compatibility version 8.0.0, current version 8.1.0)
    @executable_path/libfreetype.6.dylib (compatibility version 15.0.0, current version 15.0.0)
    @executable_path/libexpat.1.dylib (compatibility version 7.0.0, current version 7.2.0)
    @executable_path/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.6)
    @executable_path/libz.1.dylib (compatibility version 1.0.0, current version 1.2.6)
    ...
38
Akos Cz

DYLD_LIBRARY_PATH環境変数を設定する必要があります。

dyld manページ から:

      This  is  a  colon  separated  list  of directories that contain libraries. The dynamic linker
      searches these directories before it searches the default locations for libraries.  It  allows
      you to test new versions of existing libraries.

      For  each  library  that  a program uses, the dynamic linker looks for it in each directory in
      DYLD_LIBRARY_PATH in turn. If it still can't find the library,  it  then  searches  DYLD_FALL-
      BACK_FRAMEWORK_PATH and DYLD_FALLBACK_LIBRARY_PATH in turn.
14
EmeryBerger
6
justin

DylibがライブラリのINSTALL_NAMEで指定された場所にある場合、Just Work *になります。

それ以外の場合は、dylibの場所をDYLD_LIBRARY_PATHに追加できます。 dyld documentation を読みたいかもしれません。

*)完全に正確であるためには、DYLD_ROOT_PATH/INSTALL_NAMEにある必要がありますが、DYLD_ROOT_PATHに煩わされることはほとんどありません。

2
Stephen Canon