Przeglądaj źródła

cmGeneratorExpressionDAGChecker: Simplify transitive property table

Refactor the table of builtin transitive properties to avoid
preprocessor-generated cascading-if blocks with duplicate code.
Brad King 1 rok temu
rodzic
commit
79a3ae9a0d

+ 6 - 6
Source/cmExportTryCompileFileGenerator.cxx

@@ -2,9 +2,11 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExportTryCompileFileGenerator.h"
 
+#include <map>
 #include <utility>
 
 #include <cm/memory>
+#include <cm/string_view>
 
 #include "cmFileSet.h"
 #include "cmGeneratorExpression.h"
@@ -44,12 +46,10 @@ bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
       ImportPropertyMap properties;
 
       for (std::string const& lang : this->Languages) {
-#define FIND_TARGETS(PROPERTY)                                                \
-  this->FindTargets("INTERFACE_" #PROPERTY, te, lang, emittedDeps);
-
-        CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(FIND_TARGETS)
-
-#undef FIND_TARGETS
+        for (auto i : cmGeneratorTarget::BuiltinTransitiveProperties) {
+          this->FindTargets(std::string(i.second.InterfaceName), te, lang,
+                            emittedDeps);
+        }
       }
 
       this->PopulateProperties(te, properties, emittedDeps);

+ 10 - 42
Source/cmGeneratorExpressionDAGChecker.cxx

@@ -2,10 +2,10 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmGeneratorExpressionDAGChecker.h"
 
-#include <cstring>
 #include <sstream>
 #include <utility>
 
+#include <cm/optional>
 #include <cm/string_view>
 #include <cmext/string_view>
 
@@ -38,14 +38,12 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
   , Content(content)
   , Backtrace(std::move(backtrace))
 {
-  static_cast<void>(contextLG);
   if (parent) {
     this->TopIsTransitiveProperty = parent->TopIsTransitiveProperty;
   } else {
-#define TEST_TRANSITIVE_PROPERTY_METHOD(METHOD) this->METHOD() ||
-    this->TopIsTransitiveProperty = (CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
-      TEST_TRANSITIVE_PROPERTY_METHOD) false); // NOLINT(*)
-#undef TEST_TRANSITIVE_PROPERTY_METHOD
+    this->TopIsTransitiveProperty =
+      this->Target->IsTransitiveProperty(this->Property, contextLG)
+        .has_value();
   }
 
   this->CheckResult = this->CheckGraph();
@@ -171,6 +169,12 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingCompileExpression() const
     property == "COMPILE_DEFINITIONS"_s || property == "COMPILE_OPTIONS"_s;
 }
 
+bool cmGeneratorExpressionDAGChecker::EvaluatingSources() const
+{
+  return this->Property == "SOURCES"_s ||
+    this->Property == "INTERFACE_SOURCES"_s;
+}
+
 bool cmGeneratorExpressionDAGChecker::EvaluatingLinkExpression() const
 {
   cm::string_view property(this->Top->Property);
@@ -224,39 +228,3 @@ cmGeneratorTarget const* cmGeneratorExpressionDAGChecker::TopTarget() const
 {
   return this->Top->Target;
 }
-
-enum class TransitiveProperty
-{
-#define DEFINE_ENUM_ENTRY(NAME) NAME,
-  CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(DEFINE_ENUM_ENTRY)
-#undef DEFINE_ENUM_ENTRY
-    Terminal
-};
-
-template <TransitiveProperty>
-bool additionalTest(const char* const /*unused*/)
-{
-  return false;
-}
-
-template <>
-bool additionalTest<TransitiveProperty::COMPILE_DEFINITIONS>(
-  const char* const prop)
-{
-  return cmHasLiteralPrefix(prop, "COMPILE_DEFINITIONS_");
-}
-
-#define DEFINE_TRANSITIVE_PROPERTY_METHOD(METHOD, PROPERTY)                   \
-  bool cmGeneratorExpressionDAGChecker::METHOD() const                        \
-  {                                                                           \
-    const char* const prop = this->Property.c_str();                          \
-    if (strcmp(prop, #PROPERTY) == 0 ||                                       \
-        strcmp(prop, "INTERFACE_" #PROPERTY) == 0) {                          \
-      return true;                                                            \
-    }                                                                         \
-    return additionalTest<TransitiveProperty::PROPERTY>(prop);                \
-  }
-
-CM_FOR_EACH_TRANSITIVE_PROPERTY(DEFINE_TRANSITIVE_PROPERTY_METHOD)
-
-#undef DEFINE_TRANSITIVE_PROPERTY_METHOD

+ 1 - 32
Source/cmGeneratorExpressionDAGChecker.h

@@ -15,33 +15,6 @@ struct cmGeneratorExpressionContext;
 class cmGeneratorTarget;
 class cmLocalGenerator;
 
-#define CM_SELECT_BOTH(F, A1, A2) F(A1, A2)
-#define CM_SELECT_FIRST(F, A1, A2) F(A1)
-#define CM_SELECT_SECOND(F, A1, A2) F(A2)
-
-#define CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, SELECT)                       \
-  SELECT(F, EvaluatingIncludeDirectories, INCLUDE_DIRECTORIES)                \
-  SELECT(F, EvaluatingSystemIncludeDirectories, SYSTEM_INCLUDE_DIRECTORIES)   \
-  SELECT(F, EvaluatingCompileDefinitions, COMPILE_DEFINITIONS)                \
-  SELECT(F, EvaluatingCompileOptions, COMPILE_OPTIONS)                        \
-  SELECT(F, EvaluatingAutoMocMacroNames, AUTOMOC_MACRO_NAMES)                 \
-  SELECT(F, EvaluatingAutoUicOptions, AUTOUIC_OPTIONS)                        \
-  SELECT(F, EvaluatingSources, SOURCES)                                       \
-  SELECT(F, EvaluatingCompileFeatures, COMPILE_FEATURES)                      \
-  SELECT(F, EvaluatingLinkOptions, LINK_OPTIONS)                              \
-  SELECT(F, EvaluatingLinkDirectories, LINK_DIRECTORIES)                      \
-  SELECT(F, EvaluatingLinkDepends, LINK_DEPENDS)                              \
-  SELECT(F, EvaluatingPrecompileHeaders, PRECOMPILE_HEADERS)
-
-#define CM_FOR_EACH_TRANSITIVE_PROPERTY(F)                                    \
-  CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH)
-
-#define CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(F)                             \
-  CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_FIRST)
-
-#define CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(F)                               \
-  CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_SECOND)
-
 struct cmGeneratorExpressionDAGChecker
 {
   cmGeneratorExpressionDAGChecker(cmListFileBacktrace backtrace,
@@ -86,11 +59,7 @@ struct cmGeneratorExpressionDAGChecker
   bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr,
                                ForGenex genex = ForGenex::ANY) const;
 
-#define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const;
-
-  CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(DECLARE_TRANSITIVE_PROPERTY_METHOD)
-
-#undef DECLARE_TRANSITIVE_PROPERTY_METHOD
+  bool EvaluatingSources() const;
 
   bool GetTransitivePropertiesOnly() const;
   void SetTransitivePropertiesOnly() { this->TransitivePropertiesOnly = true; }

+ 4 - 17
Source/cmGeneratorExpressionNode.cxx

@@ -2877,24 +2877,11 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
     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";
-      }
+    if (cm::optional<cmGeneratorTarget::TransitiveProperty> transitiveProp =
+          target->IsTransitiveProperty(propertyName, context->LG)) {
+      interfacePropertyName = std::string(transitiveProp->InterfaceName);
+      isInterfaceProperty = transitiveProp->InterfaceName == propertyName;
     }
