installer l'outil de nom pour mettre à jour un exécutable pour rechercher dylib dans Mac OS X
j'ai un libtest dynamique.dylib qui est installé dans /PATH/lib
, et un binaire d'exécution, myapp, qui utilise le dylib installé dans /PATH/bin
.
je peux courir myapp
pour trouver le dylib comme suit ( Est-il possible d'utiliser DYLD_LIBRARY_PATH sur Mac OS X? Et quel est l'algorithme de recherche dynamique de bibliothèque avec ça? ):
DYLD_LIBRARY_PATH="/PATH/lib" myapp
je pense que je peux utiliser install_name_tool
pour mettre à jour la bibliothèque et exécutable pour que la bibliothèque puisse être trouvée avec rpath. J'ai utilisé les indices 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
à 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 le rpath est correctement mis à jour dans myapp.
Load command 16
cmd LC_RPATH
cmdsize 40
path @executable_path/../lib/ (offset 12)
il en est de même avec libtest.dylib
Load command 13
cmd LC_RPATH
cmdsize 40
path @executable_path/../lib/ (offset 12)
Qu'est-ce qui ne va pas?
ajouté
bien sûr, je peux utiliser cc -install_name
lors de la compilation et du temps de liaison, mais je voulais savoir comment faire la même chose en modifiant le dylib générique et le binaire d'exécution.
Dans le répertoire "lib":
cc -install_name "@loader_path/../lib/libtest.dylib" -dynamiclib -o libtest.dylib test.c
ou, le nom d'installation peut utiliser @rpath:
cc -install_name "@rpath/libtest.dylib" -dynamiclib -o libtest.dylib test.c
De la poubelle:
cc -I../lib -c main.c
cc -o main main.o ../lib/libtest.dylib -Wl,-rpath -Wl,@loader_path/../lib
ou une seule ligne:
cc -I../lib -L../lib -o main main.c -ltest -Wl,-rpath -Wl,@loader_path/../lib
1 réponses
à Partir de otool -l
, j'ai analysé ce qui doit être ajouté ou modifié à partir de la bibliothèque d'origine, et en binaire.
Dylib
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 utiliser rpath:
install_name_tool -id "@rpath/libtest.dylib" libtest.dylib
L'exécutable
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)
c'est la commande pour accomplir le changement
install_name_tool -change libtest.dylib @loader_path/../lib/libtest.dylib myapp
il me fallait aussi 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
l'idée
le binaire essaie de trouver la bibliothèque, il sait où elle est située à partir de install_name_tool -add_rpath "@loader_path/../lib" myapp
. Il charge la bibliothèque, et l'id de la Bibliothèque est @rpath/libtest.dylib
où @rpath
est défini à @loader_path/../lib
dans le binaire exécutable pour faire la correspondance.
référence
Cmake
lors de L'utilisation de CMake, nous pouvons automatiser le processus avec L'ajout suivant dans CMakeLists.fichier txt.
BibliothèqueL'id doit ê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"
)
Exécutable
le rpath doit être spécifié:
SET(CMAKE_INSTALL_RPATH "@loader_path/../lib/libtest.dylib")