diff --git a/Help/policy/CMP0189.rst b/Help/policy/CMP0189.rst index c2a5893136..71d35200c7 100644 --- a/Help/policy/CMP0189.rst +++ b/Help/policy/CMP0189.rst @@ -18,7 +18,9 @@ target properties transitively because they are among the This policy provides compatibility for projects that have not been updated to expect the new behavior. It takes effect during buildsystem generation. Generator expressions are evaluated in each directory using the policy setting -as of the end of its ``CMakeLists.txt``. +as of the end of its ``CMakeLists.txt``. As an exception, generator +expressions evaluated by the :command:`file(GENERATE)` command use the +policy setting as of its call site. The ``OLD`` behavior of this policy is for :genex:`TARGET_PROPERTY` to not evaluate :prop_tgt:`LINK_LIBRARIES` and :prop_tgt:`INTERFACE_LINK_LIBRARIES` diff --git a/Help/release/4.1.rst b/Help/release/4.1.rst index 095526fd8d..a984269501 100644 --- a/Help/release/4.1.rst +++ b/Help/release/4.1.rst @@ -234,3 +234,12 @@ Changes made since CMake 4.1.0 include the following. * This version made no changes to documented features or interfaces. Some implementation updates were made to support ecosystem changes and/or fix regressions. + +4.1.2 +----- + +* The :command:`file(GENERATE)` command, when evaluating generator + expressions, now uses the value of policy :policy:`CMP0189` as of + each call site. Previously, it used the value as of the end of the + directory's ``CMakeLists.txt``, as all other generator expression + evaluations do. diff --git a/Source/cmGenExContext.cxx b/Source/cmGenExContext.cxx index 1089e5b35f..1699051ce8 100644 --- a/Source/cmGenExContext.cxx +++ b/Source/cmGenExContext.cxx @@ -4,6 +4,11 @@ #include +#include + +#include "cmLocalGenerator.h" +#include "cmPolicies.h" + namespace cm { namespace GenEx { @@ -15,5 +20,18 @@ Context::Context(cmLocalGenerator const* lg, std::string config, { } +void Context::SetCMP0189(cmPolicies::PolicyStatus cmp0189) +{ + this->CMP0189 = cmp0189; +} + +cmPolicies::PolicyStatus Context::GetCMP0189() const +{ + if (this->CMP0189.has_value()) { + return *this->CMP0189; + } + return this->LG->GetPolicyStatus(cmPolicies::CMP0189); +} + } } diff --git a/Source/cmGenExContext.h b/Source/cmGenExContext.h index 4e4e7c4dab..85c8ab2a29 100644 --- a/Source/cmGenExContext.h +++ b/Source/cmGenExContext.h @@ -4,6 +4,10 @@ #include +#include + +#include "cmPolicies.h" + class cmLocalGenerator; namespace cm { @@ -17,6 +21,12 @@ struct Context final cmLocalGenerator const* LG; std::string Config; std::string Language; + + void SetCMP0189(cmPolicies::PolicyStatus cmp0189); + cmPolicies::PolicyStatus GetCMP0189() const; + +private: + cm::optional CMP0189; }; } diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index c7e71f7c78..77946f3115 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -35,9 +35,7 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( this->TopIsTransitiveProperty = parent->TopIsTransitiveProperty; } else { this->TopIsTransitiveProperty = - this->Target - ->IsTransitiveProperty(this->Property, context.LG, context.Config, - this) + this->Target->IsTransitiveProperty(this->Property, context, this) .has_value(); } diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx index 7909fc0c42..38a320bf4f 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.cxx +++ b/Source/cmGeneratorExpressionEvaluationFile.cxx @@ -23,7 +23,8 @@ cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile( std::unique_ptr outputFileExpr, std::unique_ptr condition, bool inputIsContent, std::string newLineCharacter, mode_t permissions, - cmPolicies::PolicyStatus policyStatusCMP0070) + cmPolicies::PolicyStatus policyStatusCMP0070, + cmPolicies::PolicyStatus policyStatusCMP0189) : Input(std::move(input)) , Target(std::move(target)) , OutputFileExpr(std::move(outputFileExpr)) @@ -31,6 +32,7 @@ cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile( , InputIsContent(inputIsContent) , NewLineCharacter(std::move(newLineCharacter)) , PolicyStatusCMP0070(policyStatusCMP0070) + , PolicyStatusCMP0189(policyStatusCMP0189) , Permissions(permissions) { } @@ -41,6 +43,7 @@ void cmGeneratorExpressionEvaluationFile::Generate( std::map& outputFiles, mode_t perm) { cm::GenEx::Context context(lg, config, lang); + context.SetCMP0189(this->PolicyStatusCMP0189); std::string rawCondition = this->Condition->GetInput(); cmGeneratorTarget* target = lg->FindGeneratorTargetToUse(this->Target); if (!rawCondition.empty()) { @@ -126,6 +129,7 @@ void cmGeneratorExpressionEvaluationFile::CreateOutputFile( for (std::string const& lang : enabledLanguages) { cm::GenEx::Context context(lg, config, lang); + context.SetCMP0189(this->PolicyStatusCMP0189); std::string const name = this->GetOutputFileName(context, target); cmSourceFile* sf = lg->GetMakefile()->GetOrCreateGeneratedSource(name); diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h index dab5f14ff9..01955bab9e 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.h +++ b/Source/cmGeneratorExpressionEvaluationFile.h @@ -31,7 +31,8 @@ public: std::unique_ptr outputFileExpr, std::unique_ptr condition, bool inputIsContent, std::string newLineCharacter, mode_t permissions, - cmPolicies::PolicyStatus policyStatusCMP0070); + cmPolicies::PolicyStatus policyStatusCMP0070, + cmPolicies::PolicyStatus policyStatusCMP0189); void Generate(cmLocalGenerator* lg); @@ -64,5 +65,6 @@ private: bool const InputIsContent; std::string const NewLineCharacter; cmPolicies::PolicyStatus PolicyStatusCMP0070; + cmPolicies::PolicyStatus PolicyStatusCMP0189; mode_t Permissions; }; diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 2c0c7291f8..b9e780c11b 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -3097,8 +3097,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode cmGeneratorTarget::UseTo usage = cmGeneratorTarget::UseTo::Compile; if (cm::optional transitiveProp = - target->IsTransitiveProperty(propertyName, eval->Context.LG, - eval->Context.Config, + target->IsTransitiveProperty(propertyName, eval->Context, dagCheckerParent)) { interfacePropertyName = std::string(transitiveProp->InterfaceName); isInterfaceProperty = transitiveProp->InterfaceName == propertyName; diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index ee266ee2f8..e96ddad1ce 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -1032,8 +1032,7 @@ public: BuiltinTransitiveProperties; cm::optional IsTransitiveProperty( - cm::string_view prop, cmLocalGenerator const* lg, - std::string const& config, + cm::string_view prop, cm::GenEx::Context const& context, cmGeneratorExpressionDAGChecker const* dagChecker) const; bool HaveInstallTreeRPATH(std::string const& config) const; diff --git a/Source/cmGeneratorTarget_TransitiveProperty.cxx b/Source/cmGeneratorTarget_TransitiveProperty.cxx index a6ab68c2d3..81072f28b9 100644 --- a/Source/cmGeneratorTarget_TransitiveProperty.cxx +++ b/Source/cmGeneratorTarget_TransitiveProperty.cxx @@ -177,7 +177,7 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty( cm::optional cmGeneratorTarget::IsTransitiveProperty( - cm::string_view prop, cmLocalGenerator const* lg, std::string const& config, + cm::string_view prop, cm::GenEx::Context const& context, cmGeneratorExpressionDAGChecker const* dagChecker) const { cm::optional result; @@ -192,15 +192,14 @@ cmGeneratorTarget::IsTransitiveProperty( if (i != BuiltinTransitiveProperties.end() && // Look up CMP0189 in the context where evaluation occurs, // not where the target was created. - lg->GetPolicyStatus(cmPolicies::CMP0189) != cmPolicies::NEW && - prop == "LINK_LIBRARIES"_s) { + context.GetCMP0189() != cmPolicies::NEW && prop == "LINK_LIBRARIES"_s) { i = BuiltinTransitiveProperties.end(); } if (i != BuiltinTransitiveProperties.end()) { result = i->second; if (result->Usage != cmGeneratorTarget::UseTo::Compile) { cmPolicies::PolicyStatus cmp0166 = - lg->GetPolicyStatus(cmPolicies::CMP0166); + context.LG->GetPolicyStatus(cmPolicies::CMP0166); if ((cmp0166 == cmPolicies::WARN || cmp0166 == cmPolicies::OLD) && (prop == "LINK_DIRECTORIES"_s || prop == "LINK_DEPENDS"_s || prop == "LINK_OPTIONS"_s)) { @@ -211,7 +210,7 @@ cmGeneratorTarget::IsTransitiveProperty( // Honor TRANSITIVE_COMPILE_PROPERTIES and TRANSITIVE_LINK_PROPERTIES // from the link closure when we are not evaluating the closure itself. CustomTransitiveProperties const& ctp = - this->GetCustomTransitiveProperties(config, propertyFor); + this->GetCustomTransitiveProperties(context.Config, propertyFor); auto ci = ctp.find(std::string(prop)); if (ci != ctp.end()) { result = ci->second; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index e58b303579..911485bd4c 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -942,7 +942,8 @@ void cmMakefile::AddEvaluationFile( cm::make_unique( inputFile, targetName, std::move(outputName), std::move(condition), inputIsContent, newLineCharacter, permissions, - this->GetPolicyStatus(cmPolicies::CMP0070))); + this->GetPolicyStatus(cmPolicies::CMP0070), + this->GetPolicyStatus(cmPolicies::CMP0189))); } std::vector> const& diff --git a/Tests/CustomTransitiveProperties/CMP0189/CMakeLists.txt b/Tests/CustomTransitiveProperties/CMP0189/CMakeLists.txt index 04fb1b4f63..8df28ccd7d 100644 --- a/Tests/CustomTransitiveProperties/CMP0189/CMakeLists.txt +++ b/Tests/CustomTransitiveProperties/CMP0189/CMakeLists.txt @@ -1,10 +1,18 @@ +set(out "${CMAKE_CURRENT_BINARY_DIR}/out-OLD-$.txt") +file(GENERATE OUTPUT "${out}" CONTENT "# file(GENERATE) produced: +${in_LINK_LIBRARIES} +") +add_custom_target(check-CMP0189-OLD ALL VERBATIM + COMMAND ${CMAKE_COMMAND} -Dconfig=$ -Dout=${out} -P${CMAKE_CURRENT_SOURCE_DIR}/check-OLD.cmake +) + cmake_policy(SET CMP0189 NEW) -set(out "${CMAKE_CURRENT_BINARY_DIR}/out-$.txt") +set(out "${CMAKE_CURRENT_BINARY_DIR}/out-NEW-$.txt") file(GENERATE OUTPUT "${out}" CONTENT "# file(GENERATE) produced: ${in_LINK_LIBRARIES} ") add_custom_target(check-CMP0189-NEW ALL VERBATIM - COMMAND ${CMAKE_COMMAND} -Dconfig=$ -Dout=${out} -P${CMAKE_CURRENT_SOURCE_DIR}/check.cmake + COMMAND ${CMAKE_COMMAND} -Dconfig=$ -Dout=${out} -P${CMAKE_CURRENT_SOURCE_DIR}/check-NEW.cmake COMMAND check-args "$" "" "$" "" diff --git a/Tests/CustomTransitiveProperties/CMP0189/check.cmake b/Tests/CustomTransitiveProperties/CMP0189/check-NEW.cmake similarity index 100% rename from Tests/CustomTransitiveProperties/CMP0189/check.cmake rename to Tests/CustomTransitiveProperties/CMP0189/check-NEW.cmake diff --git a/Tests/CustomTransitiveProperties/CMP0189/check-OLD.cmake b/Tests/CustomTransitiveProperties/CMP0189/check-OLD.cmake new file mode 100644 index 0000000000..94dd066829 --- /dev/null +++ b/Tests/CustomTransitiveProperties/CMP0189/check-OLD.cmake @@ -0,0 +1,32 @@ +set(expect [[ +# file\(GENERATE\) produced: +iface1 LINK_LIBRARIES: '' +iface1 INTERFACE_LINK_LIBRARIES: '' +iface2 LINK_LIBRARIES: '' +iface2 INTERFACE_LINK_LIBRARIES: 'iface1' +static1 LINK_LIBRARIES: 'iface2' +static1 INTERFACE_LINK_LIBRARIES: '\$' +main LINK_LIBRARIES: 'static1;object1' +main INTERFACE_LINK_LIBRARIES: '' +iface10 LINK_LIBRARIES: '' +iface10 INTERFACE_LINK_LIBRARIES: '' +iface11 LINK_LIBRARIES: '' +iface11 INTERFACE_LINK_LIBRARIES: 'iface10' +static10 LINK_LIBRARIES: 'iface11;iface10' +static10 INTERFACE_LINK_LIBRARIES: 'iface11;iface10' +static11 LINK_LIBRARIES: 'static10;iface11;iface11;iface10' +static11 INTERFACE_LINK_LIBRARIES: 'static10;iface11;iface11;iface10' +main10 LINK_LIBRARIES: 'static11;static10;static10;iface11;iface11;iface10' +main10 INTERFACE_LINK_LIBRARIES: '' +iface20 LINK_LIBRARIES: '' +iface20 INTERFACE_LINK_LIBRARIES: '' +iface21 LINK_LIBRARIES: '' +iface21 INTERFACE_LINK_LIBRARIES: 'iface20' +static20 LINK_LIBRARIES: 'iface21' +static20 INTERFACE_LINK_LIBRARIES: '\$' +static21 LINK_LIBRARIES: 'static20;iface21' +static21 INTERFACE_LINK_LIBRARIES: '\$;\$' +main20 LINK_LIBRARIES: 'static21;static20' +main20 INTERFACE_LINK_LIBRARIES: '' +]]) +include(${CMAKE_CURRENT_LIST_DIR}/../check-common.cmake)