install_name_tool to update a executable to search for dylib in Mac OS X
From otool -l
, I analyzed what should be added or modified from the original library and binary.
Dylib
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
The executable
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 idea
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.
Reference
Cmake
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")
prosseek
A software engineer/programmer/researcher/professor who loves everything about software building. Programming Language: C/C++, D, Java/Groovy/Scala, C#, Objective-C, Python, Ruby, Lisp, Prolog, SQL, Smalltalk, Haskell, F#, OCaml, Erlang/Elixir, Forth, Rebol/Red Programming Tools and environments: Emacs, Eclipse, TextMate, JVM, .NET Programming Methodology: Refactoring, Design Patterns, Agile, eXtreme Computer Science: Algorithm, Compiler, Artificial Intelligence
Updated on November 30, 2020Comments
-
prosseek over 3 years
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
inbin
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?
ADDED
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
-
v.shashenko almost 7 yearsIt seems that the attributes in a dylib don't really matter during runtime. They are used only during the build time to copy the attributes from the dylib to the executable. For the case when you already have an executable linked to a dylib but you need to change the paths, then it's enough to edit only the executable to set LC_LOAD_DYLIB and, optionally, LC_RPATH. The second is needed only if the first one has @rpath in it.