| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 | 
							- /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 
-    file Copyright.txt or https://cmake.org/licensing for details.  */
 
- #include "cmGeneratorExpressionDAGChecker.h"
 
- #include <cstring>
 
- #include <sstream>
 
- #include <utility>
 
- #include <cm/string_view>
 
- #include <cmext/string_view>
 
- #include "cmGeneratorExpressionContext.h"
 
- #include "cmGeneratorExpressionEvaluator.h"
 
- #include "cmGeneratorTarget.h"
 
- #include "cmLocalGenerator.h"
 
- #include "cmMessageType.h"
 
- #include "cmStringAlgorithms.h"
 
- #include "cmake.h"
 
- cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
 
-   cmListFileBacktrace backtrace, cmGeneratorTarget const* target,
 
-   std::string property, const GeneratorExpressionContent* content,
 
-   cmGeneratorExpressionDAGChecker* parent)
 
-   : Parent(parent)
 
-   , Target(target)
 
-   , Property(std::move(property))
 
-   , Content(content)
 
-   , Backtrace(std::move(backtrace))
 
-   , TransitivePropertiesOnly(false)
 
- {
 
-   this->Initialize();
 
- }
 
- cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
 
-   cmGeneratorTarget const* target, std::string property,
 
-   const GeneratorExpressionContent* content,
 
-   cmGeneratorExpressionDAGChecker* parent)
 
-   : Parent(parent)
 
-   , Target(target)
 
-   , Property(std::move(property))
 
-   , Content(content)
 
-   , Backtrace()
 
-   , TransitivePropertiesOnly(false)
 
- {
 
-   this->Initialize();
 
- }
 
- void cmGeneratorExpressionDAGChecker::Initialize()
 
- {
 
-   const auto* top = this->Top();
 
-   this->CheckResult = this->CheckGraph();
 
- #define TEST_TRANSITIVE_PROPERTY_METHOD(METHOD) top->METHOD() ||
 
-   if (this->CheckResult == DAG &&
 
-       (CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
 
-         TEST_TRANSITIVE_PROPERTY_METHOD) false)) // NOLINT(*)
 
- #undef TEST_TRANSITIVE_PROPERTY_METHOD
 
-   {
 
-     auto it = top->Seen.find(this->Target);
 
-     if (it != top->Seen.end()) {
 
-       const std::set<std::string>& propSet = it->second;
 
-       if (propSet.find(this->Property) != propSet.end()) {
 
-         this->CheckResult = ALREADY_SEEN;
 
-         return;
 
-       }
 
-     }
 
-     top->Seen[this->Target].insert(this->Property);
 
-   }
 
- }
 
- cmGeneratorExpressionDAGChecker::Result
 
- cmGeneratorExpressionDAGChecker::Check() const
 
- {
 
-   return this->CheckResult;
 
- }
 
- void cmGeneratorExpressionDAGChecker::ReportError(
 
-   cmGeneratorExpressionContext* context, const std::string& expr)
 
- {
 
-   if (this->CheckResult == DAG) {
 
-     return;
 
-   }
 
-   context->HadError = true;
 
-   if (context->Quiet) {
 
-     return;
 
-   }
 
-   const cmGeneratorExpressionDAGChecker* parent = this->Parent;
 
-   if (parent && !parent->Parent) {
 
-     std::ostringstream e;
 
-     e << "Error evaluating generator expression:\n"
 
-       << "  " << expr << "\n"
 
-       << "Self reference on target \"" << context->HeadTarget->GetName()
 
-       << "\".\n";
 
-     context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
 
-                                                   e.str(), parent->Backtrace);
 
-     return;
 
-   }
 
-   {
 
-     std::ostringstream e;
 
-     /* clang-format off */
 
-   e << "Error evaluating generator expression:\n"
 
-     << "  " << expr << "\n"
 
-     << "Dependency loop found.";
 
-     /* clang-format on */
 
-     context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
 
-                                                   e.str(), context->Backtrace);
 
-   }
 
-   int loopStep = 1;
 
-   while (parent) {
 
-     std::ostringstream e;
 
-     e << "Loop step " << loopStep << "\n"
 
-       << "  "
 
-       << (parent->Content ? parent->Content->GetOriginalExpression() : expr)
 
-       << "\n";
 
-     context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
 
-                                                   e.str(), parent->Backtrace);
 
