CMAKE_SKIP_RPATH/CMAKE_SKIP_INSTALL_RPATH and INSTALL_NAME_DIR precedence on macOS
I don't know much about macOS, but I've been investigating a little about this with @francesco.romano.1987 and @claudiofantacci.
Apparently there is no way to get libraries installed with RPATH disabled and the full path in the install_name
.
We made a few tests combining all the options, and this is our result:
test |
SKIP_RPATH ^ |
INSTALL_RPATH † |
INSTALL_NAME_DIR |
MACOSX_RPATH |
RPATH | install_name |
---|---|---|---|---|---|---|
1 | OFF | DEFINED | DEFINED | ON | set | /path/foo.dylib |
2 | OFF | DEFINED | DEFINED | OFF | set | /path/foo.dylib |
3 | OFF | DEFINED | NOT DEFINED | ON | set | @rpath/foo.dylib |
4 | OFF | DEFINED | NOT DEFINED | OFF | set | foo.dylib |
5 | OFF | NOT DEFINED | DEFINED | ON | not set | /path/foo.dylib |
6 | OFF | NOT DEFINED | DEFINED | OFF | not set | /path/foo.dylib |
7 | OFF | NOT DEFINED | NOT DEFINED | ON | not set | @rpath/foo.dylib |
8 | OFF | NOT DEFINED | NOT DEFINED | OFF | not set | foo.dylib |
9 | ON | DEFINED | DEFINED | ON | not set | foo.dylib |
10 | ON | DEFINED | DEFINED | OFF | not set | foo.dylib |
11 | ON | DEFINED | NOT DEFINED | ON | not set | @rpath/foo.dylib |
12 | ON | DEFINED | NOT DEFINED | OFF | not set | foo.dylib |
13 | ON | NOT DEFINED | DEFINED | ON | not set | foo.dylib |
14 | ON | NOT DEFINED | DEFINED | OFF | not set | foo.dylib |
15 | ON | NOT DEFINED | NOT DEFINED | ON | not set | @rpath/foo.dylib |
16 | ON | NOT DEFINED | NOT DEFINED | OFF | not set | foo.dylib |
^ SKIP_RPATH
= CMAKE_SKIP_RPATH OR CMAKE_SKIP_INSTALL_RPATH
† INSTALL_RPATH
is considered DEFINED
even if NOT DEFINED
, but the INSTALL_RPATH_USE_LINK_PATH
is set and some linked libraries are outside the system paths.
As you can see from the table, there is no way to install a library with install_name=/path/foo.dylib
AND RPATH=not set
, unless you can somehow ensure that INSTALL_RPATH
is not set, and even if you can ensure that the INSTALL_RPATH_USE_LINK_PATH
property is not set, since it modifies the INSTALL_RPATH
property.
Is this the intended behaviour? From the behaviour of the green cases (1
, 2
, 5
and 6
that set install_name=/path/foo.dylib
and 11
and 15
that set install_name=@rpath/foo.dylib
, one would expect either that the red ones (13
and 14
) should be /path/foo.dylib
(i.e. INSTALL_NAME_DIR
wins over SKIP_RPATH
), or that 11
and 15
should not contain @rpath
and should be instad foo.dylib
(i.e. SKIP_RPATH
wins over INSTALL_NAME_DIR
).
Instead a mixed behaviour is used where neither INSTALL_NAME_DIR
nor SKIP_RPATH
has the precedence.
Also the documentation is not clear here (I'll report the relative documentation here to clarify):
MACOSX_RPATH
Whether this target on OS X or iOS is located at runtime using rpaths.
When this property is set to
TRUE
, the directory portion of theinstall_name
field of this shared library will be@rpath
unless overridden byINSTALL_NAME_DIR
. This indicates the shared library is to be found at runtime using runtime paths (rpaths).This property is initialized by the value of the variable
CMAKE_MACOSX_RPATH
if it is set when a target is created.Runtime paths will also be embedded in binaries using this target and can be controlled by the
INSTALL_RPATH
target property on the target linking to this target.Policy
CMP0042
was introduced to change the default value ofMACOSX_RPATH
toTRUE
. This is because use of@rpath
is a more flexible and powerful alternative to@executable_path
and@loader_path
.
INSTALL_NAME_DIR
Mac OSX directory name for installed targets.
INSTALL_NAME_DIR is a string specifying the directory portion of the "install_name" field of shared libraries on Mac OSX to use in the installed targets.
INSTALL_RPATH
The rpath to use for installed targets.
A semicolon-separated list specifying the rpath to use in installed targets (for platforms that support it). This property is initialized by the value of the variable CMAKE_INSTALL_RPATH if it is set when a target is created.
INSTALL_RPATH_USE_LINK_PATH
Add paths to linker search and installed rpath.
INSTALL_RPATH_USE_LINK_PATH is a boolean that if set to true will append directories in the linker search path and outside the project to the INSTALL_RPATH. This property is initialized by the value of the variable CMAKE_INSTALL_RPATH_USE_LINK_PATH if it is set when a target is created.
CMAKE_SKIP_INSTALL_RPATH
Do not include RPATHs in the install tree.
Normally CMake uses the build tree for the RPATH when building executables etc on systems that use RPATH. When the software is installed the executables etc are relinked by CMake to have the install RPATH. If this variable is set to true then the software is always installed without RPATH, even if RPATH is enabled when building. This can be useful for example to allow running tests from the build directory with RPATH enabled before the installation step. To omit RPATH in both the build and install steps, use
CMAKE_SKIP_RPATH
instead.
CMAKE_SKIP_RPATH
If true, do not add run time path information.
If this is set to
TRUE
, then the rpath information is not added to compiled executables. The default is to add rpath information if the platform supports it. This allows for easy running from the build tree. To omit RPATH in the install step, but not the build step, useCMAKE_SKIP_INSTALL_RPATH
instead.
Neither the CMAKE_SKIP_INSTALL_RPATH
nor the CMAKE_SKIP_RPATH
is documented to have any effect on the INSTALL_NAME_DIR
, nonetheless it has some influence on the install_name
when INSTALL_NAME_DIR
is set, but it has no effect when INSTALL_NAME_DIR
is not set.
I suggest either to update the documentation to document this behaviour or (imho a better option) to change 9
and 13
and maybe also 10
and 14
(or 2
and 6
) to use (or not) the INSTALL_NAME_DIR
variable coherently.
What do you think?