I have a collection of projects that I'm compiling as dynamic libraries. Each of these .dylibs depend on other various .dylibs that I would like to place in various other directories (i.e. some at the executable path, some at the loader path, some at a fixed path).
When I run otool -L
on the compiled libraries, I get a list of paths to those dependencies but I have know idea how those paths are being set/determined. They almost appear pseudo random. I've spent hours messing with the "Build Settings" in Xcode to try and change these paths (w/ @rpath, @executable_path, @loader_path, etc.) but I can't seem to change anything (as checked by running otool -L
). I'm not even entirely sure where to add these flags and don't really understand the difference between the following or how to properly use them:
Linking - "Dynamic Library Install Name"
Linking - "Runpath Search Paths"
Linking - "Other Linking Flags"
Search Paths - "Library Search Paths"
When I run install_name_tool -change
on the various libraries, I am able to successfully change the run path search paths (again as verified by running otool -L
to confirm).
I'm running Xcode 4.2 and I'm very close to giving up and just using a post-build script that runs install_tool_name to make the changes. But its a kludge hack fix and I'd prefer not to do it.
Where can I see how the search/run paths for the dylib dependencies are being set?
Anyone have any ideas on what I might be doing wrong?
In computing, rpath designates the run-time search path hard-coded in an executable file or library. Dynamic linking loaders use the rpath to find required libraries. Specifically, it encodes a path to shared libraries into the header of an executable (or another shared library).
executable_path is the parameter through which users can pass the absolute path of the GeckoDriver binary overriding the system path of GeckoDriver binary to be used for Firefox 47.0. 1 and greater.
The search paths for libraries come from three sources: the environment variable LD_LIBRARY_PATH (if set), any rpath encoded in the binary (more on this later), and the system default search paths. They're searched in this order, and the first matching library found is used.
By default, the runtime linker knows of only one standard place to look for libraries, /usr/lib when processing 32-bit objects, and /usr/lib/64 when processing 64-bit objects. All other directories to be searched must be added to the runtime linker's search path explicitly.
Typically, in my dylib's target, I set INSTALL_PATH
aka "Installation Directory" to the prefix I want (e.g. @executable_path/../Frameworks
).
I leave LD_DYLIB_INSTALL_NAME
aka "Dynamic Library Install Name" set to its default value, which is $(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)
.
Xcode expands that based on your target's name, so it might end up being @executable_path/../Frameworks/MyFramework.framework/Versions/A/MyFramework
, for instance.
The important thing to realize is that the install path is built into the dylib, as part of its build process. Later on, when you link B.dylib that refers to A.dylib, A.dylib's install path is copied into B.dylib. (That's what otool
is showing you -- those copied install paths.) So it's best to get the correct install path built into the dylib in the first place.
Before trying to get all the dylibs working together, check each one individually. Build it, then otool -L
on the built dylib. The first line for each architecture should be what LD_DYLIB_INSTALL_NAME
was showing you.
Once you have that organized, try to get the dylibs linking against each other. It should be much more straightforward.
install_name_tool
is very useful for setting the names and paths. Its especially useful if the program runs its self-tests in the build directory, and then things change during a make install
. In this case, you can use install_name_tool
without the need for a separate build.
install_name_tool
is also useful because Apple's LD does not honor rpath
linker options like Linux/GCC does. That is, you need to use a different set of commands to set them.
Here's the man page for it. Its included in its entirety because it discusses other options, like -headerpad_max_install_names
.
INSTALL_NAME_TOOL(1) INSTALL_NAME_TOOL(1)
NAME
install_name_tool - change dynamic shared library install names
SYNOPSIS
install_name_tool [-change old new ] ... [-rpath old new ] ...
[-add_rpath new ] ... [-delete_rpath new ] ... [-id name] file
DESCRIPTION
Install_name_tool changes the dynamic shared library install names and
or adds, changes or deletes the rpaths recorded in a Mach-O binary.
For this tool to work when the install names or rpaths are larger the
binary should be built with the ld(1) -headerpad_max_install_names
option.
-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.
-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.
-rpath old new
Changes the rpath path 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 rpath path name in a
specified -rpath it is an error.
-add_rpath new
Adds the rpath path name new in the specified Mach-O binary.
More than one of these options can be specified. If the Mach-O
binary already contains the new rpath path name specified in
-add_rpath it is an error.
-delete_rpath old
deletes the rpath path name old in the specified Mach-O binary.
More than one of these options can be specified. If the Mach-O
binary does not contains the old rpath path name specified in
-delete_rpath it is an error.
SEE ALSO
ld(1)
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