1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2012 Stephen Kelly <steveire@gmail.com>
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
8 This software is distributed WITHOUT ANY WARRANTY; without even the
9 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License for more information.
11 ============================================================================*/
13 #include "cmGeneratorExpressionDAGChecker.h"
15 #include "cmMakefile.h"
17 //----------------------------------------------------------------------------
18 cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
19 const cmListFileBacktrace &backtrace,
20 const std::string &target,
21 const std::string &property,
22 const GeneratorExpressionContent *content,
23 cmGeneratorExpressionDAGChecker *parent)
24 : Parent(parent), Target(target), Property(property),
25 Content(content), Backtrace(backtrace), TransitivePropertiesOnly(false)
27 const cmGeneratorExpressionDAGChecker *top = this;
28 const cmGeneratorExpressionDAGChecker *p = this->Parent;
34 this->CheckResult = this->checkGraph();
36 #define TEST_TRANSITIVE_PROPERTY_METHOD(METHOD) \
39 if (CheckResult == DAG && (
40 CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(TEST_TRANSITIVE_PROPERTY_METHOD)
44 std::map<cmStdString, std::set<cmStdString> >::const_iterator it
45 = top->Seen.find(target);
46 if (it != top->Seen.end())
48 const std::set<cmStdString> &propSet = it->second;
49 const std::set<cmStdString>::const_iterator i = propSet.find(property);
50 if (i != propSet.end())
52 this->CheckResult = ALREADY_SEEN;
56 const_cast<cmGeneratorExpressionDAGChecker *>(top)
57 ->Seen[target].insert(property);
61 //----------------------------------------------------------------------------
62 cmGeneratorExpressionDAGChecker::Result
63 cmGeneratorExpressionDAGChecker::check() const
65 return this->CheckResult;
68 //----------------------------------------------------------------------------
69 void cmGeneratorExpressionDAGChecker::reportError(
70 cmGeneratorExpressionContext *context,
71 const std::string &expr)
73 if (this->CheckResult == DAG)
78 context->HadError = true;
84 const cmGeneratorExpressionDAGChecker *parent = this->Parent;
86 if (parent && !parent->Parent)
89 e << "Error evaluating generator expression:\n"
90 << " " << expr << "\n"
91 << "Self reference on target \""
92 << context->HeadTarget->GetName() << "\".\n";
93 context->Makefile->GetCMakeInstance()
94 ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
101 e << "Error evaluating generator expression:\n"
102 << " " << expr << "\n"
103 << "Dependency loop found.";
104 context->Makefile->GetCMakeInstance()
105 ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
113 e << "Loop step " << loopStep << "\n"
115 << (parent->Content ? parent->Content->GetOriginalExpression() : expr)
117 context->Makefile->GetCMakeInstance()
118 ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
120 parent = parent->Parent;
125 //----------------------------------------------------------------------------
126 cmGeneratorExpressionDAGChecker::Result
127 cmGeneratorExpressionDAGChecker::checkGraph() const
129 const cmGeneratorExpressionDAGChecker *parent = this->Parent;
132 if (this->Target == parent->Target && this->Property == parent->Property)
134 return (parent == this->Parent) ? SELF_REFERENCE : CYCLIC_REFERENCE;
136 parent = parent->Parent;
141 //----------------------------------------------------------------------------
142 bool cmGeneratorExpressionDAGChecker::GetTransitivePropertiesOnly()
144 const cmGeneratorExpressionDAGChecker *top = this;
145 const cmGeneratorExpressionDAGChecker *parent = this->Parent;
149 parent = parent->Parent;
152 return top->TransitivePropertiesOnly;
155 //----------------------------------------------------------------------------
156 bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char *tgt)
158 const cmGeneratorExpressionDAGChecker *top = this;
159 const cmGeneratorExpressionDAGChecker *parent = this->Parent;
163 parent = parent->Parent;
166 const char *prop = top->Property.c_str();
170 return top->Target == tgt && strcmp(prop, "LINK_LIBRARIES") == 0;
173 return (strcmp(prop, "LINK_LIBRARIES") == 0
174 || strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0
175 || strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0
176 || strncmp(prop, "LINK_INTERFACE_LIBRARIES_", 25) == 0
177 || strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 34) == 0)
178 || strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
181 //----------------------------------------------------------------------------
182 bool cmGeneratorExpressionDAGChecker::EvaluatingIncludeDirectories() const
184 const char *prop = this->Property.c_str();
185 return (strcmp(prop, "INCLUDE_DIRECTORIES") == 0
186 || strcmp(prop, "INTERFACE_INCLUDE_DIRECTORIES") == 0 );
189 //----------------------------------------------------------------------------
191 cmGeneratorExpressionDAGChecker::EvaluatingSystemIncludeDirectories() const
193 const char *prop = this->Property.c_str();
194 return strcmp(prop, "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES") == 0;
197 //----------------------------------------------------------------------------
198 bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions() const
200 const char *prop = this->Property.c_str();
201 return (strcmp(prop, "COMPILE_DEFINITIONS") == 0
202 || strcmp(prop, "INTERFACE_COMPILE_DEFINITIONS") == 0
203 || strncmp(prop, "COMPILE_DEFINITIONS_", 20) == 0);
206 //----------------------------------------------------------------------------
207 bool cmGeneratorExpressionDAGChecker::EvaluatingCompileOptions() const
209 const char *prop = this->Property.c_str();
210 return (strcmp(prop, "COMPILE_OPTIONS") == 0
211 || strcmp(prop, "INTERFACE_COMPILE_OPTIONS") == 0 );