diff options
author | Brad King <brad.king@kitware.com> | 2019-07-21 11:57:08 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2019-07-23 10:46:34 (GMT) |
commit | 11fa818ecda0b50446aef891b06976973005e94b (patch) | |
tree | 96346a94e65e0aae090da50ad8862b9fec4b2aab /Source/cmGeneratorExpressionNode.cxx | |
parent | 0239bf8ac88bb8ae9d8945be506cee2c9adb08f5 (diff) | |
download | CMake-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.cxx | 35 |
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; |