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"
32struct DepCollectorPPCallbacks :
public PPCallbacks {
33 DependencyCollector &DepCollector;
35 DepCollectorPPCallbacks(DependencyCollector &L, Preprocessor &PP)
36 : DepCollector(L), PP(PP) {}
38 void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
40 SourceLocation Loc)
override {
41 if (Reason != PPCallbacks::LexedFileChangeReason::EnterFile)
47 if (std::optional<StringRef> Filename =
48 PP.getSourceManager().getNonBuiltinFilenameForID(FID))
49 DepCollector.maybeAddDependency(
50 llvm::sys::path::remove_leading_dotslash(*Filename),
55 void FileSkipped(
const FileEntryRef &SkippedFile,
const Token &FilenameTok,
58 llvm::sys::path::remove_leading_dotslash(SkippedFile.
getName());
59 DepCollector.maybeAddDependency(Filename,
false,
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,
78 bool EmbedFileNotFound(StringRef
FileName)
override {
79 DepCollector.maybeAddDependency(
80 llvm::sys::path::remove_leading_dotslash(
FileName),
89 void InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
91 CharSourceRange FilenameRange,
93 StringRef RelativePath,
const Module *SuggestedModule,
97 DepCollector.maybeAddDependency(
FileName,
false,
104 void HasEmbed(SourceLocation, StringRef,
bool,
109 llvm::sys::path::remove_leading_dotslash(
File->getName());
110 DepCollector.maybeAddDependency(Filename,
116 void HasInclude(SourceLocation Loc, StringRef SpelledFilename,
bool IsAngled,
122 llvm::sys::path::remove_leading_dotslash(
File->getName());
123 DepCollector.maybeAddDependency(Filename,
false,
129 void EndOfMainFile()
override {
130 DepCollector.finishedMainFile(PP.getDiagnostics());
135 DependencyCollector &DepCollector;
136 DepCollectorMMCallbacks(DependencyCollector &DC) : DepCollector(DC) {}
138 void moduleMapFileRead(SourceLocation Loc, FileEntryRef Entry,
139 bool IsSystem)
override {
140 StringRef Filename = Entry.
getName();
141 DepCollector.maybeAddDependency(Filename,
false,
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();
157 void visitModuleFile(StringRef Filename,
159 DepCollector.maybeAddDependency(Filename,
true,
163 bool visitInputFile(StringRef Filename,
bool IsSystem,
164 bool IsOverridden,
bool IsExplicitModule)
override {
165 if (IsOverridden || IsExplicitModule)
170 if (
auto FE = FileMgr.getOptionalFileRef(Filename))
171 Filename = FE->getName();
173 DepCollector.maybeAddDependency(Filename,
true, IsSystem,
182 bool FromModule,
bool IsSystem,
185 if (
sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing))
190 StringRef SearchPath;
194 llvm::sys::path::native(TmpPath);
195 std::transform(TmpPath.begin(), TmpPath.end(), TmpPath.begin(), ::tolower);
196 SearchPath = TmpPath.str();
198 SearchPath = Filename;
201 if (Seen.insert(SearchPath).second) {
202 Dependencies.push_back(std::string(Filename));
209 return Filename ==
"<built-in>";
213 bool IsSystem,
bool IsModuleFile,
221 PP.
addPPCallbacks(std::make_unique<DepCollectorPPCallbacks>(*
this, PP));
223 std::make_unique<DepCollectorMMCallbacks>(*
this));
227 std::make_unique<DepCollectorASTListener>(*
this, R.
getFileManager()));
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))
246 if (AddMissingHeaderDeps)
253 bool IsSystem,
bool IsModuleFile,
257 if (AddMissingHeaderDeps)
259 SeenMissingHeader =
true;
262 if (IsModuleFile && !IncludeModuleFiles)
268 if (IncludeSystemHeaders)
330 llvm::sys::path::native(Filename.str(), NativePath);
336 if (NativePath.find_first_of(
" #${}^!") != StringRef::npos)
337 OS <<
'\"' << NativePath <<
'\"';
343 for (
unsigned i = 0, e = NativePath.size(); i != e; ++i) {
344 if (NativePath[i] ==
'#')
346 else if (NativePath[i] ==
' ') {
349 while (j > 0 && NativePath[--j] ==
'\\')
351 }
else if (NativePath[i] ==
'$')
358 if (SeenMissingHeader) {
359 llvm::sys::fs::remove(OutputFile);
364 llvm::raw_fd_ostream
OS(OutputFile, EC, llvm::sys::fs::OF_TextWithCRLF);
366 Diags.
Report(diag::err_fe_error_opening) << OutputFile << EC.message();
378 const unsigned MaxColumns = 75;
379 unsigned Columns = 0;
381 for (StringRef
Target : Targets) {
382 unsigned N =
Target.size();
385 }
else if (Columns + N + 2 > MaxColumns) {
402 for (StringRef
File : Files) {
403 if (
File ==
"<stdin>")
408 unsigned N =
File.size();
409 if (Columns + (N + 1) + 2 > MaxColumns) {
420 if (PhonyTarget && !Files.empty()) {
422 for (
auto I = Files.begin(), E = Files.end(); I != E; ++I) {
423 if (Index++ == InputFileIndex)
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...
static bool isSpecialFilename(StringRef Filename)
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.
bool addDependency(StringRef Filename)
Return true if the filename was added to the list of dependencies, false otherwise.
virtual void attachToPreprocessor(Preprocessor &PP)
ArrayRef< std::string > getDependencies() const
virtual void attachToASTReader(ASTReader &R)
virtual ~DependencyCollector()
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.
void outputDependencyFile(llvm::raw_ostream &OS)
void attachToPreprocessor(Preprocessor &PP) override
void finishedMainFile(DiagnosticsEngine &Diags) override
Called when the end of the main file is reached.
bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing) final
Called when a new file is seen.
DependencyFileGenerator(const DependencyOutputOptions &Opts)
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.