I have been struggling with this concept for a while and I cannot really understand what the difference is between -change and -id.The man page states
-id name
Changes the shared library identification name of a dynamic shared library to name. If the Mach-O binary is not a dynamic
shared library and the -id option is specified it is ignored.
-change old new
Changes the dependent shared library install name old to new in the specified Mach-O binary. More than one of these options
can be specified. If the Mach-O binary does not contain the old install name in a specified -change option the option is
ignored.
So far I have experimented with -change. Suppose I have the following structure
Test.App
|_Contents
|_MacOS
| |_test -----> item A
|_Library
|_test_library.dylib --->item B
|_another_library.dylib --->item C
Now suppose I ran the following on itemB
$ otool -L test_library.dylib
test_library.dylib
/some/path/another_library.dylib -->item D
The above result indicates that test_library.dylib depends on another_library.dylib now if I needed to change the location of another_library.dylib I would do this
install_name_tool -change /some/path/another_library.dylib some/new/path/another_library.dylib test_library.dylib
this would change the location of item D. My question is what does install-name_tool -id do and when do I use that ?
Install Name
The term install name refers to the exact path of the
.dylibfile in the end-user system so the runtime linker can find and load the dynamic library.The name can be either:
.dylibwill be embedded in the app bundle and on the developer system they will be either pre-built in/usr/local,/opt/localor somewhere else, or they will be built from source as part of the app build.The latter is the main problem as when the
.dylibis built, its install name is stamped into the.dylibby the linker and that's where it's expected to be found and loaded from at runtime. Obviously this won't work on the end-user system as that path only exists on the developer's system, so the solution is to useinstall_name_toolto modify the install name of the libraries, and executables that reference those libraries, when putting the app bundle together.Placeholders
As executables/app bundles can be installed in different places on the end-user system you can use a placeholder system to abstract the install name location:
@executable_path: The full path of the main executable.@loader_path: The full path of the referencing executable or.dylib.@rpath: The RPATH set in the main executable. This can also be changed usinginstall_name_tool.So for example in a macOS app bundle the executable would be in
TheApp.app/Contents/MacOS/TheAppand libraries would be inTheApp.app/Contents/Frameworksso you would want to reference the libraries using the path@executable_path/../Frameworks/Library.dylib.It's better to set RPATH of the main executable to
@executable_path/../Frameworkshowever, and refer to the libraries using@rpath/Library.dylib.install_name_tool
install_name_toolhas two main options:-id: This sets the install name of the.dylibfile itself and will be used as the prototype install name from that point forward when something links with the.dylib. You could "correct" the install name immediately after building the.dylib, however that's an unusual workflow as how would a library know about the environment of whatever is using it?-change: This changes the install name of a.dylibwithin a referencing executable (or dylib).What happens when the
-idname doesn't match the.dylibs location on disk? Nothing. The-changeoption is the important one to get right as once the runtime linker has found the.dylibthen that's mission accomplished.Why have an
-idname at all? Surely if the linker is told to look for libraries indirA,dirB,dirC(using-Lfor example) and it finds the library it's looking for then why does the library itself have to have its-idstamped into it? No idea; it's probably some archaic nonsense.xcodedevtools
You would obviously script all this fixing-up as part of the build process, wouldn't you, and I've done that and published it here . See the
README.mdfor details of how to configure it within Xcode.