clang: lib/Frontend/DependencyFile.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
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#include
28
29using namespace clang;
30
31namespace {
32struct DepCollectorPPCallbacks : public PPCallbacks {
33 DependencyCollector &DepCollector;
34 Preprocessor &PP;
35 DepCollectorPPCallbacks(DependencyCollector &L, Preprocessor &PP)
36 : DepCollector(L), PP(PP) {}
37
38 void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
40 SourceLocation Loc) override {
41 if (Reason != PPCallbacks::LexedFileChangeReason::EnterFile)
42 return;
43
44
45
46
47 if (std::optional Filename =
48 PP.getSourceManager().getNonBuiltinFilenameForID(FID))
49 DepCollector.maybeAddDependency(
50 llvm::sys::path::remove_leading_dotslash(*Filename),
51 false, isSystem(FileType), false,
52 false);
53 }
54
55 void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok,
57 StringRef Filename =
58 llvm::sys::path::remove_leading_dotslash(SkippedFile.getName());
59 DepCollector.maybeAddDependency(Filename, false,
61 false,
62 false);
63 }
64
65 void EmbedDirective(SourceLocation, StringRef, bool,
67 const LexEmbedParametersResult &) override {
68 assert(File && "expected to only be called when the file is found");
70 llvm::sys::path::remove_leading_dotslash(File->getName());
71 DepCollector.maybeAddDependency(FileName,
72 false,
73 false,
74 false,
75 false);
76 }
77
78 bool EmbedFileNotFound(StringRef FileName) override {
79 DepCollector.maybeAddDependency(
80 llvm::sys::path::remove_leading_dotslash(FileName),
81 false,
82 false,
83 false,
84 true);
85
86 return true;
87 }
88
89 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
90 StringRef FileName, bool IsAngled,
91 CharSourceRange FilenameRange,
93 StringRef RelativePath, const Module *SuggestedModule,
94 bool ModuleImported,
97 DepCollector.maybeAddDependency(FileName, false,
98 false,
99 false,
100 true);
101
102 }
103
104 void HasEmbed(SourceLocation, StringRef, bool,
107 return;
108 StringRef Filename =
109 llvm::sys::path::remove_leading_dotslash(File->getName());
110 DepCollector.maybeAddDependency(Filename,
111 false, false,
112 false,
113 false);
114 }
115
116 void HasInclude(SourceLocation Loc, StringRef SpelledFilename, bool IsAngled,
120 return;
121 StringRef Filename =
122 llvm::sys::path::remove_leading_dotslash(File->getName());
123 DepCollector.maybeAddDependency(Filename, false,
125 false,
126 false);
127 }
128
129 void EndOfMainFile() override {
130 DepCollector.finishedMainFile(PP.getDiagnostics());
131 }
132};
133
135 DependencyCollector &DepCollector;
136 DepCollectorMMCallbacks(DependencyCollector &DC) : DepCollector(DC) {}
137
138 void moduleMapFileRead(SourceLocation Loc, FileEntryRef Entry,
139 bool IsSystem) override {
140 StringRef Filename = Entry.getName();
141 DepCollector.maybeAddDependency(Filename, false,
142 IsSystem,
143 false,
144 false);
145 }
146};
147
149 DependencyCollector &DepCollector;
150 FileManager &FileMgr;
151 DepCollectorASTListener(DependencyCollector &L, FileManager &FileMgr)
152 : DepCollector(L), FileMgr(FileMgr) {}
153 bool needsInputFileVisitation() override { return true; }
154 bool needsSystemInputFileVisitation() override {
155 return DepCollector.needSystemDependencies();
156 }
157 void visitModuleFile(StringRef Filename,
159 DepCollector.maybeAddDependency(Filename, true,
160 false, true,
161 false);
162 }
163 bool visitInputFile(StringRef Filename, bool IsSystem,
164 bool IsOverridden, bool IsExplicitModule) override {
165 if (IsOverridden || IsExplicitModule)
166 return true;
167
168
169
170 if (auto FE = FileMgr.getOptionalFileRef(Filename))
171 Filename = FE->getName();
172
173 DepCollector.maybeAddDependency(Filename, true, IsSystem,
174 false,
175 false);
176 return true;
177 }
178};
179}
180
182 bool FromModule, bool IsSystem,
183 bool IsModuleFile,
184 bool IsMissing) {
185 if (sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing))
187}
188
190 StringRef SearchPath;
191#ifdef _WIN32
192
194 llvm::sys::path::native(TmpPath);
195 std::transform(TmpPath.begin(), TmpPath.end(), TmpPath.begin(), ::tolower);
196 SearchPath = TmpPath.str();
197#else
198 SearchPath = Filename;
199#endif
200
201 if (Seen.insert(SearchPath).second) {
202 Dependencies.push_back(std::string(Filename));
203 return true;
204 }
205 return false;
206}
207
209 return Filename == "";
210}
211
213 bool IsSystem, bool IsModuleFile,
214 bool IsMissing) {
217}
218
221 PP.addPPCallbacks(std::make_unique(*this, PP));
223 std::make_unique(*this));
224}
227 std::make_unique(*this, R.getFileManager()));
228}
229
232 : OutputFile(Opts.OutputFile), Targets(Opts.Targets),
233 IncludeSystemHeaders(Opts.IncludeSystemHeaders),
234 PhonyTarget(Opts.UsePhonyTargets),
235 AddMissingHeaderDeps(Opts.AddMissingHeaderDeps), SeenMissingHeader(false),
236 IncludeModuleFiles(Opts.IncludeModuleFiles),
237 OutputFormat(Opts.OutputFormat), InputFileIndex(0) {
238 for (const auto &ExtraDep : Opts.ExtraDeps) {
239 if (addDependency(ExtraDep.first))
240 ++InputFileIndex;
241 }
242}
243
245
246 if (AddMissingHeaderDeps)
248
250}
251
253 bool IsSystem, bool IsModuleFile,
254 bool IsMissing) {
255 if (IsMissing) {
256
257 if (AddMissingHeaderDeps)
258 return true;
259 SeenMissingHeader = true;
260 return false;
261 }
262 if (IsModuleFile && !IncludeModuleFiles)
263 return false;
264
266 return false;
267
268 if (IncludeSystemHeaders)
269 return true;
270
271 return !IsSystem;
272}
273
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326static void PrintFilename(raw_ostream &OS, StringRef Filename,
328
330 llvm::sys::path::native(Filename.str(), NativePath);
331
333
334
335
336 if (NativePath.find_first_of(" #${}^!") != StringRef::npos)
337 OS << '\"' << NativePath << '\"';
338 else
339 OS << NativePath;
340 return;
341 }
343 for (unsigned i = 0, e = NativePath.size(); i != e; ++i) {
344 if (NativePath[i] == '#')
345 OS << '\\';
346 else if (NativePath[i] == ' ') {
347 OS << '\\';
348 unsigned j = i;
349 while (j > 0 && NativePath[--j] == '\\')
350 OS << '\\';
351 } else if (NativePath[i] == '$')
352 OS << '$';
353 OS << NativePath[i];
354 }
355}
356
358 if (SeenMissingHeader) {
359 llvm::sys::fs::remove(OutputFile);
360 return;
361 }
362
363 std::error_code EC;
364 llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_TextWithCRLF);
365 if (EC) {
366 Diags.Report(diag::err_fe_error_opening) << OutputFile << EC.message();
367 return;
368 }
369
371}
372
374
375
376
377
378 const unsigned MaxColumns = 75;
379 unsigned Columns = 0;
380
381 for (StringRef Target : Targets) {
382 unsigned N = Target.size();
383 if (Columns == 0) {
384 Columns += N;
385 } else if (Columns + N + 2 > MaxColumns) {
386 Columns = N + 2;
387 OS << " \\\n ";
388 } else {
389 Columns += N + 1;
390 OS << ' ';
391 }
392
394 }
395
396 OS << ':';
397 Columns += 1;
398
399
400
402 for (StringRef File : Files) {
403 if (File == "")
404 continue;
405
406
407
408 unsigned N = File.size();
409 if (Columns + (N + 1) + 2 > MaxColumns) {
410 OS << " \\\n ";
411 Columns = 2;
412 }
413 OS << ' ';
415 Columns += N + 1;
416 }
417 OS << '\n';
418
419
420 if (PhonyTarget && !Files.empty()) {
421 unsigned Index = 0;
422 for (auto I = Files.begin(), E = Files.end(); I != E; ++I) {
423 if (Index++ == InputFileIndex)
424 continue;
426 OS << ":\n";
427 }
428 }
429}
static void PrintFilename(raw_ostream &OS, StringRef Filename, DependencyOutputFormat OutputFormat)
Print the filename, with escaping or quoting that accommodates the three most likely tools that use d...
Definition DependencyFile.cpp:326
static bool isSpecialFilename(StringRef Filename)
Definition DependencyFile.cpp:208
Defines the clang::FileManager interface and associated types.
llvm::MachO::FileType FileType
Defines the PPCallbacks interface.
Defines the clang::Preprocessor interface.
Defines the SourceManager interface.
Abstract interface for callback invocations by the ASTReader.
Reads an AST files chain containing the contents of a translation unit.
void addListener(std::unique_ptr< ASTReaderListener > L)
Add an AST callback listener.
FileManager & getFileManager() const
virtual void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing)
Add a dependency Filename if it has not been seen before and sawDependency() returns true.
Definition DependencyFile.cpp:181
bool addDependency(StringRef Filename)
Return true if the filename was added to the list of dependencies, false otherwise.
Definition DependencyFile.cpp:189
virtual void attachToPreprocessor(Preprocessor &PP)
Definition DependencyFile.cpp:220
ArrayRef< std::string > getDependencies() const
virtual void attachToASTReader(ASTReader &R)
Definition DependencyFile.cpp:225
virtual ~DependencyCollector()
Definition DependencyFile.cpp:219
virtual bool needSystemDependencies()
Return true if system files should be passed to sawDependency().
virtual bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing)
Called when a new file is seen.
Definition DependencyFile.cpp:212
void outputDependencyFile(llvm::raw_ostream &OS)
Definition DependencyFile.cpp:373
void attachToPreprocessor(Preprocessor &PP) override
Definition DependencyFile.cpp:244
void finishedMainFile(DiagnosticsEngine &Diags) override
Called when the end of the main file is reached.
Definition DependencyFile.cpp:274
bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing) final
Called when a new file is seen.
Definition DependencyFile.cpp:252
DependencyFileGenerator(const DependencyOutputOptions &Opts)
Definition DependencyFile.cpp:230
DependencyOutputOptions - Options for controlling the compiler dependency file generation.
std::vector< std::pair< std::string, ExtraDepKind > > ExtraDeps
A list of extra dependencies (filename and kind) to be used for every target.
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
StringRef getName() const
The name of this FileEntry.
A mechanism to observe the actions of the module map loader as it reads module map files.
void addModuleMapCallbacks(std::unique_ptr< ModuleMapCallbacks > Callback)
Add a module map callback.
This interface provides a way to observe the actions of the preprocessor as it does its thing.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
HeaderSearch & getHeaderSearchInfo() const
void SetSuppressIncludeNotFoundError(bool Suppress)
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
bool isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
ModuleKind
Specifies the kind of module that has been loaded.
The JSON file list parser is used to communicate input to InstallAPI.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
DependencyOutputFormat
DependencyOutputFormat - Format for the compiler dependency file.