BUILD_RPATH/INSTALL_RPATH: Add generator expression support

Fixes: #19423
This commit is contained in:
Kyle Edwards
2019-06-24 18:30:38 -04:00
parent 1009fd1860
commit d29ed8a114
9 changed files with 109 additions and 31 deletions

View File

@@ -8,3 +8,6 @@ tree. See also the :prop_tgt:`INSTALL_RPATH` target property.
This property is initialized by the value of the variable This property is initialized by the value of the variable
:variable:`CMAKE_BUILD_RPATH` if it is set when a target is created. :variable:`CMAKE_BUILD_RPATH` if it is set when a target is created.
This property supports
:manual:`generator expressions <cmake-generator-expressions(7)>`.

View File

@@ -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 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 by the value of the variable :variable:`CMAKE_INSTALL_RPATH` if it is set when
a target is created. a target is created.
This property supports
:manual:`generator expressions <cmake-generator-expressions(7)>`.

View 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)>`.

View File

@@ -1695,7 +1695,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
(for_install || (for_install ||
this->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")); this->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"));
bool use_install_rpath = bool use_install_rpath =
(outputRuntime && this->Target->HaveInstallTreeRPATH() && (outputRuntime && this->Target->HaveInstallTreeRPATH(this->Config) &&
linking_for_install); linking_for_install);
bool use_build_rpath = bool use_build_rpath =
(outputRuntime && this->Target->HaveBuildTreeRPATH(this->Config) && (outputRuntime && this->Target->HaveBuildTreeRPATH(this->Config) &&
@@ -1715,15 +1715,17 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
// Construct the RPATH. // Construct the RPATH.
std::set<std::string> emitted; std::set<std::string> emitted;
if (use_install_rpath) { if (use_install_rpath) {
const char* install_rpath = this->Target->GetProperty("INSTALL_RPATH"); std::string install_rpath;
cmCLI_ExpandListUnique(install_rpath, runtimeDirs, emitted); this->Target->GetInstallRPATH(this->Config, install_rpath);
cmCLI_ExpandListUnique(install_rpath.c_str(), runtimeDirs, emitted);
} }
if (use_build_rpath) { if (use_build_rpath) {
// Add directories explicitly specified by user // 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 // This will not resolve entries to use $ORIGIN, the user is expected to
// do that if necessary. // 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) { if (use_build_rpath || use_link_rpath) {

View File

@@ -1612,7 +1612,7 @@ bool cmGeneratorTarget::NeedRelinkBeforeInstall(
// will likely change between the build tree and install tree and // will likely change between the build tree and install tree and
// this target must be relinked. // this target must be relinked.
bool have_rpath = bool have_rpath =
this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH(); this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH(config);
bool is_ninja = bool is_ninja =
this->LocalGenerator->GetGlobalGenerator()->GetName() == "Ninja"; this->LocalGenerator->GetGlobalGenerator()->GetName() == "Ninja";
@@ -5479,13 +5479,41 @@ bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind,
return true; return true;
} }
bool cmGeneratorTarget::HaveInstallTreeRPATH() const bool cmGeneratorTarget::HaveInstallTreeRPATH(const std::string& config) const
{ {
const char* install_rpath = this->GetProperty("INSTALL_RPATH"); std::string install_rpath;
return (install_rpath && *install_rpath) && this->GetInstallRPATH(config, install_rpath);
return !install_rpath.empty() &&
!this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH"); !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( void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
const std::string& config, cmOptionalLinkInterface& iface, const std::string& config, cmOptionalLinkInterface& iface,
cmGeneratorTarget const* headTarget, bool usage_requirements_only) const 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")) { if (this->GetPropertyAsBool("SKIP_BUILD_RPATH")) {
return false; return false;
} }
if (this->GetProperty("BUILD_RPATH")) { std::string build_rpath;
if (this->GetBuildRPATH(config, build_rpath)) {
return true; return true;
} }
if (cmLinkImplementationLibraries const* impl = if (cmLinkImplementationLibraries const* impl =

View File

@@ -674,7 +674,10 @@ public:
class TargetPropertyEntry; 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. */ /** Whether this library has \@rpath and platform supports it. */
bool HasMacOSXRpathInstallNameDir(const std::string& config) const; bool HasMacOSXRpathInstallNameDir(const std::string& config) const;
@@ -913,6 +916,9 @@ private:
ManagedType CheckManagedType(std::string const& propval) const; ManagedType CheckManagedType(std::string const& propval) const;
bool GetRPATH(const std::string& config, const std::string& prop,
std::string& rpath) const;
public: public:
const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure( const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure(
const std::string& config) const; const std::string& config) const;

View 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
)

View 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()

View File

@@ -1,32 +1,26 @@
include(RunCMake) include(RunCMake)
function(run_SymlinkImplicit) function(run_RuntimePath name)
# Use a single build tree for a few tests without cleaning. # 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) set(RunCMake_TEST_NO_CLEAN 1)
if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
endif() endif()
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
run_cmake(SymlinkImplicit) run_cmake(${name})
run_cmake_command(SymlinkImplicit-build ${CMAKE_COMMAND} --build . --config Debug) run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --config Debug)
run_cmake_command(SymlinkImplicitCheck
${CMAKE_COMMAND} -Ddir=${RunCMake_TEST_BINARY_DIR} -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake)
endfunction() endfunction()
run_SymlinkImplicit()
function(run_Relative) run_RuntimePath(SymlinkImplicit)
# Use a single build tree for a few tests without cleaning. run_cmake_command(SymlinkImplicitCheck
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Relative-build) ${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/SymlinkImplicit-build -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake)
set(RunCMake_TEST_NO_CLEAN 1)
if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) run_RuntimePath(Relative)
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) # FIXME: Run RelativeCheck (appears to be broken currently)
endif()
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") run_RuntimePath(Genex)
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") run_cmake_command(GenexCheck
run_cmake(Relative) ${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/Genex-build -P ${RunCMake_SOURCE_DIR}/GenexCheck.cmake)
run_cmake_command(Relative-build ${CMAKE_COMMAND} --build . --config Debug)
endfunction()
run_Relative()