Browse Source

OS X: Add CMP0042 to enable MACOSX_RPATH by default

Also adding documentation for CMAKE_MACOSX_RPATH, and improving
documentation for MACOSX_RPATH.
Clinton Stimpson 12 years ago
parent
commit
d25ad482e9

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

@@ -75,3 +75,4 @@ All Policies
    /policy/CMP0039
    /policy/CMP0039
    /policy/CMP0040
    /policy/CMP0040
    /policy/CMP0041
    /policy/CMP0041
+   /policy/CMP0042

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -207,6 +207,7 @@ Variables that Control the Build
    /variable/CMAKE_LINK_LIBRARY_FILE_FLAG
    /variable/CMAKE_LINK_LIBRARY_FILE_FLAG
    /variable/CMAKE_LINK_LIBRARY_FLAG
    /variable/CMAKE_LINK_LIBRARY_FLAG
    /variable/CMAKE_MACOSX_BUNDLE
    /variable/CMAKE_MACOSX_BUNDLE
+   /variable/CMAKE_MACOSX_RPATH
    /variable/CMAKE_MAP_IMPORTED_CONFIG_CONFIG
    /variable/CMAKE_MAP_IMPORTED_CONFIG_CONFIG
    /variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG
    /variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG
    /variable/CMAKE_MODULE_LINKER_FLAGS
    /variable/CMAKE_MODULE_LINKER_FLAGS

+ 19 - 0
Help/policy/CMP0042.rst

@@ -0,0 +1,19 @@
+CMP0042
+-------
+
+:prop_tgt:`MACOSX_RPATH` is enabled by default.
+
+CMake 2.8.12 and newer has support for using ``@rpath`` in a target's install
+name.  This was enabled by setting the target property
+:prop_tgt:`MACOSX_RPATH`.  The ``@rpath`` in an install name is a more
+flexible and powerful mechanism than ``@executable_path`` or ``@loader_path``
+for locating shared libraries.
+
+CMake 3.0.0 and later prefer this property to be ON by default.  Projects
+wanting ``@rpath`` in a target's install name may remove any setting of
+the :prop_tgt:`INSTALL_NAME_DIR` and :variable:`CMAKE_INSTALL_NAME_DIR`
+variables.
+
+This policy was introduced in CMake version 3.0.0.  CMake version
+|release| warns when the policy is not set and uses OLD behavior.  Use
+the cmake_policy command to set it to OLD or NEW explicitly.

+ 12 - 4
Help/prop_tgt/MACOSX_RPATH.rst

@@ -4,7 +4,15 @@ MACOSX_RPATH
 Whether to use rpaths on Mac OS X.
 Whether to use rpaths on Mac OS X.
 
 
 When this property is set to true, the directory portion of
 When this property is set to true, the directory portion of
-the"install_name" field of shared libraries will default to
-"@rpath".Runtime paths will also be embedded in binaries using this
-target.This property is initialized by the value of the variable
-CMAKE_MACOSX_RPATH if it is set when a target is created.
+the "install_name" field of shared libraries will be ``@rpath``
+unless overridden by :prop_tgt:`INSTALL_NAME_DIR`.  Runtime
+paths will also be embedded in binaries using this target and
+can be controlled by the :prop_tgt:`INSTALL_RPATH` target property.
+This property is initialized by the value of the variable
+:variable:`CMAKE_MACOSX_RPATH` if it is set when a target is
+created.
+
+Policy CMP0042 was introduced to change the default value of
+MACOSX_RPATH to ON.  This is because use of ``@rpath`` is a
+more flexible and powerful alternative to ``@executable_path`` and
+``@loader_path``.

+ 7 - 0
Help/variable/CMAKE_MACOSX_RPATH.rst

@@ -0,0 +1,7 @@
+CMAKE_MACOSX_RPATH
+-------------------
+
+Whether to use rpaths on Mac OS X.
+
+This variable is used to initialize the :prop_tgt:`MACOSX_RPATH` property on
+all targets.

+ 1 - 1
Source/cmComputeLinkInformation.cxx

