[Cmake-commits] CMake branch, master, updated. v3.15.0-492-gd9156c3
Kitware Robot
kwrobot at kitware.com
Fri Jul 26 07:43:07 EDT 2019
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".
The branch, master has been updated
via d9156c387c60bc15523a27bba83809ec9fa2a8bf (commit)
via 8df10447a18d6479160189509a248a465d6e967c (commit)
via 52ea0c4676e2e9893312a9f73609603129cd6886 (commit)
via 838278f4babe248eeb302f98651662ef8d94c7e6 (commit)
via 3b113cc131a2c477a29960676cccb697994353ec (commit)
via 1d3841b6003d4f1a45e79f6b9e6d6357514905f1 (commit)
via b5460f99315f8e6a6bdc985ebc0ca18dd8a294a8 (commit)
via ad2b3a32d1b54716d1e87ae89db8c31d614a4730 (commit)
via 11fa818ecda0b50446aef891b06976973005e94b (commit)
via 0239bf8ac88bb8ae9d8945be506cee2c9adb08f5 (commit)
via 7caebeb0e4babc41e5c84b4ce0ea70adcfdea4a1 (commit)
via b2785a0fbdcfa703f3ad3aaa2949ec7db55a27d9 (commit)
from 467e6ac728cefa484f9e9369a7da4d05b04ec403 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d9156c387c60bc15523a27bba83809ec9fa2a8bf
commit d9156c387c60bc15523a27bba83809ec9fa2a8bf
Merge: 8df1044 838278f
Author: Brad King <brad.king at kitware.com>
AuthorDate: Fri Jul 26 07:37:55 2019 -0400
Commit: Brad King <brad.king at kitware.com>
CommitDate: Fri Jul 26 07:37:55 2019 -0400
Merge branch 'release-3.15'
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8df10447a18d6479160189509a248a465d6e967c
commit 8df10447a18d6479160189509a248a465d6e967c
Merge: 52ea0c4 3b113cc
Author: Brad King <brad.king at kitware.com>
AuthorDate: Fri Jul 26 11:37:10 2019 +0000
Commit: Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri Jul 26 07:37:19 2019 -0400
Merge topic 'doc-relnotes-3.15'
3b113cc131 Help: Add 3.15.1 release notes
Acked-by: Kitware Robot <kwrobot at kitware.com>
Merge-request: !3608
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=52ea0c4676e2e9893312a9f73609603129cd6886
commit 52ea0c4676e2e9893312a9f73609603129cd6886
Merge: 467e6ac 1d3841b
Author: Brad King <brad.king at kitware.com>
AuthorDate: Fri Jul 26 11:29:53 2019 +0000
Commit: Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri Jul 26 07:33:27 2019 -0400
Merge topic 'optimize-usage-requirements'
1d3841b600 Genex: Memoize usage requirement TARGET_PROPERTY existence
b5460f9931 cmLinkItem: Expose HadHeadSensitiveCondition in cmLinkInterfaceLibraries
ad2b3a32d1 Genex: Optimize build setting TARGET_PROPERTY evaluation
11fa818ecd Genex: Optimize usage requirement TARGET_PROPERTY recursion
0239bf8ac8 Genex: In TARGET_PROPERTY check for usage reqs in link libs earlier
7caebeb0e4 Genex: Re-order TARGET_PROPERTY logic to de-duplicate checks
b2785a0fbd Genex: Move TARGET_PROPERTY linked targets evaluation to end
Acked-by: Kitware Robot <kwrobot at kitware.com>
Acked-by: Cristian Adam <cristian.adam at gmail.com>
Merge-request: !3589
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1d3841b6003d4f1a45e79f6b9e6d6357514905f1
commit 1d3841b6003d4f1a45e79f6b9e6d6357514905f1
Author: Brad King <brad.king at kitware.com>
AuthorDate: Tue Jul 23 10:01:13 2019 -0400
Commit: Brad King <brad.king at kitware.com>
CommitDate: Tue Jul 23 10:44:19 2019 -0400
Genex: Memoize usage requirement TARGET_PROPERTY existence
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.
In cases that a target's transitive closure of dependencies does not
depend on the target being linked (the "head" target), we can memoize
whether or not a usage requirement property exists at all for that
target. When a usage requirement does not exist for a target, we
can skip evaluating it for every consuming target.
Fixes: #18964, #18965
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index b22d8b6..7c41045 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -1143,12 +1143,59 @@ bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const
return this->Target->GetPropertyAsBool(prop);
}
+bool cmGeneratorTarget::MaybeHaveInterfaceProperty(
+ std::string const& prop, cmGeneratorExpressionContext* context) const
+{
+ std::string const key = prop + '@' + context->Config;
+ auto i = this->MaybeInterfacePropertyExists.find(key);
+ if (i == this->MaybeInterfacePropertyExists.end()) {
+ // Insert an entry now in case there is a cycle.
+ i = this->MaybeInterfacePropertyExists.emplace(key, false).first;
+ bool& maybeInterfaceProp = i->second;
+
+ // If this target itself has a non-empty property value, we are done.
+ const char* p = this->GetProperty(prop);
+ maybeInterfaceProp = p && *p;
+
+ // Otherwise, recurse to interface dependencies.
+ if (!maybeInterfaceProp) {
+ cmGeneratorTarget const* headTarget =
+ context->HeadTarget ? context->HeadTarget : this;
+ if (cmLinkInterfaceLibraries const* iface =
+ this->GetLinkInterfaceLibraries(context->Config, headTarget,
+ true)) {
+ if (iface->HadHeadSensitiveCondition) {
+ // With a different head target we may get to a library with
+ // this interface property.
+ maybeInterfaceProp = true;
+ } else {
+ // The transitive interface libraries do not depend on the
+ // head target, so we can follow them.
+ for (cmLinkItem const& lib : iface->Libraries) {
+ if (lib.Target &&
+ lib.Target->MaybeHaveInterfaceProperty(prop, context)) {
+ maybeInterfaceProp = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return i->second;
+}
+
std::string cmGeneratorTarget::EvaluateInterfaceProperty(
std::string const& prop, cmGeneratorExpressionContext* context,
cmGeneratorExpressionDAGChecker* dagCheckerParent) const
{
std::string result;
+ // If the property does not appear transitively at all, we are done.
+ if (!this->MaybeHaveInterfaceProperty(prop, context)) {
+ return result;
+ }
+
// Evaluate $<TARGET_PROPERTY:this,prop> as if it were compiled. This is
// a subset of TargetPropertyNode::Evaluate without stringify/parse steps
// but sufficient for transitive interface properties.
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index b875c40..3874738 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -14,6 +14,7 @@
#include <set>
#include <stddef.h>
#include <string>
+#include <unordered_map>
#include <utility>
#include <vector>
@@ -856,6 +857,10 @@ private:
mutable std::vector<AllConfigSource> AllConfigSources;
void ComputeAllConfigSources() const;
+ mutable std::unordered_map<std::string, bool> MaybeInterfacePropertyExists;
+ bool MaybeHaveInterfaceProperty(std::string const& prop,
+ cmGeneratorExpressionContext* context) const;
+
std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
std::vector<TargetPropertyEntry*> CompileOptionsEntries;
std::vector<TargetPropertyEntry*> CompileFeaturesEntries;
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b5460f99315f8e6a6bdc985ebc0ca18dd8a294a8
commit b5460f99315f8e6a6bdc985ebc0ca18dd8a294a8
Author: Brad King <brad.king at kitware.com>
AuthorDate: Tue Jul 23 09:52:33 2019 -0400
Commit: Brad King <brad.king at kitware.com>
CommitDate: Tue Jul 23 10:06:35 2019 -0400
cmLinkItem: Expose HadHeadSensitiveCondition in cmLinkInterfaceLibraries
Clients may be able to avoid repeating work if they know the transitive
link interface libraries do not depend on what is linking them.
diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h
index 5b635b5..6450c62 100644
--- a/Source/cmLinkItem.h
+++ b/Source/cmLinkItem.h
@@ -58,6 +58,9 @@ struct cmLinkInterfaceLibraries
{
// Libraries listed in the interface.
std::vector<cmLinkItem> Libraries;
+
+ // Whether the list depends on a genex referencing the head target.
+ bool HadHeadSensitiveCondition = false;
};
struct cmLinkInterface : public cmLinkInterfaceLibraries
@@ -84,7 +87,6 @@ struct cmOptionalLinkInterface : public cmLinkInterface
bool LibrariesDone = false;
bool AllDone = false;
bool Exists = false;
- bool HadHeadSensitiveCondition = false;
const char* ExplicitLibraries = nullptr;
};
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ad2b3a32d1b54716d1e87ae89db8c31d614a4730
commit ad2b3a32d1b54716d1e87ae89db8c31d614a4730
Author: Brad King <brad.king at kitware.com>
AuthorDate: Sun Jul 21 07:58:29 2019 -0400
Commit: Brad King <brad.king at kitware.com>
CommitDate: Tue Jul 23 06:50:31 2019 -0400
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
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 8d02b68..49d0c47 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -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)
-{
- 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 = ";";
- }
- }
- if (!depString.empty()) {
- linkedTargetsContent =
- cmGeneratorExpressionNode::EvaluateDependentExpression(
- depString, target->GetLocalGenerator(), context, headTarget, target,
- dagChecker);
- }
- linkedTargetsContent =
- cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent);
- return linkedTargetsContent;
+ cmGeneratorTarget const* target, std::string const& prop,
+ cmGeneratorExpressionContext* context,
+ cmGeneratorExpressionDAGChecker* dagChecker)
+{
+ 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;
+ }
+ }
+ }
+ }
+ }
+ 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;
}
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 21da2fd..b22d8b6 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -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));
}
}
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=11fa818ecda0b50446aef891b06976973005e94b
commit 11fa818ecda0b50446aef891b06976973005e94b
Author: Brad King <brad.king at kitware.com>
AuthorDate: Sun Jul 21 07:57:08 2019 -0400
Commit: Brad King <brad.king at kitware.com>
CommitDate: Tue Jul 23 06:46:34 2019 -0400
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
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;
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 6e6c917..21da2fd 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -22,7 +22,9 @@
#include "cmCustomCommandGenerator.h"
#include "cmCustomCommandLines.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGeneratorExpressionNode.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
@@ -1141,6 +1143,79 @@ bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const
return this->Target->GetPropertyAsBool(prop);
}
+std::string cmGeneratorTarget::EvaluateInterfaceProperty(
+ std::string const& prop, cmGeneratorExpressionContext* context,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const
+{
+ std::string result;
+
+ // Evaluate $<TARGET_PROPERTY:this,prop> as if it were compiled. This is
+ // a subset of TargetPropertyNode::Evaluate without stringify/parse steps
+ // but sufficient for transitive interface properties.
+ cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, this, prop,
+ nullptr, dagCheckerParent);
+ switch (dagChecker.Check()) {
+ case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
+ dagChecker.ReportError(
+ context, "$<TARGET_PROPERTY:" + this->GetName() + "," + prop + ">");
+ return result;
+ case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
+ // No error. We just skip cyclic references.
+ return result;
+ case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
+ // No error. We have already seen this transitive property.
+ return result;
+ case cmGeneratorExpressionDAGChecker::DAG:
+ break;
+ }
+
+ cmGeneratorTarget const* headTarget =
+ context->HeadTarget ? context->HeadTarget : this;
+
+ if (const char* p = this->GetProperty(prop)) {
+ result = cmGeneratorExpressionNode::EvaluateDependentExpression(
+ p, context->LG, context, headTarget, this, &dagChecker);
+ }
+
+ if (cmLinkInterfaceLibraries const* iface =
+ this->GetLinkInterfaceLibraries(context->Config, headTarget, true)) {
+ for (cmLinkItem const& lib : iface->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 (lib.Target && lib.Target != this) {
+ // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in the
+ // above property and hand-evaluate it as if it were compiled.
+ // Create a context as cmCompiledGeneratorExpression::Evaluate does.
+ cmGeneratorExpressionContext libContext(
+ context->LG, context->Config, context->Quiet, headTarget, this,
+ context->EvaluateForBuildsystem, context->Backtrace,
+ context->Language);
+ std::string libResult = cmGeneratorExpression::StripEmptyListElements(
+ 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;
+ }
+ }
+ context->HadContextSensitiveCondition =
+ context->HadContextSensitiveCondition ||
+ libContext.HadContextSensitiveCondition;
+ context->HadHeadSensitiveCondition =
+ context->HadHeadSensitiveCondition ||
+ libContext.HadHeadSensitiveCondition;
+ }
+ }
+ }
+
+ return result;
+}
+
namespace {
void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
std::string const& config, std::string const& prop,
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index e86535d..b875c40 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -25,6 +25,9 @@ class cmMakefile;
class cmSourceFile;
class cmTarget;
+struct cmGeneratorExpressionContext;
+struct cmGeneratorExpressionDAGChecker;
+
class cmGeneratorTarget
{
public:
@@ -674,6 +677,10 @@ public:
class TargetPropertyEntry;
+ std::string EvaluateInterfaceProperty(
+ std::string const& prop, cmGeneratorExpressionContext* context,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const;
+
bool HaveInstallTreeRPATH(const std::string& config) const;
bool GetBuildRPATH(const std::string& config, std::string& rpath) const;
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0239bf8ac88bb8ae9d8945be506cee2c9adb08f5
commit 0239bf8ac88bb8ae9d8945be506cee2c9adb08f5
Author: Brad King <brad.king at kitware.com>
AuthorDate: Sat Jul 20 19:29:13 2019 -0400
Commit: Brad King <brad.king at kitware.com>
CommitDate: Sun Jul 21 08:17:04 2019 -0400
Genex: In TARGET_PROPERTY check for usage reqs in link libs earlier
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index b027cd4..b268ea2 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -1219,6 +1219,30 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
}
#undef POPULATE_INTERFACE_PROPERTY_NAME
+ bool evaluatingLinkLibraries = false;
+
+ if (dagCheckerParent) {
+ if (dagCheckerParent->EvaluatingGenexExpression() ||
+ dagCheckerParent->EvaluatingPICExpression()) {
+ // No check required.
+ } else if (dagCheckerParent->EvaluatingLinkLibraries()) {
+ evaluatingLinkLibraries = true;
+ if (!interfacePropertyName.empty()) {
+ reportError(
+ context, content->GetOriginalExpression(),
+ "$<TARGET_PROPERTY:...> expression in link libraries "
+ "evaluation depends on target property which is transitive "
+ "over the link libraries, creating a recursion.");
+ return std::string();
+ }
+ } else {
+#define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) dagCheckerParent->METHOD() ||
+ assert(CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
+ ASSERT_TRANSITIVE_PROPERTY_METHOD) false); // NOLINT(clang-tidy)
+#undef ASSERT_TRANSITIVE_PROPERTY_METHOD
+ }
+ }
+
cmGeneratorExpressionDAGChecker dagChecker(
context->Backtrace, target, propertyName, content, dagCheckerParent);
@@ -1243,31 +1267,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
if (const char* p = target->GetProperty(propertyName)) {
result = p;
haveProp = true;
- }
-
- if (dagCheckerParent) {
- if (dagCheckerParent->EvaluatingGenexExpression() ||
- dagCheckerParent->EvaluatingPICExpression()) {
- // No check required.
- } else if (dagCheckerParent->EvaluatingLinkLibraries()) {
- if (!interfacePropertyName.empty()) {
- reportError(
- context, content->GetOriginalExpression(),
- "$<TARGET_PROPERTY:...> expression in link libraries "
- "evaluation depends on target property which is transitive "
- "over the link libraries, creating a recursion.");
- return std::string();
- }
-
- if (!haveProp) {
- return std::string();
- }
- } else {
-#define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) dagCheckerParent->METHOD() ||
- assert(CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
- ASSERT_TRANSITIVE_PROPERTY_METHOD) false); // NOLINT(clang-tidy)
-#undef ASSERT_TRANSITIVE_PROPERTY_METHOD
- }
+ } else if (evaluatingLinkLibraries) {
+ return std::string();
}
if (!haveProp && !target->IsImported() &&
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7caebeb0e4babc41e5c84b4ce0ea70adcfdea4a1
commit 7caebeb0e4babc41e5c84b4ce0ea70adcfdea4a1
Author: Brad King <brad.king at kitware.com>
AuthorDate: Sat Jul 20 17:30:31 2019 -0400
Commit: Brad King <brad.king at kitware.com>
CommitDate: Sun Jul 21 08:14:27 2019 -0400
Genex: Re-order TARGET_PROPERTY logic to de-duplicate checks
Check for usage requirement properties early enough to avoid duplicate
checks in other conditions.
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 1973e99..b027cd4 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -1038,14 +1038,6 @@ static const struct CompileLanguageAndIdNode : public cmGeneratorExpressionNode
}
} languageAndIdNode;
-#define TRANSITIVE_PROPERTY_NAME(PROPERTY) , "INTERFACE_" #PROPERTY
-
-static const char* targetPropertyTransitiveWhitelist[] = {
- nullptr CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME)
-};
-
-#undef TRANSITIVE_PROPERTY_NAME
-
template <typename T>
std::string getLinkedTargetsContent(
std::vector<T> const& libraries, cmGeneratorTarget const* target,
@@ -1205,6 +1197,28 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
return target->GetLinkerLanguage(context->Config);
}
+ std::string interfacePropertyName;
+ bool isInterfaceProperty = false;
+
+#define POPULATE_INTERFACE_PROPERTY_NAME(prop) \
+ if (propertyName == #prop) { \
+ interfacePropertyName = "INTERFACE_" #prop; \
+ } else if (propertyName == "INTERFACE_" #prop) { \
+ interfacePropertyName = "INTERFACE_" #prop; \
+ isInterfaceProperty = true; \
+ } else
+
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(POPULATE_INTERFACE_PROPERTY_NAME)
+ // Note that the above macro terminates with an else
+ /* else */ if (cmHasLiteralPrefix(propertyName, "COMPILE_DEFINITIONS_")) {
+ cmPolicies::PolicyStatus polSt =
+ context->LG->GetPolicyStatus(cmPolicies::CMP0043);
+ if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
+ interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
+ }
+ }
+#undef POPULATE_INTERFACE_PROPERTY_NAME
+
cmGeneratorExpressionDAGChecker dagChecker(
context->Backtrace, target, propertyName, content, dagCheckerParent);
@@ -1216,12 +1230,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
// No error. We just skip cyclic references.
return std::string();
case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
- for (size_t i = 1; i < cm::size(targetPropertyTransitiveWhitelist);
- ++i) {
- if (targetPropertyTransitiveWhitelist[i] == propertyName) {
- // No error. We're not going to find anything new here.
- return std::string();
- }
+ if (isInterfaceProperty) {
+ // No error. We're not going to find anything new here.
+ return std::string();
}
case cmGeneratorExpressionDAGChecker::DAG:
break;
@@ -1239,10 +1250,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
dagCheckerParent->EvaluatingPICExpression()) {
// No check required.
} else if (dagCheckerParent->EvaluatingLinkLibraries()) {
-#define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \
- (#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) ||
- if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(
- TRANSITIVE_PROPERTY_COMPARE) false) { // NOLINT(*)
+ if (!interfacePropertyName.empty()) {
reportError(
context, content->GetOriginalExpression(),
"$<TARGET_PROPERTY:...> expression in link libraries "
@@ -1250,42 +1258,18 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
"over the link libraries, creating a recursion.");
return std::string();
}
-#undef TRANSITIVE_PROPERTY_COMPARE
if (!haveProp) {
return std::string();
}
} else {
#define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) dagCheckerParent->METHOD() ||
-
assert(CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
ASSERT_TRANSITIVE_PROPERTY_METHOD) false); // NOLINT(clang-tidy)
#undef ASSERT_TRANSITIVE_PROPERTY_METHOD
}
}
- std::string interfacePropertyName;
- bool isInterfaceProperty = false;
-
-#define POPULATE_INTERFACE_PROPERTY_NAME(prop) \
- if (propertyName == #prop) { \
- interfacePropertyName = "INTERFACE_" #prop; \
- } else if (propertyName == "INTERFACE_" #prop) { \
- interfacePropertyName = "INTERFACE_" #prop; \
- isInterfaceProperty = true; \
- } else
-
- CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(POPULATE_INTERFACE_PROPERTY_NAME)
- // Note that the above macro terminates with an else
- /* else */ if (cmHasLiteralPrefix(propertyName, "COMPILE_DEFINITIONS_")) {
- cmPolicies::PolicyStatus polSt =
- context->LG->GetPolicyStatus(cmPolicies::CMP0043);
- if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
- interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
- }
- }
-#undef POPULATE_INTERFACE_PROPERTY_NAME
-
if (!haveProp && !target->IsImported() &&
target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b2785a0fbdcfa703f3ad3aaa2949ec7db55a27d9
commit b2785a0fbdcfa703f3ad3aaa2949ec7db55a27d9
Author: Brad King <brad.king at kitware.com>
AuthorDate: Sat Jul 20 16:09:03 2019 -0400
Commit: Brad King <brad.king at kitware.com>
CommitDate: Sun Jul 21 07:47:27 2019 -0400
Genex: Move TARGET_PROPERTY linked targets evaluation to end
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index d828dac..1973e99 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -1227,10 +1227,10 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
break;
}
- std::string prop;
+ std::string result;
bool haveProp = false;
if (const char* p = target->GetProperty(propertyName)) {
- prop = p;
+ result = p;
haveProp = true;
}
@@ -1264,8 +1264,6 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
}
}
- std::string linkedTargetsContent;
-
std::string interfacePropertyName;
bool isInterfaceProperty = false;
@@ -1287,32 +1285,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
}
}
#undef POPULATE_INTERFACE_PROPERTY_NAME
- cmGeneratorTarget const* headTarget =
- context->HeadTarget && isInterfaceProperty ? context->HeadTarget
- : target;
-
- if (isInterfaceProperty) {
- if (cmLinkInterfaceLibraries const* iface =
- target->GetLinkInterfaceLibraries(context->Config, headTarget,
- true)) {
- linkedTargetsContent =
- getLinkedTargetsContent(iface->Libraries, target, headTarget,
- context, &dagChecker, interfacePropertyName);
- }
- } else if (!interfacePropertyName.empty()) {
- if (cmLinkImplementationLibraries const* impl =
- target->GetLinkImplementationLibraries(context->Config)) {
- linkedTargetsContent =
- getLinkedTargetsContent(impl->Libraries, target, target, context,
- &dagChecker, interfacePropertyName);
- }
- }
- if (!haveProp) {
- if (target->IsImported() ||
- target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- return linkedTargetsContent;
- }
+ if (!haveProp && !target->IsImported() &&
+ target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
context->Config)) {
context->HadContextSensitiveCondition = true;
@@ -1345,8 +1320,6 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
context->Config);
return propContent ? propContent : "";
}
-
- return linkedTargetsContent;
}
if (!target->IsImported() && dagCheckerParent &&
@@ -1368,15 +1341,35 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
return propContent ? propContent : "";
}
}
+
if (!interfacePropertyName.empty()) {
- std::string result = this->EvaluateDependentExpression(
- prop, context->LG, context, headTarget, target, &dagChecker);
+ cmGeneratorTarget const* headTarget =
+ context->HeadTarget && isInterfaceProperty ? context->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 (!linkedTargetsContent.empty()) {
result += (result.empty() ? "" : ";") + linkedTargetsContent;
}
- return result;
}
- return prop;
+ return result;
}
} targetPropertyNode;
-----------------------------------------------------------------------
Summary of changes:
Help/release/3.15.rst | 17 +++
Source/cmGeneratorExpressionNode.cxx | 208 +++++++++++++++--------------------
Source/cmGeneratorTarget.cxx | 144 +++++++++++++++++++++---
Source/cmGeneratorTarget.h | 12 ++
Source/cmLinkItem.h | 4 +-
5 files changed, 248 insertions(+), 137 deletions(-)
hooks/post-receive
--
CMake
More information about the Cmake-commits
mailing list