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 void InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
80 CharSourceRange FilenameRange,
82 StringRef RelativePath,
const Module *SuggestedModule,
86 DepCollector.maybeAddDependency(
FileName,
false,
93 void HasEmbed(SourceLocation, StringRef,
bool,
98 llvm::sys::path::remove_leading_dotslash(
File->getName());
99 DepCollector.maybeAddDependency(Filename,
105 void HasInclude(SourceLocation Loc, StringRef SpelledFilename,
bool IsAngled,
111 llvm::sys::path::remove_leading_dotslash(
File->getName());
112 DepCollector.maybeAddDependency(Filename,
false,
118 void EndOfMainFile()
override {
119 DepCollector.finishedMainFile(PP.getDiagnostics());
124 DependencyCollector &DepCollector;
125 DepCollectorMMCallbacks(DependencyCollector &DC) : DepCollector(DC) {}
127 void moduleMapFileRead(SourceLocation Loc, FileEntryRef Entry,
128 bool IsSystem)
override {
129 StringRef Filename = Entry.
getName();
130 DepCollector.maybeAddDependency(Filename,
false,
138 DependencyCollector &DepCollector;
139 FileManager &FileMgr;
140 DepCollectorASTListener(DependencyCollector &L, FileManager &FileMgr)
141 : DepCollector(L), FileMgr(FileMgr) {}
142 bool needsInputFileVisitation()
override {
return true; }
143 bool needsSystemInputFileVisitation()
override {
144 return DepCollector.needSystemDependencies();
146 void visitModuleFile(StringRef Filename,
148 DepCollector.maybeAddDependency(Filename,
true,
152 bool visitInputFile(StringRef Filename,
bool IsSystem,
153 bool IsOverridden,
bool IsExplicitModule)
override {
154 if (IsOverridden || IsExplicitModule)
159 if (
auto FE = FileMgr.getOptionalFileRef(Filename))
160 Filename = FE->getName();
162 DepCollector.maybeAddDependency(Filename,
true, IsSystem,
171 bool FromModule,
bool IsSystem,
174 if (
sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing))
179 StringRef SearchPath;
183 llvm::sys::path::native(TmpPath);
184 std::transform(TmpPath.begin(), TmpPath.end(), TmpPath.begin(), ::tolower);
185 SearchPath = TmpPath.str();
187 SearchPath = Filename;
190 if (Seen.insert(SearchPath).second) {
191 Dependencies.push_back(std::string(Filename));
198 return Filename ==
"<built-in>";
202 bool IsSystem,
bool IsModuleFile,
210 PP.
addPPCallbacks(std::make_unique<DepCollectorPPCallbacks>(*
this, PP));
212 std::make_unique<DepCollectorMMCallbacks>(*
this));
216 std::make_unique<DepCollectorASTListener>(*
this, R.
getFileManager()));
221 : OutputFile(Opts.OutputFile), Targets(Opts.Targets),
222 IncludeSystemHeaders(Opts.IncludeSystemHeaders),
223 PhonyTarget(Opts.UsePhonyTargets),
224 AddMissingHeaderDeps(Opts.AddMissingHeaderDeps), SeenMissingHeader(
false),
225 IncludeModuleFiles(Opts.IncludeModuleFiles),
226 OutputFormat(Opts.OutputFormat), InputFileIndex(0) {
227 for (
const auto &ExtraDep : Opts.
ExtraDeps) {
228 if (addDependency(ExtraDep.first))
235 if (AddMissingHeaderDeps)
242 bool IsSystem,
bool IsModuleFile,
246 if (AddMissingHeaderDeps)
248 SeenMissingHeader =
true;
251 if (IsModuleFile && !IncludeModuleFiles)
257 if (IncludeSystemHeaders)
319 llvm::sys::path::native(Filename.str(), NativePath);
325 if (NativePath.find_first_of(
" #${}^!") != StringRef::npos)
326 OS <<
'\"' << NativePath <<
'\"';
332 for (
unsigned i = 0, e = NativePath.size(); i != e; ++i) {
333 if (NativePath[i] ==
'#')
335 else if (NativePath[i] ==
' ') {
338 while (j > 0 && NativePath[--j] ==
'\\')
340 }
else if (NativePath[i] ==
'$')
347 if (SeenMissingHeader) {
348 llvm::sys::fs::remove(OutputFile);
353 llvm::raw_fd_ostream
OS(OutputFile, EC, llvm::sys::fs::OF_TextWithCRLF);
355 Diags.
Report(diag::err_fe_error_opening) << OutputFile << EC.message();
367 const unsigned MaxColumns = 75;
368 unsigned Columns = 0;
370 for (StringRef
Target : Targets) {
371 unsigned N =
Target.size();
374 }
else if (Columns + N + 2 > MaxColumns) {
391 for (StringRef
File : Files) {
392 if (
File ==
"<stdin>")
397 unsigned N =
File.size();
398 if (Columns + (N + 1) + 2 > MaxColumns) {
409 if (PhonyTarget && !Files.empty()) {
411 for (
auto I = Files.begin(), E = Files.end(); I != E; ++I) {
412 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.