Reputation: 6429
When linking an executable with a dylib, is install_name_tool
the only way to make the dylib path relative to the executable, or is there a way of doing so in clang's linking step?
Given the following project structure:
- Project Root
| compile.sh
- lib_src
| myprint.cpp
| myprint.h
- main_src
| main.cpp
with these files: https://gist.github.com/JohannesMP/8fa140b60b8ffeb2cae0
Running compile.sh
(used instead of a make file for simplicity's sake here) results in the following files:
- Project Root
| main (a unix executable linked to myprint.dylib)
| myprint.dylib (a dynamic library that main uses)
Running the program with ./main
while cd
'd into the project works fine, but attempting to run it from anywhere else, such as by simply double clicking it, will result in the following error:
dyld: Library not loaded: myprint.dylib
Referenced from: /Users/Jo/Sandbox/libtest/main
Reason: image not found
Trace/BPT trap: 5
When inspecting main with otool
I can see that this is because the path for myprint.dylib is not defined in terms of the executable:
$ otool -L main
main:
myprint.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
As far as I've been able to find out, the suggested way to fix this is by using install_name_tool -change
and modify the path to use @executable_path
:
install_name_tool -change myprint.dylib @executable_path/myprint.dylib main
While the above fix clearly works, it seems somewhat unintuitive to me that there is no way of telling clang to just link main
in such a way that it already uses the @executable_path
to start with. It seems odd that when compiling a program with an arbitrary number of dylibs, that this has to be done for every single one.
Is this really the only way? Is this what cmake and xcode do under the hood? Is there a reason why we can't just have clang++
link relatively rather than absolutely by default?
I have found some tools that make the process easier, such as the mac dylib bundler, but I'm curious if anyone has any insight as to why it is done this way.
Is there a way to change just this line to avoid having to run install_name_tool -change
?
Upvotes: 5
Views: 3217
Reputation: 6429
It is indeed possible:
When compiling my library I set its install_name
to be in terms of @rpath
:
clang++ -dynamiclib lib_src/myprint.cpp -o myprint.dylib -install_name @rpath/myprint.dylib
And then in when compiling the executable I set rpath
to be in terms of @executable_path
, which can be done in a single step:
clang++ main_src/main.cpp -o main -I ./lib_src myprint.dylib -rpath @executable_path
For a detailed explanation of @rpath
and @executable_path
please check this wiki: https://wincent.com/wiki/@executable_path,_@load_path_and_@rpath
Upvotes: 5