25 #include "llvm/ADT/StringSet.h" 26 #include "llvm/ADT/StringSwitch.h" 27 #include "llvm/Support/FileSystem.h" 28 #include "llvm/Support/Path.h" 29 #include "llvm/Support/raw_ostream.h" 31 using namespace clang;
34 struct DepCollectorPPCallbacks :
public PPCallbacks {
38 : DepCollector(L), SM(SM) { }
55 llvm::sys::path::remove_leading_dotslash(FE->
getName());
63 StringRef FileName,
bool IsAngled,
65 StringRef SearchPath, StringRef RelativePath,
66 const Module *Imported)
override {
74 void EndOfMainFile()
override {
84 bool IsSystem)
override {
85 StringRef Filename = Entry.
getName();
96 bool needsInputFileVisitation()
override {
return true; }
97 bool needsSystemInputFileVisitation()
override {
100 void visitModuleFile(StringRef Filename,
106 bool visitInputFile(StringRef Filename,
bool IsSystem,
107 bool IsOverridden,
bool IsExplicitModule)
override {
108 if (IsOverridden || IsExplicitModule)
119 bool IsSystem,
bool IsModuleFile,
121 if (Seen.insert(Filename).second &&
122 sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing))
123 Dependencies.push_back(Filename);
127 return llvm::StringSwitch<bool>(
Filename)
128 .Case(
"<built-in>",
true)
129 .Case(
"<stdin>",
true)
134 bool IsSystem,
bool IsModuleFile,
137 (needSystemDependencies() || !IsSystem);
145 llvm::make_unique<DepCollectorMMCallbacks>(*
this));
148 R.
addListener(llvm::make_unique<DepCollectorASTListener>(*
this));
154 std::vector<std::string> Files;
155 llvm::StringSet<> FilesSet;
157 std::string OutputFile;
158 std::vector<std::string> Targets;
159 bool IncludeSystemHeaders;
161 bool AddMissingHeaderDeps;
162 bool SeenMissingHeader;
163 bool IncludeModuleFiles;
167 bool FileMatchesDepCriteria(
const char *Filename,
169 void OutputDependencyFile();
177 SeenMissingHeader(
false),
180 for (
const auto &ExtraDep : Opts.
ExtraDeps) {
181 AddFilename(ExtraDep);
189 StringRef FileName,
bool IsAngled,
191 StringRef SearchPath, StringRef RelativePath,
192 const Module *Imported)
override;
194 void EndOfMainFile()
override {
195 OutputDependencyFile();
198 void AddFilename(StringRef Filename);
199 bool includeSystemHeaders()
const {
return IncludeSystemHeaders; }
200 bool includeModuleFiles()
const {
return IncludeModuleFiles; }
206 DFGMMCallback(DFGImpl &Parent) :
Parent(Parent) {}
208 bool IsSystem)
override {
209 if (!IsSystem || Parent.includeSystemHeaders())
210 Parent.AddFilename(Entry.
getName());
217 DFGASTReaderListener(DFGImpl &Parent)
219 bool needsInputFileVisitation()
override {
return true; }
220 bool needsSystemInputFileVisitation()
override {
221 return Parent.includeSystemHeaders();
223 void visitModuleFile(StringRef Filename,
225 bool visitInputFile(StringRef Filename,
bool isSystem,
226 bool isOverridden,
bool isExplicitModule)
override;
230 DependencyFileGenerator::DependencyFileGenerator(
void *Impl)
245 DFGImpl *Callback =
new DFGImpl(&PP, Opts);
248 llvm::make_unique<DFGMMCallback>(*Callback));
253 DFGImpl *I =
reinterpret_cast<DFGImpl *
>(Impl);
254 assert(I &&
"missing implementation");
255 R.
addListener(llvm::make_unique<DFGASTReaderListener>(*I));
260 bool DFGImpl::FileMatchesDepCriteria(
const char *Filename,
265 if (IncludeSystemHeaders)
272 FileChangeReason Reason,
287 StringRef Filename = FE->
getName();
288 if (!FileMatchesDepCriteria(Filename.data(), FileType))
291 AddFilename(llvm::sys::path::remove_leading_dotslash(Filename));
295 const Token &IncludeTok,
300 StringRef SearchPath,
301 StringRef RelativePath,
304 if (AddMissingHeaderDeps)
305 AddFilename(FileName);
307 SeenMissingHeader =
true;
311 void DFGImpl::AddFilename(StringRef Filename) {
312 if (FilesSet.insert(Filename).second)
313 Files.push_back(Filename);
370 if (Filename.find_first_of(
" #${}^!") != StringRef::npos)
371 OS <<
'\"' << Filename <<
'\"';
377 for (
unsigned i = 0, e = Filename.size(); i != e; ++i) {
378 if (Filename[i] ==
'#')
380 else if (Filename[i] ==
' ') {
383 while (j > 0 && Filename[--j] ==
'\\')
385 }
else if (Filename[i] ==
'$')
391 void DFGImpl::OutputDependencyFile() {
392 if (SeenMissingHeader) {
393 llvm::sys::fs::remove(OutputFile);
398 llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_Text);
400 PP->getDiagnostics().Report(diag::err_fe_error_opening) << OutputFile
409 const unsigned MaxColumns = 75;
410 unsigned Columns = 0;
412 for (StringRef Target : Targets) {
413 unsigned N = Target.size();
416 }
else if (Columns + N + 2 > MaxColumns) {
432 for (StringRef File : Files) {
436 unsigned N = File.size();
437 if (Columns + (N + 1) + 2 > MaxColumns) {
448 if (PhonyTarget && !Files.empty()) {
450 for (
auto I = Files.begin() + 1, E = Files.end(); I != E; ++I) {
458 bool DFGASTReaderListener::visitInputFile(llvm::StringRef Filename,
459 bool IsSystem,
bool IsOverridden,
460 bool IsExplicitModule) {
461 assert(!IsSystem || needsSystemInputFileVisitation());
462 if (IsOverridden || IsExplicitModule)
465 Parent.AddFilename(Filename);
469 void DFGASTReaderListener::visitModuleFile(llvm::StringRef Filename,
471 if (
Parent.includeModuleFiles())
472 Parent.AddFilename(Filename);
Defines the clang::FileManager interface and associated types.
An interface for collecting the dependencies of a compilation.
Defines the SourceManager interface.
unsigned IncludeModuleFiles
Include module file dependencies.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
This interface provides a way to observe the actions of the preprocessor as it does its thing...
unsigned IncludeSystemHeaders
Include system header dependencies.
virtual bool needSystemDependencies()
Return true if system files should be passed to sawDependency().
Token - This structure provides full information about a lexed token.
Describes a module or submodule.
void SetSuppressIncludeNotFoundError(bool Suppress)
virtual void attachToASTReader(ASTReader &R)
HeaderSearch & getHeaderSearchInfo() const
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
void addModuleMapCallbacks(std::unique_ptr< ModuleMapCallbacks > Callback)
Add a module map callback.
Builds a depdenency file when attached to a Preprocessor (for includes) and ASTReader (for module imp...
static DependencyFileGenerator * CreateAndAttachToPreprocessor(Preprocessor &PP, const DependencyOutputOptions &Opts)
ModuleKind
Specifies the kind of module that has been loaded.
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...
static bool isSpecialFilename(StringRef Filename)
Represents a character-granular source range.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
virtual void finishedMainFile()
Called when the end of the main file is reached.
Defines the clang::Preprocessor interface.
A mechanism to observe the actions of the module map parser as it reads module map files...
Record the location of an inclusion directive, such as an #include or #import statement.
SourceManager & getSourceManager() const
void addListener(std::unique_ptr< ASTReaderListener > L)
Add an AST callback listener.
void AttachToASTReader(ASTReader &R)
Encodes a location in the source.
StringRef getName() const
Cached information about one file (either on disk or in the virtual file system). ...
DependencyOutputOptions - Options for controlling the compiler dependency file generation.
std::vector< std::string > ExtraDeps
A list of filenames to be used as extra dependencies for every target.
std::string OutputFile
The file to write dependency output to.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
DependencyOutputFormat OutputFormat
The format for the dependency file.
Dataflow Directional Tag Classes.
Reads an AST files chain containing the contents of a translation unit.
unsigned UsePhonyTargets
Include phony targets for each dependency, which can avoid some 'make' problems.
virtual ~DependencyCollector()
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
Abstract interface for callback invocations by the ASTReader.
virtual void attachToPreprocessor(Preprocessor &PP)
Defines the PPCallbacks interface.
DiagnosticsEngine & getDiagnostics() const
std::vector< std::string > Targets
A list of names to use as the targets in the dependency file; this list must contain at least one ent...
unsigned AddMissingHeaderDeps
Add missing headers to dependency list.
virtual bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing)
Called when a new file is seen.
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...
DependencyOutputFormat
DependencyOutputFormat - Format for the compiler dependency file.
bool isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
This class handles loading and caching of source files into memory.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.