summaryrefslogtreecommitdiffstats
path: root/Source/cmGeneratorExpressionNode.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2019-07-21 11:57:08 (GMT)
committerBrad King <brad.king@kitware.com>2019-07-23 10:46:34 (GMT)
commit11fa818ecda0b50446aef891b06976973005e94b (patch)
tree96346a94e65e0aae090da50ad8862b9fec4b2aab /Source/cmGeneratorExpressionNode.cxx
parent0239bf8ac88bb8ae9d8945be506cee2c9adb08f5 (diff)
downloadCMake-11fa818ecda0b50446aef891b06976973005e94b.zip
CMake-11fa818ecda0b50446aef891b06976973005e94b.tar.gz
CMake-11fa818ecda0b50446aef891b06976973005e94b.tar.bz2
Genex: Optimize usage requirement TARGET_PROPERTY recursion
In large projects the generation process spends a lot of time evaluating usage requirements through transitive interface properties on targets. This can be seen in a contrived example with deep dependencies: set(prev "") foreach(i RANGE 1 500) add_library(a${i} a.c) target_compile_definitions(a${i} PUBLIC A${i}) target_link_libraries(a${i} PUBLIC ${prev}) set(prev a${i}) endforeach() For each usage requirement (such as `INTERFACE_COMPILE_DEFINITIONS` or `INTERFACE_INCLUDE_DIRECTORIES`), the value of the generator expression `$<TARGET_PROPERTY:target,prop>` includes the values of the same 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 creating and using a dedicated evaluation method `cmGeneratorTarget::EvaluateInterfaceProperty` that looks up the properties directly. Issue: #18964, #18965
Diffstat (limited to 'Source/cmGeneratorExpressionNode.cxx')
-rw-r--r--Source/cmGeneratorExpressionNode.cxx35
1 files changed, 13 insertions, 22 deletions
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index b268ea2..8d02b68 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -1243,6 +1243,11 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
}
}
+ if (isInterfaceProperty) {
+ return target->EvaluateInterfaceProperty(propertyName, context,
+ dagCheckerParent);
+ }
+
cmGeneratorExpressionDAGChecker dagChecker(
context->Backtrace, target, propertyName, content, dagCheckerParent);
@@ -1254,10 +1259,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
// No error. We just skip cyclic references.
return std::string();
case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
- if (isInterfaceProperty) {
- // No error. We're not going to find anything new here.
- return std::string();
- }
+ // We handle transitive properties above. For non-transitive
+ // properties we accept repeats anyway.
case cmGeneratorExpressionDAGChecker::DAG:
break;
}
@@ -1328,27 +1331,15 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
}
if (!interfacePropertyName.empty()) {
- cmGeneratorTarget const* headTarget =
- context->HeadTarget && isInterfaceProperty ? context->HeadTarget
- : target;
+ cmGeneratorTarget const* headTarget = target;
result = this->EvaluateDependentExpression(
result, context->LG, context, headTarget, target, &dagChecker);
std::string linkedTargetsContent;
- if (isInterfaceProperty) {
- if (cmLinkInterfaceLibraries const* iface =
- target->GetLinkInterfaceLibraries(context->Config, headTarget,
- true)) {
- linkedTargetsContent = getLinkedTargetsContent(
- iface->Libraries, target, headTarget, context, &dagChecker,
- interfacePropertyName);
- }
- } else {
- if (cmLinkImplementationLibraries const* impl =
- target->GetLinkImplementationLibraries(context->Config)) {
- linkedTargetsContent =
- getLinkedTargetsContent(impl->Libraries, target, target, context,
- &dagChecker, interfacePropertyName);
- }
+ if (cmLinkImplementationLibraries const* impl =
+ target->GetLinkImplementationLibraries(context->Config)) {
+ linkedTargetsContent =
+ getLinkedTargetsContent(impl->Libraries, target, target, context,
+ &dagChecker, interfacePropertyName);
}
if (!linkedTargetsContent.empty()) {
result += (result.empty() ? "" : ";") + linkedTargetsContent;