summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2024-05-17 16:22:14 (GMT)
committerBrad King <brad.king@kitware.com>2024-05-20 23:29:15 (GMT)
commit09c74c6d0c891bfb7372548b5231406d9a6ef7f9 (patch)
treed8194fafaeb8bc4ab99467e7f31be696170959ab
parentfeaca409311dd05b5b9c9702b21a6b6d151deb0d (diff)
downloadCMake-09c74c6d0c891bfb7372548b5231406d9a6ef7f9.zip
CMake-09c74c6d0c891bfb7372548b5231406d9a6ef7f9.tar.gz
CMake-09c74c6d0c891bfb7372548b5231406d9a6ef7f9.tar.bz2
cmGeneratorTarget: Factor transitive property methods into own source
-rw-r--r--Source/CMakeLists.txt1
-rw-r--r--Source/cmGeneratorTarget.cxx182
-rw-r--r--Source/cmGeneratorTarget_TransitiveProperty.cxx207
-rwxr-xr-xbootstrap1
4 files changed, 210 insertions, 181 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 8582b39..2bd3bdd 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -292,6 +292,7 @@ add_library(
cmGeneratorTarget_Options.cxx
cmGeneratorTarget_Sources.cxx
cmGeneratorTarget_TargetPropertyEntry.cxx
+ cmGeneratorTarget_TransitiveProperty.cxx
cmLinkItemGraphVisitor.cxx
cmLinkItemGraphVisitor.h
cmGetPipes.cxx
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 13f6feb..ce53316 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -29,9 +29,7 @@
#include "cmFileTimes.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
-#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionDAGChecker.h"
-#include "cmGeneratorExpressionNode.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
#include "cmLocalGenerator.h"
@@ -56,30 +54,7 @@
namespace {
using UseTo = cmGeneratorTarget::UseTo;
-using TransitiveProperty = cmGeneratorTarget::TransitiveProperty;
-}
-
-const std::map<cm::string_view, TransitiveProperty>
- cmGeneratorTarget::BuiltinTransitiveProperties = {
- { "AUTOMOC_MACRO_NAMES"_s,
- { "INTERFACE_AUTOMOC_MACRO_NAMES"_s, UseTo::Compile } },
- { "AUTOUIC_OPTIONS"_s, { "INTERFACE_AUTOUIC_OPTIONS"_s, UseTo::Compile } },
- { "COMPILE_DEFINITIONS"_s,
- { "INTERFACE_COMPILE_DEFINITIONS"_s, UseTo::Compile } },
- { "COMPILE_FEATURES"_s,
- { "INTERFACE_COMPILE_FEATURES"_s, UseTo::Compile } },
- { "COMPILE_OPTIONS"_s, { "INTERFACE_COMPILE_OPTIONS"_s, UseTo::Compile } },
- { "INCLUDE_DIRECTORIES"_s,
- { "INTERFACE_INCLUDE_DIRECTORIES"_s, UseTo::Compile } },
- { "LINK_DEPENDS"_s, { "INTERFACE_LINK_DEPENDS"_s, UseTo::Link } },
- { "LINK_DIRECTORIES"_s, { "INTERFACE_LINK_DIRECTORIES"_s, UseTo::Link } },
- { "LINK_OPTIONS"_s, { "INTERFACE_LINK_OPTIONS"_s, UseTo::Link } },
- { "PRECOMPILE_HEADERS"_s,
- { "INTERFACE_PRECOMPILE_HEADERS"_s, UseTo::Compile } },
- { "SOURCES"_s, { "INTERFACE_SOURCES"_s, UseTo::Compile } },
- { "SYSTEM_INCLUDE_DIRECTORIES"_s,
- { "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES"_s, UseTo::Compile } },
- };
+}
template <>
cmValue cmTargetPropertyComputer::GetSources<cmGeneratorTarget>(
@@ -1248,161 +1223,6 @@ bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const
return this->Target->GetPropertyAsBool(prop);
}
-bool cmGeneratorTarget::MaybeHaveInterfaceProperty(
- std::string const& prop, cmGeneratorExpressionContext* context,
- UseTo usage) 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.
- maybeInterfaceProp = cmNonempty(this->GetProperty(prop));
-
- // Otherwise, recurse to interface dependencies.
- if (!maybeInterfaceProp) {
- cmGeneratorTarget const* headTarget =
- context->HeadTarget ? context->HeadTarget : this;
- if (cmLinkInterfaceLibraries const* iface =
- this->GetLinkInterfaceLibraries(context->Config, headTarget,
- usage)) {
- 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, usage)) {
- maybeInterfaceProp = true;
- break;
- }
- }
- }
- }
- }
- }
- return i->second;
-}
-
-std::string cmGeneratorTarget::EvaluateInterfaceProperty(
- std::string const& prop, cmGeneratorExpressionContext* context,
- cmGeneratorExpressionDAGChecker* dagCheckerParent, UseTo usage) const
-{
- std::string result;
-
- // If the property does not appear transitively at all, we are done.
- if (!this->MaybeHaveInterfaceProperty(prop, context, usage)) {
- 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.
- cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, this, prop,
- nullptr, dagCheckerParent,
- this->LocalGenerator);
- 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.
- 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 (cmValue p = this->GetProperty(prop)) {
- result = cmGeneratorExpressionNode::EvaluateDependentExpression(
- *p, context->LG, context, headTarget, &dagChecker, this);
- }
-
- if (cmLinkInterfaceLibraries const* iface =
- this->GetLinkInterfaceLibraries(context->Config, headTarget, usage)) {
- context->HadContextSensitiveCondition =
- context->HadContextSensitiveCondition ||
- iface->HadContextSensitiveCondition;
- 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,
- usage));
- 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;
-}
-
-cm::optional<cmGeneratorTarget::TransitiveProperty>
-cmGeneratorTarget::IsTransitiveProperty(cm::string_view prop,
- cmLocalGenerator const* lg) const
-{
- cm::optional<TransitiveProperty> result;
- static const cm::string_view kINTERFACE_ = "INTERFACE_"_s;
- if (cmHasPrefix(prop, kINTERFACE_)) {
- prop = prop.substr(kINTERFACE_.length());
- }
- auto i = BuiltinTransitiveProperties.find(prop);
- if (i != BuiltinTransitiveProperties.end()) {
- result = i->second;
- if (result->Usage != cmGeneratorTarget::UseTo::Compile) {
- cmPolicies::PolicyStatus cmp0166 =
- lg->GetPolicyStatus(cmPolicies::CMP0166);
- if ((cmp0166 == cmPolicies::WARN || cmp0166 == cmPolicies::OLD) &&
- (prop == "LINK_DIRECTORIES"_s || prop == "LINK_DEPENDS"_s ||
- prop == "LINK_OPTIONS"_s)) {
- result->Usage = cmGeneratorTarget::UseTo::Compile;
- }
- }
- } else if (cmHasLiteralPrefix(prop, "COMPILE_DEFINITIONS_")) {
- cmPolicies::PolicyStatus cmp0043 =
- lg->GetPolicyStatus(cmPolicies::CMP0043);
- if (cmp0043 == cmPolicies::WARN || cmp0043 == cmPolicies::OLD) {
- result = TransitiveProperty{ "INTERFACE_COMPILE_DEFINITIONS"_s,
- UseTo::Compile };
- }
- }
- return result;
-}
-
std::string cmGeneratorTarget::GetCompilePDBName(
const std::string& config) const
{
diff --git a/Source/cmGeneratorTarget_TransitiveProperty.cxx b/Source/cmGeneratorTarget_TransitiveProperty.cxx
new file mode 100644
index 0000000..f5d9a1a
--- /dev/null
+++ b/Source/cmGeneratorTarget_TransitiveProperty.cxx
@@ -0,0 +1,207 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+/* clang-format off */
+#include "cmGeneratorTarget.h"
+/* clang-format on */
+
+#include <map>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include <cm/optional>
+#include <cm/string_view>
+#include <cmext/string_view>
+
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionContext.h"
+#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGeneratorExpressionNode.h"
+#include "cmLinkItem.h"
+#include "cmLocalGenerator.h"
+#include "cmPolicies.h"
+#include "cmStringAlgorithms.h"
+#include "cmValue.h"
+
+namespace {
+using UseTo = cmGeneratorTarget::UseTo;
+using TransitiveProperty = cmGeneratorTarget::TransitiveProperty;
+}
+
+const std::map<cm::string_view, TransitiveProperty>
+ cmGeneratorTarget::BuiltinTransitiveProperties = {
+ { "AUTOMOC_MACRO_NAMES"_s,
+ { "INTERFACE_AUTOMOC_MACRO_NAMES"_s, UseTo::Compile } },
+ { "AUTOUIC_OPTIONS"_s, { "INTERFACE_AUTOUIC_OPTIONS"_s, UseTo::Compile } },
+ { "COMPILE_DEFINITIONS"_s,
+ { "INTERFACE_COMPILE_DEFINITIONS"_s, UseTo::Compile } },
+ { "COMPILE_FEATURES"_s,
+ { "INTERFACE_COMPILE_FEATURES"_s, UseTo::Compile } },
+ { "COMPILE_OPTIONS"_s, { "INTERFACE_COMPILE_OPTIONS"_s, UseTo::Compile } },
+ { "INCLUDE_DIRECTORIES"_s,
+ { "INTERFACE_INCLUDE_DIRECTORIES"_s, UseTo::Compile } },
+ { "LINK_DEPENDS"_s, { "INTERFACE_LINK_DEPENDS"_s, UseTo::Link } },
+ { "LINK_DIRECTORIES"_s, { "INTERFACE_LINK_DIRECTORIES"_s, UseTo::Link } },
+ { "LINK_OPTIONS"_s, { "INTERFACE_LINK_OPTIONS"_s, UseTo::Link } },
+ { "PRECOMPILE_HEADERS"_s,
+ { "INTERFACE_PRECOMPILE_HEADERS"_s, UseTo::Compile } },
+ { "SOURCES"_s, { "INTERFACE_SOURCES"_s, UseTo::Compile } },
+ { "SYSTEM_INCLUDE_DIRECTORIES"_s,
+ { "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES"_s, UseTo::Compile } },
+ };
+
+bool cmGeneratorTarget::MaybeHaveInterfaceProperty(
+ std::string const& prop, cmGeneratorExpressionContext* context,
+ UseTo usage) 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.
+ maybeInterfaceProp = cmNonempty(this->GetProperty(prop));
+
+ // Otherwise, recurse to interface dependencies.
+ if (!maybeInterfaceProp) {
+ cmGeneratorTarget const* headTarget =
+ context->HeadTarget ? context->HeadTarget : this;
+ if (cmLinkInterfaceLibraries const* iface =
+ this->GetLinkInterfaceLibraries(context->Config, headTarget,
+ usage)) {
+ 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, usage)) {
+ maybeInterfaceProp = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return i->second;
+}
+
+std::string cmGeneratorTarget::EvaluateInterfaceProperty(
+ std::string const& prop, cmGeneratorExpressionContext* context,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent, UseTo usage) const
+{
+ std::string result;
+
+ // If the property does not appear transitively at all, we are done.
+ if (!this->MaybeHaveInterfaceProperty(prop, context, usage)) {
+ 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.
+ cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, this, prop,
+ nullptr, dagCheckerParent,
+ this->LocalGenerator);
+ 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.
+ 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 (cmValue p = this->GetProperty(prop)) {
+ result = cmGeneratorExpressionNode::EvaluateDependentExpression(
+ *p, context->LG, context, headTarget, &dagChecker, this);
+ }
+
+ if (cmLinkInterfaceLibraries const* iface =
+ this->GetLinkInterfaceLibraries(context->Config, headTarget, usage)) {
+ context->HadContextSensitiveCondition =
+ context->HadContextSensitiveCondition ||
+ iface->HadContextSensitiveCondition;
+ 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,
+ usage));
+ 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;
+}
+
+cm::optional<cmGeneratorTarget::TransitiveProperty>
+cmGeneratorTarget::IsTransitiveProperty(cm::string_view prop,
+ cmLocalGenerator const* lg) const
+{
+ cm::optional<TransitiveProperty> result;
+ static const cm::string_view kINTERFACE_ = "INTERFACE_"_s;
+ if (cmHasPrefix(prop, kINTERFACE_)) {
+ prop = prop.substr(kINTERFACE_.length());
+ }
+ auto i = BuiltinTransitiveProperties.find(prop);
+ if (i != BuiltinTransitiveProperties.end()) {
+ result = i->second;
+ if (result->Usage != cmGeneratorTarget::UseTo::Compile) {
+ cmPolicies::PolicyStatus cmp0166 =
+ lg->GetPolicyStatus(cmPolicies::CMP0166);
+ if ((cmp0166 == cmPolicies::WARN || cmp0166 == cmPolicies::OLD) &&
+ (prop == "LINK_DIRECTORIES"_s || prop == "LINK_DEPENDS"_s ||
+ prop == "LINK_OPTIONS"_s)) {
+ result->Usage = cmGeneratorTarget::UseTo::Compile;
+ }
+ }
+ } else if (cmHasLiteralPrefix(prop, "COMPILE_DEFINITIONS_")) {
+ cmPolicies::PolicyStatus cmp0043 =
+ lg->GetPolicyStatus(cmPolicies::CMP0043);
+ if (cmp0043 == cmPolicies::WARN || cmp0043 == cmPolicies::OLD) {
+ result = TransitiveProperty{ "INTERFACE_COMPILE_DEFINITIONS"_s,
+ UseTo::Compile };
+ }
+ }
+ return result;
+}
diff --git a/bootstrap b/bootstrap
index fbd2058..9958a6d 100755
--- a/bootstrap
+++ b/bootstrap
@@ -388,6 +388,7 @@ CMAKE_CXX_SOURCES="\
cmGeneratorTarget_Options \
cmGeneratorTarget_Sources \
cmGeneratorTarget_TargetPropertyEntry \
+ cmGeneratorTarget_TransitiveProperty \
cmGetCMakePropertyCommand \
cmGetDirectoryPropertyCommand \
cmGetFilenameComponentCommand \