DependencyFile.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. //===--- DependencyFile.cpp - Generate dependency file --------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This code generates dependency files.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/Frontend/Utils.h"
  14. #include "clang/Basic/FileManager.h"
  15. #include "clang/Basic/SourceManager.h"
  16. #include "clang/Frontend/DependencyOutputOptions.h"
  17. #include "clang/Frontend/FrontendDiagnostic.h"
  18. #include "clang/Lex/DirectoryLookup.h"
  19. #include "clang/Lex/LexDiagnostic.h"
  20. #include "clang/Lex/PPCallbacks.h"
  21. #include "clang/Lex/Preprocessor.h"
  22. #include "clang/Serialization/ASTReader.h"
  23. #include "llvm/ADT/StringSet.h"
  24. #include "llvm/Support/FileSystem.h"
  25. #include "llvm/Support/Path.h"
  26. #include "llvm/Support/raw_ostream.h"
  27. using namespace clang;
  28. namespace {
  29. struct DepCollectorPPCallbacks : public PPCallbacks {
  30. DependencyCollector &DepCollector;
  31. SourceManager &SM;
  32. DepCollectorPPCallbacks(DependencyCollector &L, SourceManager &SM)
  33. : DepCollector(L), SM(SM) { }
  34. void FileChanged(SourceLocation Loc, FileChangeReason Reason,
  35. SrcMgr::CharacteristicKind FileType,
  36. FileID PrevFID) override {
  37. if (Reason != PPCallbacks::EnterFile)
  38. return;
  39. // Dependency generation really does want to go all the way to the
  40. // file entry for a source location to find out what is depended on.
  41. // We do not want #line markers to affect dependency generation!
  42. const FileEntry *FE =
  43. SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc)));
  44. if (!FE)
  45. return;
  46. StringRef Filename = FE->getName();
  47. // Remove leading "./" (or ".//" or "././" etc.)
  48. while (Filename.size() > 2 && Filename[0] == '.' &&
  49. llvm::sys::path::is_separator(Filename[1])) {
  50. Filename = Filename.substr(1);
  51. while (llvm::sys::path::is_separator(Filename[0]))
  52. Filename = Filename.substr(1);
  53. }
  54. DepCollector.maybeAddDependency(Filename, /*FromModule*/false,
  55. FileType != SrcMgr::C_User,
  56. /*IsModuleFile*/false, /*IsMissing*/false);
  57. }
  58. void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
  59. StringRef FileName, bool IsAngled,
  60. CharSourceRange FilenameRange, const FileEntry *File,
  61. StringRef SearchPath, StringRef RelativePath,
  62. const Module *Imported) override {
  63. if (!File)
  64. DepCollector.maybeAddDependency(FileName, /*FromModule*/false,
  65. /*IsSystem*/false, /*IsModuleFile*/false,
  66. /*IsMissing*/true);
  67. // Files that actually exist are handled by FileChanged.
  68. }
  69. void EndOfMainFile() override {
  70. DepCollector.finishedMainFile();
  71. }
  72. };
  73. struct DepCollectorASTListener : public ASTReaderListener {
  74. DependencyCollector &DepCollector;
  75. DepCollectorASTListener(DependencyCollector &L) : DepCollector(L) { }
  76. bool needsInputFileVisitation() override { return true; }
  77. bool needsSystemInputFileVisitation() override {
  78. return DepCollector.needSystemDependencies();
  79. }
  80. void visitModuleFile(StringRef Filename) override {
  81. DepCollector.maybeAddDependency(Filename, /*FromModule*/true,
  82. /*IsSystem*/false, /*IsModuleFile*/true,
  83. /*IsMissing*/false);
  84. }
  85. bool visitInputFile(StringRef Filename, bool IsSystem,
  86. bool IsOverridden) override {
  87. if (IsOverridden)
  88. return true;
  89. DepCollector.maybeAddDependency(Filename, /*FromModule*/true, IsSystem,
  90. /*IsModuleFile*/false, /*IsMissing*/false);
  91. return true;
  92. }
  93. };
  94. } // end anonymous namespace
  95. void DependencyCollector::maybeAddDependency(StringRef Filename, bool FromModule,
  96. bool IsSystem, bool IsModuleFile,
  97. bool IsMissing) {
  98. if (Seen.insert(Filename) &&
  99. sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing))
  100. Dependencies.push_back(Filename);
  101. }
  102. bool DependencyCollector::sawDependency(StringRef Filename, bool FromModule,
  103. bool IsSystem, bool IsModuleFile,
  104. bool IsMissing) {
  105. return Filename != "<built-in>" && (needSystemDependencies() || !IsSystem);
  106. }
  107. DependencyCollector::~DependencyCollector() { }
  108. void DependencyCollector::attachToPreprocessor(Preprocessor &PP) {
  109. PP.addPPCallbacks(
  110. llvm::make_unique<DepCollectorPPCallbacks>(*this, PP.getSourceManager()));
  111. }
  112. void DependencyCollector::attachToASTReader(ASTReader &R) {
  113. R.addListener(llvm::make_unique<DepCollectorASTListener>(*this));
  114. }
  115. namespace {
  116. /// Private implementation for DependencyFileGenerator
  117. class DFGImpl : public PPCallbacks {
  118. std::vector<std::string> Files;
  119. llvm::StringSet<> FilesSet;
  120. const Preprocessor *PP;
  121. std::string OutputFile;
  122. std::vector<std::string> Targets;
  123. bool IncludeSystemHeaders;
  124. bool PhonyTarget;
  125. bool AddMissingHeaderDeps;
  126. bool SeenMissingHeader;
  127. bool IncludeModuleFiles;
  128. private:
  129. bool FileMatchesDepCriteria(const char *Filename,
  130. SrcMgr::CharacteristicKind FileType);
  131. void OutputDependencyFile();
  132. public:
  133. DFGImpl(const Preprocessor *_PP, const DependencyOutputOptions &Opts)
  134. : PP(_PP), OutputFile(Opts.OutputFile), Targets(Opts.Targets),
  135. IncludeSystemHeaders(Opts.IncludeSystemHeaders),
  136. PhonyTarget(Opts.UsePhonyTargets),
  137. AddMissingHeaderDeps(Opts.AddMissingHeaderDeps),
  138. SeenMissingHeader(false),
  139. IncludeModuleFiles(Opts.IncludeModuleFiles) {}
  140. void FileChanged(SourceLocation Loc, FileChangeReason Reason,
  141. SrcMgr::CharacteristicKind FileType,
  142. FileID PrevFID) override;
  143. void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
  144. StringRef FileName, bool IsAngled,
  145. CharSourceRange FilenameRange, const FileEntry *File,
  146. StringRef SearchPath, StringRef RelativePath,
  147. const Module *Imported) override;
  148. void EndOfMainFile() override {
  149. OutputDependencyFile();
  150. }
  151. void AddFilename(StringRef Filename);
  152. bool includeSystemHeaders() const { return IncludeSystemHeaders; }
  153. bool includeModuleFiles() const { return IncludeModuleFiles; }
  154. };
  155. class DFGASTReaderListener : public ASTReaderListener {
  156. DFGImpl &Parent;
  157. public:
  158. DFGASTReaderListener(DFGImpl &Parent)
  159. : Parent(Parent) { }
  160. bool needsInputFileVisitation() override { return true; }
  161. bool needsSystemInputFileVisitation() override {
  162. return Parent.includeSystemHeaders();
  163. }
  164. void visitModuleFile(StringRef Filename) override;
  165. bool visitInputFile(StringRef Filename, bool isSystem,
  166. bool isOverridden) override;
  167. };
  168. }
  169. DependencyFileGenerator::DependencyFileGenerator(void *Impl)
  170. : Impl(Impl) { }
  171. DependencyFileGenerator *DependencyFileGenerator::CreateAndAttachToPreprocessor(
  172. clang::Preprocessor &PP, const clang::DependencyOutputOptions &Opts) {
  173. if (Opts.Targets.empty()) {
  174. PP.getDiagnostics().Report(diag::err_fe_dependency_file_requires_MT);
  175. return nullptr;
  176. }
  177. // Disable the "file not found" diagnostic if the -MG option was given.
  178. if (Opts.AddMissingHeaderDeps)
  179. PP.SetSuppressIncludeNotFoundError(true);
  180. DFGImpl *Callback = new DFGImpl(&PP, Opts);
  181. PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callback));
  182. return new DependencyFileGenerator(Callback);
  183. }
  184. void DependencyFileGenerator::AttachToASTReader(ASTReader &R) {
  185. DFGImpl *I = reinterpret_cast<DFGImpl *>(Impl);
  186. assert(I && "missing implementation");
  187. R.addListener(llvm::make_unique<DFGASTReaderListener>(*I));
  188. }
  189. /// FileMatchesDepCriteria - Determine whether the given Filename should be
  190. /// considered as a dependency.
  191. bool DFGImpl::FileMatchesDepCriteria(const char *Filename,
  192. SrcMgr::CharacteristicKind FileType) {
  193. if (strcmp("<built-in>", Filename) == 0)
  194. return false;
  195. if (IncludeSystemHeaders)
  196. return true;
  197. return FileType == SrcMgr::C_User;
  198. }
  199. void DFGImpl::FileChanged(SourceLocation Loc,
  200. FileChangeReason Reason,
  201. SrcMgr::CharacteristicKind FileType,
  202. FileID PrevFID) {
  203. if (Reason != PPCallbacks::EnterFile)
  204. return;
  205. // Dependency generation really does want to go all the way to the
  206. // file entry for a source location to find out what is depended on.
  207. // We do not want #line markers to affect dependency generation!
  208. SourceManager &SM = PP->getSourceManager();
  209. const FileEntry *FE =
  210. SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc)));
  211. if (!FE) return;
  212. StringRef Filename = FE->getName();
  213. if (!FileMatchesDepCriteria(Filename.data(), FileType))
  214. return;
  215. // Remove leading "./" (or ".//" or "././" etc.)
  216. while (Filename.size() > 2 && Filename[0] == '.' &&
  217. llvm::sys::path::is_separator(Filename[1])) {
  218. Filename = Filename.substr(1);
  219. while (llvm::sys::path::is_separator(Filename[0]))
  220. Filename = Filename.substr(1);
  221. }
  222. AddFilename(Filename);
  223. }
  224. void DFGImpl::InclusionDirective(SourceLocation HashLoc,
  225. const Token &IncludeTok,
  226. StringRef FileName,
  227. bool IsAngled,
  228. CharSourceRange FilenameRange,
  229. const FileEntry *File,
  230. StringRef SearchPath,
  231. StringRef RelativePath,
  232. const Module *Imported) {
  233. if (!File) {
  234. if (AddMissingHeaderDeps)
  235. AddFilename(FileName);
  236. else
  237. SeenMissingHeader = true;
  238. }
  239. }
  240. void DFGImpl::AddFilename(StringRef Filename) {
  241. if (FilesSet.insert(Filename))
  242. Files.push_back(Filename);
  243. }
  244. /// PrintFilename - GCC escapes spaces, # and $, but apparently not ' or " or
  245. /// other scary characters.
  246. static void PrintFilename(raw_ostream &OS, StringRef Filename) {
  247. for (unsigned i = 0, e = Filename.size(); i != e; ++i) {
  248. if (Filename[i] == ' ' || Filename[i] == '#')
  249. OS << '\\';
  250. else if (Filename[i] == '$') // $ is escaped by $$.
  251. OS << '$';
  252. OS << Filename[i];
  253. }
  254. }
  255. void DFGImpl::OutputDependencyFile() {
  256. if (SeenMissingHeader) {
  257. llvm::sys::fs::remove(OutputFile);
  258. return;
  259. }
  260. std::error_code EC;
  261. llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_Text);
  262. if (EC) {
  263. PP->getDiagnostics().Report(diag::err_fe_error_opening) << OutputFile
  264. << EC.message();
  265. return;
  266. }
  267. // Write out the dependency targets, trying to avoid overly long
  268. // lines when possible. We try our best to emit exactly the same
  269. // dependency file as GCC (4.2), assuming the included files are the
  270. // same.
  271. const unsigned MaxColumns = 75;
  272. unsigned Columns = 0;
  273. for (std::vector<std::string>::iterator
  274. I = Targets.begin(), E = Targets.end(); I != E; ++I) {
  275. unsigned N = I->length();
  276. if (Columns == 0) {
  277. Columns += N;
  278. } else if (Columns + N + 2 > MaxColumns) {
  279. Columns = N + 2;
  280. OS << " \\\n ";
  281. } else {
  282. Columns += N + 1;
  283. OS << ' ';
  284. }
  285. // Targets already quoted as needed.
  286. OS << *I;
  287. }
  288. OS << ':';
  289. Columns += 1;
  290. // Now add each dependency in the order it was seen, but avoiding
  291. // duplicates.
  292. for (std::vector<std::string>::iterator I = Files.begin(),
  293. E = Files.end(); I != E; ++I) {
  294. // Start a new line if this would exceed the column limit. Make
  295. // sure to leave space for a trailing " \" in case we need to
  296. // break the line on the next iteration.
  297. unsigned N = I->length();
  298. if (Columns + (N + 1) + 2 > MaxColumns) {
  299. OS << " \\\n ";
  300. Columns = 2;
  301. }
  302. OS << ' ';
  303. PrintFilename(OS, *I);
  304. Columns += N + 1;
  305. }
  306. OS << '\n';
  307. // Create phony targets if requested.
  308. if (PhonyTarget && !Files.empty()) {
  309. // Skip the first entry, this is always the input file itself.
  310. for (std::vector<std::string>::iterator I = Files.begin() + 1,
  311. E = Files.end(); I != E; ++I) {
  312. OS << '\n';
  313. PrintFilename(OS, *I);
  314. OS << ":\n";
  315. }
  316. }
  317. }
  318. bool DFGASTReaderListener::visitInputFile(llvm::StringRef Filename,
  319. bool IsSystem, bool IsOverridden) {
  320. assert(!IsSystem || needsSystemInputFileVisitation());
  321. if (IsOverridden)
  322. return true;
  323. Parent.AddFilename(Filename);
  324. return true;
  325. }
  326. void DFGASTReaderListener::visitModuleFile(llvm::StringRef Filename) {
  327. if (Parent.includeModuleFiles())
  328. Parent.AddFilename(Filename);
  329. }