mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-11 16:32:14 -06:00
cmGeneratorExpressionDAGChecker: Simplify transitive property table
Refactor the table of builtin transitive properties to avoid preprocessor-generated cascading-if blocks with duplicate code.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user