Commit a79abb82 authored by Brad King's avatar Brad King Committed by Kitware Robot
Browse files

Merge topic 'extract-cmMessenger'

1462576b Parser: Port away from cmMakefile
421012a3 cmMessenger: Extract from cmake class
14a8d61f cmMakefile: Port nested error logic away from cmExecutionStatus
2af853de cmMakefile: Simplify IssueMessage implementation
33bb9cfa Parser: Issue messages through cmake, not cmSystemTools
db7de303 Parser: Store the Backtrace for use in issuing messages
parents ce8fadc7 1462576b
......@@ -319,6 +319,8 @@ set(SRCS
cmMakefileExecutableTargetGenerator.cxx
cmMakefileLibraryTargetGenerator.cxx
cmMakefileUtilityTargetGenerator.cxx
cmMessenger.cxx
cmMessenger.h
cmOSXBundleGenerator.cxx
cmOSXBundleGenerator.h
cmOutputConverter.cxx
......
......@@ -38,16 +38,12 @@ public:
this->ReturnInvoked = false;
this->BreakInvoked = false;
this->ContinueInvoked = false;
this->NestedError = false;
}
void SetNestedError(bool val) { this->NestedError = val; }
bool GetNestedError() { return this->NestedError; }
private:
bool ReturnInvoked;
bool BreakInvoked;
bool ContinueInvoked;
bool NestedError;
};
#endif
......@@ -76,7 +76,7 @@ public:
};
bool cmFunctionHelperCommand::InvokeInitialPass(
const std::vector<cmListFileArgument>& args, cmExecutionStatus& inStatus)
const std::vector<cmListFileArgument>& args, cmExecutionStatus&)
{
// Expand the argument list to the function.
std::vector<std::string> expandedArgs;
......@@ -129,11 +129,11 @@ bool cmFunctionHelperCommand::InvokeInitialPass(
for (unsigned int c = 0; c < this->Functions.size(); ++c) {
cmExecutionStatus status;
if (!this->Makefile->ExecuteCommand(this->Functions[c], status) ||
status.GetNestedError()) {
(cmSystemTools::GetErrorOccuredFlag() &&
!cmSystemTools::GetFatalErrorOccured())) {
// The error message should have already included the call stack
// so we do not need to report an error here.
functionScope.Quiet();
inStatus.SetNestedError(true);
return false;
}
if (status.GetReturnInvoked()) {
......
......@@ -12,7 +12,7 @@
#include "cmListFileCache.h"
#include "cmListFileLexer.h"
#include "cmMakefile.h"
#include "cmMessenger.h"
#include "cmOutputConverter.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
......@@ -21,15 +21,18 @@
struct cmListFileParser
{
cmListFileParser(cmListFile* lf, cmMakefile* mf, const char* filename);
cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt,
cmMessenger* messenger, const char* filename);
~cmListFileParser();
void IssueFileOpenError(std::string const& text) const;
void IssueError(std::string const& text) const;
bool ParseFile();
bool ParseFunction(const char* name, long line);
bool AddArgument(cmListFileLexer_Token* token,
cmListFileArgument::Delimiter delim);
cmListFile* ListFile;
cmMakefile* Makefile;
cmListFileBacktrace Backtrace;
cmMessenger* Messenger;
const char* FileName;
cmListFileLexer* Lexer;
cmListFileFunction Function;
......@@ -41,10 +44,12 @@ struct cmListFileParser
} Separation;
};
cmListFileParser::cmListFileParser(cmListFile* lf, cmMakefile* mf,
cmListFileParser::cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt,
cmMessenger* messenger,
const char* filename)
: ListFile(lf)
, Makefile(mf)
, Backtrace(lfbt)
, Messenger(messenger)
, FileName(filename)
, Lexer(cmListFileLexer_New())
{
......@@ -57,7 +62,18 @@ cmListFileParser::~cmListFileParser()
void cmListFileParser::IssueFileOpenError(const std::string& text) const
{
this->Makefile->IssueMessage(cmake::FATAL_ERROR, text);
this->Messenger->IssueMessage(cmake::FATAL_ERROR, text, this->Backtrace);
}
void cmListFileParser::IssueError(const std::string& text) const
{
cmListFileContext lfc;
lfc.FilePath = this->FileName;
lfc.Line = cmListFileLexer_GetCurrentLine(this->Lexer);
cmListFileBacktrace lfbt = this->Backtrace;
lfbt = lfbt.Push(lfc);
this->Messenger->IssueMessage(cmake::FATAL_ERROR, text, lfbt);
cmSystemTools::SetFatalErrorOccured();
}
bool cmListFileParser::ParseFile()
......@@ -96,29 +112,26 @@ bool cmListFileParser::ParseFile()
}
} else {
std::ostringstream error;
error << "Error in cmake code at\n"
<< this->FileName << ":" << token->line << ":\n"
<< "Parse error. Expected a newline, got "
error << "Parse error. Expected a newline, got "
<< cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
cmSystemTools::Error(error.str().c_str());
this->IssueError(error.str());
return false;
}
} else {
std::ostringstream error;
error << "Error in cmake code at\n"
<< this->FileName << ":" << token->line << ":\n"
<< "Parse error. Expected a command name, got "
error << "Parse error. Expected a command name, got "
<< cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
cmSystemTools::Error(error.str().c_str());
this->IssueError(error.str());
return false;
}
}
return true;
}
bool cmListFile::ParseFile(const char* filename, cmMakefile* mf)
bool cmListFile::ParseFile(const char* filename, cmMessenger* messenger,
cmListFileBacktrace const& lfbt)
{
if (!cmSystemTools::FileExists(filename) ||
cmSystemTools::FileIsDirectory(filename)) {
......@@ -128,7 +141,7 @@ bool cmListFile::ParseFile(const char* filename, cmMakefile* mf)
bool parseError = false;
{
cmListFileParser parser(this, mf, filename);
cmListFileParser parser(this, lfbt, messenger, filename);
parseError = !parser.ParseFile();
}
......@@ -154,18 +167,15 @@ bool cmListFileParser::ParseFunction(const char* name, long line)
<< cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n"
<< "Parse error. Function missing opening \"(\".";
/* clang-format on */
cmSystemTools::Error(error.str().c_str());
this->IssueError(error.str());
return false;
}
if (token->type != cmListFileLexer_Token_ParenLeft) {
std::ostringstream error;
error << "Error in cmake code at\n"
<< this->FileName << ":"
<< cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n"
<< "Parse error. Expected \"(\", got "
error << "Parse error. Expected \"(\", got "
<< cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
cmSystemTools::Error(error.str().c_str());
this->IssueError(error.str());
return false;
}
......@@ -217,25 +227,24 @@ bool cmListFileParser::ParseFunction(const char* name, long line)
} else {
// Error.
std::ostringstream error;
error << "Error in cmake code at\n"
<< this->FileName << ":"
<< cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n"
<< "Parse error. Function missing ending \")\". "
error << "Parse error. Function missing ending \")\". "
<< "Instead found "
<< cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
cmSystemTools::Error(error.str().c_str());
this->IssueError(error.str());
return false;
}
}
std::ostringstream error;
error << "Error in cmake code at\n"
<< this->FileName << ":" << lastLine << ":\n"
<< "Parse error. Function missing ending \")\". "
cmListFileContext lfc;
lfc.FilePath = this->FileName;
lfc.Line = lastLine;
cmListFileBacktrace lfbt = this->Backtrace;
lfbt = lfbt.Push(lfc);
error << "Parse error. Function missing ending \")\". "
<< "End of file reached.";
cmSystemTools::Error(error.str().c_str());
this->Messenger->IssueMessage(cmake::FATAL_ERROR, error.str(), lfbt);
return false;
}
......@@ -250,17 +259,21 @@ bool cmListFileParser::AddArgument(cmListFileLexer_Token* token,
bool isError = (this->Separation == SeparationError ||
delim == cmListFileArgument::Bracket);
std::ostringstream m;
/* clang-format off */
m << "Syntax " << (isError? "Error":"Warning") << " in cmake code at\n"
<< " " << this->FileName << ":" << token->line << ":"
<< token->column << "\n"
cmListFileContext lfc;
lfc.FilePath = this->FileName;
lfc.Line = token->line;
cmListFileBacktrace lfbt = this->Backtrace;
lfbt = lfbt.Push(lfc);
m << "Syntax " << (isError ? "Error" : "Warning") << " in cmake code at "
<< "column " << token->column << "\n"
<< "Argument not separated from preceding token by whitespace.";
/* clang-format on */
if (isError) {
this->Makefile->IssueMessage(cmake::FATAL_ERROR, m.str());
this->Messenger->IssueMessage(cmake::FATAL_ERROR, m.str(), lfbt);
return false;
}
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, m.str());
this->Messenger->IssueMessage(cmake::AUTHOR_WARNING, m.str(), lfbt);
return true;
}
......
......@@ -23,7 +23,7 @@
* cmake list files.
*/
class cmMakefile;
class cmMessenger;
struct cmCommandContext
{
......@@ -158,7 +158,8 @@ private:
struct cmListFile
{
bool ParseFile(const char* path, cmMakefile* mf);
bool ParseFile(const char* path, cmMessenger* messenger,
cmListFileBacktrace const& lfbt);
std::vector<cmListFileFunction> Functions;
};
......
......@@ -159,11 +159,11 @@ bool cmMacroHelperCommand::InvokeInitialPass(
}
cmExecutionStatus status;
if (!this->Makefile->ExecuteCommand(newLFF, status) ||
status.GetNestedError()) {
(cmSystemTools::GetErrorOccuredFlag() &&
!cmSystemTools::GetFatalErrorOccured())) {
// The error message should have already included the call stack
// so we do not need to report an error here.
macroScope.Quiet();
inStatus.SetNestedError(true);
return false;
}
if (status.GetReturnInvoked()) {
......
......@@ -25,6 +25,7 @@
#include "cmGlobalGenerator.h"
#include "cmInstallGenerator.h"
#include "cmListFileCache.h"
#include "cmMessenger.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmState.h"
......@@ -115,12 +116,6 @@ cmMakefile::~cmMakefile()
void cmMakefile::IssueMessage(cmake::MessageType t,
std::string const& text) const
{
// Collect context information.
if (!this->ExecutionStatusStack.empty()) {
if ((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR)) {
this->ExecutionStatusStack.back()->SetNestedError(true);
}
}
this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace());
}
......@@ -281,11 +276,19 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
if (this->GetCMakeInstance()->GetTrace()) {
this->PrintCommandTrace(lff);
}
// Try invoking the command.
bool hadPreviousNonFatalError = cmSystemTools::GetErrorOccuredFlag() &&
!cmSystemTools::GetFatalErrorOccured();
cmSystemTools::ResetErrorOccuredFlag();
bool invokeSucceeded = pcmd->InvokeInitialPass(lff.Arguments, status);
bool hadNestedError = status.GetNestedError();
bool hadNestedError = cmSystemTools::GetErrorOccuredFlag() &&
!cmSystemTools::GetFatalErrorOccured();
if (hadPreviousNonFatalError) {
cmSystemTools::SetErrorOccured();
}
if (!invokeSucceeded || hadNestedError) {
if (!hadNestedError) {
if (!hadNestedError && !cmSystemTools::GetFatalErrorOccured()) {
// The command invocation requested that we report an error.
this->IssueMessage(cmake::FATAL_ERROR, pcmd->GetError());
}
......@@ -455,7 +458,8 @@ bool cmMakefile::ReadDependentFile(const char* filename, bool noPolicyScope)
IncludeScope incScope(this, filenametoread, noPolicyScope);
cmListFile listFile;
if (!listFile.ParseFile(filenametoread.c_str(), this)) {
if (!listFile.ParseFile(filenametoread.c_str(), this->GetMessenger(),
this->Backtrace)) {
return false;
}
......@@ -504,7 +508,8 @@ bool cmMakefile::ReadListFile(const char* filename)
ListFileScope scope(this, filenametoread);
cmListFile listFile;
if (!listFile.ParseFile(filenametoread.c_str(), this)) {
if (!listFile.ParseFile(filenametoread.c_str(), this->GetMessenger(),
this->Backtrace)) {
return false;
}
......@@ -1450,7 +1455,8 @@ void cmMakefile::Configure()
this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentStart.c_str());
cmListFile listFile;
if (!listFile.ParseFile(currentStart.c_str(), this)) {
if (!listFile.ParseFile(currentStart.c_str(), this->GetMessenger(),
this->Backtrace)) {
return;
}
if (this->IsRootMakefile()) {
......@@ -3272,6 +3278,11 @@ cmake* cmMakefile::GetCMakeInstance() const
return this->GlobalGenerator->GetCMakeInstance();
}
cmMessenger* cmMakefile::GetMessenger() const
{
return this->GetCMakeInstance()->GetMessenger();
}
cmGlobalGenerator* cmMakefile::GetGlobalGenerator() const
{
return this->GlobalGenerator;
......
......@@ -607,6 +607,7 @@ public:
* Get the instance
*/
cmake* GetCMakeInstance() const;
cmMessenger* GetMessenger() const;
cmGlobalGenerator* GetGlobalGenerator() const;
/**
......
......@@ -11,6 +11,8 @@
============================================================================*/
#include "cmMessageCommand.h"
#include "cmMessenger.h"
// cmLibraryCommand
bool cmMessageCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus&)
......@@ -65,8 +67,8 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args,
if (type != cmake::MESSAGE) {
// we've overriden the message type, above, so display it directly
cmake* cm = this->Makefile->GetCMakeInstance();
cm->DisplayMessage(type, message, this->Makefile->GetBacktrace());
cmMessenger* m = this->Makefile->GetMessenger();
m->DisplayMessage(type, message, this->Makefile->GetBacktrace());
} else {
if (status) {
this->Makefile->DisplayStatus(message.c_str(), -1);
......
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
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 "cmMessenger.h"
#include "cmDocumentationFormatter.h"
#include "cmMessenger.h"
#include "cmOutputConverter.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
#include <cmsys/SystemInformation.hxx>
#endif
cmake::MessageType cmMessenger::ConvertMessageType(cmake::MessageType t) const
{
bool warningsAsErrors;
if (t == cmake::AUTHOR_WARNING || t == cmake::AUTHOR_ERROR) {
warningsAsErrors = this->GetDevWarningsAsErrors();
if (warningsAsErrors && t == cmake::AUTHOR_WARNING) {
t = cmake::AUTHOR_ERROR;
} else if (!warningsAsErrors && t == cmake::AUTHOR_ERROR) {
t = cmake::AUTHOR_WARNING;
}
} else if (t == cmake::DEPRECATION_WARNING ||
t == cmake::DEPRECATION_ERROR) {
warningsAsErrors = this->GetDeprecatedWarningsAsErrors();
if (warningsAsErrors && t == cmake::DEPRECATION_WARNING) {
t = cmake::DEPRECATION_ERROR;
} else if (!warningsAsErrors && t == cmake::DEPRECATION_ERROR) {
t = cmake::DEPRECATION_WARNING;
}
}
return t;
}
bool cmMessenger::IsMessageTypeVisible(cmake::MessageType t) const
{
bool isVisible = true;
if (t == cmake::DEPRECATION_ERROR) {
if (!this->GetDeprecatedWarningsAsErrors()) {
isVisible = false;
}
} else if (t == cmake::DEPRECATION_WARNING) {
if (this->GetSuppressDeprecatedWarnings()) {
isVisible = false;
}
} else if (t == cmake::AUTHOR_ERROR) {
if (!this->GetDevWarningsAsErrors()) {
isVisible = false;
}
} else if (t == cmake::AUTHOR_WARNING) {
if (this->GetSuppressDevWarnings()) {
isVisible = false;
}
}
return isVisible;
}
static bool printMessagePreamble(cmake::MessageType t, std::ostream& msg)
{
// Construct the message header.
if (t == cmake::FATAL_ERROR) {
msg << "CMake Error";
} else if (t == cmake::INTERNAL_ERROR) {
msg << "CMake Internal Error (please report a bug)";
} else if (t == cmake::LOG) {
msg << "CMake Debug Log";
} else if (t == cmake::DEPRECATION_ERROR) {
msg << "CMake Deprecation Error";
} else if (t == cmake::DEPRECATION_WARNING) {
msg << "CMake Deprecation Warning";
} else if (t == cmake::AUTHOR_WARNING) {
msg << "CMake Warning (dev)";
} else if (t == cmake::AUTHOR_ERROR) {
msg << "CMake Error (dev)";
} else {
msg << "CMake Warning";
}
return true;
}
void printMessageText(std::ostream& msg, std::string const& text)
{
msg << ":\n";
cmDocumentationFormatter formatter;
formatter.SetIndent(" ");
formatter.PrintFormatted(msg, text.c_str());
}
void displayMessage(cmake::MessageType t, std::ostringstream& msg)
{
// Add a note about warning suppression.
if (t == cmake::AUTHOR_WARNING) {
msg << "This warning is for project developers. Use -Wno-dev to suppress "
"it.";
} else if (t == cmake::AUTHOR_ERROR) {
msg << "This error is for project developers. Use -Wno-error=dev to "
"suppress "
"it.";
}
// Add a terminating blank line.
msg << "\n";
#if defined(CMAKE_BUILD_WITH_CMAKE)
// Add a C++ stack trace to internal errors.
if (t == cmake::INTERNAL_ERROR) {
std::string stack = cmsys::SystemInformation::GetProgramStack(0, 0);
if (!stack.empty()) {
if (cmHasLiteralPrefix(stack, "WARNING:")) {
stack = "Note:" + stack.substr(8);
}
msg << stack << "\n";
}
}
#endif
// Output the message.
if (t == cmake::FATAL_ERROR || t == cmake::INTERNAL_ERROR ||
t == cmake::DEPRECATION_ERROR || t == cmake::AUTHOR_ERROR) {
cmSystemTools::SetErrorOccured();
cmSystemTools::Message(msg.str().c_str(), "Error");
} else {
cmSystemTools::Message(msg.str().c_str(), "Warning");
}
}
cmMessenger::cmMessenger(cmState* state)
: State(state)
{
}
void cmMessenger::IssueMessage(cmake::MessageType t, const std::string& text,
const cmListFileBacktrace& backtrace) const
{
bool force = false;
if (!force) {
// override the message type, if needed, for warnings and errors
cmake::MessageType override = this->ConvertMessageType(t);
if (override != t) {
t = override;
force = true;
}
}
if (!force && !this->IsMessageTypeVisible(t)) {
return;
}
this->DisplayMessage(t, text, backtrace);
}
void cmMessenger::DisplayMessage(cmake::MessageType t, const std::string& text,
const cmListFileBacktrace& backtrace) const
{
std::ostringstream msg;
if (!printMessagePreamble(t, msg)) {
return;
}
// Add the immediate context.
backtrace.PrintTitle(msg);
printMessageText(msg, text);
// Add the rest of the context.
backtrace.PrintCallStack(msg);
displayMessage(t, msg);
}
bool cmMessenger::GetSuppressDevWarnings() const
{
const char* cacheEntryValue =
this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_WARNINGS");
return cmSystemTools::IsOn(cacheEntryValue);
}
bool cmMessenger::GetSuppressDeprecatedWarnings() const
{
const char* cacheEntryValue =
this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED");
return cacheEntryValue && cmSystemTools::IsOff(cacheEntryValue);
}
bool cmMessenger::GetDevWarningsAsErrors() const
{
const char* cacheEntryValue =
this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_ERRORS");
return cacheEntryValue && cmSystemTools::IsOff(cacheEntryValue);
}
bool cmMessenger::GetDeprecatedWarningsAsErrors() const
{
const char* cacheEntryValue =
this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED");
return cmSystemTools::IsOn(cacheEntryValue);
}
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
Distributed under the OSI-approved BSD License (the "License");