Add a PARENT_SCOPE argument to cmake_policy(SET) that makes the policy
apply to the parent (strong) scope - it will break out of exactly one
level of the policy stack.

This is intended to be used from a "settings file" which is applied to a
group of CMake projects. This allows the file to control which policies
apply only within the file and which apply to the project. It also means
that users of the settings file are not forced to use NO_POLICY_SCOPE
(particularly important if the settings file did not originally have any
policy settings in it, but later acquired some).
---
 Source/cmCMakePolicyCommand.cxx                    | 19 +++++-
 Source/cmMakefile.cxx                              | 14 +++--
 Source/cmMakefile.h                                |  4 +-
 Tests/PolicyScope/CMakeLists.txt                   | 73 +++++++++++++++++++++-
 Tests/PolicyScope/FindFoo.cmake                    |  1 +
 Tests/PolicyScope/IncludesUsesParentScope.cmake    |  1 +
 .../IncludesUsesParentScopeWithCMP0011New.cmake    |  2 +
 .../IncludesUsesParentScopeWithCMP0011Old.cmake    |  2 +
 Tests/PolicyScope/UsesParentScope.cmake            |  3 +
 9 files changed, 109 insertions(+), 10 deletions(-)
 create mode 100644 Tests/PolicyScope/IncludesUsesParentScope.cmake
 create mode 100644 
Tests/PolicyScope/IncludesUsesParentScopeWithCMP0011New.cmake
 create mode 100644 
Tests/PolicyScope/IncludesUsesParentScopeWithCMP0011Old.cmake
 create mode 100644 Tests/PolicyScope/UsesParentScope.cmake

diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx
index 3ef6d35..5e249a5 100644
--- a/Source/cmCMakePolicyCommand.cxx
+++ b/Source/cmCMakePolicyCommand.cxx
@@ -65,9 +65,9 @@ bool cmCMakePolicyCommand
 //----------------------------------------------------------------------------
 bool cmCMakePolicyCommand::HandleSetMode(std::vector<std::string> const& args)
 {
-  if(args.size() != 3)
+  if(args.size() != 3 && args.size() != 4)
     {
-    this->SetError("SET must be given exactly 2 additional arguments.");
+    this->SetError("SET must be given 2-3 additional arguments.");
     return false;
     }
 
@@ -88,7 +88,20 @@ bool 
cmCMakePolicyCommand::HandleSetMode(std::vector<std::string> const& args)
     return false;
     }
 
-  if(!this->Makefile->SetPolicy(args[1].c_str(), status))
+  bool include_parent = false;
+  if(args.size() == 4)
+    {
+    include_parent = true;
+    if (args[3] != "PARENT_SCOPE")
+      {
+      std::ostringstream e;
+      e << "SET given unexpected third argument \"" << args[3] << "\"";
+      this->SetError(e.str());
+      return false;
+      }
+    }
+
+  if(!this->Makefile->SetPolicy(args[1].c_str(), status, include_parent))
     {
     this->SetError("SET failed to set policy.");
     return false;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 57e33df..3859938 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -4791,7 +4791,8 @@ bool cmMakefile::PolicyOptionalWarningEnabled(std::string 
const& var)
 }
 
 bool cmMakefile::SetPolicy(const char *id,
-                           cmPolicies::PolicyStatus status)
+                           cmPolicies::PolicyStatus status,
+                           bool include_parent)
 {
   cmPolicies::PolicyID pid;
   if (!cmPolicies::GetPolicyID(id, /* out */ pid))
@@ -4801,12 +4802,13 @@ bool cmMakefile::SetPolicy(const char *id,
     this->IssueMessage(cmake::FATAL_ERROR, e.str());
     return false;
     }
-  return this->SetPolicy(pid,status);
+  return this->SetPolicy(pid,status,include_parent);
 }
 
 //----------------------------------------------------------------------------
 bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