@@ -1751,7 +1751,7 @@ cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath,
   // @loader_path or full paths.
   // @loader_path or full paths.
   if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
   if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
     {
     {
-    if(!target->HasMacOSXRpath(this->Config))
+    if(!target->HasMacOSXRpathInstallNameDir(this->Config))
       {
       {
       return;
       return;
       }
       }

+ 28 - 0
Source/cmGlobalGenerator.cxx

@@ -1045,6 +1045,12 @@ cmGlobalGenerator::GetExportedTargetsFile(const std::string &filename) const
   return it == this->BuildExportSets.end() ? 0 : it->second;
   return it == this->BuildExportSets.end() ? 0 : it->second;
 }
 }
 
 
+//----------------------------------------------------------------------------
+void cmGlobalGenerator::AddCMP0042WarnTarget(const std::string& target)
+{
+  this->CMP0042WarnTargets.insert(target);
+}
+
 bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
 bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
 {
 {
   // If the property is not enabled then okay.
   // If the property is not enabled then okay.
@@ -1072,6 +1078,9 @@ void cmGlobalGenerator::Generate()
   // Start with an empty vector:
   // Start with an empty vector:
   this->FilesReplacedDuringGenerate.clear();
   this->FilesReplacedDuringGenerate.clear();
 
 
+  // clear targets to issue warning CMP0042 for
+  this->CMP0042WarnTargets.clear();
+
   // Check whether this generator is allowed to run.
   // Check whether this generator is allowed to run.
   if(!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS())
   if(!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS())
     {
     {
@@ -1203,6 +1212,25 @@ void cmGlobalGenerator::Generate()
     this->ExtraGenerator->Generate();
     this->ExtraGenerator->Generate();
     }
     }
 
 
+  if(!this->CMP0042WarnTargets.empty())
+    {
+    cmOStringStream w;
+    w <<
+      (this->GetCMakeInstance()->GetPolicies()->
+       GetPolicyWarning(cmPolicies::CMP0042)) << "\n";
+    w << "MACOSX_RPATH is not specified for"
+         " the following targets:\n";
+    for(std::set<std::string>::iterator
+      iter = this->CMP0042WarnTargets.begin();
+      iter != this->CMP0042WarnTargets.end();
+      ++iter)
+      {
+      w << " " << *iter << "\n";
+      }
+    this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str(),
+                                           cmListFileBacktrace());
+    }
+
   this->CMakeInstance->UpdateProgress("Generating done", -1);
   this->CMakeInstance->UpdateProgress("Generating done", -1);
 }
 }
 
 

+ 5 - 0
Source/cmGlobalGenerator.h

@@ -315,6 +315,8 @@ public:
   bool GenerateImportFile(const std::string &file);
   bool GenerateImportFile(const std::string &file);
   cmExportBuildFileGenerator*
   cmExportBuildFileGenerator*
   GetExportedTargetsFile(const std::string &filename) const;
   GetExportedTargetsFile(const std::string &filename) const;
+  void AddCMP0042WarnTarget(const std::string& target);
+
 protected:
 protected:
   typedef std::vector<cmLocalGenerator*> GeneratorVector;
   typedef std::vector<cmLocalGenerator*> GeneratorVector;
   // for a project collect all its targets by following depend
   // for a project collect all its targets by following depend
@@ -446,6 +448,9 @@ private:
 
 
   // Set of binary directories on disk.
   // Set of binary directories on disk.
   std::set<cmStdString> BinaryDirectories;
   std::set<cmStdString> BinaryDirectories;
+
+  // track targets to issue CMP0042 warning for.
+  std::set<std::string> CMP0042WarnTargets;
 };
 };
 
 
 #endif
 #endif

+ 29 - 0
Source/cmLocalXCodeGenerator.cxx

@@ -12,6 +12,7 @@
 #include "cmLocalXCodeGenerator.h"
 #include "cmLocalXCodeGenerator.h"
 #include "cmGlobalXCodeGenerator.h"
 #include "cmGlobalXCodeGenerator.h"
 #include "cmSourceFile.h"
 #include "cmSourceFile.h"
+#include "cmMakefile.h"
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 cmLocalXCodeGenerator::cmLocalXCodeGenerator()
 cmLocalXCodeGenerator::cmLocalXCodeGenerator()
@@ -42,3 +43,31 @@ void cmLocalXCodeGenerator::AppendFlagEscape(std::string& flags,
     static_cast<cmGlobalXCodeGenerator*>(this->GlobalGenerator);
     static_cast<cmGlobalXCodeGenerator*>(this->GlobalGenerator);
   gg->AppendFlag(flags, rawFlag);
   gg->AppendFlag(flags, rawFlag);
 }
 }
