123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- /*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Stephen Kelly <[email protected]>
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
- ============================================================================*/
- #include "cmGeneratorExpressionDAGChecker.h"
- #include "cmMakefile.h"
- //----------------------------------------------------------------------------
- cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
- const cmListFileBacktrace &backtrace,
- const std::string &target,
- const std::string &property,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *parent)
- : Parent(parent), Target(target), Property(property),
- Content(content), Backtrace(backtrace), TransitivePropertiesOnly(false)
- {
- const cmGeneratorExpressionDAGChecker *top = this;
- const cmGeneratorExpressionDAGChecker *p = this->Parent;
- while (p)
- {
- top = p;
- p = p->Parent;
- }
- this->CheckResult = this->CheckGraph();
- #define TEST_TRANSITIVE_PROPERTY_METHOD(METHOD) \
- top->METHOD () ||
- if (CheckResult == DAG && (
- CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(TEST_TRANSITIVE_PROPERTY_METHOD)
- false)
- )
- #undef TEST_TRANSITIVE_PROPERTY_METHOD
- {
- std::map<std::string, std::set<std::string> >::const_iterator it
- = top->Seen.find(target);
- if (it != top->Seen.end())
- {
- const std::set<std::string> &propSet = it->second;
- const std::set<std::string>::const_iterator i = propSet.find(property);
- if (i != propSet.end())
- {
- this->CheckResult = ALREADY_SEEN;
- return;
- }
- }
- const_cast<cmGeneratorExpressionDAGChecker *>(top)
- ->Seen[target].insert(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)
- {
- cmOStringStream e;
- e << "Error evaluating generator expression:\n"
- << " " << expr << "\n"
- << "Self reference on target \""
- << context->HeadTarget->GetName() << "\".\n";
- context->Makefile->GetCMakeInstance()
- ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
- parent->Backtrace);
- return;
- }
- {
- cmOStringStream e;
- e << "Error evaluating generator expression:\n"
- << " " << expr << "\n"
- << "Dependency loop found.";
- context->Makefile->GetCMakeInstance()
- ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
- context->Backtrace);
- }
- int loopStep = 1;
- while (parent)
- {
- cmOStringStream e;
- e << "Loop step " << loopStep << "\n"
- << " "
- << (parent->Content ? parent->Content->GetOriginalExpression() : expr)
- << "\n";
- context->Makefile->GetCMakeInstance()
- ->IssueMessage(cmake::FATAL_ERROR, e.str().c_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 cmGeneratorExpressionDAGChecker *top = this;
- const cmGeneratorExpressionDAGChecker *parent = this->Parent;
- while (parent)
- {
- top = parent;
- parent = parent->Parent;
- }
- return top->TransitivePropertiesOnly;
- }
- //----------------------------------------------------------------------------
- bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char *tgt)
- {
- const cmGeneratorExpressionDAGChecker *top = this;
- const cmGeneratorExpressionDAGChecker *parent = this->Parent;
- while (parent)
- {
- top = parent;
- parent = parent->Parent;
- }
- const char *prop = top->Property.c_str();
- if (tgt)
- {
- return top->Target == tgt && strcmp(prop, "LINK_LIBRARIES") == 0;
- }
- return (strcmp(prop, "LINK_LIBRARIES") == 0
- || strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0
- || strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0
- || cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES_")
- || cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_"))
- || strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
- }
- 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)
- {
- 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
|