web-dev-qa-db-de.com

So verwenden Sie dylib unter Mac OS X (C ++)

Ich habe eine Anwendung (eine ausführbare Datei) erstellt, die erfolgreich eine Dylib aufgerufen hat. Die Dylib-Dateien und die ausführbare Datei befinden sich jedoch in einem anderen Verzeichnis. Ich habe der Umgebungsvariablen $ PATH das Verzeichnis mit den Dylib-Dateien hinzugefügt, es wird jedoch immer noch nicht geladen. Ich kopiere alle Dylib-Dateien in die ausführbare Datei, das Programm läuft schließlich. Dies bestätigt, dass die Dylib-Dateien kein Problem haben. Wie kann ich dem Betriebssystem jedoch mitteilen, dass es es finden soll? In Windows muss ich nur den Verzeichnispfad hinzufügen, der DLL-Dateien zu $ ​​PATH enthält. Was muss ich für Mac OS X tun? Danke vielmals!

34
Alfred Zhong

Nachdem ich den von Justin bereitgestellten Link gelesen hatte, konnte ich das Token @executable_path Verwenden, um meinen dylib-Installationsnamen so zu ändern, dass er auf dasselbe Verzeichnis verweist, in dem sich meine ausführbare Datei befindet.

@ executable_path Absolute Pfade nerven. Manchmal möchten Sie ein Framework in eine Anwendung einbetten, anstatt das Framework in/Library oder an einem ähnlichen Speicherort installieren zu müssen.

Die Mac-Lösung dafür ist @executable_path. Dies ist ein magisches Token, das am Anfang des Installationsnamens einer Bibliothek auf den Pfad der ausführbaren Datei erweitert wird, die es lädt, abzüglich der letzten Komponente. Angenommen, Bar.app verlinkt gegen Foo.framework. Wenn Bar.app in/Applications installiert ist, wird @executable_path zu /Applications/Bar.app/Contents/MacOS erweitert. Wenn Sie das Framework in Contents/Frameworks einbetten möchten, können Sie den Installationsnamen von Foo.framework einfach auf @executable_path /../ Frameworks/Foo.framework/Versions/A/Foo setzen. Der dynamische Linker erweitert dies zu /Applications/Bar.app/Contents/MacOS/../Frameworks/Foo.framework/Versions/A/Foo und findet dort das Framework.

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

Ich werde mit einem Beispiel demonstrieren.

Angenommen, ich habe die folgende ausführbare Datei /opt/local/bin/convert und ihre Dylibs befinden sich in /opt/local/lib. Ich möchte es in ein anderes Verzeichnis kopieren und seine Dylibs aus demselben Verzeichnis laden lassen, in das ich die ausführbare Datei kopiert habe.

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

Rufen Sie eine Liste der ausführbaren Dylibs ab

> 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)
    ...

Ich kümmere mich nur um die Dylibs in /opt/local/lib dir, also ziehen wir nur Dylibs in /opt heraus. Ich möchte alle anderen dylib-Referenzen intakt halten, insbesondere für /usr/lib/libSystem Sachen.

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

Kopieren Sie alle Dylibs, auf die die ausführbare Datei verweist, in dasselbe Verzeichnis, in das die ausführbare Datei kopiert wurde.

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

Verwenden Sie den install_name_tool, Um den Installationsnamen aller Dylibs zu ändern, die wir im obigen Schritt herausgezogen haben, und ersetzen Sie sie, indem Sie dem Dylib-Namen den @executable_path Voranstellen. Dadurch sucht der Dynamic Linker in demselben Verzeichnis nach der Dylib, in dem sich die ausführbare Datei befindet.

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

Stellen Sie sicher, dass die Installationsnamen geändert wurden und dass libSystem immer noch auf /usr/lib/libSystem zeigt.

> 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

Sie müssen das DYLD_LIBRARY_PATH Umgebungsvariable.

Aus der dyld man page :

      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

Befindet sich die Dylib an der in INSTALL_NAME der Bibliothek angegebenen Stelle, funktioniert sie einfach *.

Andernfalls können Sie den Speicherort der Dylib zu DYLD_LIBRARY_PATH hinzufügen. Vielleicht möchten Sie die dyld-Dokumentation lesen .

*) Um ganz genau zu sein, muss es bei DYLD_ROOT_PATH/INSTALL_NAME sein, aber es ist ziemlich selten, mit DYLD_ROOT_PATH zu fummeln.

2
Stephen Canon