1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-14 02:08:27 +08:00

file(GENERATE): Record CMP0189 at each call site

Policy CMP0189, introduced by commit b3da9c6d60 (GenEx: Evaluate
LINK_LIBRARIES target properties transitively, 2025-02-24,
v4.1.0-rc1~731^2), takes effect at generation time, and so uses the
policy value as of the end of each directory.  However, some projects
may rely on `file(GENERATE)` with the policy's OLD behavior in order
to extract targets' *direct* dependencies from `LINK_LIBRARIES`.
Pending a first-class solution to that problem, make it easier for
projects to port to the policy's NEW behavior in general while
retaining the OLD behavior in an isolated context.

Fixes: #27220
This commit is contained in:
Brad King
2025-09-23 11:27:53 -04:00
parent 9b862e7013
commit deb7b4b658
11 changed files with 93 additions and 8 deletions

View File

@@ -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`

View File

@@ -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.

View File

@@ -4,6 +4,11 @@
#include <utility>
#include <cm/optional>
#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);
}
}
}

View File

@@ -4,6 +4,10 @@
#include <string>
#include <cm/optional>
#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<cmPolicies::PolicyStatus> CMP0189;
};
}

View File

@@ -23,7 +23,8 @@ cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile(
std::unique_ptr<cmCompiledGeneratorExpression> outputFileExpr,
std::unique_ptr<cmCompiledGeneratorExpression> 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<std::string, std::string>& 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);

View File

@@ -31,7 +31,8 @@ public:
std::unique_ptr<cmCompiledGeneratorExpression> outputFileExpr,
std::unique_ptr<cmCompiledGeneratorExpression> 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;
};

View File

@@ -192,8 +192,7 @@ cmGeneratorTarget::IsTransitiveProperty(
if (i != BuiltinTransitiveProperties.end() &&
// Look up CMP0189 in the context where evaluation occurs,
// not where the target was created.
context.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()) {

View File

@@ -941,7 +941,8 @@ void cmMakefile::AddEvaluationFile(
cm::make_unique<cmGeneratorExpressionEvaluationFile>(
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<std::unique_ptr<cmGeneratorExpressionEvaluationFile>> const&

View File

@@ -1,10 +1,18 @@
set(out "${CMAKE_CURRENT_BINARY_DIR}/out-OLD-$<CONFIG>.txt")
file(GENERATE OUTPUT "${out}" CONTENT "# file(GENERATE) produced:
${in_LINK_LIBRARIES}
")
add_custom_target(check-CMP0189-OLD ALL VERBATIM
COMMAND ${CMAKE_COMMAND} -Dconfig=$<CONFIG> -Dout=${out} -P${CMAKE_CURRENT_SOURCE_DIR}/check-OLD.cmake
)
cmake_policy(SET CMP0189 NEW)
set(out "${CMAKE_CURRENT_BINARY_DIR}/out-$<CONFIG>.txt")
set(out "${CMAKE_CURRENT_BINARY_DIR}/out-NEW-$<CONFIG>.txt")
file(GENERATE OUTPUT "${out}" CONTENT "# file(GENERATE) produced:
${in_LINK_LIBRARIES}
")
add_custom_target(check-CMP0189-NEW ALL VERBATIM
COMMAND ${CMAKE_COMMAND} -Dconfig=$<CONFIG> -Dout=${out} -P${CMAKE_CURRENT_SOURCE_DIR}/check.cmake
COMMAND ${CMAKE_COMMAND} -Dconfig=$<CONFIG> -Dout=${out} -P${CMAKE_CURRENT_SOURCE_DIR}/check-NEW.cmake
COMMAND check-args
"$<TARGET_PROPERTY:iface1,LINK_LIBRARIES>" ""
"$<TARGET_PROPERTY:iface1,INTERFACE_LINK_LIBRARIES>" ""

View File

@@ -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: '\$<LINK_ONLY:iface2>'
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: '\$<LINK_ONLY:iface21>'
static21 LINK_LIBRARIES: 'static20;iface21'
static21 INTERFACE_LINK_LIBRARIES: '\$<LINK_ONLY:static20>;\$<LINK_ONLY:iface21>'
main20 LINK_LIBRARIES: 'static21;static20'
main20 INTERFACE_LINK_LIBRARIES: ''
]])
include(${CMAKE_CURRENT_LIST_DIR}/../check-common.cmake)