Use the clang RemoveCStrCalls tool to automatically migrate the code. This was only run on linux, so does not have any positive or negative effect on other platforms.
216 lines
6.3 KiB
C++
216 lines
6.3 KiB
C++
/*============================================================================
|
|
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), 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(),
|
|
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(),
|
|
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(),
|
|
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
|