Skip to content

Commit

Permalink
Merge topic 'install_name_policy'
Browse files Browse the repository at this point in the history
1ba9129 Add policy CMP0068 separate install_name and RPATH settings on macOS
f7b9bf4 Apple: Add BUILD_WITH_INSTALL_NAME_DIR target property
4bff2d1 Apple: Refactor support for using INSTALL_NAME_DIR.
624fb9d Help: Format BUILD_WITH_INSTALL_RPATH documentation
  • Loading branch information
bradking authored and kwrobot committed Feb 17, 2017
2 parents 988c635 + 1ba9129 commit f3e8a89
Show file tree
Hide file tree
Showing 27 changed files with 257 additions and 29 deletions.
8 changes: 8 additions & 0 deletions Help/manual/cmake-policies.7.rst
Expand Up @@ -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
================================

Expand Down
1 change: 1 addition & 0 deletions Help/manual/cmake-properties.7.rst
Expand Up @@ -123,6 +123,7 @@ Properties on Targets
/prop_tgt/AUTORCC_OPTIONS
/prop_tgt/BINARY_DIR
/prop_tgt/BUILD_RPATH
/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR
/prop_tgt/BUILD_WITH_INSTALL_RPATH
/prop_tgt/BUNDLE_EXTENSION
/prop_tgt/BUNDLE
Expand Down
1 change: 1 addition & 0 deletions Help/manual/cmake-variables.7.rst
Expand Up @@ -263,6 +263,7 @@ Variables that Control the Build
/variable/CMAKE_AUTOUIC
/variable/CMAKE_AUTOUIC_OPTIONS
/variable/CMAKE_BUILD_RPATH
/variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR
/variable/CMAKE_BUILD_WITH_INSTALL_RPATH
/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY
/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG
Expand Down
35 changes: 35 additions & 0 deletions 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
13 changes: 13 additions & 0 deletions Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst
@@ -0,0 +1,13 @@
BUILD_WITH_INSTALL_NAME_DIR
---------------------------

``BUILD_WITH_INSTALL_NAME_DIR`` is a boolean specifying whether the macOS
``install_name`` of a target in the build tree uses the directory given by
:prop_tgt:`INSTALL_NAME_DIR`. This setting only applies to targets on macOS.

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 and policy :policy:`CMP0068` is not ``NEW``, the
value of :prop_tgt:`BUILD_WITH_INSTALL_RPATH` is used in its place.
18 changes: 11 additions & 7 deletions Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst
@@ -1,11 +1,15 @@
BUILD_WITH_INSTALL_RPATH
------------------------

Should build tree targets have install tree rpaths.
``BUILD_WITH_INSTALL_RPATH`` is a boolean specifying whether to link the target
in the build tree with the :prop_tgt:`INSTALL_RPATH`. This takes precedence
over :prop_tgt:`SKIP_BUILD_RPATH` and avoids the need for relinking before
installation.

BUILD_WITH_INSTALL_RPATH is a boolean specifying whether to link the
target in the build tree with the INSTALL_RPATH. This takes
precedence over SKIP_BUILD_RPATH and avoids the need for relinking
before installation. This property is initialized by the value of the
variable CMAKE_BUILD_WITH_INSTALL_RPATH if it is set when a target is
created.
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.

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.
11 changes: 11 additions & 0 deletions Help/release/dev/install_name_policy.rst
@@ -0,0 +1,11 @@
install_name_policy
-------------------

* A :prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR` target property and corresponding
:variable:`CMAKE_BUILD_WITH_INSTALL_NAME_DIR` variable were added to
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`.
7 changes: 7 additions & 0 deletions Help/variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst
@@ -0,0 +1,7 @@
CMAKE_BUILD_WITH_INSTALL_NAME_DIR
---------------------------------

Whether to use :prop_tgt:`INSTALL_NAME_DIR` on targets in the build tree.

