diff options
author | Brad King <brad.king@kitware.com> | 2008-03-13 17:48:57 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2008-03-13 17:48:57 (GMT) |
commit | f7f03347a64c629149803594b92c2b4b40e783fd (patch) | |
tree | 5035b672977616bb63be8f10fc2605e7dac83741 | |
parent | 73df9a5cd4f6ac66ea71c073ce3e01d68c512074 (diff) | |
download | CMake-f7f03347a64c629149803594b92c2b4b40e783fd.zip CMake-f7f03347a64c629149803594b92c2b4b40e783fd.tar.gz CMake-f7f03347a64c629149803594b92c2b4b40e783fd.tar.bz2 |
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.cxx | 15 | ||||
-rw-r--r-- | Source/cmListFileCache.h | 4 | ||||
-rw-r--r-- | Source/cmMakefile.cxx | 122 | ||||
-rw-r--r-- | Source/cmMakefile.h | 5 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 13 | ||||
-rw-r--r-- | Source/cmTarget.h | 4 | ||||
-rw-r--r-- | Source/cmake.cxx | 78 | ||||
-rw-r--r-- | Source/cmake.h | 5 |
8 files changed, 155 insertions, 91 deletions
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 2849c3d..5711da2 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 18ec0df..b5d8a05 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 79fca4a..4819c63 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 33309e1..b91ddb4 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 2d650ac..429c5f9 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 1b430e6..a8b2863 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 5f014c9..32c0911 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 8630607..f599c31 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); |