I have a dynamic libray libtest.dylib that is installed in /PATH/lib
, and an execution binary, myapp, that uses the dylib installed in /PATH/bin
.
I can run myapp
to find the dylib as follows (Is it OK to use DYLD_LIBRARY_PATH on Mac OS X? And, what's the dynamic library search algorithm with it?):
DYLD_LIBRARY_PATH="/PATH/lib" myapp
I think I can use install_name_tool
to update the library and executable so that the library can be found with rpath. I used the hints in this post - How can I specify the rpath in a dylib?.
In lib, I executed this command to add rpath.
install_name_tool -id "@rpath/libtest.dylib" libtest.dylib install_name_tool -add_rpath "@executable_path/../lib/" libtest.dylib
In bin, I executed install_name_tool -add_rpath "@executable_path/../lib/" myapp
.
However, when I executed myapp
in bin
directory, I have the error messages.
dyld: Library not loaded: libtest.dylib Referenced from: /PATH/bin/./myapp Reason: image not found Trace/BPT trap: 5
otool -l myapp
shows the rpath is correctly updated in myapp.
Load command 16 cmd LC_RPATH cmdsize 40 path @executable_path/../lib/ (offset 12)
The same is true with libtest.dylib
Load command 13 cmd LC_RPATH cmdsize 40 path @executable_path/../lib/ (offset 12)
What might be wrong?
Of course, I can use cc -install_name
when compile and link time, but I wanted to know how to do the same thing my modifying the generatd dylib and execution binary.
From the lib:
cc -install_name "@loader_path/../lib/libtest.dylib" -dynamiclib -o libtest.dylib test.c
Or, the install_name can use @rpath:
cc -install_name "@rpath/libtest.dylib" -dynamiclib -o libtest.dylib test.c
From the bin:
cc -I../lib -c main.c cc -o main main.o ../lib/libtest.dylib -Wl,-rpath -Wl,@loader_path/../lib
Or just one line:
cc -I../lib -L../lib -o main main.c -ltest -Wl,-rpath -Wl,@loader_path/../lib
@rpath stands for Runpath Search Path. In the Xcode, it's set with LD_RUNPATH_SEARCH_PATH setting. In ld command tool it's set with -rpath parameter when linking. So it's a search path for the linker. Runtime Search Path instructs the dynamic linker to search a list of paths in order, to locate the dynamic library.
From otool -l
, I analyzed what should be added or modified from the original library and binary.
The change is in 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)
This is the command to accomplish the change:
install_name_tool -id "@loader_path/../lib/libtest.dylib" libtest.dylib
Or use rpath:
install_name_tool -id "@rpath/libtest.dylib" libtest.dylib
There are two changes: rpath and 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)
This is the command to accomplish the change
install_name_tool -change libtest.dylib @loader_path/../lib/libtest.dylib myapp
Also I needed to add the rpath
Load command 14 cmd LC_RPATH cmdsize 32 path @loader_path/../lib (offset 12)
This is the command to accomplish the addition:
install_name_tool -add_rpath "@loader_path/../lib" myapp
The binary tries to find the library, it knows where it is located from install_name_tool -add_rpath "@loader_path/../lib" myapp
. It loads the library, and the library's id is @rpath/libtest.dylib
where @rpath
is set to @loader_path/../lib
in the executable binary to make the match.
When using CMake, we can automatize the process with the following addition in CMakeLists.txt file.
LibraryThe id should be added.
# https://cmake.org/pipermail/cmake/2006-October/011530.html SET_TARGET_PROPERTIES (test PROPERTIES BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@rpath" )
Executable The rpath should be specified:
SET(CMAKE_INSTALL_RPATH "@loader_path/../lib/libtest.dylib")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With