This variable is used to initialize the :prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR`
property on all targets.
86 changes: 66 additions & 20 deletions Source/cmGeneratorTarget.cxx
Expand Up @@ -1321,8 +1321,7 @@ bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir(
return false;
}
const char* install_name = this->GetProperty("INSTALL_NAME_DIR");
bool use_install_name =
this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
bool use_install_name = this->MacOSXUseInstallNameDir();
if (install_name && use_install_name &&
std::string(install_name) == "@rpath") {
install_name_is_rpath = true;
Expand Down Expand Up @@ -1395,6 +1394,53 @@ bool cmGeneratorTarget::MacOSXRpathInstallNameDirDefault() const
return cmp0042 == cmPolicies::NEW;
}

bool cmGeneratorTarget::MacOSXUseInstallNameDir() const
{
const char* build_with_install_name =
this->GetProperty("BUILD_WITH_INSTALL_NAME_DIR");
if (build_with_install_name) {
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");
} else {
skip |= this->GetPropertyAsBool("SKIP_BUILD_RPATH");
}

if (skip && cmp0068 == cmPolicies::WARN) {
this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget(
this->GetName());
}

return !skip;
}

std::string cmGeneratorTarget::GetSOName(const std::string& config) const
{
if (this->IsImported()) {
Expand Down Expand Up @@ -1503,24 +1549,25 @@ std::string cmGeneratorTarget::GetFullName(const std::string& config,
std::string cmGeneratorTarget::GetInstallNameDirForBuildTree(
const std::string& config) const
{
// If building directly for installation then the build tree install_name
// is the same as the install tree.
if (this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) {
return this->GetInstallNameDirForInstallTree();
}
if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {

// Use the build tree directory for the target.
if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME") &&
!this->Makefile->IsOn("CMAKE_SKIP_RPATH") &&
!this->GetPropertyAsBool("SKIP_BUILD_RPATH")) {
std::string dir;
if (this->MacOSXRpathInstallNameDirDefault()) {
dir = "@rpath";
} else {
dir = this->GetDirectory(config);
// If building directly for installation then the build tree install_name
// is the same as the install tree.
if (this->MacOSXUseInstallNameDir()) {
return this->GetInstallNameDirForInstallTree();
}

// Use the build tree directory for the target.
if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_BUILD)) {
std::string dir;
if (this->MacOSXRpathInstallNameDirDefault()) {
dir = "@rpath";
} else {
dir = this->GetDirectory(config);
}
dir += "/";
return dir;
}
dir += "/";
return dir;
}
return "";
}
Expand All @@ -1531,8 +1578,7 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const
std::string dir;
const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR");

if (!this->Makefile->IsOn("CMAKE_SKIP_RPATH") &&
!this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH")) {
if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) {
if (install_name_dir && *install_name_dir) {
dir = install_name_dir;
dir += "/";
Expand Down
10 changes: 10 additions & 0 deletions Source/cmGeneratorTarget.h
Expand Up @@ -525,6 +525,16 @@ class cmGeneratorTarget
/** Whether this library defaults to \@rpath. */
bool MacOSXRpathInstallNameDirDefault() const;

enum InstallNameType
{
INSTALL_NAME_FOR_BUILD,
INSTALL_NAME_FOR_INSTALL
};
/** Whether to use INSTALL_NAME_DIR. */
bool MacOSXUseInstallNameDir() const;
/** Whether to generate an install_name. */
bool CanGenerateInstallNameDir(InstallNameType t) const;

/** Test for special case of a third-party shared library that has
no soname at all. */
bool IsImportedSharedLibWithoutSOName(const std::string& config) const;
Expand Down
25 changes: 25 additions & 0 deletions Source/cmGlobalGenerator.cxx
Expand Up @@ -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.
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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);
}

Expand Down
3 changes: 3 additions & 0 deletions Source/cmGlobalGenerator.h
Expand Up @@ -357,6 +357,7 @@ class cmGlobalGenerator
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;

Expand Down Expand Up @@ -562,6 +563,8 @@ class cmGlobalGenerator

// 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;
Expand Down
8 changes: 6 additions & 2 deletions Source/cmPolicies.h
Expand Up @@ -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) \
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions Source/cmTarget.cxx
Expand Up @@ -253,6 +253,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
this->SetPropertyDefault("WIN32_EXECUTABLE", CM_NULLPTR);
this->SetPropertyDefault("MACOSX_BUNDLE", CM_NULLPTR);
this->SetPropertyDefault("MACOSX_RPATH", CM_NULLPTR);
this->SetPropertyDefault("BUILD_WITH_INSTALL_NAME_DIR", CM_NULLPTR);
this->SetPropertyDefault("C_CLANG_TIDY", CM_NULLPTR);
this->SetPropertyDefault("C_COMPILER_LAUNCHER", CM_NULLPTR);
this->SetPropertyDefault("C_CPPLINT", CM_NULLPTR);
Expand Down
1 change: 1 addition & 0 deletions Tests/RunCMake/CMP0068/CMP0068-NEW-result.txt
@@ -0,0 +1 @@
0
6 changes: 6 additions & 0 deletions 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 change: 1 addition & 0 deletions Tests/RunCMake/CMP0068/CMP0068-OLD-result.txt
@@ -0,0 +1 @@
0
6 changes: 6 additions & 0 deletions 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 change: 1 addition & 0 deletions Tests/RunCMake/CMP0068/CMP0068-WARN-result.txt
@@ -0,0 +1 @@
0
12 changes: 12 additions & 0 deletions 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 changes: 12 additions & 0 deletions 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 changes: 3 additions & 0 deletions Tests/RunCMake/CMP0068/CMakeLists.txt
@@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.8)
project(${RunCMake_TEST} CXX)
include(${RunCMake_TEST}.cmake)

0 comments on commit f3e8a89

Please sign in to comment.