Browse Source

Add policy CMP0068 separate install_name and RPATH settings on macOS

BUILD_WITH_INSTALL_RPATH, SKIP_BUILD_RPATH, CMAKE_SKIP_RPATH and
CMAKE_SKIP_INSTALL_RPATH no longer any effect on the install name
of a target on macOS.

Fixes: #16589
Clinton Stimpson 8 years ago
parent
commit
1ba91291e3

+ 8 - 0
Help/manual/cmake-policies.7.rst

@@ -51,6 +51,14 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used
 to determine whether to report an error on use of deprecated macros or
 functions.
 
+Policies Introduced by CMake 3.9
+================================
+
+.. toctree::
+   :maxdepth: 1
+
+   CMP0068: RPATH settings on macOS do not affect install_name. </policy/CMP0068>
+
 Policies Introduced by CMake 3.8
 ================================
 

+ 35 - 0
Help/policy/CMP0068.rst

@@ -0,0 +1,35 @@
+CMP0068
+-------
+
+``RPATH`` settings on macOS do not affect ``install_name``.
+
+CMake 3.9 and newer remove any effect the following settings may have on the
+``install_name`` of a target on macOS:
+
+* :prop_tgt:`BUILD_WITH_INSTALL_RPATH` target property
+* :prop_tgt:`SKIP_BUILD_RPATH` target property
+* :variable:`CMAKE_SKIP_RPATH` variable
+* :variable:`CMAKE_SKIP_INSTALL_RPATH` variable
+
+Previously, setting :prop_tgt:`BUILD_WITH_INSTALL_RPATH` had the effect of
+setting both the ``install_name`` of a target to :prop_tgt:`INSTALL_NAME_DIR`
+and the ``RPATH`` to :prop_tgt:`INSTALL_RPATH`.  In CMake 3.9, it only affects
+setting of ``RPATH``.  However, if one wants :prop_tgt:`INSTALL_NAME_DIR` to
+apply to the target in the build tree, one may set
+:prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR`.
+
+If :prop_tgt:`SKIP_BUILD_RPATH`, :variable:`CMAKE_SKIP_RPATH` or
+:variable:`CMAKE_SKIP_INSTALL_RPATH` were used to strip the directory portion
+of the ``install_name`` of a target, one may set ``INSTALL_NAME_DIR=""``
+instead.
+
+The ``OLD`` behavior of this policy is to use the ``RPATH`` settings for
+``install_name`` on macOS.  The ``NEW`` behavior of this policy is to ignore
+the ``RPATH`` settings for ``install_name`` on macOS.
+
+This policy was introduced in CMake version 3.9.  CMake version
+|release| warns when the policy is not set and uses ``OLD`` behavior.
+Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW``
+explicitly.
+
+.. include:: DEPRECATED.txt

+ 2 - 2
Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst

@@ -9,5 +9,5 @@ This property is initialized by the value of the variable
 :variable:`CMAKE_BUILD_WITH_INSTALL_NAME_DIR` if it is set when a target is
 created.
 
-If this property is not set, the value of :prop_tgt:`BUILD_WITH_INSTALL_RPATH`
-is used in its place.
+If this property is not set and policy :policy:`CMP0068` is not ``NEW``, the
+value of :prop_tgt:`BUILD_WITH_INSTALL_RPATH` is used in its place.

+ 3 - 3
Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst

@@ -10,6 +10,6 @@ This property is initialized by the value of the
 :variable:`CMAKE_BUILD_WITH_INSTALL_RPATH` variable if it is set when a target
 is created.
 
-This property also controls use of :prop_tgt:`INSTALL_NAME_DIR` in the build
-tree on macOS, but defers to the :prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR` target
-property if the latter is set.
+If policy :policy:`CMP0068` is not ``NEW``, this property also controls use of
+:prop_tgt:`INSTALL_NAME_DIR` in the build tree on macOS.  Either way, the
+:prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR` target property takes precedence.

+ 3 - 0
Help/release/dev/install_name_policy.rst

@@ -6,3 +6,6 @@ install_name_policy
   control whether to use the :prop_tgt:`INSTALL_NAME_DIR` target property
   value for binaries in the build tree.  This is for macOS ``install_name``
   as :prop_tgt:`BUILD_WITH_INSTALL_RPATH` is for ``RPATH``.
+
+* On macOS, ``RPATH`` settings such as :prop_tgt:`BUILD_WITH_INSTALL_RPATH`
+  no longer affect the ``install_name`` field.  See policy :policy:`CMP0068`.

+ 21 - 0
Source/cmGeneratorTarget.cxx

@@ -1402,14 +1402,30 @@ bool cmGeneratorTarget::MacOSXUseInstallNameDir() const
     return cmSystemTools::IsOn(build_with_install_name);
   }
 
+  cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068();
+  if (cmp0068 == cmPolicies::NEW) {
+    return false;
+  }
+
   bool use_install_name = this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
 
+  if (use_install_name && cmp0068 == cmPolicies::WARN) {
+    this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget(
+      this->GetName());
+  }
+
   return use_install_name;
 }
 
 bool cmGeneratorTarget::CanGenerateInstallNameDir(
   InstallNameType name_type) const
 {
+  cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068();
+
+  if (cmp0068 == cmPolicies::NEW) {
+    return true;
+  }
+
   bool skip = this->Makefile->IsOn("CMAKE_SKIP_RPATH");
   if (name_type == INSTALL_NAME_FOR_INSTALL) {
     skip |= this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
@@ -1417,6 +1433,11 @@ bool cmGeneratorTarget::CanGenerateInstallNameDir(
     skip |= this->GetPropertyAsBool("SKIP_BUILD_RPATH");
   }
 
+  if (skip && cmp0068 == cmPolicies::WARN) {
+    this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget(
+      this->GetName());
+  }
+
   return !skip;
 }
 

+ 25 - 0
Source/cmGlobalGenerator.cxx

@@ -1194,6 +1194,11 @@ void cmGlobalGenerator::AddCMP0042WarnTarget(const std::string& target)
   this->CMP0042WarnTargets.insert(target);
 }
 
+void cmGlobalGenerator::AddCMP0068WarnTarget(const std::string& target)
+{
+  this->CMP0068WarnTargets.insert(target);
+}
+
 bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const
 {
   // If the property is not enabled then okay.
@@ -1235,6 +1240,8 @@ bool cmGlobalGenerator::Compute()
 
   // clear targets to issue warning CMP0042 for
   this->CMP0042WarnTargets.clear();
+  // clear targets to issue warning CMP0068 for
+  this->CMP0068WarnTargets.clear();
 
   // Check whether this generator is allowed to run.
   if (!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS()) {
@@ -1366,6 +1373,24 @@ void cmGlobalGenerator::Generate()
     this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str());
   }
 
+  if (!this->CMP0068WarnTargets.empty()) {
+    std::ostringstream w;
+    /* clang-format off */
+    w <<
+      cmPolicies::GetPolicyWarning(cmPolicies::CMP0068) << "\n"
+      "For compatibility with older versions of CMake, the install_name "
+      "fields for the following targets are still affected by RPATH "
+      "settings:\n"
+      ;
+    /* clang-format on */
+    for (std::set<std::string>::iterator iter =
+           this->CMP0068WarnTargets.begin();
+         iter != this->CMP0068WarnTargets.end(); ++iter) {
+      w << " " << *iter << "\n";
+    }
+    this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+  }
+
   this->CMakeInstance->UpdateProgress("Generating done", -1);
 }
 

+ 3 - 0
Source/cmGlobalGenerator.h

@@ -357,6 +357,7 @@ public:
   cmExportBuildFileGenerator* GetExportedTargetsFile(
     const std::string& filename) const;
   void AddCMP0042WarnTarget(const std::string& target);
+  void AddCMP0068WarnTarget(const std::string& target);
 
   virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
 
@@ -562,6 +563,8 @@ private:
 
   // track targets to issue CMP0042 warning for.
   std::set<std::string> CMP0042WarnTargets;
+  // track targets to issue CMP0068 warning for.
+  std::set<std::string> CMP0068WarnTargets;
 
   mutable std::map<cmSourceFile*, std::set<cmGeneratorTarget const*> >
     FilenameTargetDepends;

+ 6 - 2
Source/cmPolicies.h

@@ -200,7 +200,10 @@ class cmMakefile;
          7, 0, cmPolicies::WARN)                                              \
   SELECT(POLICY, CMP0067,                                                     \
          "Honor language standard in try_compile() source-file signature.",   \
-         3, 8, 0, cmPolicies::WARN)
+         3, 8, 0, cmPolicies::WARN)                                           \
+  SELECT(POLICY, CMP0068,                                                     \
+         "RPATH settings on macOS do not affect install_name.", 3, 9, 0,      \
+         cmPolicies::WARN)
 
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
 #define CM_FOR_EACH_POLICY_ID(POLICY)                                         \
@@ -221,7 +224,8 @@ class cmMakefile;
   F(CMP0052)                                                                  \
   F(CMP0060)                                                                  \
   F(CMP0063)                                                                  \
-  F(CMP0065)
+  F(CMP0065)                                                                  \
+  F(CMP0068)
 
 /** \class cmPolicies
  * \brief Handles changes in CMake behavior and policies

+ 1 - 0
Tests/RunCMake/CMP0068/CMP0068-NEW-result.txt

@@ -0,0 +1 @@
+0

+ 6 - 0
Tests/RunCMake/CMP0068/CMP0068-NEW.cmake

@@ -0,0 +1,6 @@
+
+cmake_policy(SET CMP0068 NEW)
+cmake_policy(SET CMP0042 NEW)
+
+add_library(foo SHARED empty.cpp)
+set_target_properties(foo PROPERTIES INSTALL_NAME_DIR "@rpath" INSTALL_RPATH "@loader_path/" BUILD_WITH_INSTALL_RPATH 1)

+ 1 - 0
Tests/RunCMake/CMP0068/CMP0068-OLD-result.txt

@@ -0,0 +1 @@
+0

+ 6 - 0
Tests/RunCMake/CMP0068/CMP0068-OLD.cmake

@@ -0,0 +1,6 @@
+
+cmake_policy(SET CMP0068 OLD)
+cmake_policy(SET CMP0042 NEW)
+
+add_library(foo SHARED empty.cpp)
+set_target_properties(foo PROPERTIES INSTALL_NAME_DIR "@rpath" INSTALL_RPATH "@loader_path/" BUILD_WITH_INSTALL_RPATH 1)

+ 1 - 0
Tests/RunCMake/CMP0068/CMP0068-WARN-result.txt

@@ -0,0 +1 @@
+0

+ 12 - 0
Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt

@@ -0,0 +1,12 @@
+CMake Warning \(dev\):
+  Policy CMP0068 is not set: RPATH settings on macOS do not affect
+  install_name.  Run "cmake --help-policy CMP0068" for policy details.  Use
+  the cmake_policy command to set the policy and suppress this warning.
+
+  For compatibility with older versions of CMake, the install_name fields for
+  the following targets are still affected by RPATH settings:
+
+   foo3
+   foo4
+
+This warning is for project developers.  Use -Wno-dev to suppress it.

+ 12 - 0
Tests/RunCMake/CMP0068/CMP0068-WARN.cmake

@@ -0,0 +1,12 @@
+cmake_policy(SET CMP0042 NEW)
+
+add_library(foo SHARED empty.cpp)
+add_library(foo-static STATIC empty.cpp)
+add_library(foo2 SHARED empty.cpp)
+set_target_properties(foo2 PROPERTIES MACOSX_RPATH 1)
+add_library(foo3 SHARED empty.cpp)
+set_target_properties(foo3 PROPERTIES BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@loader_path")
+add_library(foo4 SHARED empty.cpp)
+set_target_properties(foo4 PROPERTIES BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@rpath")
+add_library(foo5 SHARED empty.cpp)
+set_target_properties(foo5 PROPERTIES BUILD_WITH_INSTALL_RPATH 1 BUILD_WITH_INSTALL_NAME_DIR 1 INSTALL_NAME_DIR "@rpath")

+ 3 - 0
Tests/RunCMake/CMP0068/CMakeLists.txt

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.8)
+project(${RunCMake_TEST} CXX)
+include(${RunCMake_TEST}.cmake)

+ 5 - 0
Tests/RunCMake/CMP0068/RunCMakeTest.cmake

@@ -0,0 +1,5 @@
+include(RunCMake)
+
+run_cmake(CMP0068-OLD)
+run_cmake(CMP0068-NEW)
+run_cmake(CMP0068-WARN)

+ 7 - 0
Tests/RunCMake/CMP0068/empty.cpp

@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+  int empty()
+{
+  return 0;
+}

+ 3 - 0
Tests/RunCMake/CMakeLists.txt

@@ -104,6 +104,9 @@ add_RunCMake_test(CMP0057)
 add_RunCMake_test(CMP0059)
 add_RunCMake_test(CMP0060)
 add_RunCMake_test(CMP0064)
+if(CMAKE_SYSTEM_NAME MATCHES Darwin AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG)
+  add_RunCMake_test(CMP0068)
+endif()
 
 # The test for Policy 65 requires the use of the
 # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode

+ 1 - 0
Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt

@@ -20,6 +20,7 @@
    \* CMP0060
    \* CMP0063
    \* CMP0065
+   \* CMP0068
 
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)

+ 1 - 0
Tests/RunCMake/install/EXPORT-OldIFace.cmake

@@ -1,5 +1,6 @@
 enable_language(C)
 set(CMAKE_BUILD_WITH_INSTALL_RPATH 1)
+set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR 1)
 add_subdirectory(EXPORT-OldIFace)
 add_library(foo SHARED empty.c)
 target_link_libraries(foo bar)