RPATH: Add SKIP_INSTALL_RPATH target property

Re-implement the CMAKE_SKIP_INSTALL_RPATH variable in terms of the
property, with a policy for compatibility.

Fixes: #28213
This commit is contained in:
Robert Maynard authored and Brad King committed 2026-11-03 10:14:20 -05:00
1 parent 2d4a6a6fbd
commit 0a9fcf679e
20 files changed
+186 -9

No files matched your search

+1
View File
@@ -100,6 +100,7 @@ Policies Introduced by CMake 4.6
.. toctree::
:maxdepth: 1
CMP0229: The CMAKE_SKIP_INSTALL_RPATH variable takes effect at target creation. </policy/CMP0229>
CMP0228: File set usage requirements are evaluated for the consumer. </policy/CMP0228>
CMP0227: AIX shared objects are named with VERSION and SOVERSION. </policy/CMP0227>
+1
View File
@@ -455,6 +455,7 @@ Properties on Targets
/prop_tgt/RUNTIME_OUTPUT_NAME_CONFIG
/prop_tgt/Rust_EDITION
/prop_tgt/SKIP_BUILD_RPATH
/prop_tgt/SKIP_INSTALL_RPATH
/prop_tgt/SKIP_LINTING
/prop_tgt/SOURCE_DIR
/prop_tgt/SOURCE_DIRS
+27
View File
@@ -0,0 +1,27 @@
CMP0229
-------
.. versionadded:: 4.6
The :variable:`CMAKE_SKIP_INSTALL_RPATH` variable takes effect at target creation.
CMake 4.5 and below apply the :variable:`CMAKE_SKIP_INSTALL_RPATH` variable's
value at the end of each directory to every target in that directory. CMake
4.6 and above instead prefer to initialize the :prop_tgt:`SKIP_INSTALL_RPATH`
target property from the variable as each target is created. This policy
provides compatibility for projects expecting the prior behavior.
The ``OLD`` behavior for this policy ignores the value of the
:variable:`CMAKE_SKIP_INSTALL_RPATH` variable on target creation
and use its value at the end of each directory.
The ``NEW`` behavior for this policy uses the value of the
:variable:`CMAKE_SKIP_INSTALL_RPATH` variable at target creation to
initialize the :prop_tgt:`SKIP_INSTALL_RPATH` property. After that
the target property is used instead of the variable.
.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.6
.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
.. include:: include/STANDARD_ADVICE.rst
.. include:: include/DEPRECATED.rst
+18
View File
@@ -0,0 +1,18 @@
SKIP_INSTALL_RPATH
------------------
.. versionadded:: 4.6
Should rpaths be used for the install tree.
``SKIP_INSTALL_RPATH`` is a boolean property that when 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.
See also the :prop_tgt:`INSTALL_RPATH` target property.
This property is initialized by the value of the variable
:variable:`CMAKE_SKIP_INSTALL_RPATH` when policy :policy:`CMP0229` is
set to ``NEW``.
@@ -0,0 +1,7 @@
SKIP_INSTALL_RPATH_target_property
----------------------------------
* The :prop_tgt:`SKIP_INSTALL_RPATH` target property was added to control
whether a target is installed without an RPATH on a per-target basis.
It is initialized by the :variable:`CMAKE_SKIP_INSTALL_RPATH` variable.
See policy :policy:`CMP0229`.
+7 -3
View File
@@ -11,9 +11,13 @@ 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.
.. versionchanged:: 4.6
This variable is used to initialize the :prop_tgt:`SKIP_INSTALL_RPATH` target
property when a target is created. See policy :policy:`CMP0229`.
For more information on RPATH handling see
the :prop_tgt:`INSTALL_RPATH` and :prop_tgt:`BUILD_RPATH` target properties.
See also the :variable:`CMAKE_SKIP_BUILD_RPATH` variable.
To omit ``RPATH`` in both the build and install steps, use
:variable:`CMAKE_SKIP_RPATH` instead.
For more information on RPATH handling see the :prop_tgt:`INSTALL_RPATH`
and :prop_tgt:`BUILD_RPATH` target properties.
+1 -1
View File
@@ -2228,7 +2228,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
(outputRuntime && this->Target->HaveBuildTreeRPATH(this->Config) &&
!linking_for_install);
bool use_link_rpath = outputRuntime && linking_for_install &&
!this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH") &&
!this->Target->SkipInstallRPATH() &&
this->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH");
// Select whether to use $ORIGIN in RPATHs for artifacts in the build tree.
+13 -3
View File
@@ -1703,7 +1703,7 @@ bool cmGeneratorTarget::CanGenerateInstallNameDir(
bool skip = this->Makefile->IsOn("CMAKE_SKIP_RPATH");
if (name_type == INSTALL_NAME_FOR_INSTALL) {
skip |= this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
skip |= this->SkipInstallRPATH();
} else {
skip |= this->GetPropertyAsBool("SKIP_BUILD_RPATH");
}
@@ -5131,12 +5131,22 @@ bool cmGeneratorTarget::ComputePDBOutputDir(std::string const& kind,
return true;
}
bool cmGeneratorTarget::SkipInstallRPATH() const
{
if (cmValue skip = this->GetProperty("SKIP_INSTALL_RPATH")) {
return skip.IsOn();
}
if (this->GetPolicyStatusCMP0229() == cmPolicies::NEW) {
return false;
}
return this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
}
bool cmGeneratorTarget::HaveInstallTreeRPATH(std::string const& config) const
{
std::string install_rpath;
this->GetInstallRPATH(config, install_rpath);
return !install_rpath.empty() &&
!this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
return !install_rpath.empty() && !this->SkipInstallRPATH();
}
bool cmGeneratorTarget::GetBuildRPATH(std::string const& config,
+2
View File
@@ -1094,6 +1094,8 @@ public:
cm::string_view prop, cm::GenEx::Context const& context,
cmGeneratorExpressionDAGChecker const* dagChecker) const;
bool SkipInstallRPATH() const;
bool HaveInstallTreeRPATH(std::string const& config) const;
bool GetBuildRPATH(std::string const& config, std::string& rpath) const;
+7 -2
View File
@@ -688,7 +688,11 @@ class cmMakefile;
WARN) \
SELECT(POLICY, CMP0228, \
"File set usage requirements are evaluated for the consumer.", 4, 6, \
0, WARN)
0, WARN) \
SELECT(POLICY, CMP0229, \
"The CMAKE_SKIP_INSTALL_RPATH variable takes effect at target " \
"creation.", \
4, 6, 0, WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@@ -750,7 +754,8 @@ class cmMakefile;
F(CMP0216) \
F(CMP0226) \
F(CMP0227) \
F(CMP0228)
F(CMP0228) \
F(CMP0229)
#define CM_FOR_EACH_CUSTOM_COMMAND_POLICY(F) \
F(CMP0116) \
+7
View File
@@ -1194,6 +1194,13 @@ cmTarget::cmTarget(std::string name, cm::TargetType type, Visibility vis,
this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
}
if (this->GetPolicyStatus(cmPolicies::CMP0229) == cmPolicies::NEW &&
metConditions.count(TargetProperty::InitCondition::CanCompileSources)) {
if (cmValue value = mf->GetDefinition("CMAKE_SKIP_INSTALL_RPATH")) {
this->SetProperty("SKIP_INSTALL_RPATH", value);
}
}
// check for "CMAKE_VS_GLOBALS" variable and set up target properties
// if any
cmValue globals = mf->GetDefinition("CMAKE_VS_GLOBALS");
@@ -33,6 +33,18 @@ if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/Genex-build -P ${RunCMake_SOURCE_DIR}/GenexCheck.cmake)
run_RuntimePath(SysrootSlash)
run_RuntimePath(SkipInstallRPATHVariable)
run_cmake_command(SkipInstallRPATHVariableCheck
${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/SkipInstallRPATHVariable-build -P ${RunCMake_SOURCE_DIR}/SkipInstallRPATHCheck.cmake)
run_RuntimePath(SkipInstallRPATHProperty)
run_cmake_command(SkipInstallRPATHPropertyCheck
${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/SkipInstallRPATHProperty-build -P ${RunCMake_SOURCE_DIR}/SkipInstallRPATHCheck.cmake)
run_RuntimePath(SkipInstallRPATHPropertyOld)
run_cmake_command(SkipInstallRPATHPropertyOldCheck
${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/SkipInstallRPATHPropertyOld-build -P ${RunCMake_SOURCE_DIR}/SkipInstallRPATHCheck.cmake)
endif()
block()
@@ -0,0 +1,16 @@
function(check_rpath name expect_rpath)
file(GLOB_RECURSE files "${dir}/${name}")
list(LENGTH files count)
if(NOT count EQUAL 1)
message(FATAL_ERROR "Expected one '${name}' under '${dir}', found: ${files}")
endif()
file(STRINGS "${files}" found REGEX "/opt/foo/lib")
if(expect_rpath AND NOT found)
message(SEND_ERROR "'${name}' is missing the expected RPATH /opt/foo/lib")
elseif(NOT expect_rpath AND found)
message(SEND_ERROR "'${name}' unexpectedly contains RPATH /opt/foo/lib")
endif()
endfunction()
check_rpath(skipped FALSE)
check_rpath(kept TRUE)
@@ -0,0 +1,19 @@
cmake_policy(SET CMP0229 NEW)
enable_language(C)
add_library(A STATIC A.c)
add_executable(skipped main.c)
target_link_libraries(skipped A)
set_target_properties(skipped PROPERTIES
INSTALL_RPATH /opt/foo/lib
BUILD_WITH_INSTALL_RPATH 1
SKIP_INSTALL_RPATH ON
)
add_executable(kept main.c)
target_link_libraries(kept A)
set_target_properties(kept PROPERTIES
INSTALL_RPATH /opt/foo/lib
BUILD_WITH_INSTALL_RPATH 1
)
@@ -0,0 +1,22 @@
cmake_policy(SET CMP0229 OLD)
enable_language(C)
add_library(A STATIC A.c)
add_executable(skipped main.c)
target_link_libraries(skipped A)
set_target_properties(skipped PROPERTIES
INSTALL_RPATH /opt/foo/lib
BUILD_WITH_INSTALL_RPATH 1
)
# Control target created with the variable unset.
add_executable(kept main.c)
target_link_libraries(kept A)
set_target_properties(kept PROPERTIES
INSTALL_RPATH /opt/foo/lib
BUILD_WITH_INSTALL_RPATH 1
SKIP_INSTALL_RPATH OFF
)
set(CMAKE_SKIP_INSTALL_RPATH ON)
@@ -0,0 +1,20 @@
cmake_policy(SET CMP0229 NEW)
enable_language(C)
add_library(A STATIC A.c)
set(CMAKE_SKIP_INSTALL_RPATH ON)
add_executable(skipped main.c)
target_link_libraries(skipped A)
set_target_properties(skipped PROPERTIES
INSTALL_RPATH /opt/foo/lib
BUILD_WITH_INSTALL_RPATH 1
)
set(CMAKE_SKIP_INSTALL_RPATH OFF)
add_executable(kept main.c)
target_link_libraries(kept A)
set_target_properties(kept PROPERTIES
INSTALL_RPATH /opt/foo/lib
BUILD_WITH_INSTALL_RPATH 1
)
@@ -61,6 +61,7 @@
\* CMP0226
\* CMP0227
\* CMP0228
\* CMP0229
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
@@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 3.12)
project(${RunCMake_TEST} C)
# Make sure SKIP_INSTALL_RPATH property exists
cmake_policy(SET CMP0229 NEW)
set(main_sources main.c)
set(library_sources library.c)
@@ -105,6 +105,7 @@ set(properties
"INSTALL_REMOVE_ENVIRONMENT_RPATH" "ON" "<SAME>"
"INSTALL_RPATH" "@rpath/" "<SAME>"
"INSTALL_RPATH_USE_LINK_PATH" "ON" "<SAME>"
"SKIP_INSTALL_RPATH" "ON" "<SAME>"
## Platforms
### Android
"ANDROID_JAR_DIRECTORIES" "${dir}" "<SAME>"
@@ -37,6 +37,7 @@ set(not_in_table
# property reason
"notset" "Never initialized, checks the harness itself"
"SYSTEM" "Initialized separately for non-normal targets"
"SKIP_INSTALL_RPATH" "Initialized separately, conditional on CMP0229"
)
# Extract the property names from a "property reason" table.