-     parent = parent->Parent;
 
-     ++loopStep;
 
-   }
 
- }
 
- cmGeneratorExpressionDAGChecker::Result
 
- cmGeneratorExpressionDAGChecker::CheckGraph() const
 
- {
 
-   const cmGeneratorExpressionDAGChecker* parent = this->Parent;
 
-   while (parent) {
 
-     if (this->Target == parent->Target && this->Property == parent->Property) {
 
-       return (parent == this->Parent) ? SELF_REFERENCE : CYCLIC_REFERENCE;
 
-     }
 
-     parent = parent->Parent;
 
-   }
 
-   return DAG;
 
- }
 
- bool cmGeneratorExpressionDAGChecker::GetTransitivePropertiesOnly() const
 
- {
 
-   return this->Top()->TransitivePropertiesOnly;
 
- }
 
- bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression() const
 
- {
 
-   return cmHasLiteralPrefix(this->Property, "TARGET_GENEX_EVAL:") ||
 
-     cmHasLiteralPrefix(this->Property, "GENEX_EVAL:");
 
- }
 
- bool cmGeneratorExpressionDAGChecker::EvaluatingPICExpression() const
 
- {
 
-   return this->Top()->Property == "INTERFACE_POSITION_INDEPENDENT_CODE";
 
- }
 
- bool cmGeneratorExpressionDAGChecker::EvaluatingCompileExpression() const
 
- {
 
-   cm::string_view property(this->Top()->Property);
 
-   return property == "INCLUDE_DIRECTORIES"_s ||
 
-     property == "COMPILE_DEFINITIONS"_s || property == "COMPILE_OPTIONS"_s;
 
- }
 
- bool cmGeneratorExpressionDAGChecker::EvaluatingLinkExpression() const
 
- {
 
-   cm::string_view property(this->Top()->Property);
 
-   return property == "LINK_DIRECTORIES"_s || property == "LINK_OPTIONS"_s ||
 
-     property == "LINK_DEPENDS"_s;
 
- }
 
- bool cmGeneratorExpressionDAGChecker::EvaluatingLinkOptionsExpression() const
 
- {
 
-   cm::string_view property(this->Top()->Property);
 
-   return property == "LINK_OPTIONS"_s;
 
- }
 
- bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
 
-   cmGeneratorTarget const* tgt) const
 
- {
 
-   const auto* top = this->Top();
 
-   cm::string_view prop(top->Property);
 
-   if (tgt) {
 
-     return top->Target == tgt && prop == "LINK_LIBRARIES"_s;
 
-   }
 
-   return prop == "LINK_LIBRARIES"_s || prop == "LINK_INTERFACE_LIBRARIES"_s ||
 
-     prop == "IMPORTED_LINK_INTERFACE_LIBRARIES"_s ||
 
-     cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES_") ||
 
-     cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_") ||
 
-     prop == "INTERFACE_LINK_LIBRARIES"_s;
 
- }
 
- cmGeneratorExpressionDAGChecker const* cmGeneratorExpressionDAGChecker::Top()
 
-   const
 
- {
 
-   const cmGeneratorExpressionDAGChecker* top = this;
 
-   const cmGeneratorExpressionDAGChecker* parent = this->Parent;
 
-   while (parent) {
 
-     top = parent;
 
-     parent = parent->Parent;
 
-   }
 
-   return top;
 
- }
 
- cmGeneratorTarget const* cmGeneratorExpressionDAGChecker::TopTarget() const
 
- {
 
-   return this->Top()->Target;
 
- }
 
- enum TransitiveProperty
 
- {
 
- #define DEFINE_ENUM_ENTRY(NAME) NAME,
 
-   CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(DEFINE_ENUM_ENTRY)
 
- #undef DEFINE_ENUM_ENTRY
 
-     TransitivePropertyTerminal
 
- };
 
- template <TransitiveProperty>
 
- bool additionalTest(const char* const /*unused*/)
 
- {
 
-   return false;
 
- }
 
- template <>
 
- bool additionalTest<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<PROPERTY>(prop);                                    \
 
-   }
 
- CM_FOR_EACH_TRANSITIVE_PROPERTY(DEFINE_TRANSITIVE_PROPERTY_METHOD)
 
- #undef DEFINE_TRANSITIVE_PROPERTY_METHOD
 
 
  |