Browse Source

Merge topic 'build-install-rpath-genex'

d29ed8a114 BUILD_RPATH/INSTALL_RPATH: Add generator expression support

Acked-by: Kitware Robot <[email protected]>
Merge-request: !3481
Brad King 6 years ago
parent
commit
06f1560a58

+ 3 - 0
Help/prop_tgt/BUILD_RPATH.rst

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

+ 3 - 0
Help/prop_tgt/INSTALL_RPATH.rst

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

+ 5 - 0
Help/release/dev/build-install-rpath-genex.rst

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

+ 7 - 5
Source/cmComputeLinkInformation.cxx

@@ -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");
-    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) {
   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) {

+ 34 - 5
Source/cmGeneratorTarget.cxx

@@ -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");
-  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");
     !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 =

+ 7 - 1
Source/cmGeneratorTarget.h

@@ -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;

+ 29 - 0
Tests/RunCMake/RuntimePath/Genex.cmake

@@ -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 - 0
Tests/RunCMake/RuntimePath/GenexCheck.cmake

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

+ 14 - 20
Tests/RunCMake/RuntimePath/RunCMakeTest.cmake

@@ -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_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()
 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)