J'ai un libray dynamique libtest.dylib qui est installé dans /PATH/lib
, et un binaire d’exécution, myapp, qui utilise le dylib installé dans /PATH/bin
.
Je peux exécuter myapp
pour trouver le fichier dylib comme suit ( Peut-on utiliser DYLD_LIBRARY_PATH sur Mac OS X? Et quel est l'algorithme de recherche de bibliothèque dynamique? ):
DYLD_LIBRARY_PATH="/PATH/lib" myapp
Je pense que je peux utiliser install_name_tool
pour mettre à jour la bibliothèque et l'exécutable afin que la bibliothèque puisse être trouvée avec rpath. J'ai utilisé les astuces dans ce post - Comment puis-je spécifier le rpath dans un dylib? .
Dans lib, j'ai exécuté cette commande pour ajouter rpath.
install_name_tool -id "@rpath/libtest.dylib" libtest.dylib
install_name_tool -add_rpath "@executable_path/../lib/" libtest.dylib
Dans bin, j'ai exécuté install_name_tool -add_rpath "@executable_path/../lib/" myapp
.
Cependant, lorsque j'ai exécuté myapp
dans le répertoire bin
, j'ai les messages d'erreur.
dyld: Library not loaded: libtest.dylib
Referenced from: /PATH/bin/./myapp
Reason: image not found
Trace/BPT trap: 5
otool -l myapp
montre que rpath est correctement mis à jour dans myapp.
Load command 16
cmd LC_RPATH
cmdsize 40
path @executable_path/../lib/ (offset 12)
La même chose est vraie avec libtest.dylib
Load command 13
cmd LC_RPATH
cmdsize 40
path @executable_path/../lib/ (offset 12)
Quel est le problème?
Bien sûr, je peux utiliser cc -install_name
quand compiler et lier du temps, mais je voulais savoir comment faire la même chose en modifiant le binaire généré et le binaire d’exécution.
De la lib:
cc -install_name "@loader_path/../lib/libtest.dylib" -dynamiclib -o libtest.dylib test.c
Ou, le nom_installation peut utiliser @rpath:
cc -install_name "@rpath/libtest.dylib" -dynamiclib -o libtest.dylib test.c
De la corbeille:
cc -I../lib -c main.c
cc -o main main.o ../lib/libtest.dylib -Wl,-rpath -Wl,@loader_path/../lib
Ou juste une ligne:
cc -I../lib -L../lib -o main main.c -ltest -Wl,-rpath -Wl,@loader_path/../lib
De otool -l
, J’ai analysé ce qui devrait être ajouté ou modifié à partir de la bibliothèque d’origine et binaire.
Le changement est dans 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)
C'est la commande pour accomplir le changement:
install_name_tool -id "@loader_path/../lib/libtest.dylib" libtest.dylib
Ou utilisez rpath:
install_name_tool -id "@rpath/libtest.dylib" libtest.dylib
Il y a deux changements: rpath et 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)
Ceci est la commande pour accomplir le changement
install_name_tool -change libtest.dylib @loader_path/../lib/libtest.dylib myapp
Aussi j'avais besoin d'ajouter le rpath
Load command 14
cmd LC_RPATH
cmdsize 32
path @loader_path/../lib (offset 12)
C'est la commande pour accomplir l'addition:
install_name_tool -add_rpath "@loader_path/../lib" myapp
Le binaire essaie de trouver la bibliothèque, il sait où il se trouve à partir de install_name_tool -add_rpath "@loader_path/../lib" myapp
. Il charge la bibliothèque et son identifiant est @rpath/libtest.dylib
où @rpath
est réglé sur @loader_path/../lib
dans le binaire exécutable pour faire la correspondance.
Lors de l'utilisation de CMake, nous pouvons automatiser le processus avec l'ajout suivant dans le fichier CMakeLists.txt.
L'identifiant devrait être ajouté.
# https://cmake.org/pipermail/cmake/2006-October/011530.html
SET_TARGET_PROPERTIES (test
PROPERTIES BUILD_WITH_INSTALL_RPATH 1
INSTALL_NAME_DIR "@rpath"
)
Le rpath doit être spécifié:
SET(CMAKE_INSTALL_RPATH "@loader_path/../lib/libtest.dylib")