-                           cmPolicies::PolicyStatus status)
+                           cmPolicies::PolicyStatus status,
+                           bool include_parent)
 {
   // A REQUIRED_ALWAYS policy may be set only to NEW.
   if(status != cmPolicies::NEW &&
@@ -4822,9 +4824,13 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
   // Update the policy stack from the top to the top-most strong entry.
   bool previous_was_weak = true;
   for(PolicyStackType::reverse_iterator psi = this->PolicyStack.rbegin();
-      previous_was_weak && psi != this->PolicyStack.rend(); ++psi)
+      (previous_was_weak || include_parent) && psi != 
this->PolicyStack.rend(); ++psi)
     {
     psi->Set(id, status);
+    if (!previous_was_weak)
+      {
+      include_parent = false;
+      }
     previous_was_weak = psi->Weak;
     }
 
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 7938fcc..44a47f5 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -318,8 +318,8 @@ public:
   /**
      * Set, Push, Pop policy values for CMake.
      */
-  bool SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status);
-  bool SetPolicy(const char *id, cmPolicies::PolicyStatus status);
+  bool SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status, 
bool include_parent = false);
+  bool SetPolicy(const char *id, cmPolicies::PolicyStatus status, bool 
include_parent = false);
   cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id) const;
   bool SetPolicyVersion(const char *version);
   void RecordPolicies(cmPolicies::PolicyMap& pm);
diff --git a/Tests/PolicyScope/CMakeLists.txt b/Tests/PolicyScope/CMakeLists.txt
index 413195a..277b7cc 100644
--- a/Tests/PolicyScope/CMakeLists.txt
+++ b/Tests/PolicyScope/CMakeLists.txt
@@ -27,10 +27,12 @@ cmake_policy(GET CMP0003 cmp)
 check(CMP0003 "OLD" "${cmp}")
 cmake_policy(GET CMP0002 cmp)
 check(CMP0002 "NEW" "${cmp}")
+cmake_policy(GET CMP0005 cmp)
+check(CMP0005 "OLD" "${cmp}")
 cmake_policy(GET CMP0011 cmp)
 check(CMP0011 "NEW" "${cmp}")
 
-# Make sure an included file cannot change policies.
+# Make sure an included file does not change policies.
 include(Bar)
 cmake_policy(GET CMP0003 cmp)
 check(CMP0003 "OLD" "${cmp}")
@@ -40,6 +42,75 @@ include(Bar NO_POLICY_SCOPE)
 cmake_policy(GET CMP0003 cmp)
 check(CMP0003 "NEW" "${cmp}")
 
