ENH: Improve new error/warning message generation
- Add cmListFileBacktrace to record stack traces - Move main IssueMessage method to the cmake class instance (make the backtrace an explicit argument) - Change cmMakefile::IssueMessage to construct a backtrace and call the cmake instance version - Record a backtrace at the point a target is created (useful later for messages issued by generators)
This commit is contained in:
parent
73df9a5cd4
commit
f7f03347a6
|
@ -268,3 +268,18 @@ bool cmListFileCacheParseFunction(cmListFileLexer* lexer,
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc)
|
||||||
|
{
|
||||||
|
os << lfc.FilePath;
|
||||||
|
if(lfc.Line)
|
||||||
|
{
|
||||||
|
os << ":" << lfc.Line;
|
||||||
|
if(!lfc.Name.empty())
|
||||||
|
{
|
||||||
|
os << " (" << lfc.Name << ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
|
@ -57,11 +57,15 @@ struct cmListFileContext
|
||||||
long Line;
|
long Line;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream&, cmListFileContext const&);
|
||||||
|
|
||||||
struct cmListFileFunction: public cmListFileContext
|
struct cmListFileFunction: public cmListFileContext
|
||||||
{
|
{
|
||||||
std::vector<cmListFileArgument> Arguments;
|
std::vector<cmListFileArgument> Arguments;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class cmListFileBacktrace: public std::vector<cmListFileContext> {};
|
||||||
|
|
||||||
struct cmListFile
|
struct cmListFile
|
||||||
{
|
{
|
||||||
cmListFile()
|
cmListFile()
|
||||||
|
|
|
@ -35,8 +35,6 @@
|
||||||
#include "cmake.h"
|
#include "cmake.h"
|
||||||
#include <stdlib.h> // required for atoi
|
#include <stdlib.h> // required for atoi
|
||||||
|
|
||||||
#include "cmDocumentationFormatterText.h"
|
|
||||||
|
|
||||||
#include <cmsys/RegularExpression.hxx>
|
#include <cmsys/RegularExpression.hxx>
|
||||||
|
|
||||||
#include <cmsys/auto_ptr.hxx>
|
#include <cmsys/auto_ptr.hxx>
|
||||||
|
@ -287,108 +285,51 @@ bool cmMakefile::CommandExists(const char* name) const
|
||||||
void cmMakefile::IssueMessage(cmake::MessageType t,
|
void cmMakefile::IssueMessage(cmake::MessageType t,
|
||||||
std::string const& text) const
|
std::string const& text) const
|
||||||
{
|
{
|
||||||
cmOStringStream msg;
|
// Collect context information.
|
||||||
bool isError = false;
|
cmListFileBacktrace backtrace;
|
||||||
// Construct the message header.
|
if(!this->CallStack.empty())
|
||||||
if(t == cmake::FATAL_ERROR)
|
|
||||||
{
|
{
|
||||||
isError = true;
|
if((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR))
|
||||||
msg << "CMake Error:";
|
|
||||||
}
|
|
||||||
else if(t == cmake::INTERNAL_ERROR)
|
|
||||||
{
|
|
||||||
isError = true;
|
|
||||||
msg << "CMake Internal Error, please report a bug: ";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
msg << "CMake Warning";
|
|
||||||
if(t == cmake::AUTHOR_WARNING)
|
|
||||||
{
|
{
|
||||||
if(this->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS"))
|
this->CallStack.back().Status->SetNestedError(true);
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
msg << "(dev)";
|
|
||||||
}
|
}
|
||||||
msg << ":";
|
this->GetBacktrace(backtrace);
|
||||||
}
|
|
||||||
|
|
||||||
// Add the immediate context.
|
|
||||||
CallStackType::const_reverse_iterator i = this->CallStack.rbegin();
|
|
||||||
if(i != this->CallStack.rend())
|
|
||||||
{
|
|
||||||
if(isError)
|
|
||||||
{
|
|
||||||
(*i).Status->SetNestedError(true);
|
|
||||||
}
|
|
||||||
cmListFileContext const& lfc = *(*i).Context;
|
|
||||||
msg
|
|
||||||
<< " at "
|
|
||||||
<< this->LocalGenerator->Convert(lfc.FilePath.c_str(),
|
|
||||||
cmLocalGenerator::HOME)
|
|
||||||
<< ":" << lfc.Line << " " << lfc.Name;
|
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
else if(!this->ListFileStack.empty())
|
else if(!this->ListFileStack.empty())
|
||||||
{
|
{
|
||||||
// We are processing the project but are not currently executing a
|
// We are processing the project but are not currently executing a
|
||||||
// command. Add whatever context information we have.
|
// command. Add whatever context information we have.
|
||||||
if(this->LocalGenerator->GetParent())
|
cmListFileContext lfc;
|
||||||
|
lfc.FilePath = this->ListFileStack.back();
|
||||||
|
lfc.Line = 0;
|
||||||
|
if(!this->GetCMakeInstance()->GetIsInTryCompile())
|
||||||
{
|
{
|
||||||
msg << " in directory "
|
lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath.c_str(),
|
||||||
<< this->LocalGenerator->Convert(this->GetCurrentDirectory(),
|
cmLocalGenerator::HOME);
|
||||||
cmLocalGenerator::HOME);
|
|
||||||
}
|
|
||||||
else if(this->GetCMakeInstance()->GetIsInTryCompile())
|
|
||||||
{
|
|
||||||
msg << " in directory " << this->GetCurrentDirectory();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
msg << " in top-level directory";
|
|
||||||
}
|
}
|
||||||
|
backtrace.push_back(lfc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the message text.
|
// Issue the message.
|
||||||
{
|
this->GetCMakeInstance()->IssueMessage(t, text, backtrace);
|
||||||
msg << " {\n";
|
}
|
||||||
cmDocumentationFormatterText formatter;
|
|
||||||
formatter.SetIndent(" ");
|
|
||||||
formatter.PrintFormatted(msg, text.c_str());
|
|
||||||
msg << "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the rest of the context.
|
//----------------------------------------------------------------------------
|
||||||
if(i != this->CallStack.rend())
|
bool cmMakefile::GetBacktrace(cmListFileBacktrace& backtrace) const
|
||||||
|
{
|
||||||
|
if(this->CallStack.empty())
|
||||||
{
|
{
|
||||||
msg << " with call stack {\n";
|
return false;
|
||||||
while(i != this->CallStack.rend())
|
|
||||||
{
|
|
||||||
cmListFileContext const& lfc = *(*i).Context;
|
|
||||||
msg << " "
|
|
||||||
<< this->LocalGenerator->Convert(lfc.FilePath.c_str(),
|
|
||||||
cmLocalGenerator::HOME)
|
|
||||||
<< ":" << lfc.Line << " " << lfc.Name << "\n";
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
msg << "}\n";
|
|
||||||
}
|
}
|
||||||
else
|
for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin();
|
||||||
|
i != this->CallStack.rend(); ++i)
|
||||||
{
|
{
|
||||||
msg << "\n";
|
cmListFileContext lfc = *(*i).Context;
|
||||||
}
|
lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath.c_str(),
|
||||||
|
cmLocalGenerator::HOME);
|
||||||
// Output the message.
|
backtrace.push_back(lfc);
|
||||||
if(isError)
|
|
||||||
{
|
|
||||||
cmSystemTools::SetErrorOccured();
|
|
||||||
cmSystemTools::Message(msg.str().c_str(), "Error");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cmSystemTools::Message(msg.str().c_str(), "Warning");
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -1647,12 +1588,11 @@ cmTarget* cmMakefile::AddExecutable(const char *exeName,
|
||||||
cmTarget*
|
cmTarget*
|
||||||
cmMakefile::AddNewTarget(cmTarget::TargetType type, const char* name)
|
cmMakefile::AddNewTarget(cmTarget::TargetType type, const char* name)
|
||||||
{
|
{
|
||||||
cmTargets::iterator it;
|
cmTargets::iterator it =
|
||||||
cmTarget target;
|
this->Targets.insert(cmTargets::value_type(name, cmTarget())).first;
|
||||||
|
cmTarget& target = it->second;
|
||||||
target.SetType(type, name);
|
target.SetType(type, name);
|
||||||
target.SetMakefile(this);
|
target.SetMakefile(this);
|
||||||
it=this->Targets.insert(
|
|
||||||
cmTargets::value_type(target.GetName(), target)).first;
|
|
||||||
this->LocalGenerator->GetGlobalGenerator()->AddTarget(*it);
|
this->LocalGenerator->GetGlobalGenerator()->AddTarget(*it);
|
||||||
return &it->second;
|
return &it->second;
|
||||||
}
|
}
|
||||||
|
|
|
@ -606,6 +606,11 @@ public:
|
||||||
*/
|
*/
|
||||||
std::string GetListFileStack();
|
std::string GetListFileStack();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current context backtrace.
|
||||||
|
*/
|
||||||
|
bool GetBacktrace(cmListFileBacktrace& backtrace) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the vector of files created by this makefile
|
* Get the vector of files created by this makefile
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "cmLocalGenerator.h"
|
#include "cmLocalGenerator.h"
|
||||||
#include "cmGlobalGenerator.h"
|
#include "cmGlobalGenerator.h"
|
||||||
#include "cmComputeLinkInformation.h"
|
#include "cmComputeLinkInformation.h"
|
||||||
|
#include "cmListFileCache.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
@ -43,6 +44,9 @@ public:
|
||||||
typedef cmTarget::SourceFileFlags SourceFileFlags;
|
typedef cmTarget::SourceFileFlags SourceFileFlags;
|
||||||
std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap;
|
std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap;
|
||||||
bool SourceFileFlagsConstructed;
|
bool SourceFileFlagsConstructed;
|
||||||
|
|
||||||
|
// The backtrace when the target was created.
|
||||||
|
cmListFileBacktrace Backtrace;
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -719,6 +723,15 @@ void cmTarget::SetMakefile(cmMakefile* mf)
|
||||||
this->SetPropertyDefault(property.c_str(), 0);
|
this->SetPropertyDefault(property.c_str(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save the backtrace of target construction.
|
||||||
|
this->Makefile->GetBacktrace(this->Internal->Backtrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
cmListFileBacktrace const& cmTarget::GetBacktrace() const
|
||||||
|
{
|
||||||
|
return this->Internal->Backtrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
|
@ -25,6 +25,7 @@ class cmMakefile;
|
||||||
class cmSourceFile;
|
class cmSourceFile;
|
||||||
class cmGlobalGenerator;
|
class cmGlobalGenerator;
|
||||||
class cmComputeLinkInformation;
|
class cmComputeLinkInformation;
|
||||||
|
class cmListFileBacktrace;
|
||||||
|
|
||||||
struct cmTargetLinkInformationMap:
|
struct cmTargetLinkInformationMap:
|
||||||
public std::map<cmStdString, cmComputeLinkInformation*>
|
public std::map<cmStdString, cmComputeLinkInformation*>
|
||||||
|
@ -374,6 +375,9 @@ public:
|
||||||
/** Return whether this target is an executable Bundle on Apple. */
|
/** Return whether this target is an executable Bundle on Apple. */
|
||||||
bool IsAppBundleOnApple();
|
bool IsAppBundleOnApple();
|
||||||
|
|
||||||
|
/** Get a backtrace from the creation of the target. */
|
||||||
|
cmListFileBacktrace const& GetBacktrace() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* A list of direct dependencies. Use in conjunction with DependencyMap.
|
* A list of direct dependencies. Use in conjunction with DependencyMap.
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "cmSourceFile.h"
|
#include "cmSourceFile.h"
|
||||||
#include "cmVersion.h"
|
#include "cmVersion.h"
|
||||||
#include "cmTest.h"
|
#include "cmTest.h"
|
||||||
|
#include "cmDocumentationFormatterText.h"
|
||||||
|
|
||||||
#if defined(CMAKE_BUILD_WITH_CMAKE)
|
#if defined(CMAKE_BUILD_WITH_CMAKE)
|
||||||
# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
|
# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
|
||||||
|
@ -4108,3 +4109,80 @@ int cmake::VisualStudioLinkNonIncremental(std::vector<std::string>& args,
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmake::IssueMessage(cmake::MessageType t, std::string const& text,
|
||||||
|
cmListFileBacktrace const& backtrace)
|
||||||
|
{
|
||||||
|
cmOStringStream msg;
|
||||||
|
bool isError = false;
|
||||||
|
// Construct the message header.
|
||||||
|
if(t == cmake::FATAL_ERROR)
|
||||||
|
{
|
||||||
|
isError = true;
|
||||||
|
msg << "CMake Error";
|
||||||
|
}
|
||||||
|
else if(t == cmake::INTERNAL_ERROR)
|
||||||
|
{
|
||||||
|
isError = true;
|
||||||
|
msg << "CMake Internal Error (please report a bug)";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg << "CMake Warning";
|
||||||
|
if(t == cmake::AUTHOR_WARNING)
|
||||||
|
{
|
||||||
|
// Allow suppression of these warnings.
|
||||||
|
cmCacheManager::CacheIterator it = this->CacheManager
|
||||||
|
->GetCacheIterator("CMAKE_SUPPRESS_DEVELOPER_WARNINGS");
|
||||||
|
if(!it.IsAtEnd() && it.GetValueAsBool())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
msg << " (dev)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the immediate context.
|
||||||
|
cmListFileBacktrace::const_iterator i = backtrace.begin();
|
||||||
|
if(i != backtrace.end())
|
||||||
|
{
|
||||||
|
cmListFileContext const& lfc = *i;
|
||||||
|
msg << (lfc.Line? " at ": " in ") << lfc;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the message text.
|
||||||
|
{
|
||||||
|
msg << ":\n";
|
||||||
|
cmDocumentationFormatterText formatter;
|
||||||
|
formatter.SetIndent(" ");
|
||||||
|
formatter.PrintFormatted(msg, text.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the rest of the context.
|
||||||
|
if(i != backtrace.end())
|
||||||
|
{
|
||||||
|
msg << "Call Stack (most recent call first):\n";
|
||||||
|
while(i != backtrace.end())
|
||||||
|
{
|
||||||
|
cmListFileContext const& lfc = *i;
|
||||||
|
msg << " " << lfc << "\n";
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a terminating blank line.
|
||||||
|
msg << "\n";
|
||||||
|
|
||||||
|
// Output the message.
|
||||||
|
if(isError)
|
||||||
|
{
|
||||||
|
cmSystemTools::SetErrorOccured();
|
||||||
|
cmSystemTools::Message(msg.str().c_str(), "Error");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmSystemTools::Message(msg.str().c_str(), "Warning");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ class cmFileTimeComparison;
|
||||||
class cmExternalMakefileProjectGenerator;
|
class cmExternalMakefileProjectGenerator;
|
||||||
class cmDocumentationSection;
|
class cmDocumentationSection;
|
||||||
class cmPolicies;
|
class cmPolicies;
|
||||||
|
class cmListFileBacktrace;
|
||||||
|
|
||||||
class cmake
|
class cmake
|
||||||
{
|
{
|
||||||
|
@ -349,6 +350,10 @@ class cmake
|
||||||
{
|
{
|
||||||
this->SuppressDevWarnings = v;
|
this->SuppressDevWarnings = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Display a message to the user. */
|
||||||
|
void IssueMessage(cmake::MessageType t, std::string const& text,
|
||||||
|
cmListFileBacktrace const& backtrace);
|
||||||
protected:
|
protected:
|
||||||
void InitializeProperties();
|
void InitializeProperties();
|
||||||
int HandleDeleteCacheVariables(const char* var);
|
int HandleDeleteCacheVariables(const char* var);
|
||||||
|
|
Loading…
Reference in New Issue