Browse Source
Add API to check that dependent target properties form a DAG.
Add API to check that dependent target properties form a DAG.
Initially this will only be used to check for self-references, but can be extended to check for cycles when chaining properties of other targets.pull/27/head

committed by
Brad King

8 changed files with 204 additions and 26 deletions
-
2Source/CMakeLists.txt
-
6Source/cmGeneratorExpression.cxx
-
4Source/cmGeneratorExpression.h
-
106Source/cmGeneratorExpressionDAGChecker.cxx
-
44Source/cmGeneratorExpressionDAGChecker.h
-
55Source/cmGeneratorExpressionEvaluator.cxx
-
12Source/cmGeneratorExpressionEvaluator.h
-
1bootstrap
@ -0,0 +1,106 @@ |
|||
/*============================================================================
|
|||
CMake - Cross Platform Makefile Generator |
|||
Copyright 2012 Stephen Kelly <steveire@gmail.com> |
|||
|
|||
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) |
|||
{ |
|||
this->IsDAG = this->isDAG(); |
|||
} |
|||
|
|||
//----------------------------------------------------------------------------
|
|||
bool cmGeneratorExpressionDAGChecker::check() const |
|||
{ |
|||
return this->IsDAG; |
|||
} |
|||
|
|||
//----------------------------------------------------------------------------
|
|||
void cmGeneratorExpressionDAGChecker::reportError( |
|||
cmGeneratorExpressionContext *context, |
|||
const std::string &expr) |
|||
{ |
|||
if (this->IsDAG) |
|||
{ |
|||
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->Target->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; |
|||
} |
|||
} |
|||
|
|||
//----------------------------------------------------------------------------
|
|||
bool cmGeneratorExpressionDAGChecker::isDAG() const |
|||
{ |
|||
const cmGeneratorExpressionDAGChecker *parent = this->Parent; |
|||
while (parent) |
|||
{ |
|||
if (this->Target == parent->Target && this->Property == parent->Property) |
|||
{ |
|||
return false; |
|||
} |
|||
parent = parent->Parent; |
|||
} |
|||
return true; |
|||
} |
@ -0,0 +1,44 @@ |
|||
/*============================================================================ |
|||
CMake - Cross Platform Makefile Generator |
|||
Copyright 2012 Stephen Kelly <steveire@gmail.com> |
|||
|
|||
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. |
|||
============================================================================*/ |
|||
#ifndef cmGeneratorExpressionDAGChecker_h |
|||
#define cmGeneratorExpressionDAGChecker_h |
|||
|
|||
#include "cmStandardIncludes.h" |
|||
|
|||
#include "cmGeneratorExpressionEvaluator.h" |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
struct cmGeneratorExpressionDAGChecker |
|||
{ |
|||
cmGeneratorExpressionDAGChecker(const cmListFileBacktrace &backtrace, |
|||
const std::string &target, |
|||
const std::string &property, |
|||
const GeneratorExpressionContent *content, |
|||
cmGeneratorExpressionDAGChecker *parent); |
|||
|
|||
bool check() const; |
|||
|
|||
void reportError(cmGeneratorExpressionContext *context, |
|||
const std::string &expr); |
|||
private: |
|||
bool isDAG() const; |
|||
|
|||
private: |
|||
const cmGeneratorExpressionDAGChecker * const Parent; |
|||
const std::string Target; |
|||
const std::string Property; |
|||
const GeneratorExpressionContent * const Content; |
|||
const cmListFileBacktrace Backtrace; |
|||
bool IsDAG; |
|||
}; |
|||
|
|||
#endif |
Write
Preview
Loading…
Cancel
Save
Reference in new issue