20 #include "llvm/ADT/SetVector.h"
21 #include "llvm/Support/GraphWriter.h"
22 #include "llvm/Support/raw_ostream.h"
24 using namespace clang;
25 namespace DOT = llvm::DOT;
28 class DependencyGraphCallback :
public PPCallbacks {
32 llvm::SetVector<FileEntryRef> AllFiles;
34 llvm::DenseMap<FileEntryRef, SmallVector<FileEntryRef, 2>>;
36 DependencyMap Dependencies;
39 raw_ostream &writeNodeReference(raw_ostream &OS,
41 void OutputGraphFile();
44 DependencyGraphCallback(
const Preprocessor *_PP, StringRef OutputFile,
46 : PP(_PP), OutputFile(OutputFile.str()), SysRoot(SysRoot.str()) { }
49 StringRef FileName,
bool IsAngled,
52 StringRef RelativePath,
const Module *Imported,
55 void EndOfMainFile()
override {
64 PP.
addPPCallbacks(std::make_unique<DependencyGraphCallback>(&PP, OutputFile,
68 void DependencyGraphCallback::InclusionDirective(
70 const Token &IncludeTok,
76 StringRef RelativePath,
84 SM.getFileEntryRefForID(
SM.getFileID(
SM.getExpansionLoc(HashLoc)));
88 Dependencies[*FromFile].push_back(*File);
90 AllFiles.insert(*File);
91 AllFiles.insert(*FromFile);
95 DependencyGraphCallback::writeNodeReference(raw_ostream &OS,
97 OS <<
"header_" <<
Node->getUID();
101 void DependencyGraphCallback::OutputGraphFile() {
103 llvm::raw_fd_ostream
OS(OutputFile, EC, llvm::sys::fs::OF_TextWithCRLF);
105 PP->getDiagnostics().Report(diag::err_fe_error_opening) << OutputFile
110 OS <<
"digraph \"dependencies\" {\n";
113 for (
unsigned I = 0, N = AllFiles.size(); I != N; ++I) {
116 writeNodeReference(OS, AllFiles[I]);
117 OS <<
" [ shape=\"box\", label=\"";
118 StringRef FileName = AllFiles[I].getName();
119 if (FileName.startswith(SysRoot))
120 FileName = FileName.substr(SysRoot.size());
126 for (DependencyMap::iterator F = Dependencies.begin(),
127 FEnd = Dependencies.end();
129 for (
unsigned I = 0, N = F->second.size(); I != N; ++I) {
131 writeNodeReference(OS, F->first);
133 writeNodeReference(OS, F->second[I]);