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,
66 void EmbedDirective(SourceLocation, StringRef,
bool,
68 const LexEmbedParametersResult &)
override {
69 assert(
File &&
"expected to only be called when the file is found");
71 llvm::sys::path::remove_leading_dotslash(
File->getName());
72 DepCollector.maybeAddDependency(
FileName,
80 bool EmbedFileNotFound(StringRef
FileName)
override {
81 DepCollector.maybeAddDependency(
82 llvm::sys::path::remove_leading_dotslash(
FileName),
92 void InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
94 CharSourceRange FilenameRange,
96 StringRef RelativePath,
const Module *SuggestedModule,
100 DepCollector.maybeAddDependency(
FileName,
false,
108 void HasEmbed(SourceLocation, StringRef,
bool,
113 llvm::sys::path::remove_leading_dotslash(
File->getName());
114 DepCollector.maybeAddDependency(Filename,
121 void HasInclude(SourceLocation Loc, StringRef SpelledFilename,
bool IsAngled,
127 llvm::sys::path::remove_leading_dotslash(
File->getName());
128 DepCollector.maybeAddDependency(Filename,
false,
135 void EndOfMainFile()
override {
136 DepCollector.finishedMainFile(PP.getDiagnostics());
141 DependencyCollector &DepCollector;
142 DepCollectorMMCallbacks(DependencyCollector &DC) : DepCollector(DC) {}
144 void moduleMapFileRead(SourceLocation Loc, FileEntryRef Entry,
145 bool IsSystem)
override {
146 StringRef Filename = Entry.
getName();
147 DepCollector.maybeAddDependency(Filename,
false,
156 DependencyCollector &DepCollector;
157 FileManager &FileMgr;
158 DepCollectorASTListener(DependencyCollector &L, FileManager &FileMgr)
159 : DepCollector(L), FileMgr(FileMgr) {}
160 bool needsInputFileVisitation()
override {
return true; }
161 bool needsSystemInputFileVisitation()
override {
162 return DepCollector.needSystemDependencies();
165 bool DirectlyImported)
override {
166 DepCollector.maybeAddDependency(Filename,
true,
171 bool visitInputFile(StringRef Filename,
bool IsSystem,
172 bool IsOverridden,
bool IsExplicitModule)
override {
173 if (IsOverridden || IsExplicitModule)
178 if (
auto FE = FileMgr.getOptionalFileRef(Filename))
179 Filename = FE->getName();
181 DepCollector.maybeAddDependency(Filename,
true, IsSystem,
191 bool FromModule,
bool IsSystem,
193 bool IsDirectModuleImport,
195 if (
sawDependency(Filename, FromModule, IsSystem, IsModuleFile,
196 IsDirectModuleImport, IsMissing))
201 StringRef SearchPath;
205 llvm::sys::path::native(TmpPath);
206 std::transform(TmpPath.begin(), TmpPath.end(), TmpPath.begin(), ::tolower);
207 SearchPath = TmpPath.str();
209 SearchPath = Filename;
212 if (Seen.insert(SearchPath).second) {
213 Dependencies.push_back(std::string(Filename));
220 return Filename ==
"<built-in>";
224 bool IsSystem,
bool IsModuleFile,
225 bool IsDirectModuleImport,
233 PP.
addPPCallbacks(std::make_unique<DepCollectorPPCallbacks>(*
this, PP));
235 std::make_unique<DepCollectorMMCallbacks>(*
this));
239 std::make_unique<DepCollectorASTListener>(*
this, R.getFileManager()));
244 : OutputFile(Opts.OutputFile), Targets(Opts.Targets),
245 IncludeSystemHeaders(Opts.IncludeSystemHeaders),
246 PhonyTarget(Opts.UsePhonyTargets),
247 AddMissingHeaderDeps(Opts.AddMissingHeaderDeps), SeenMissingHeader(
false),
250 OutputFormat(Opts.OutputFormat), InputFileIndex(0) {
251 for (
const auto &ExtraDep : Opts.
ExtraDeps) {
252 if (addDependency(ExtraDep.first))
259 if (AddMissingHeaderDeps)
266 bool IsSystem,
bool IsModuleFile,
267 bool IsDirectModuleImport,
271 if (AddMissingHeaderDeps)
273 SeenMissingHeader =
true;
279 if (IncludeModuleFiles ==
MFDK_Direct && !IsDirectModuleImport)
286 if (IncludeSystemHeaders)
348 llvm::sys::path::native(Filename.str(), NativePath);
354 if (NativePath.find_first_of(
" #${}^!") != StringRef::npos)
355 OS <<
'\"' << NativePath <<
'\"';
361 for (
unsigned i = 0, e = NativePath.size(); i != e; ++i) {
362 if (NativePath[i] ==
'#')
364 else if (NativePath[i] ==
' ') {
367 while (j > 0 && NativePath[--j] ==
'\\')
369 }
else if (NativePath[i] ==
'$')
376 if (SeenMissingHeader) {
377 llvm::sys::fs::remove(OutputFile);
382 llvm::raw_fd_ostream
OS(OutputFile, EC, llvm::sys::fs::OF_TextWithCRLF);
384 Diags.
Report(diag::err_fe_error_opening) << OutputFile << EC.message();
396 const unsigned MaxColumns = 75;
397 unsigned Columns = 0;
399 for (StringRef
Target : Targets) {
400 unsigned N =
Target.size();
403 }
else if (Columns + N + 2 > MaxColumns) {
420 for (StringRef
File : Files) {
421 if (
File ==
"<stdin>")
426 unsigned N =
File.size();
427 if (Columns + (N + 1) + 2 > MaxColumns) {
438 if (PhonyTarget && !Files.empty()) {
440 for (
auto I = Files.begin(), E = Files.end(); I != E; ++I) {
441 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.
bool addDependency(StringRef Filename)
Return true if the filename was added to the list of dependencies, false otherwise.
virtual void attachToPreprocessor(Preprocessor &PP)
virtual void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsDirectModuleImport, bool IsMissing)
Add a dependency Filename if it has not been seen before and sawDependency() returns true.
ArrayRef< std::string > getDependencies() const
virtual void attachToASTReader(ASTReader &R)
virtual ~DependencyCollector()
virtual bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsDirectModuleImport, bool IsMissing)
Called when a new file is seen.
virtual bool needSystemDependencies()
Return true if system files should be passed to sawDependency().
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 IsDirectModuleImport, 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...
ModuleFileDepsKind
ModuleFileDepsKind - Whether to include module file dependencies.
@ MFDK_Direct
Include only directly imported module file dependencies.
@ MFDK_None
Do not include module file dependencies.
DependencyOutputFormat
DependencyOutputFormat - Format for the compiler dependency file.