+
+//----------------------------------------------------------------------------
+void cmLocalXCodeGenerator::Generate()
+{
+  cmLocalGenerator::Generate();
+
+  cmTargets& targets = this->Makefile->GetTargets();
+  for(cmTargets::iterator iter = targets.begin();
+      iter != targets.end(); ++iter)
+    {
+    cmTarget* t = &iter->second;
+    t->HasMacOSXRpathInstallNameDir(NULL);
+    }
+}
+
+//----------------------------------------------------------------------------
+void cmLocalXCodeGenerator::GenerateInstallRules()
+{
+  cmLocalGenerator::GenerateInstallRules();
+
+  cmTargets& targets = this->Makefile->GetTargets();
+  for(cmTargets::iterator iter = targets.begin();
+      iter != targets.end(); ++iter)
+    {
+    cmTarget* t = &iter->second;
+    t->HasMacOSXRpathInstallNameDir(NULL);
+    }
+}

+ 2 - 0
Source/cmLocalXCodeGenerator.h

@@ -29,6 +29,8 @@ public:
   virtual ~cmLocalXCodeGenerator();
   virtual ~cmLocalXCodeGenerator();
   virtual std::string GetTargetDirectory(cmTarget const& target) const;
   virtual std::string GetTargetDirectory(cmTarget const& target) const;
   virtual void AppendFlagEscape(std::string& flags, const char* rawFlag);
   virtual void AppendFlagEscape(std::string& flags, const char* rawFlag);
+  virtual void Generate();
+  virtual void GenerateInstallRules();
 private:
 private:
 
 
 };
 };

+ 5 - 0
Source/cmPolicies.cxx

@@ -311,6 +311,11 @@ cmPolicies::cmPolicies()
     CMP0041, "CMP0041",
     CMP0041, "CMP0041",
     "Error on relative include with generator expression.",
     "Error on relative include with generator expression.",
     3,0,0,0, cmPolicies::WARN);
     3,0,0,0, cmPolicies::WARN);
+
+  this->DefinePolicy(
+    CMP0042, "CMP0042",
+    "MACOSX_RPATH is enabled by default.",
+    3,0,0,0, cmPolicies::WARN);
 }
 }
 
 
 cmPolicies::~cmPolicies()
 cmPolicies::~cmPolicies()

+ 1 - 0
Source/cmPolicies.h

@@ -95,6 +95,7 @@ public:
     CMP0040, ///< The target in the TARGET signature of
     CMP0040, ///< The target in the TARGET signature of
     /// add_custom_command() must exist.
     /// add_custom_command() must exist.
     CMP0041, ///< Error on relative include with generator expression
     CMP0041, ///< Error on relative include with generator expression
