mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-11 08:20:18 -06:00
Genex: Optimize build setting TARGET_PROPERTY evaluation
For each build setting property (such as `COMPILE_DEFINITIONS` or `INCLUDE_DIRECTORIES`), the value of `$<TARGET_PROPERTY:target,prop>` includes the values of the corresponding `INTERFACE_*` usage requirement property from the transitive closure of link libraries of the target. Previously we computed this by constructing a generator expression string like `$<TARGET_PROPERTY:lib,INTERFACE_COMPILE_DEFINITIONS>` and recursively evaluating it with the generator expression engine. Avoid the string construction and parsing by using the dedicated evaluation method `cmGeneratorTarget::EvaluateInterfaceProperty`. Issue: #18964, #18965
This commit is contained in:
@@ -1038,37 +1038,38 @@ static const struct CompileLanguageAndIdNode : public cmGeneratorExpressionNode
|
||||
}
|
||||
} languageAndIdNode;
|
||||
|
||||
template <typename T>
|
||||
std::string getLinkedTargetsContent(
|
||||
std::vector<T> const& libraries, cmGeneratorTarget const* target,
|
||||
cmGeneratorTarget const* headTarget, cmGeneratorExpressionContext* context,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker,
|
||||
const std::string& interfacePropertyName)
|
||||
cmGeneratorTarget const* target, std::string const& prop,
|
||||
cmGeneratorExpressionContext* context,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker)
|
||||
{
|
||||
std::string linkedTargetsContent;
|
||||
std::string sep;
|
||||
std::string depString;
|
||||
for (T const& l : libraries) {
|
||||
// Broken code can have a target in its own link interface.
|
||||
// Don't follow such link interface entries so as not to create a
|
||||
// self-referencing loop.
|
||||
if (l.Target && l.Target != target) {
|
||||
std::string uniqueName =
|
||||
target->GetGlobalGenerator()->IndexGeneratorTargetUniquely(l.Target);
|
||||
depString += sep + "$<TARGET_PROPERTY:" + std::move(uniqueName) + "," +
|
||||
interfacePropertyName + ">";
|
||||
sep = ";";
|
||||
std::string result;
|
||||
if (cmLinkImplementationLibraries const* impl =
|
||||
target->GetLinkImplementationLibraries(context->Config)) {
|
||||
for (cmLinkImplItem const& lib : impl->Libraries) {
|
||||
if (lib.Target) {
|
||||
// Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
|
||||
// caller's property and hand-evaluate it as if it were compiled.
|
||||
// Create a context as cmCompiledGeneratorExpression::Evaluate does.
|
||||
cmGeneratorExpressionContext libContext(
|
||||
target->GetLocalGenerator(), context->Config, context->Quiet, target,
|
||||
target, context->EvaluateForBuildsystem, lib.Backtrace,
|
||||
context->Language);
|
||||
std::string libResult =
|
||||
lib.Target->EvaluateInterfaceProperty(prop, &libContext, dagChecker);
|
||||
if (!libResult.empty()) {
|
||||
if (result.empty()) {
|
||||
result = std::move(libResult);
|
||||
} else {
|
||||
result.reserve(result.size() + 1 + libResult.size());
|
||||
result += ";";
|
||||
result += libResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!depString.empty()) {
|
||||
linkedTargetsContent =
|
||||
cmGeneratorExpressionNode::EvaluateDependentExpression(
|
||||
depString, target->GetLocalGenerator(), context, headTarget, target,
|
||||
dagChecker);
|
||||
}
|
||||
linkedTargetsContent =
|
||||
cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent);
|
||||
return linkedTargetsContent;
|
||||
return result;
|
||||
}
|
||||
|
||||
static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||
@@ -1331,16 +1332,10 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||
}
|
||||
|
||||
if (!interfacePropertyName.empty()) {
|
||||
cmGeneratorTarget const* headTarget = target;
|
||||
result = this->EvaluateDependentExpression(
|
||||
result, context->LG, context, headTarget, target, &dagChecker);
|
||||
std::string linkedTargetsContent;
|
||||
if (cmLinkImplementationLibraries const* impl =
|
||||
target->GetLinkImplementationLibraries(context->Config)) {
|
||||
linkedTargetsContent =
|
||||
getLinkedTargetsContent(impl->Libraries, target, target, context,
|
||||
&dagChecker, interfacePropertyName);
|
||||
}
|
||||
result = this->EvaluateDependentExpression(result, context->LG, context,
|
||||
target, target, &dagChecker);
|
||||
std::string linkedTargetsContent = getLinkedTargetsContent(
|
||||
target, interfacePropertyName, context, &dagChecker);
|
||||
if (!linkedTargetsContent.empty()) {
|
||||
result += (result.empty() ? "" : ";") + linkedTargetsContent;
|
||||
}
|
||||
|
||||
@@ -1227,23 +1227,17 @@ void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
|
||||
headTarget->GetLinkImplementationLibraries(config)) {
|
||||
for (cmLinkImplItem const& lib : impl->Libraries) {
|
||||
if (lib.Target) {
|
||||
std::string uniqueName =
|
||||
headTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely(
|
||||
lib.Target);
|
||||
std::string genex =
|
||||
"$<TARGET_PROPERTY:" + std::move(uniqueName) + "," + prop + ">";
|
||||
cmGeneratorExpression ge(lib.Backtrace);
|
||||
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
|
||||
cge->SetEvaluateForBuildsystem(true);
|
||||
|
||||
EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
|
||||
// Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
|
||||
// caller's property and hand-evaluate it as if it were compiled.
|
||||
// Create a context as cmCompiledGeneratorExpression::Evaluate does.
|
||||
cmGeneratorExpressionContext context(
|
||||
headTarget->GetLocalGenerator(), config, false, headTarget,
|
||||
headTarget, true, lib.Backtrace, lang);
|
||||
cmSystemTools::ExpandListArgument(
|
||||
cge->Evaluate(headTarget->GetLocalGenerator(), config, false,
|
||||
headTarget, dagChecker, lang),
|
||||
lib.Target->EvaluateInterfaceProperty(prop, &context, dagChecker),
|
||||
ee.Values);
|
||||
if (cge->GetHadContextSensitiveCondition()) {
|
||||
ee.ContextDependent = true;
|
||||
}
|
||||
ee.ContextDependent = context.HadContextSensitiveCondition;
|
||||
entries.emplace_back(std::move(ee));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user