[cfe-commits] r58122 - in /cfe/trunk: Driver/DependencyFile.cpp Driver/clang.cpp Driver/clang.h win32/clangDriver/clangDriver.vcproj

Daniel Dunbar daniel at zuster.org
Fri Oct 24 15:12:41 PDT 2008


Author: ddunbar
Date: Fri Oct 24 17:12:41 2008
New Revision: 58122

URL: http://llvm.org/viewvc/llvm-project?rev=58122&view=rev
Log:
Add initial dependency file generation support. Patch by Kovarththanan
Rajaratnam, with some updates and formatting changes.

Added:
    cfe/trunk/Driver/DependencyFile.cpp
Modified:
    cfe/trunk/Driver/clang.cpp
    cfe/trunk/Driver/clang.h
    cfe/trunk/win32/clangDriver/clangDriver.vcproj

Added: cfe/trunk/Driver/DependencyFile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/DependencyFile.cpp?rev=58122&view=auto

==============================================================================
--- cfe/trunk/Driver/DependencyFile.cpp (added)
+++ cfe/trunk/Driver/DependencyFile.cpp Fri Oct 24 17:12:41 2008
@@ -0,0 +1,220 @@
+//===--- DependencyFile.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 dependency files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/DirectoryLookup.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/System/Path.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Compiler.h"
+#include <fstream>
+#include <string>
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN DependencyFileCallback : public PPCallbacks {
+  llvm::StringSet<> Files;
+  const Preprocessor *PP;
+  std::ofstream OS;
+  const std::string &InputFile;
+  std::string Target;
+
+private:
+  bool FileMatchesDepCriteria(const char *Filename,
+                              SrcMgr::Characteristic_t FileType);
+  void OutputDependencyFile();
+
+public:
+  DependencyFileCallback(const Preprocessor *PP, 
+                         const std::string &InputFile,
+                         const std::string &DepFile,
+                         const std::string &Target,
+                         const char  *&ErrStr);
+  ~DependencyFileCallback();
+  virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+                           SrcMgr::Characteristic_t FileType);
+};
+}
+
+static const char *DependencyFileExt = "d";
+static const char *ObjectFileExt = "o";
+
+//===----------------------------------------------------------------------===//
+// Dependency file options
+//===----------------------------------------------------------------------===//
+static llvm::cl::opt<bool>
+GenerateDependencyFile("MD",
+             llvm::cl::desc("Generate dependency for main source file "
+                            "(system headers included)"));
+
+static llvm::cl::opt<bool>
+GenerateDependencyFileNoSysHeaders("MMD",
+             llvm::cl::desc("Generate dependency for main source file "
+                            "(no system headers)"));
+
+static llvm::cl::opt<std::string>
+DependencyOutputFile("MF",
+           llvm::cl::desc("Specify dependency output file"));
+
+static llvm::cl::opt<std::string>
+DependencyTarget("MT",
+         llvm::cl::desc("Specify target for dependency"));
+
+// FIXME: Implement feature
+static llvm::cl::opt<bool>
+PhonyDependencyTarget("MP",
+            llvm::cl::desc("Create phony target for each dependency "
+                           "(other than main file)"));
+
+bool clang::CreateDependencyFileGen(Preprocessor *PP,
+                                    std::string &OutputFile,
+                                    const std::string &InputFile,
+                                    const char  *&ErrStr) {
+  assert(!InputFile.empty() && "No file given");
+  
+  ErrStr = NULL;
+
+  if (!GenerateDependencyFile && !GenerateDependencyFileNoSysHeaders) {
+    if (!DependencyOutputFile.empty() || !DependencyTarget.empty() || 
+        PhonyDependencyTarget)
+      ErrStr = "Error: to generate dependencies you must specify -MD or -MMD\n";
+    return false;
+  }
+  
+  // Handle conflicting options
+  if (GenerateDependencyFileNoSysHeaders)
+    GenerateDependencyFile = false;
+
+  // Determine name of dependency output filename
+  llvm::sys::Path DepFile;
+  if (!DependencyOutputFile.empty())
+    DepFile = DependencyOutputFile;
+  else if (!OutputFile.empty()) {
+    DepFile = OutputFile;
+    DepFile.eraseSuffix();
+    DepFile.appendSuffix(DependencyFileExt);
+  }
+  else {
+    DepFile = InputFile;
+    DepFile.eraseSuffix();
+    DepFile.appendSuffix(DependencyFileExt);
+  }
+
+  // Determine name of target
+  std::string Target;
+  if (!DependencyTarget.empty())
+    Target = DependencyTarget;
+  else if (!OutputFile.empty()) {
+    llvm::sys::Path TargetPath(OutputFile);
+    TargetPath.eraseSuffix();
+    TargetPath.appendSuffix(ObjectFileExt);
+    Target = TargetPath.toString();
+  }
+  else {
+    llvm::sys::Path TargetPath(InputFile);
+    TargetPath.eraseSuffix();
+    TargetPath.appendSuffix(ObjectFileExt);
+    Target = TargetPath.toString();
+  }
+
+  DependencyFileCallback *PPDep = 
+    new DependencyFileCallback(PP, InputFile, DepFile.toString(),
+                               Target, ErrStr);
+  if (ErrStr){
+    delete PPDep;
+    return false;
+  }
+  else {
+    PP->setPPCallbacks(PPDep);
+    return true;
+  }
+}
+
+/// FileMatchesDepCriteria - Determine whether the given Filename should be
+/// considered as a dependency.
+bool DependencyFileCallback::FileMatchesDepCriteria(const char *Filename,
+                                            SrcMgr::Characteristic_t FileType) {
+  if (strcmp(InputFile.c_str(), Filename) != 0 &&
+      strcmp("<predefines>", Filename) != 0) {
+      if (GenerateDependencyFileNoSysHeaders)
+        return FileType == SrcMgr::C_User;
+      else
+        return true;
+  }
+
+  return false;
+}
+
+void DependencyFileCallback::FileChanged(SourceLocation Loc,
+                                         FileChangeReason Reason,
+                                         SrcMgr::Characteristic_t FileType) {
+  if (Reason != PPCallbacks::EnterFile)
+    return;
+
+  const char *Filename = PP->getSourceManager().getSourceName(Loc);
+  if (!FileMatchesDepCriteria(Filename, FileType))
+    return;
+
+  // Remove leading "./"
+  if(Filename[0] == '.' && Filename[1] == '/')
+    Filename = &Filename[2];
+
+  Files.insert(Filename);
+}
+
+void DependencyFileCallback::OutputDependencyFile() {
+  std::string Output;
+  // Add "target: mainfile"
+  Output += Target;
+  Output += ": ";
+  Output += InputFile;
+
+  // Now add each dependency
+  for (llvm::StringSet<>::iterator I = Files.begin(),
+       E = Files.end(); I != E; ++I) {
+      // FIXME: Wrap lines
+      Output += " ";
+      Output += I->getKeyData();
+  }
+
+  OS << Output << "\n";
+}
+
+DependencyFileCallback::DependencyFileCallback(const Preprocessor *PP,
+                                               const std::string &InputFile,
+                                               const std::string &DepFile,
+                                               const std::string &Target,
+                                               const char  *&ErrStr)
+  : PP(PP), InputFile(InputFile), Target(Target) {
+
+  OS.open(DepFile.c_str());
+  if (OS.fail())
+    ErrStr = "Could not open dependency output file\n";
+  else
+    ErrStr = NULL;
+}
+
+DependencyFileCallback::~DependencyFileCallback() {
+  if ((!GenerateDependencyFile && !GenerateDependencyFileNoSysHeaders) || 
+      OS.fail())
+    return;
+  
+  OutputDependencyFile();
+  OS.close();
+}
+

