cmGeneratorExpressionDAGChecker.cxx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2012 Stephen Kelly <[email protected]>
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmGeneratorExpressionDAGChecker.h"
  11. #include "cmMakefile.h"
  12. //----------------------------------------------------------------------------
  13. cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
  14. const cmListFileBacktrace &backtrace,
  15. const std::string &target,
  16. const std::string &property,
  17. const GeneratorExpressionContent *content,
  18. cmGeneratorExpressionDAGChecker *parent)
  19. : Parent(parent), Target(target), Property(property),
  20. Content(content), Backtrace(backtrace)
  21. {
  22. const cmGeneratorExpressionDAGChecker *top = this;
  23. const cmGeneratorExpressionDAGChecker *p = this->Parent;
  24. while (p)
  25. {
  26. top = p;
  27. p = p->Parent;
  28. }
  29. this->CheckResult = this->checkGraph();
  30. if (CheckResult == DAG && (top->Property == "INCLUDE_DIRECTORIES"
  31. || top->Property == "COMPILE_DEFINITIONS") )
  32. {
  33. std::map<cmStdString, std::set<cmStdString> >::const_iterator it
  34. = top->Seen.find(target);
  35. if (it != top->Seen.end())
  36. {
  37. const std::set<cmStdString> &propSet = it->second;
  38. const std::set<cmStdString>::const_iterator i = propSet.find(property);
  39. if (i != propSet.end())
  40. {
  41. this->CheckResult = ALREADY_SEEN;
  42. return;
  43. }
  44. }
  45. const_cast<cmGeneratorExpressionDAGChecker *>(top)
  46. ->Seen[target].insert(property);
  47. }
  48. }
  49. //----------------------------------------------------------------------------
  50. cmGeneratorExpressionDAGChecker::Result
  51. cmGeneratorExpressionDAGChecker::check() const
  52. {
  53. return this->CheckResult;
  54. }
  55. //----------------------------------------------------------------------------
  56. void cmGeneratorExpressionDAGChecker::reportError(
  57. cmGeneratorExpressionContext *context,
  58. const std::string &expr)
  59. {
  60. if (this->CheckResult == DAG)
  61. {
  62. return;
  63. }
  64. context->HadError = true;
  65. if (context->Quiet)
  66. {
  67. return;
  68. }
  69. const cmGeneratorExpressionDAGChecker *parent = this->Parent;
  70. if (parent && !parent->Parent)
  71. {
  72. cmOStringStream e;
  73. e << "Error evaluating generator expression:\n"
  74. << " " << expr << "\n"
  75. << "Self reference on target \""
  76. << context->HeadTarget->GetName() << "\".\n";
  77. context->Makefile->GetCMakeInstance()
  78. ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
  79. parent->Backtrace);
  80. return;
  81. }
  82. {
  83. cmOStringStream e;
  84. e << "Error evaluating generator expression:\n"
  85. << " " << expr << "\n"
  86. << "Dependency loop found.";
  87. context->Makefile->GetCMakeInstance()
  88. ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
  89. context->Backtrace);
  90. }
  91. int loopStep = 1;
  92. while (parent)
  93. {
  94. cmOStringStream e;
  95. e << "Loop step " << loopStep << "\n"
  96. << " "
  97. << (parent->Content ? parent->Content->GetOriginalExpression() : expr)
  98. << "\n";
  99. context->Makefile->GetCMakeInstance()
  100. ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
  101. parent->Backtrace);
  102. parent = parent->Parent;
  103. ++loopStep;
  104. }
  105. }
  106. //----------------------------------------------------------------------------
  107. cmGeneratorExpressionDAGChecker::Result
  108. cmGeneratorExpressionDAGChecker::checkGraph() const
  109. {
  110. const cmGeneratorExpressionDAGChecker *parent = this->Parent;
  111. while (parent)
  112. {
  113. if (this->Target == parent->Target && this->Property == parent->Property)
  114. {
  115. return (parent == this->Parent) ? SELF_REFERENCE : CYCLIC_REFERENCE;
  116. }
  117. parent = parent->Parent;
  118. }
  119. return DAG;
  120. }
  121. //----------------------------------------------------------------------------
  122. bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries()
  123. {
  124. const cmGeneratorExpressionDAGChecker *top = this;
  125. const cmGeneratorExpressionDAGChecker *parent = this->Parent;
  126. while (parent)
  127. {
  128. top = parent;
  129. parent = parent->Parent;
  130. }
  131. const char *prop = top->Property.c_str();
  132. return (strcmp(prop, "LINK_LIBRARIES") == 0
  133. || strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0
  134. || strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0
  135. || strncmp(prop, "LINK_INTERFACE_LIBRARIES_", 25) == 0
  136. || strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 34) == 0);
  137. }
  138. //----------------------------------------------------------------------------
  139. bool cmGeneratorExpressionDAGChecker::EvaluatingIncludeDirectories()
  140. {
  141. const char *prop = this->Property.c_str();
  142. return (strcmp(prop, "INCLUDE_DIRECTORIES") == 0
  143. || strcmp(prop, "INTERFACE_INCLUDE_DIRECTORIES") == 0 );
  144. }
  145. //----------------------------------------------------------------------------
  146. bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions()
  147. {
  148. const char *prop = this->Property.c_str();
  149. return (strcmp(prop, "COMPILE_DEFINITIONS") == 0
  150. || strcmp(prop, "INTERFACE_COMPILE_DEFINITIONS") == 0
  151. || strncmp(prop, "COMPILE_DEFINITIONS_", 20) == 0);
  152. }