+    CMP0042, ///< Enable MACOSX_RPATH by default
 
 
     /** \brief Always the last entry.
     /** \brief Always the last entry.
      *
      *

+ 48 - 5
Source/cmTarget.cxx

@@ -3185,13 +3185,17 @@ std::string cmTarget::GetSOName(const char* config) const
 }
 }
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
-bool cmTarget::HasMacOSXRpath(const char* config) const
+bool cmTarget::HasMacOSXRpathInstallNameDir(const char* config) const
 {
 {
   bool install_name_is_rpath = false;
   bool install_name_is_rpath = false;
-  bool macosx_rpath = this->GetPropertyAsBool("MACOSX_RPATH");
+  bool macosx_rpath = false;
 
 
   if(!this->IsImportedTarget)
   if(!this->IsImportedTarget)
     {
     {
+    if(this->GetType() != cmTarget::SHARED_LIBRARY)
+      {
+      return false;
+      }
     const char* install_name = this->GetProperty("INSTALL_NAME_DIR");
     const char* install_name = this->GetProperty("INSTALL_NAME_DIR");
     bool use_install_name =
     bool use_install_name =
       this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
       this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
@@ -3204,6 +3208,10 @@ bool cmTarget::HasMacOSXRpath(const char* config) const
       {
       {
       return false;
       return false;
       }
       }
+    if(!install_name_is_rpath)
+      {
+      macosx_rpath = this->MacOSXRpathInstallNameDirDefault();
+      }
     }
     }
   else
   else
     {
     {
@@ -3257,6 +3265,37 @@ bool cmTarget::HasMacOSXRpath(const char* config) const
   return true;
   return true;
 }
 }
 
 
+//----------------------------------------------------------------------------
+bool cmTarget::MacOSXRpathInstallNameDirDefault() const
+{
+  // we can't do rpaths when unsupported
+  if(!this->Makefile->IsSet("CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG"))
+    {
+    return false;
+    }
+
+  const char* macosx_rpath_str = this->GetProperty("MACOSX_RPATH");
+  if(macosx_rpath_str)
+    {
+    return this->GetPropertyAsBool("MACOSX_RPATH");
+    }
+
+  cmPolicies::PolicyStatus cmp0042 = this->GetPolicyStatusCMP0042();
+
+  if(cmp0042 == cmPolicies::WARN)
+    {
+    this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
+      AddCMP0042WarnTarget(this->GetName());
+    }
+
+  if(cmp0042 == cmPolicies::NEW)
+    {
+    return true;
+    }
+
+  return false;
+}
+
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config) const
 bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config) const
 {
 {
@@ -3846,7 +3885,8 @@ std::string cmTarget::GetInstallNameDirForBuildTree(const char* config) const
      !this->GetPropertyAsBool("SKIP_BUILD_RPATH"))
      !this->GetPropertyAsBool("SKIP_BUILD_RPATH"))
     {
     {
     std::string dir;
     std::string dir;
-    if(this->GetPropertyAsBool("MACOSX_RPATH"))
+    bool macosx_rpath = this->MacOSXRpathInstallNameDirDefault();
+    if(macosx_rpath)
       {
       {
       dir = "@rpath";
       dir = "@rpath";
       }
       }
@@ -3880,9 +3920,12 @@ std::string cmTarget::GetInstallNameDirForInstallTree() const
         dir += "/";
         dir += "/";
         }
         }
       }
       }
-    if(!install_name_dir && this->GetPropertyAsBool("MACOSX_RPATH"))
+    if(!install_name_dir)
       {
       {
-      dir = "@rpath/";
+      if(this->MacOSXRpathInstallNameDirDefault())
+        {
+        dir = "@rpath/";
+        }
       }
       }
     return dir;
     return dir;
     }
     }

+ 6 - 2
Source/cmTarget.h

@@ -26,7 +26,8 @@
   F(CMP0020) \
   F(CMP0020) \
   F(CMP0021) \
   F(CMP0021) \
   F(CMP0022) \
   F(CMP0022) \
-  F(CMP0041)
+  F(CMP0041) \
+  F(CMP0042)
 
 
 class cmake;
 class cmake;
 class cmMakefile;
 class cmMakefile;
@@ -382,7 +383,10 @@ public:
   std::string GetSOName(const char* config) const;
   std::string GetSOName(const char* config) const;
 
 
   /** Whether this library has \@rpath and platform supports it.  */
   /** Whether this library has \@rpath and platform supports it.  */
-  bool HasMacOSXRpath(const char* config) const;
+  bool HasMacOSXRpathInstallNameDir(const char* config) const;
+
+  /** Whether this library defaults to \@rpath.  */
+  bool MacOSXRpathInstallNameDirDefault() const;
 
 
   /** Test for special case of a third-party shared library that has
   /** Test for special case of a third-party shared library that has
       no soname at all.  */
       no soname at all.  */

+ 4 - 2
Tests/MacRuntimePath/A/CMakeLists.txt