Modified: cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.cpp?rev=58122&r1=58121&r2=58122&view=diff

==============================================================================
--- cfe/trunk/Driver/clang.cpp (original)
+++ cfe/trunk/Driver/clang.cpp Fri Oct 24 17:12:41 2008
@@ -1084,6 +1084,16 @@
       return NULL;
     }
     
+    /// FIXME: PP can only handle one callback
+    if (ProgAction != PrintPreprocessedInput) {    
+      const char* ErrStr;
+      bool DFG = CreateDependencyFileGen(PP, OutputFile, InFile, ErrStr);
+       if (!DFG && ErrStr) {
+        fprintf(stderr, ErrStr);
+        return NULL;
+      }
+    }
+
     InitializeSourceMgr = false;
     return PP;
   }

Modified: cfe/trunk/Driver/clang.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.h?rev=58122&r1=58121&r2=58122&view=diff

==============================================================================
--- cfe/trunk/Driver/clang.h (original)
+++ cfe/trunk/Driver/clang.h Fri Oct 24 17:12:41 2008
@@ -50,6 +50,13 @@
 /// CheckDiagnostics - Gather the expected diagnostics and check them.
 bool CheckDiagnostics(Preprocessor &PP);
 
+/// CreateDependencyFileGen - Create dependency file generator.
+/// This is only done if either -MD or -MMD has been specified.
+bool CreateDependencyFileGen(Preprocessor *PP,
+                             std::string &OutputFile,
+                             const std::string &InputFile,
+                             const char  *&ErrStr);
+
 /// CacheTokens - Cache tokens for use with PCH.
 void CacheTokens(Preprocessor& PP, const std::string& OutFile);
 

Modified: cfe/trunk/win32/clangDriver/clangDriver.vcproj
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/win32/clangDriver/clangDriver.vcproj?rev=58122&r1=58121&r2=58122&view=diff

==============================================================================
--- cfe/trunk/win32/clangDriver/clangDriver.vcproj (original)
+++ cfe/trunk/win32/clangDriver/clangDriver.vcproj Fri Oct 24 17:12:41 2008
@@ -208,6 +208,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\Driver\DependencyFile.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\..\Driver\DiagChecker.cpp"
 				>
 			</File>





More information about the cfe-commits mailing list