[cfe-commits] r149575 - in /cfe/trunk: include/clang/Driver/CC1Options.td include/clang/Frontend/DependencyOutputOptions.h include/clang/Frontend/Utils.h lib/Frontend/CMakeLists.txt lib/Frontend/CompilerInstance.cpp lib/Frontend/CompilerInvocation.cpp lib/Frontend/DependencyGraph.cpp

Douglas Gregor dgregor at apple.com
Wed Feb 1 16:54:53 PST 2012


Author: dgregor
Date: Wed Feb  1 18:54:52 2012
New Revision: 149575

URL: http://llvm.org/viewvc/llvm-project?rev=149575&view=rev
Log:
Introduce a -cc1 option "-dependency-graphviz" that determines header
dependencies and outputs them in GraphViz format.

Added:
    cfe/trunk/lib/Frontend/DependencyGraph.cpp
Modified:
    cfe/trunk/include/clang/Driver/CC1Options.td
    cfe/trunk/include/clang/Frontend/DependencyOutputOptions.h
    cfe/trunk/include/clang/Frontend/Utils.h
    cfe/trunk/lib/Frontend/CMakeLists.txt
    cfe/trunk/lib/Frontend/CompilerInstance.cpp
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp

Modified: cfe/trunk/include/clang/Driver/CC1Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=149575&r1=149574&r2=149575&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/CC1Options.td (original)
+++ cfe/trunk/include/clang/Driver/CC1Options.td Wed Feb  1 18:54:52 2012
@@ -233,6 +233,8 @@
 
 def dependency_file : Separate<"-dependency-file">,
   HelpText<"Filename (or -) to write dependency output to">;
+def dependency_graphviz : Separate<"-dependency-graphviz">,
+  HelpText<"Filename to write GraphViz-formatted header dependencies to">;
 def sys_header_deps : Flag<"-sys-header-deps">,
   HelpText<"Include system headers in dependency output">;
 def header_include_file : Separate<"-header-include-file">,

Modified: cfe/trunk/include/clang/Frontend/DependencyOutputOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/DependencyOutputOptions.h?rev=149575&r1=149574&r2=149575&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/DependencyOutputOptions.h (original)
+++ cfe/trunk/include/clang/Frontend/DependencyOutputOptions.h Wed Feb  1 18:54:52 2012
@@ -25,7 +25,7 @@
                                      /// dependency, which can avoid some 'make'
                                      /// problems.
   unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list
-
+  
   /// The file to write dependency output to.
   std::string OutputFile;
 
@@ -39,6 +39,9 @@
   /// must contain at least one entry.
   std::vector<std::string> Targets;
 
+  /// \brief The file to write GraphViz-formatted header dependencies to.
+  std::string GraphvizOutputFile;
+  
 public:
   DependencyOutputOptions() {
     IncludeSystemHeaders = 0;

Modified: cfe/trunk/include/clang/Frontend/Utils.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/Utils.h?rev=149575&r1=149574&r2=149575&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/Utils.h (original)
+++ cfe/trunk/include/clang/Frontend/Utils.h Wed Feb  1 18:54:52 2012
@@ -73,6 +73,11 @@
 void AttachDependencyFileGen(Preprocessor &PP,
                              const DependencyOutputOptions &Opts);
 
+/// AttachDependencyGraphGen - Create a dependency graph generator, and attach
+/// it to the given preprocessor.
+  void AttachDependencyGraphGen(Preprocessor &PP, StringRef OutputFile,
+                                StringRef SysRoot);
+
 /// AttachHeaderIncludeGen - Create a header include list generator, and attach
 /// it to the given preprocessor.
 ///

Modified: cfe/trunk/lib/Frontend/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CMakeLists.txt?rev=149575&r1=149574&r2=149575&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CMakeLists.txt (original)
+++ cfe/trunk/lib/Frontend/CMakeLists.txt Wed Feb  1 18:54:52 2012
@@ -19,6 +19,7 @@
   CompilerInvocation.cpp
   CreateInvocationFromCommandLine.cpp
   DependencyFile.cpp
+  DependencyGraph.cpp
   DiagnosticRenderer.cpp
   FrontendAction.cpp
   FrontendActions.cpp

Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=149575&r1=149574&r2=149575&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Wed Feb  1 18:54:52 2012
@@ -275,7 +275,11 @@
   const DependencyOutputOptions &DepOpts = getDependencyOutputOpts();
   if (!DepOpts.OutputFile.empty())
     AttachDependencyFileGen(*PP, DepOpts);
+  if (!DepOpts.GraphvizOutputFile.empty())
+    AttachDependencyGraphGen(*PP, DepOpts.GraphvizOutputFile,
+                             getHeaderSearchOpts().Sysroot);
 
+  
   // Handle generating header include information, if requested.
   if (DepOpts.ShowHeaderIncludes)
     AttachHeaderIncludeGen(*PP);

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=149575&r1=149574&r2=149575&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Wed Feb  1 18:54:52 2012
@@ -1191,6 +1191,7 @@
   Opts.ShowHeaderIncludes = Args.hasArg(OPT_H);
   Opts.HeaderIncludeOutputFile = Args.getLastArgValue(OPT_header_include_file);
   Opts.AddMissingHeaderDeps = Args.hasArg(OPT_MG);
+  Opts.GraphvizOutputFile = Args.getLastArgValue(OPT_dependency_graphviz);
 }
 
 static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,