@@ -10,13 +10,15 @@ add_library(shared2 SHARED shared.cpp shared.h)
 set_target_properties(shared2 PROPERTIES
 set_target_properties(shared2 PROPERTIES
   BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@rpath")
   BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@rpath")
 
 
+cmake_policy(SET CMP0042 NEW)
+
 # a framework library
 # a framework library
 add_library(framework SHARED framework.cpp framework.h)
 add_library(framework SHARED framework.cpp framework.h)
-set_target_properties(framework PROPERTIES MACOSX_RPATH 1 FRAMEWORK 1)
+set_target_properties(framework PROPERTIES FRAMEWORK 1)
 
 
 # another framework
 # another framework
 add_library(framework2 SHARED framework2.cpp framework2.h)
 add_library(framework2 SHARED framework2.cpp framework2.h)
-set_target_properties(framework2 PROPERTIES MACOSX_RPATH 1 FRAMEWORK 1)
+set_target_properties(framework2 PROPERTIES FRAMEWORK 1)
 
 
 # executable to test a shared library dependency with install rpaths
 # executable to test a shared library dependency with install rpaths
 add_executable(test1 test1.cpp)
 add_executable(test1 test1.cpp)

+ 2 - 0
Tests/RunCMake/CMP0022/CMP0022-NOWARN-shared.cmake

@@ -1,5 +1,7 @@
 enable_language(CXX)
 enable_language(CXX)
 
 
+cmake_policy(SET CMP0042 NEW)
+
 add_library(foo SHARED empty_vs6_1.cpp)
 add_library(foo SHARED empty_vs6_1.cpp)
 add_library(bar SHARED empty_vs6_2.cpp)
 add_library(bar SHARED empty_vs6_2.cpp)
 target_link_libraries(bar foo)
 target_link_libraries(bar foo)

+ 2 - 0
Tests/RunCMake/CMP0022/CMP0022-WARN.cmake

@@ -1,6 +1,8 @@
 
 
 project(CMP0022-WARN)
 project(CMP0022-WARN)
 
 
+cmake_policy(SET CMP0042 NEW)
+
 add_library(foo SHARED empty_vs6_1.cpp)
 add_library(foo SHARED empty_vs6_1.cpp)
 add_library(bar SHARED empty_vs6_2.cpp)
 add_library(bar SHARED empty_vs6_2.cpp)
 add_library(bat SHARED empty_vs6_3.cpp)
 add_library(bat SHARED empty_vs6_3.cpp)

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

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

+ 1 - 0
Tests/RunCMake/CMP0042/CMP0042-NEW-stderr.txt

@@ -0,0 +1 @@
+^$

+ 4 - 0
Tests/RunCMake/CMP0042/CMP0042-NEW.cmake

@@ -0,0 +1,4 @@
+
+cmake_policy(SET CMP0042 NEW)
+
+add_library(foo SHARED empty.cpp)

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

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

+ 1 - 0
Tests/RunCMake/CMP0042/CMP0042-OLD-stderr.txt

@@ -0,0 +1 @@
+^$

+ 4 - 0
Tests/RunCMake/CMP0042/CMP0042-OLD.cmake

@@ -0,0 +1,4 @@
+
+cmake_policy(SET CMP0042 OLD)
+
+add_library(foo SHARED empty.cpp)

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

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

+ 10 - 0
Tests/RunCMake/CMP0042/CMP0042-WARN-stderr.txt

@@ -0,0 +1,10 @@
+CMake Warning \(dev\):
+  Policy CMP0042 is not set: MACOSX_RPATH is enabled by default.  Run "cmake
+  --help-policy CMP0042" for policy details.  Use the cmake_policy command to
+  set the policy and suppress this warning.
+
+  MACOSX_RPATH is not specified for the following targets:
+
+   foo
+
+This warning is for project developers.  Use -Wno-dev to suppress it.

+ 9 - 0
Tests/RunCMake/CMP0042/CMP0042-WARN.cmake

@@ -0,0 +1,9 @@
+
+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")

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

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

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

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

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

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

+ 3 - 0
Tests/RunCMake/CMakeLists.txt

@@ -61,6 +61,9 @@ add_RunCMake_test(CMP0038)
 add_RunCMake_test(CMP0039)
 add_RunCMake_test(CMP0039)
 add_RunCMake_test(CMP0040)
 add_RunCMake_test(CMP0040)
 add_RunCMake_test(CMP0041)
 add_RunCMake_test(CMP0041)
+if(CMAKE_SYSTEM_NAME MATCHES Darwin AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG)
+  add_RunCMake_test(CMP0042)
+endif()
 add_RunCMake_test(CTest)
 add_RunCMake_test(CTest)
 if(UNIX AND "${CMAKE_TEST_GENERATOR}" MATCHES "Unix Makefiles")
 if(UNIX AND "${CMAKE_TEST_GENERATOR}" MATCHES "Unix Makefiles")
   add_RunCMake_test(CompilerChange)
   add_RunCMake_test(CompilerChange)