فهرست منبع

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)
Brad King 18 سال پیش
والد
کامیت
f7f03347a6
8فایلهای تغییر یافته به همراه155 افزوده شده و 91 حذف شده
  1. 15 0
      Source/cmListFileCache.cxx
  2. 4 0
      Source/cmListFileCache.h
  3. 31 91
      Source/cmMakefile.cxx
  4. 5 0
      Source/cmMakefile.h
  5. 13 0
      Source/cmTarget.cxx
  6. 4 0
      Source/cmTarget.h
  7. 78 0
      Source/cmake.cxx
  8. 5 0
      Source/cmake.h

+ 15 - 0
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;
+}

+ 4 - 0
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() 

+ 31 - 91
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;
 }

+ 5 - 0
Source/cmMakefile.h

@@ -606,6 +606,11 @@ public:
      */
     std::string GetListFileStack();
 
+  /**
+   * Get the current context backtrace.
+   */
+  bool GetBacktrace(cmListFileBacktrace& backtrace) const;
+
   /**
    * Get the vector of  files created by this makefile
    */

+ 13 - 0
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;
 }
 
 //----------------------------------------------------------------------------

+ 4 - 0
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.

+ 78 - 0
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");
+    }
+}

+ 5 - 0
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);