Make cycles in target properties ignored, not an error.

Constructs such as these are an error as they are direct self-references:

 set_property(TARGET foo APPEND PROPERTY
   INCLUDE_DIRECTORIES $<TARGET_PROPERTY:foo,INCLUDE_DIRECTORIES>)
 set_property(TARGET foo APPEND PROPERTY
   INCLUDE_DIRECTORIES $<TARGET_PROPERTY:INCLUDE_DIRECTORIES>)

However, this is an indirect self-reference in a cycle, and not an error:

 set_property(TARGET foo APPEND PROPERTY
   INCLUDE_DIRECTORIES $<TARGET_PROPERTY:bar,INCLUDE_DIRECTORIES>)
 set_property(TARGET bar APPEND PROPERTY
   INCLUDE_DIRECTORIES $<TARGET_PROPERTY:foo,INCLUDE_DIRECTORIES>)
This commit is contained in:
Stephen Kelly 2012-12-21 15:49:19 +01:00
parent d0f950fdba
commit c67b8124f7
3 changed files with 25 additions and 11 deletions

View File

@ -24,13 +24,14 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
: Parent(parent), Target(target), Property(property), : Parent(parent), Target(target), Property(property),
Content(content), Backtrace(backtrace) Content(content), Backtrace(backtrace)
{ {
this->IsDAG = this->isDAG(); this->CheckResult = this->checkGraph();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmGeneratorExpressionDAGChecker::check() const cmGeneratorExpressionDAGChecker::Result
cmGeneratorExpressionDAGChecker::check() const
{ {
return this->IsDAG; return this->CheckResult;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -38,7 +39,7 @@ void cmGeneratorExpressionDAGChecker::reportError(
cmGeneratorExpressionContext *context, cmGeneratorExpressionContext *context,
const std::string &expr) const std::string &expr)
{ {
if (this->IsDAG) if (this->CheckResult == DAG)
{ {
return; return;
} }
@ -91,16 +92,17 @@ void cmGeneratorExpressionDAGChecker::reportError(
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmGeneratorExpressionDAGChecker::isDAG() const cmGeneratorExpressionDAGChecker::Result
cmGeneratorExpressionDAGChecker::checkGraph() const
{ {
const cmGeneratorExpressionDAGChecker *parent = this->Parent; const cmGeneratorExpressionDAGChecker *parent = this->Parent;
while (parent) while (parent)
{ {
if (this->Target == parent->Target && this->Property == parent->Property) if (this->Target == parent->Target && this->Property == parent->Property)
{ {
return false; return parent->Parent ? CYCLIC_REFERENCE : SELF_REFERENCE;
} }
parent = parent->Parent; parent = parent->Parent;
} }
return true; return DAG;
} }

View File

@ -25,12 +25,18 @@ struct cmGeneratorExpressionDAGChecker
const GeneratorExpressionContent *content, const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *parent); cmGeneratorExpressionDAGChecker *parent);
bool check() const; enum Result {
DAG,
SELF_REFERENCE,
CYCLIC_REFERENCE
};
Result check() const;
void reportError(cmGeneratorExpressionContext *context, void reportError(cmGeneratorExpressionContext *context,
const std::string &expr); const std::string &expr);
private: private:
bool isDAG() const; Result checkGraph() const;
private: private:
const cmGeneratorExpressionDAGChecker * const Parent; const cmGeneratorExpressionDAGChecker * const Parent;
@ -38,7 +44,7 @@ private:
const std::string Property; const std::string Property;
const GeneratorExpressionContent * const Content; const GeneratorExpressionContent * const Content;
const cmListFileBacktrace Backtrace; const cmListFileBacktrace Backtrace;
bool IsDAG; Result CheckResult;
}; };
#endif #endif

View File

@ -381,10 +381,16 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
content, content,
dagCheckerParent); dagCheckerParent);
if (!dagChecker.check()) switch (dagChecker.check())
{ {
case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
dagChecker.reportError(context, content->GetOriginalExpression()); dagChecker.reportError(context, content->GetOriginalExpression());
return std::string(); return std::string();
case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
// No error. We just skip cyclic references.
return std::string();
case cmGeneratorExpressionDAGChecker::DAG:
break;
} }
const char *prop = target->GetProperty(propertyName.c_str()); const char *prop = target->GetProperty(propertyName.c_str());