+cmake_policy(SET CMP0011 NEW)
+
+# NO_POLICY_SCOPE has no restrictions
+cmake_policy(SET CMP0003 OLD)
+cmake_policy(SET CMP0005 OLD)
+include(UsesParentScope NO_POLICY_SCOPE)
+cmake_policy(GET CMP0003 cmp)
+check(CMP0003 "NEW" "${cmp}")
+cmake_policy(GET CMP0005 cmp)
+check(CMP0005 "NEW" "${cmp}")
+
+# Only PARENT_SCOPE changes propagate
+cmake_policy(SET CMP0003 OLD)
+cmake_policy(SET CMP0005 OLD)
+include(UsesParentScope)
+cmake_policy(GET CMP0003 cmp)
+check(CMP0003 "OLD" "${cmp}")
+cmake_policy(GET CMP0005 cmp)
+check(CMP0005 "NEW" "${cmp}")
+
+# NO_POLICY_SCOPE allows PARENT_SCOPE changes from the inner include to 
propagate
+cmake_policy(SET CMP0003 OLD)
+cmake_policy(SET CMP0005 OLD)
+include(IncludesUsesParentScope NO_POLICY_SCOPE)
+cmake_policy(GET CMP0003 cmp)
+check(CMP0003 "OLD" "${cmp}")
+cmake_policy(GET CMP0005 cmp)
+check(CMP0005 "NEW" "${cmp}")
+
+# No changes from the inner include to propagate
+cmake_policy(SET CMP0003 OLD)
+cmake_policy(SET CMP0005 OLD)
+include(IncludesUsesParentScope)
+cmake_policy(GET CMP0003 cmp)
+check(CMP0003 "OLD" "${cmp}")
+cmake_policy(GET CMP0005 cmp)
+check(CMP0005 "OLD" "${cmp}")
+
+cmake_policy(SET CMP0011 OLD)
+
+# As if NO_POLICY_SCOPE was set (also applies to children)
+cmake_policy(SET CMP0003 OLD)
+cmake_policy(SET CMP0005 OLD)
+include(IncludesUsesParentScope)
+cmake_policy(GET CMP0003 cmp)
+check(CMP0003 "NEW" "${cmp}")
+cmake_policy(GET CMP0005 cmp)
+check(CMP0005 "NEW" "${cmp}")
+
+# As if NO_POLICY_SCOPE was set (does not apply to children)
+cmake_policy(SET CMP0003 OLD)
+cmake_policy(SET CMP0005 OLD)
+include(IncludesUsesParentScopeWithCMP0011New)
+cmake_policy(GET CMP0003 cmp)
+check(CMP0003 "OLD" "${cmp}")
+cmake_policy(GET CMP0005 cmp)
+check(CMP0005 "NEW" "${cmp}")
+
+cmake_policy(SET CMP0011 NEW)
+
+# As if NO_POLICY_SCOPE was set in child-level include
+cmake_policy(SET CMP0003 OLD)
+cmake_policy(SET CMP0005 OLD)
+include(IncludesUsesParentScopeWithCMP0011Old)
+cmake_policy(GET CMP0003 cmp)
+check(CMP0003 "OLD" "${cmp}")
+cmake_policy(GET CMP0005 cmp)
+check(CMP0005 "NEW" "${cmp}")
+
 #-----------------------------------------------------------------------------
 # Test function and macro policy recording.
 
diff --git a/Tests/PolicyScope/FindFoo.cmake b/Tests/PolicyScope/FindFoo.cmake
index 5b441e2..e7f8f9c 100644
--- a/Tests/PolicyScope/FindFoo.cmake
+++ b/Tests/PolicyScope/FindFoo.cmake
@@ -1,2 +1,3 @@
 cmake_minimum_required(VERSION 2.6.3)
 cmake_policy(SET CMP0003 OLD)
+cmake_policy(SET CMP0005 OLD PARENT_SCOPE)
diff --git a/Tests/PolicyScope/IncludesUsesParentScope.cmake 
b/Tests/PolicyScope/IncludesUsesParentScope.cmake
new file mode 100644
index 0000000..97a6d4c
--- /dev/null
+++ b/Tests/PolicyScope/IncludesUsesParentScope.cmake
@@ -0,0 +1 @@
+include(UsesParentScope)
diff --git a/Tests/PolicyScope/IncludesUsesParentScopeWithCMP0011New.cmake 
b/Tests/PolicyScope/IncludesUsesParentScopeWithCMP0011New.cmake
new file mode 100644
index 0000000..5900c12
--- /dev/null
+++ b/Tests/PolicyScope/IncludesUsesParentScopeWithCMP0011New.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0011 NEW)
+include(UsesParentScope)
diff --git a/Tests/PolicyScope/IncludesUsesParentScopeWithCMP0011Old.cmake 
b/Tests/PolicyScope/IncludesUsesParentScopeWithCMP0011Old.cmake
new file mode 100644
index 0000000..6b63d36
--- /dev/null
+++ b/Tests/PolicyScope/IncludesUsesParentScopeWithCMP0011Old.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0011 OLD)
+include(UsesParentScope)
diff --git a/Tests/PolicyScope/UsesParentScope.cmake 
b/Tests/PolicyScope/UsesParentScope.cmake
new file mode 100644
index 0000000..4748033
--- /dev/null
+++ b/Tests/PolicyScope/UsesParentScope.cmake
@@ -0,0 +1,3 @@
+cmake_policy(SET CMP0003 NEW)
+cmake_policy(SET CMP0005 NEW PARENT_SCOPE)
+
-- 
2.4.6


-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake-developers

Reply via email to