-#undef POPULATE_INTERFACE_PROPERTY_NAME
 
     bool evaluatingLinkLibraries = false;
 

+ 40 - 0
Source/cmGeneratorTarget.cxx

@@ -65,6 +65,7 @@
 
 namespace {
 using LinkInterfaceFor = cmGeneratorTarget::LinkInterfaceFor;
+using TransitiveProperty = cmGeneratorTarget::TransitiveProperty;
 
 const std::string kINTERFACE_LINK_LIBRARIES = "INTERFACE_LINK_LIBRARIES";
 const std::string kINTERFACE_LINK_LIBRARIES_DIRECT =
@@ -73,6 +74,23 @@ const std::string kINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE =
   "INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE";
 }
 
+const std::map<cm::string_view, TransitiveProperty>
+  cmGeneratorTarget::BuiltinTransitiveProperties = {
+    { "AUTOMOC_MACRO_NAMES"_s, { "INTERFACE_AUTOMOC_MACRO_NAMES"_s } },
+    { "AUTOUIC_OPTIONS"_s, { "INTERFACE_AUTOUIC_OPTIONS"_s } },
+    { "COMPILE_DEFINITIONS"_s, { "INTERFACE_COMPILE_DEFINITIONS"_s } },
+    { "COMPILE_FEATURES"_s, { "INTERFACE_COMPILE_FEATURES"_s } },
+    { "COMPILE_OPTIONS"_s, { "INTERFACE_COMPILE_OPTIONS"_s } },
+    { "INCLUDE_DIRECTORIES"_s, { "INTERFACE_INCLUDE_DIRECTORIES"_s } },
+    { "LINK_DEPENDS"_s, { "INTERFACE_LINK_DEPENDS"_s } },
+    { "LINK_DIRECTORIES"_s, { "INTERFACE_LINK_DIRECTORIES"_s } },
+    { "LINK_OPTIONS"_s, { "INTERFACE_LINK_OPTIONS"_s } },
+    { "PRECOMPILE_HEADERS"_s, { "INTERFACE_PRECOMPILE_HEADERS"_s } },
+    { "SOURCES"_s, { "INTERFACE_SOURCES"_s } },
+    { "SYSTEM_INCLUDE_DIRECTORIES"_s,
+      { "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES"_s } },
+  };
+
 template <>
 cmValue cmTargetPropertyComputer::GetSources<cmGeneratorTarget>(
   cmGeneratorTarget const* tgt, cmMakefile const& /* mf */)
@@ -1517,6 +1535,28 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty(
   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;
+  } 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 };
+    }
+  }
+  return result;
+}
+
 namespace {
 
 enum class IncludeDirectoryFallBack

+ 12 - 0
Source/cmGeneratorTarget.h

@@ -15,6 +15,7 @@
 #include <vector>
 
 #include <cm/optional>
+#include <cm/string_view>
 
 #include "cmAlgorithms.h"
 #include "cmComputeLinkInformation.h"
@@ -885,6 +886,17 @@ public:
     cmGeneratorExpressionDAGChecker* dagCheckerParent,
     LinkInterfaceFor interfaceFor) const;
 
+  struct TransitiveProperty
+  {
+    cm::string_view InterfaceName;
+  };
+
+  static const std::map<cm::string_view, TransitiveProperty>
+    BuiltinTransitiveProperties;
+
+  cm::optional<TransitiveProperty> IsTransitiveProperty(
+    cm::string_view prop, cmLocalGenerator const* lg) const;
+
   bool HaveInstallTreeRPATH(const std::string& config) const;
 
   bool GetBuildRPATH(const std::string& config, std::string& rpath) const;