Added: cfe/trunk/lib/Frontend/DependencyGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/DependencyGraph.cpp?rev=149575&view=auto
==============================================================================
--- cfe/trunk/lib/Frontend/DependencyGraph.cpp (added)
+++ cfe/trunk/lib/Frontend/DependencyGraph.cpp Wed Feb  1 18:54:52 2012
@@ -0,0 +1,139 @@
+//===--- DependencyGraph.cpp - Generate dependency file -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This code generates a header dependency graph in GraphViz format.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/GraphWriter.h"
+
+using namespace clang;
+namespace DOT = llvm::DOT;
+
+namespace {
+class DependencyGraphCallback : public PPCallbacks {
+  const Preprocessor *PP;
+  std::string OutputFile;
+  std::string SysRoot;
+  llvm::SetVector<const FileEntry *> AllFiles;
+  typedef llvm::DenseMap<const FileEntry *, 
+                         llvm::SmallVector<const FileEntry *, 2> >
+    DependencyMap;
+  
+  DependencyMap Dependencies;
+  
+private:
+  llvm::raw_ostream &writeNodeReference(llvm::raw_ostream &OS,
+                                        const FileEntry *Node);
+  void OutputGraphFile();
+
+public:
+  DependencyGraphCallback(const Preprocessor *_PP, StringRef OutputFile,
+                          StringRef SysRoot)
+    : PP(_PP), OutputFile(OutputFile.str()), SysRoot(SysRoot.str()) { }
+
+  virtual void InclusionDirective(SourceLocation HashLoc,
+                                  const Token &IncludeTok,
+                                  StringRef FileName,
+                                  bool IsAngled,
+                                  const FileEntry *File,
+                                  SourceLocation EndLoc,
+                                  StringRef SearchPath,
+                                  StringRef RelativePath);
+
+  virtual void EndOfMainFile() {
+    OutputGraphFile();
+  }
+  
+};
+}
+
+void clang::AttachDependencyGraphGen(Preprocessor &PP, StringRef OutputFile,
+                                     StringRef SysRoot) {
+  PP.addPPCallbacks(new DependencyGraphCallback(&PP, OutputFile, SysRoot));
+}
+
+void DependencyGraphCallback::InclusionDirective(SourceLocation HashLoc,
+                                                 const Token &IncludeTok,
+                                                 StringRef FileName,
+                                                 bool IsAngled,
+                                                 const FileEntry *File,
+                                                 SourceLocation EndLoc,
+                                                 StringRef SearchPath,
+                                                 StringRef RelativePath) {
+  if (!File)
+    return;
+  
+  SourceManager &SM = PP->getSourceManager();
+  const FileEntry *FromFile
+    = SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(HashLoc)));
+  if (FromFile == 0) 
+    return;
+
+  Dependencies[FromFile].push_back(File);
+  
+  AllFiles.insert(File);
+  AllFiles.insert(FromFile);
+}
+
+llvm::raw_ostream &
+DependencyGraphCallback::writeNodeReference(llvm::raw_ostream &OS,
+                                            const FileEntry *Node) {
+  OS << "header_" << Node->getUID();
+  return OS;
+}
+
+void DependencyGraphCallback::OutputGraphFile() {
+  std::string Err;
+  llvm::raw_fd_ostream OS(OutputFile.c_str(), Err);
+  if (!Err.empty()) {
+    PP->getDiagnostics().Report(diag::err_fe_error_opening)
+      << OutputFile << Err;
+    return;
+  }
+
+  OS << "digraph \"dependencies\" {\n";
+  
+  // Write the nodes
+  for (unsigned I = 0, N = AllFiles.size(); I != N; ++I) {
+    // Write the node itself.
+    OS.indent(2);
+    writeNodeReference(OS, AllFiles[I]);
+    OS << " [ shape=\"box\", label=\"";
+    StringRef FileName = AllFiles[I]->getName();
+    if (FileName.startswith(SysRoot))
+      FileName = FileName.substr(SysRoot.size());
+    
+    OS << DOT::EscapeString(FileName)
+    << "\"];\n";
+  }
+
+  // Write the edges
+  for (DependencyMap::iterator F = Dependencies.begin(), 
+                            FEnd = Dependencies.end();
+       F != FEnd; ++F) {    
+    for (unsigned I = 0, N = F->second.size(); I != N; ++I) {
+      OS.indent(2);
+      writeNodeReference(OS, F->first);
+      OS << " -> ";
+      writeNodeReference(OS, F->second[I]);
+      OS << ";\n";
+    }
+  }
+  OS << "}\n";
+}
+





More information about the cfe-commits mailing list