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