mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-02 03:39:43 -06:00
BUILD_RPATH/INSTALL_RPATH: Add generator expression support
Fixes: #19423
This commit is contained in:
@@ -8,3 +8,6 @@ tree. See also the :prop_tgt:`INSTALL_RPATH` target property.
|
||||
|
||||
This property is initialized by the value of the variable
|
||||
:variable:`CMAKE_BUILD_RPATH` if it is set when a target is created.
|
||||
|
||||
This property supports
|
||||
:manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||
|
||||
@@ -7,3 +7,6 @@ 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 :variable:`CMAKE_INSTALL_RPATH` if it is set when
|
||||
a target is created.
|
||||
|
||||
This property supports
|
||||
:manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||
|
||||
5
Help/release/dev/build-install-rpath-genex.rst
Normal file
5
Help/release/dev/build-install-rpath-genex.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
build-install-rpath-genex
|
||||
-------------------------
|
||||
|
||||
* :prop_tgt:`BUILD_RPATH` and :prop_tgt:`INSTALL_RPATH` now support
|
||||
:manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||
@@ -1695,7 +1695,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
|
||||
(for_install ||
|
||||
this->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"));
|
||||
bool use_install_rpath =
|
||||
(outputRuntime && this->Target->HaveInstallTreeRPATH() &&
|
||||
(outputRuntime && this->Target->HaveInstallTreeRPATH(this->Config) &&
|
||||
linking_for_install);
|
||||
bool use_build_rpath =
|
||||
(outputRuntime && this->Target->HaveBuildTreeRPATH(this->Config) &&
|
||||
@@ -1715,15 +1715,17 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
|
||||
// Construct the RPATH.
|
||||
std::set<std::string> emitted;
|
||||
if (use_install_rpath) {
|
||||
const char* install_rpath = this->Target->GetProperty("INSTALL_RPATH");
|
||||
cmCLI_ExpandListUnique(install_rpath, runtimeDirs, emitted);
|
||||
std::string install_rpath;
|
||||
this->Target->GetInstallRPATH(this->Config, install_rpath);
|
||||
cmCLI_ExpandListUnique(install_rpath.c_str(), runtimeDirs, emitted);
|
||||
}
|
||||
if (use_build_rpath) {
|
||||
// Add directories explicitly specified by user
|
||||
if (const char* build_rpath = this->Target->GetProperty("BUILD_RPATH")) {
|
||||
std::string build_rpath;
|
||||
if (this->Target->GetBuildRPATH(this->Config, build_rpath)) {
|
||||
// This will not resolve entries to use $ORIGIN, the user is expected to
|
||||
// do that if necessary.
|
||||
cmCLI_ExpandListUnique(build_rpath, runtimeDirs, emitted);
|
||||
cmCLI_ExpandListUnique(build_rpath.c_str(), runtimeDirs, emitted);
|
||||
}
|
||||
}
|
||||
if (use_build_rpath || use_link_rpath) {
|
||||
|
||||
@@ -1612,7 +1612,7 @@ bool cmGeneratorTarget::NeedRelinkBeforeInstall(
|
||||
// will likely change between the build tree and install tree and
|
||||
// this target must be relinked.
|
||||
bool have_rpath =
|
||||
this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH();
|
||||
this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH(config);
|
||||
bool is_ninja =
|
||||
this->LocalGenerator->GetGlobalGenerator()->GetName() == "Ninja";
|
||||
|
||||
@@ -5479,13 +5479,41 @@ bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmGeneratorTarget::HaveInstallTreeRPATH() const
|
||||
bool cmGeneratorTarget::HaveInstallTreeRPATH(const std::string& config) const
|
||||
{
|
||||
const char* install_rpath = this->GetProperty("INSTALL_RPATH");
|
||||
return (install_rpath && *install_rpath) &&
|
||||
std::string install_rpath;
|
||||
this->GetInstallRPATH(config, install_rpath);
|
||||
return !install_rpath.empty() &&
|
||||
!this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
|
||||
}
|
||||
|
||||
bool cmGeneratorTarget::GetBuildRPATH(const std::string& config,
|
||||
std::string& rpath) const
|
||||
{
|
||||
return this->GetRPATH(config, "BUILD_RPATH", rpath);
|
||||
}
|
||||
|
||||
bool cmGeneratorTarget::GetInstallRPATH(const std::string& config,
|
||||
std::string& rpath) const
|
||||
{
|
||||
return this->GetRPATH(config, "INSTALL_RPATH", rpath);
|
||||
}
|
||||
|
||||
bool cmGeneratorTarget::GetRPATH(const std::string& config,
|
||||
const std::string& prop,
|
||||
std::string& rpath) const
|
||||
{
|
||||
const char* value = this->GetProperty(prop);
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cmGeneratorExpression ge;
|
||||
rpath = ge.Parse(value)->Evaluate(this->LocalGenerator, config);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
|
||||
const std::string& config, cmOptionalLinkInterface& iface,
|
||||
cmGeneratorTarget const* headTarget, bool usage_requirements_only) const
|
||||
@@ -6085,7 +6113,8 @@ bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const
|
||||
if (this->GetPropertyAsBool("SKIP_BUILD_RPATH")) {
|
||||
return false;
|
||||
}
|
||||
if (this->GetProperty("BUILD_RPATH")) {
|
||||
std::string build_rpath;
|
||||
if (this->GetBuildRPATH(config, build_rpath)) {
|
||||
return true;
|
||||
}
|
||||
if (cmLinkImplementationLibraries const* impl =
|
||||
|
||||
@@ -674,7 +674,10 @@ public:
|
||||
|
||||
class TargetPropertyEntry;
|
||||
|
||||
bool HaveInstallTreeRPATH() const;
|
||||
bool HaveInstallTreeRPATH(const std::string& config) const;
|
||||
|
||||
bool GetBuildRPATH(const std::string& config, std::string& rpath) const;
|
||||
bool GetInstallRPATH(const std::string& config, std::string& rpath) const;
|
||||
|
||||
/** Whether this library has \@rpath and platform supports it. */
|
||||
bool HasMacOSXRpathInstallNameDir(const std::string& config) const;
|
||||
@@ -913,6 +916,9 @@ private:
|
||||
|
||||
ManagedType CheckManagedType(std::string const& propval) const;
|
||||
|
||||
bool GetRPATH(const std::string& config, const std::string& prop,
|
||||
std::string& rpath) const;
|
||||
|
||||
public:
|
||||
const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure(
|
||||
const std::string& config) const;
|
||||
|
||||
29
Tests/RunCMake/RuntimePath/Genex.cmake
Normal file
29
Tests/RunCMake/RuntimePath/Genex.cmake
Normal file
@@ -0,0 +1,29 @@
|
||||
enable_language(C)
|
||||
|
||||
add_library(A STATIC A.c)
|
||||
|
||||
add_executable(buildge main.c)
|
||||
target_link_libraries(buildge A)
|
||||
set_target_properties(buildge PROPERTIES
|
||||
BUILD_RPATH $<1:/opt/foo/lib>
|
||||
)
|
||||
|
||||
add_executable(buildnoge main.c)
|
||||
target_link_libraries(buildnoge A)
|
||||
set_target_properties(buildnoge PROPERTIES
|
||||
BUILD_RPATH /opt/foo/lib
|
||||
)
|
||||
|
||||
add_executable(installge main.c)
|
||||
target_link_libraries(installge A)
|
||||
set_target_properties(installge PROPERTIES
|
||||
INSTALL_RPATH $<1:/opt/foo/lib>
|
||||
BUILD_WITH_INSTALL_RPATH 1
|
||||
)
|
||||
|
||||
add_executable(installnoge main.c)
|
||||
target_link_libraries(installnoge A)
|
||||
set_target_properties(installnoge PROPERTIES
|
||||
INSTALL_RPATH /opt/foo/lib
|
||||
BUILD_WITH_INSTALL_RPATH 1
|
||||
)
|
||||
7
Tests/RunCMake/RuntimePath/GenexCheck.cmake
Normal file
7
Tests/RunCMake/RuntimePath/GenexCheck.cmake
Normal file
@@ -0,0 +1,7 @@
|
||||
file(GLOB_RECURSE files "${dir}/*")
|
||||
|
||||
foreach(file IN LISTS files)
|
||||
if(file MATCHES "/(build|install)(no)?ge$")
|
||||
file(RPATH_CHANGE FILE "${file}" OLD_RPATH "/opt/foo/lib" NEW_RPATH "/opt/bar/lib")
|
||||
endif()
|
||||
endforeach()
|
||||
@@ -1,32 +1,26 @@
|
||||
include(RunCMake)
|
||||
|
||||
|
||||
function(run_SymlinkImplicit)
|
||||
function(run_RuntimePath name)
|
||||
# Use a single build tree for a few tests without cleaning.
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SymlinkImplicit-build)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
|
||||
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
|
||||
endif()
|
||||
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||
run_cmake(SymlinkImplicit)
|
||||
run_cmake_command(SymlinkImplicit-build ${CMAKE_COMMAND} --build . --config Debug)
|
||||
run_cmake_command(SymlinkImplicitCheck
|
||||
${CMAKE_COMMAND} -Ddir=${RunCMake_TEST_BINARY_DIR} -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake)
|
||||
run_cmake(${name})
|
||||
run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --config Debug)
|
||||
endfunction()
|
||||
run_SymlinkImplicit()
|
||||
|
||||
function(run_Relative)
|
||||
# Use a single build tree for a few tests without cleaning.
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Relative-build)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
|
||||
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
|
||||
endif()
|
||||
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||
run_cmake(Relative)
|
||||
run_cmake_command(Relative-build ${CMAKE_COMMAND} --build . --config Debug)
|
||||
endfunction()
|
||||
run_Relative()
|
||||
run_RuntimePath(SymlinkImplicit)
|
||||
run_cmake_command(SymlinkImplicitCheck
|
||||
${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/SymlinkImplicit-build -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake)
|
||||
|
||||
run_RuntimePath(Relative)
|
||||
# FIXME: Run RelativeCheck (appears to be broken currently)
|
||||
|
||||
run_RuntimePath(Genex)
|
||||
run_cmake_command(GenexCheck
|
||||
${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/Genex-build -P ${RunCMake_SOURCE_DIR}/GenexCheck.cmake)
|
||||
|
||||
Reference in New Issue
Block a user