web-dev-qa-db-fra.com

Comment utiliser dylib dans Mac OS X (C ++)

J'ai fait une application (un exécutable) appelant certains dylib avec succès, cependant, les fichiers dylib et l'exécutable sont dans un répertoire différent. J'ai ajouté que le répertoire contient des fichiers dylib dans la variable d'environnement $ PATH, cependant, il ne se charge toujours pas. Je copie tous les fichiers dylib dans l'exécutable, le programme tourne enfin. Cela confirme que les fichiers dylib n'ont aucun problème. Cependant, comment dire au système d'exploitation de le trouver? Dans Windows, j'ai juste besoin d'ajouter le chemin du répertoire contenant les fichiers dll à $ PATH. Que dois-je faire pour Mac OS X? Merci beaucoup!

34
Alfred Zhong

Après avoir lu le lien fourni par Justin, j'ai réussi à utiliser le @executable_path jeton pour changer mon nom d'installation dylib pour pointer vers le même répertoire où se trouve mon exécutable.

@ executable_path Les chemins absolus sont ennuyeux. Parfois, vous souhaitez intégrer un cadre dans une application au lieu d'avoir à installer le cadre dans/Library ou un emplacement similaire.

La solution du Mac à cela est @executable_path. Il s'agit d'un jeton magique qui, lorsqu'il est placé au début du nom d'installation d'une bibliothèque, est étendu au chemin de l'exécutable qui le charge, moins le dernier composant. Par exemple, supposons que Bar.app soit lié à Foo.framework. Si Bar.app est installé dans/Applications, @executable_path se développera en /Applications/Bar.app/Contents/MacOS. Si vous avez l'intention d'incorporer le cadre dans Contents/Frameworks, vous pouvez simplement définir le nom d'installation de Foo.framework sur @executable_path /../ Frameworks/Foo.framework/Versions/A/Foo. L'éditeur de liens dynamique étendra cela à /Applications/Bar.app/Contents/MacOS/../Frameworks/Foo.framework/Versions/A/Foo et y trouvera le cadre.

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

Je vais démontrer avec un exemple.

Disons que j'ai l'exécutable suivant /opt/local/bin/convert et ses dylibs sont dans /opt/local/lib. Je veux le copier dans un autre répertoire et lui faire charger ses dylibs à partir du même répertoire que celui où j'ai copié l'exécutable.

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

Obtenir une liste des exécutables dylibs

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

Je ne me soucie que des dylibs dans le répertoire /opt/local/lib, donc nous ne retirons que les dylibs dans /opt. Je veux garder toutes les autres références dylib intactes, en particulier pour les choses /usr/lib/libSystem.

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

Copiez tous les dylibs auxquels l'exécutable fait référence dans le même répertoire où l'exécutable a été copié.

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

Utilisez le install_name_tool pour modifier le nom d'installation de tous les dylibs que nous avons retirés à l'étape ci-dessus, et les remplacer en ajoutant le @executable_path au nom de dylib. Cela fera que l'éditeur de liens dynamique recherchera le dylib dans le même répertoire que celui où se trouve l'exécutable.

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

Confirmez que les noms d'installation ont été modifiés et que libSystem pointe toujours sur /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

Vous devez définir le DYLD_LIBRARY_PATH variable d'environnement.

À partir de la page de manuel dyld :

      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

Si le dylib est à l'endroit spécifié par le INSTALL_NAME de la bibliothèque, il fonctionnera simplement *.

Sinon, vous pouvez ajouter l'emplacement du dylib à DYLD_LIBRARY_PATH. Vous voudrez peut-être lire la documentation dyld .

*) pour être totalement précis, il doit être à DYLD_ROOT_PATH/INSTALL_NAME, mais s'embêter avec DYLD_ROOT_PATH est assez rare.

2
Stephen Canon