summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2008-03-13 13:48:57 -0400
committerBrad King <brad.king@kitware.com>2008-03-13 13:48:57 -0400
commitf7f03347a64c629149803594b92c2b4b40e783fd (patch)
tree5035b672977616bb63be8f10fc2605e7dac83741
parent73df9a5cd4f6ac66ea71c073ce3e01d68c512074 (diff)
downloadcmake-f7f03347a64c629149803594b92c2b4b40e783fd.tar.gz
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)
-rw-r--r--Source/cmListFileCache.cxx15
-rw-r--r--Source/cmListFileCache.h4
-rw-r--r--Source/cmMakefile.cxx122
-rw-r--r--Source/cmMakefile.h5
-rw-r--r--Source/cmTarget.cxx13
-rw-r--r--Source/cmTarget.h4
-rw-r--r--Source/cmake.cxx78
-rw-r--r--Source/cmake.h5
8 files changed, 155 insertions, 91 deletions
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 2849c3d4fd..5711da2d69 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -268,3 +268,18 @@ bool cmListFileCacheParseFunction(cmListFileLexer* lexer,
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;
+}
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index 18ec0df6aa..b5d8a05200 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -57,11 +57,15 @@ struct cmListFileContext
long Line;
};
+std::ostream& operator<<(std::ostream&, cmListFileContext const&);
+
struct cmListFileFunction: public cmListFileContext
{
std::vector<cmListFileArgument> Arguments;
};
+class cmListFileBacktrace: public std::vector<cmListFileContext> {};
+
struct cmListFile
{
cmListFile()
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 79fca4a01a..4819c63304 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -35,8 +35,6 @@
#include "cmake.h"
#include <stdlib.h> // required for atoi
-#include "cmDocumentationFormatterText.h"
-
#include <cmsys/RegularExpression.hxx>
#include <cmsys/auto_ptr.hxx>
@@ -287,108 +285,51 @@ bool cmMakefile::CommandExists(const char* name) const
void cmMakefile::IssueMessage(cmake::MessageType t,
std::string const& text) const
{
- 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)
- {
- if(this->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS"))
- {
- return;
- }
- msg << "(dev)";
- }
- msg << ":";
- }
-
- // Add the immediate context.
- CallStackType::const_reverse_iterator i = this->CallStack.rbegin();
- if(i != this->CallStack.rend())
+ // Collect context information.
+ cmListFileBacktrace backtrace;
+ if(!this->CallStack.empty())
{
- if(isError)
+ if((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR))
{
- (*i).Status->SetNestedError(true);
+ this->CallStack.back().Status->SetNestedError(true);
}
- cmListFileContext const& lfc = *(*i).Context;
- msg
- << " at "
- << this->LocalGenerator->Convert(lfc.FilePath.c_str(),
- cmLocalGenerator::HOME)
- << ":" << lfc.Line << " " << lfc.Name;
- ++i;
+ this->GetBacktrace(backtrace);
}
else if(!this->ListFileStack.empty())
{
// We are processing the project but are not currently executing a
// command. Add whatever context information we have.
- if(this->LocalGenerator->GetParent())
- {
- msg << " in directory "
- << this->LocalGenerator->Convert(this->GetCurrentDirectory(),
- cmLocalGenerator::HOME);
- }
- else if(this->GetCMakeInstance()->GetIsInTryCompile())
- {
- msg << " in directory " << this->GetCurrentDirectory();
- }
- else
+ cmListFileContext lfc;
+ lfc.FilePath = this->ListFileStack.back();
+ lfc.Line = 0;
+ if(!this->GetCMakeInstance()->GetIsInTryCompile())
{
- msg << " in top-level directory";
+ lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath.c_str(),
+ cmLocalGenerator::HOME);
}
+ backtrace.push_back(lfc);
}
- // Add the message text.
- {
- msg << " {\n";
- cmDocumentationFormatterText formatter;
- formatter.SetIndent(" ");
- formatter.PrintFormatted(msg, text.c_str());
- msg << "}";
- }
-
- // Add the rest of the context.
- if(i != this->CallStack.rend())
- {
- msg << " with call stack {\n";
- 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
- {
- msg << "\n";
- }
+ // Issue the message.
+ this->GetCMakeInstance()->IssueMessage(t, text, backtrace);
+}
- // Output the message.
- if(isError)
+//----------------------------------------------------------------------------
+bool cmMakefile::GetBacktrace(cmListFileBacktrace& backtrace) const
+{
+ if(this->CallStack.empty())
{
- cmSystemTools::SetErrorOccured();
- cmSystemTools::Message(msg.str().c_str(), "Error");
+ return false;
}
- else
+ for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin();
+ i != this->CallStack.rend(); ++i)
{
- cmSystemTools::Message(msg.str().c_str(), "Warning");
+ cmListFileContext lfc = *(*i).Context;
+ lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath.c_str(),
+ cmLocalGenerator::HOME);
+ backtrace.push_back(lfc);
}
+ return true;
}
//----------------------------------------------------------------------------
@@ -1647,12 +1588,11 @@ cmTarget* cmMakefile::AddExecutable(const char *exeName,
cmTarget*
cmMakefile::AddNewTarget(cmTarget::TargetType type, const char* name)
{
- cmTargets::iterator it;
- cmTarget target;
+ cmTargets::iterator it =
+ this->Targets.insert(cmTargets::value_type(name, cmTarget())).first;
+ cmTarget& target = it->second;
target.SetType(type, name);
target.SetMakefile(this);
- it=this->Targets.insert(
- cmTargets::value_type(target.GetName(), target)).first;
this->LocalGenerator->GetGlobalGenerator()->AddTarget(*it);
return &it->second;
}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 33309e1ff0..b91ddb45e7 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -607,6 +607,11 @@ public:
std::string GetListFileStack();
/**
+ * Get the current context backtrace.
+ */
+ bool GetBacktrace(cmListFileBacktrace& backtrace) const;
+
+ /**
* Get the vector of files created by this makefile
*/
const std::vector<std::string>& GetOutputFiles() const
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 2d650acb45..429c5f9d70 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -21,6 +21,7 @@
#include "cmLocalGenerator.h"
#include "cmGlobalGenerator.h"
#include "cmComputeLinkInformation.h"
+#include "cmListFileCache.h"
#include <map>
#include <set>
#include <queue>
@@ -43,6 +44,9 @@ public:
typedef cmTarget::SourceFileFlags SourceFileFlags;
std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap;
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);
}
}
+
+ // Save the backtrace of target construction.
+ this->Makefile->GetBacktrace(this->Internal->Backtrace);
+}
+
+//----------------------------------------------------------------------------
+cmListFileBacktrace const& cmTarget::GetBacktrace() const
+{
+ return this->Internal->Backtrace;
}
//----------------------------------------------------------------------------
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 1b430e6040..a8b28635d0 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -25,6 +25,7 @@ class cmMakefile;
class cmSourceFile;
class cmGlobalGenerator;
class cmComputeLinkInformation;
+class cmListFileBacktrace;
struct cmTargetLinkInformationMap:
public std::map<cmStdString, cmComputeLinkInformation*>
@@ -374,6 +375,9 @@ public:
/** Return whether this target is an executable Bundle on Apple. */
bool IsAppBundleOnApple();
+ /** Get a backtrace from the creation of the target. */
+ cmListFileBacktrace const& GetBacktrace() const;
+
private:
/**
* A list of direct dependencies. Use in conjunction with DependencyMap.
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 5f014c9bb2..32c0911dd8 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -28,6 +28,7 @@
#include "cmSourceFile.h"
#include "cmVersion.h"
#include "cmTest.h"
+#include "cmDocumentationFormatterText.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
@@ -4108,3 +4109,80 @@ int cmake::VisualStudioLinkNonIncremental(std::vector<std::string>& args,
}
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");
+ }
+}
diff --git a/Source/cmake.h b/Source/cmake.h
index 86306073ff..f599c319b3 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -54,6 +54,7 @@ class cmFileTimeComparison;
class cmExternalMakefileProjectGenerator;
class cmDocumentationSection;
class cmPolicies;
+class cmListFileBacktrace;
class cmake
{
@@ -349,6 +350,10 @@ class cmake
{
this->SuppressDevWarnings = v;
}
+
+ /** Display a message to the user. */
+ void IssueMessage(cmake::MessageType t, std::string const& text,
+ cmListFileBacktrace const& backtrace);
protected:
void InitializeProperties();
int HandleDeleteCacheVariables(const char* var);