macos - install_name_tool para actualizar un ejecutable para buscar dylib en Mac OS X
path ld (1)
Desde otool -l
, analicé lo que debería agregarse o modificarse desde la biblioteca original y el binario.
Dylib
El cambio está en 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)
Este es el comando para lograr el cambio:
install_name_tool -id "@loader_path/../lib/libtest.dylib" libtest.dylib
O utilice rpath:
install_name_tool -id "@rpath/libtest.dylib" libtest.dylib
El ejecutable
Hay dos cambios: rpath y 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)
Este es el comando para realizar el cambio.
install_name_tool -change libtest.dylib @loader_path/../lib/libtest.dylib myapp
También necesitaba añadir el rpath.
Load command 14
cmd LC_RPATH
cmdsize 32
path @loader_path/../lib (offset 12)
Este es el comando para llevar a cabo la adición:
install_name_tool -add_rpath "@loader_path/../lib" myapp
La idea
El binario intenta encontrar la biblioteca, sabe dónde se encuentra desde install_name_tool -add_rpath "@loader_path/../lib" myapp
. Carga la biblioteca, y el ID de la biblioteca es @rpath/libtest.dylib
donde @rpath
se establece en @loader_path/../lib
en el binario ejecutable para hacer la coincidencia.
Referencia
Cmake
Cuando usamos CMake, podemos automatizar el proceso con la siguiente adición en el archivo CMakeLists.txt.
BibliotecaEl id debe ser agregado.
# https://cmake.org/pipermail/cmake/2006-October/011530.html
SET_TARGET_PROPERTIES (test
PROPERTIES BUILD_WITH_INSTALL_RPATH 1
INSTALL_NAME_DIR "@rpath"
)
Ejecutable
El rpath debe ser especificado:
SET(CMAKE_INSTALL_RPATH "@loader_path/../lib/libtest.dylib")
Tengo un libray libtest.dylib dinámico que está instalado en /PATH/lib
, y un binario de ejecución, myapp, que usa el dylib instalado en /PATH/bin
.
Puedo ejecutar myapp
para encontrar el dylib de la siguiente manera ( ¿está bien usar DYLD_LIBRARY_PATH en Mac OS X? Y, ¿cuál es el algoritmo de búsqueda de biblioteca dinámica con él? ):
DYLD_LIBRARY_PATH="/PATH/lib" myapp
Creo que puedo usar install_name_tool
para actualizar la biblioteca y el ejecutable para que la biblioteca pueda encontrarse con rpath. Utilicé las sugerencias en esta publicación. ¿Cómo puedo especificar la ruta en un dylib? .
En lib, ejecuté este comando para agregar rpath.
install_name_tool -id "@rpath/libtest.dylib" libtest.dylib
install_name_tool -add_rpath "@executable_path/../lib/" libtest.dylib
En bin, install_name_tool -add_rpath "@executable_path/../lib/" myapp
.
Sin embargo, cuando myapp
en el directorio bin
, tengo los mensajes de error.
dyld: Library not loaded: libtest.dylib
Referenced from: /PATH/bin/./myapp
Reason: image not found
Trace/BPT trap: 5
otool -l myapp
muestra que la ruta se ha actualizado correctamente en myapp.
Load command 16
cmd LC_RPATH
cmdsize 40
path @executable_path/../lib/ (offset 12)
Lo mismo ocurre con libtest.dylib
Load command 13
cmd LC_RPATH
cmdsize 40
path @executable_path/../lib/ (offset 12)
¿Qué podría estar mal?
ADICIONAL
Por supuesto, puedo usar cc -install_name
cuando se compila y enlaza el tiempo, pero quería saber cómo hacer lo mismo al modificar el dylib generatd y el binario de ejecución.
De la lib
cc -install_name "@loader_path/../lib/libtest.dylib" -dynamiclib -o libtest.dylib test.c
O, el nombre de instalación puede usar @rpath:
cc -install_name "@rpath/libtest.dylib" -dynamiclib -o libtest.dylib test.c
De la papelera:
cc -I../lib -c main.c
cc -o main main.o ../lib/libtest.dylib -Wl,-rpath -Wl,@loader_path/../lib
O solo una línea:
cc -I../lib -L../lib -o main main.c -ltest -Wl,-rpath -Wl,@loader_path/../lib