clang 23.0.0git
ModuleDepCollector.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_CLANG_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H
10#define LLVM_CLANG_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H
11
12#include "clang/Basic/LLVM.h"
13#include "clang/Basic/Module.h"
21#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/Hashing.h"
23#include "llvm/ADT/StringSet.h"
24#include "llvm/Support/raw_ostream.h"
25#include <optional>
26#include <string>
27#include <unordered_map>
28#include <variant>
29
30namespace clang {
31namespace dependencies {
32
36
37/// Modular dependency that has already been built prior to the dependency scan.
39 std::string ModuleName;
40 std::string PCMFile;
41 std::string ModuleMapFile;
42
43 explicit PrebuiltModuleDep(const Module *M)
44 : ModuleName(M->getTopLevelModuleName()),
45 PCMFile(M->getASTFileName()->str()),
46 ModuleMapFile(M->PresumedModuleMapFile) {}
47};
48
49/// Attributes loaded from AST files of prebuilt modules collected prior to
50/// ModuleDepCollector creation.
51using PrebuiltModulesAttrsMap = llvm::StringMap<PrebuiltModuleASTAttrs>;
53public:
54 /// When a module is discovered to not be in stable directories, traverse &
55 /// update all modules that depend on it.
56 void
58
59 /// Read-only access to whether the module is made up of dependencies in
60 /// stable directories.
61 bool isInStableDir() const { return IsInStableDirs; }
62
63 /// Read-only access to vfs map files.
64 const llvm::StringSet<> &getVFS() const { return VFSMap; }
65
66 /// Update the VFSMap to the one discovered from serializing the AST file.
67 void setVFS(llvm::StringSet<> &&VFS) { VFSMap = std::move(VFS); }
68
69 /// Add a direct dependent module file, so it can be updated if the current
70 /// module is from stable directores.
71 void addDependent(StringRef ModuleFile) {
72 ModuleFileDependents.insert(ModuleFile);
73 }
74
75 /// Update whether the prebuilt module resolves entirely in a stable
76 /// directories.
77 void setInStableDir(bool V = false) {
78 // Cannot reset attribute once it's false.
79 if (!IsInStableDirs)
80 return;
81 IsInStableDirs = V;
82 }
83
84private:
85 llvm::StringSet<> VFSMap;
86 bool IsInStableDirs = true;
87 std::set<StringRef> ModuleFileDependents;
88};
89
90/// This is used to identify a specific module.
91struct ModuleID {
92 /// The name of the module. This may include `:` for C++20 module partitions,
93 /// or a header-name for C++20 header units.
94 std::string ModuleName;
95
96 /// The context hash of a module represents the compiler options that affect
97 /// the resulting command-line invocation.
98 ///
99 /// Modules with the same name and ContextHash but different invocations could
100 /// cause non-deterministic build results.
101 ///
102 /// Modules with the same name but a different \c ContextHash should be
103 /// treated as separate modules for the purpose of a build.
104 std::string ContextHash;
105
106 bool operator==(const ModuleID &Other) const {
107 return std::tie(ModuleName, ContextHash) ==
108 std::tie(Other.ModuleName, Other.ContextHash);
109 }
110
111 bool operator<(const ModuleID &Other) const {
112 return std::tie(ModuleName, ContextHash) <
113 std::tie(Other.ModuleName, Other.ContextHash);
114 }
115};
116
117/// P1689ModuleInfo - Represents the needed information of standard C++20
118/// modules for P1689 format.
120 /// The name of the module. This may include `:` for partitions.
121 std::string ModuleName;
122
123 /// Optional. The source path to the module.
124 std::string SourcePath;
125
126 /// If this module is a standard c++ interface unit.
128
129 enum class ModuleType {
131 // To be supported
132 // AngleHeaderUnit,
133 // QuoteHeaderUnit
134 };
136};
137
138/// An output from a module compilation, such as the path of the module file.
140 /// The module file (.pcm). Required.
142 /// The path of the dependency file (.d), if any.
144 /// The null-separated list of names to use as the targets in the dependency
145 /// file, if any. Defaults to the value of \c ModuleFile, as in the driver.
147 /// The path of the serialized diagnostic file (.dia), if any.
149};
150
152 /// The identifier of the module.
154
155 /// Whether this is a "system" module.
157
158 /// Whether this module is fully composed of file & module inputs from
159 /// locations likely to stay the same across the active development and build
160 /// cycle. For example, when all those input paths only resolve in Sysroot.
161 ///
162 /// External paths, as opposed to virtual file paths, are always used
163 /// for computing this value.
165
166 /// Whether current working directory is ignored.
168
169 /// The path to the modulemap file which defines this module.
170 ///
171 /// This can be used to explicitly build this module. This file will
172 /// additionally appear in \c FileDeps as a dependency.
174
175 /// A collection of absolute paths to module map files that this module needs
176 /// to know about. The ordering is significant.
177 std::vector<std::string> ModuleMapFileDeps;
178
179 /// A collection of prebuilt modular dependencies this module directly depends
180 /// on, not including transitive dependencies.
181 std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
182
183 /// A list of module identifiers this module directly depends on, not
184 /// including transitive dependencies.
185 ///
186 /// This may include modules with a different context hash when it can be
187 /// determined that the differences are benign for this compilation.
188 std::vector<ModuleID> ClangModuleDeps;
189
190 /// The set of libraries or frameworks to link against when
191 /// an entity from this module is used.
193
194 /// Invokes \c Cb for all file dependencies of this module. Each provided
195 /// \c StringRef is only valid within the individual callback invocation.
196 void forEachFileDep(llvm::function_ref<void(StringRef)> Cb) const;
197
198 /// Get (or compute) the compiler invocation that can be used to build this
199 /// module. Does not include argv[0].
200 const std::vector<std::string> &getBuildArguments() const;
201
202private:
203 friend class ModuleDepCollector;
205
206 /// The absolute directory path that is the base for relative paths
207 /// in \c FileDeps.
208 std::string FileDepsBaseDir;
209
210 /// A collection of paths to files that this module directly depends on, not
211 /// including transitive dependencies.
212 std::vector<std::string> FileDeps;
213
214 mutable std::variant<std::monostate, CowCompilerInvocation,
215 std::vector<std::string>>
216 BuildInfo;
217};
218
220
221/// Callback that records textual includes and direct modular includes/imports
222/// during preprocessing. At the end of the main file, it also collects
223/// transitive modular dependencies and passes everything to the
224/// \c DependencyConsumer of the parent \c ModuleDepCollector.
225class ModuleDepCollectorPP final : public PPCallbacks {
226public:
228
231 SourceLocation Loc) override;
232 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
233 StringRef FileName, bool IsAngled,
234 CharSourceRange FilenameRange,
235 OptionalFileEntryRef File, StringRef SearchPath,
236 StringRef RelativePath, const Module *SuggestedModule,
237 bool ModuleImported,
239 void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
240 const Module *Imported) override;
241
242 void EndOfMainFile() override;
243
244private:
245 /// The parent dependency collector.
247
248 void handleImport(const Module *Imported);
249
250 /// Adds direct modular dependencies that have already been built to the
251 /// ModuleDeps instance.
252 void
253 addAllSubmodulePrebuiltDeps(const Module *M, ModuleDeps &MD,
254 llvm::DenseSet<const Module *> &SeenSubmodules);
255 void addModulePrebuiltDeps(const Module *M, ModuleDeps &MD,
256 llvm::DenseSet<const Module *> &SeenSubmodules);
257
258 /// Traverses the previously collected direct modular dependencies to discover
259 /// transitive modular dependencies and fills the parent \c ModuleDepCollector
260 /// with both.
261 /// Returns the ID or nothing if the dependency is spurious and is ignored.
262 std::optional<ModuleID> handleTopLevelModule(const Module *M);
263 void addAllSubmoduleDeps(const Module *M, ModuleDeps &MD,
264 llvm::DenseSet<const Module *> &AddedModules);
265 void addModuleDep(const Module *M, ModuleDeps &MD,
266 llvm::DenseSet<const Module *> &AddedModules);
267
268 /// Traverses the affecting modules and updates \c MD with references to the
269 /// parent \c ModuleDepCollector info.
270 void
271 addAllAffectingClangModules(const Module *M, ModuleDeps &MD,
272 llvm::DenseSet<const Module *> &AddedModules);
273 void addAffectingClangModule(const Module *M, ModuleDeps &MD,
274 llvm::DenseSet<const Module *> &AddedModules);
275
276 /// Add discovered module dependency for the given module.
277 void addOneModuleDep(const Module *M, const ModuleID ID, ModuleDeps &MD);
278};
279
280/// Collects modular and non-modular dependencies of the main file by attaching
281/// \c ModuleDepCollectorPP to the preprocessor.
283public:
285 std::unique_ptr<DependencyOutputOptions> Opts,
286 CompilerInstance &ScanInstance, DependencyConsumer &C,
287 DependencyActionController &Controller,
288 CompilerInvocation OriginalCI,
289 const PrebuiltModulesAttrsMap PrebuiltModulesASTMap,
290 const ArrayRef<StringRef> StableDirs);
291
292 void attachToPreprocessor(Preprocessor &PP) override;
293 void attachToASTReader(ASTReader &R) override;
294
295 PPCallbacks *getPPCallbacks() { return CollectorPPPtr; }
296
297 /// Apply any changes implied by the discovered dependencies to the given
298 /// invocation, (e.g. disable implicit modules, add explicit module paths).
300
301private:
303
304 /// The parent dependency scanning service.
306 /// The compiler instance for scanning the current translation unit.
307 CompilerInstance &ScanInstance;
308 /// The consumer of collected dependency information.
309 DependencyConsumer &Consumer;
310 /// Callbacks for computing dependency information.
311 DependencyActionController &Controller;
312 /// Mapping from prebuilt AST filepaths to their attributes referenced during
313 /// dependency collecting.
314 const PrebuiltModulesAttrsMap PrebuiltModulesASTMap;
315 /// Directory paths known to be stable through an active development and build
316 /// cycle.
317 const ArrayRef<StringRef> StableDirs;
318 /// Path to the main source file.
319 std::string MainFile;
320 /// Non-modular file dependencies. This includes the main source file and
321 /// textually included header files.
322 std::vector<std::string> FileDeps;
323 /// Direct and transitive modular dependencies of the main source file.
324 llvm::MapVector<const Module *, std::unique_ptr<ModuleDeps>> ModularDeps;
325 /// Secondary mapping for \c ModularDeps allowing lookup by ModuleID without
326 /// a preprocessor. Storage owned by \c ModularDeps.
327 llvm::DenseMap<ModuleID, ModuleDeps *> ModuleDepsByID;
328 /// Direct modular dependencies that have already been built.
329 llvm::MapVector<const Module *, PrebuiltModuleDep> DirectPrebuiltModularDeps;
330 /// Working set of direct modular dependencies.
331 llvm::SetVector<const Module *> DirectModularDeps;
332 /// Working set of direct modular dependencies, as they were imported.
334 /// All direct and transitive visible modules.
335 llvm::StringSet<> VisibleModules;
336
337 /// Options that control the dependency output generation.
338 std::unique_ptr<DependencyOutputOptions> Opts;
339 /// A Clang invocation that's based on the original TU invocation and that has
340 /// been partially transformed into one that can perform explicit build of
341 /// a discovered modular dependency. Note that this still needs to be adjusted
342 /// for each individual module.
343 CowCompilerInvocation CommonInvocation;
344
345 std::optional<P1689ModuleInfo> ProvidedStdCXXModule;
346 std::vector<P1689ModuleInfo> RequiredStdCXXModules;
347
348 /// A pointer to the preprocessor callback so we can invoke it directly
349 /// if needed. The callback is created and added to a Preprocessor instance by
350 /// attachToPreprocessor and the Preprocessor instance owns it.
351 ModuleDepCollectorPP *CollectorPPPtr = nullptr;
352
353 /// Checks whether the module is known as being prebuilt.
354 bool isPrebuiltModule(const Module *M);
355
356 /// Computes all visible modules resolved from direct imports.
357 void addVisibleModules();
358
359 /// Adds \p Path to \c FileDeps, making it absolute if necessary.
360 void addFileDep(StringRef Path);
361 /// Adds \p Path to \c MD.FileDeps, making it absolute if necessary.
362 void addFileDep(ModuleDeps &MD, StringRef Path);
363
364 /// Get a Clang invocation adjusted to build the given modular dependency.
365 /// This excludes paths that are yet-to-be-provided by the build system.
366 CowCompilerInvocation getInvocationAdjustedForModuleBuildWithoutOutputs(
367 const ModuleDeps &Deps,
368 llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const;
369
370 /// Collect module map files for given modules.
371 llvm::DenseSet<const FileEntry *>
372 collectModuleMapFiles(ArrayRef<ModuleID> ClangModuleDeps) const;
373
374 /// Add module map files to the invocation, if needed.
375 void addModuleMapFiles(CompilerInvocation &CI,
376 ArrayRef<ModuleID> ClangModuleDeps) const;
377 /// Add module files (pcm) to the invocation, if needed.
378 void addModuleFiles(CompilerInvocation &CI,
379 ArrayRef<ModuleID> ClangModuleDeps) const;
380 void addModuleFiles(CowCompilerInvocation &CI,
381 ArrayRef<ModuleID> ClangModuleDeps) const;
382
383 /// Add paths that require looking up outputs to the given dependencies.
384 void addOutputPaths(CowCompilerInvocation &CI, ModuleDeps &Deps);
385
386 /// Compute the context hash for \p Deps, and create the mapping
387 /// \c ModuleDepsByID[Deps.ID] = &Deps.
388 void associateWithContextHash(const CowCompilerInvocation &CI,
389 ModuleDeps &Deps);
390};
391
392/// Resets codegen options that don't affect modules/PCH.
394 const LangOptions &LangOpts,
395 CodeGenOptions &CGOpts);
396
397/// Determine if \c Input can be resolved within a stable directory.
398///
399/// \param Directories Paths known to be in a stable location. e.g. Sysroot.
400/// \param Input Path to evaluate.
401bool isPathInStableDir(const ArrayRef<StringRef> Directories,
402 const StringRef Input);
403
404/// Determine if options collected from a module's
405/// compilation can safely be considered as stable.
406///
407/// \param Directories Paths known to be in a stable location. e.g. Sysroot.
408/// \param HSOpts Header search options derived from the compiler invocation.
409bool areOptionsInStableDir(const ArrayRef<StringRef> Directories,
410 const HeaderSearchOptions &HSOpts);
411
412} // end namespace dependencies
413} // end namespace clang
414
415namespace llvm {
416inline hash_code hash_value(const clang::dependencies::ModuleID &ID) {
417 return hash_combine(ID.ModuleName, ID.ContextHash);
418}
419
420template <> struct DenseMapInfo<clang::dependencies::ModuleID> {
422 static inline ModuleID getEmptyKey() { return ModuleID{"", ""}; }
423 static inline ModuleID getTombstoneKey() {
424 return ModuleID{"~", "~"}; // ~ is not a valid module name or context hash
425 }
426 static unsigned getHashValue(const ModuleID &ID) { return hash_value(ID); }
427 static bool isEqual(const ModuleID &LHS, const ModuleID &RHS) {
428 return LHS == RHS;
429 }
430};
431} // namespace llvm
432
433#endif // LLVM_CLANG_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H
#define V(N, I)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::MachO::FileType FileType
Definition MachO.h:46
Defines the clang::Module class, which describes a module in the source code.
Defines the PPCallbacks interface.
Defines the SourceManager interface.
Reads an AST files chain containing the contents of a translation unit.
Definition ASTReader.h:427
Represents a byte-granular source range.
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Helper class for holding the data necessary to invoke the compiler.
Same as CompilerInvocation, but with copy-on-write optimization.
An interface for collecting the dependencies of a compilation.
Definition Utils.h:63
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
HeaderSearchOptions - Helper class for storing options related to the initialization of the HeaderSea...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Describes a module or submodule.
Definition Module.h:251
This interface provides a way to observe the actions of the preprocessor as it does its thing.
Definition PPCallbacks.h:37
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Encodes a location in the source.
Token - This structure provides full information about a lexed token.
Definition Token.h:36
Dependency scanner callbacks that are used during scanning to influence the behaviour of the scan - f...
The dependency scanning service contains shared configuration and state that is used by the individua...
Callback that records textual includes and direct modular includes/imports during preprocessing.
void EndOfMainFile() override
Callback invoked when the end of the main file is reached.
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, bool ModuleImported, SrcMgr::CharacteristicKind FileType) override
Callback invoked whenever an inclusion directive of any kind (#include, #import, etc....
void LexedFileChanged(FileID FID, LexedFileChangeReason Reason, SrcMgr::CharacteristicKind FileType, FileID PrevFID, SourceLocation Loc) override
Callback invoked whenever the Lexer moves to a different file for lexing.
void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path, const Module *Imported) override
Callback invoked whenever there was an explicit module-import syntax.
Collects modular and non-modular dependencies of the main file by attaching ModuleDepCollectorPP to t...
ModuleDepCollector(DependencyScanningService &Service, std::unique_ptr< DependencyOutputOptions > Opts, CompilerInstance &ScanInstance, DependencyConsumer &C, DependencyActionController &Controller, CompilerInvocation OriginalCI, const PrebuiltModulesAttrsMap PrebuiltModulesASTMap, const ArrayRef< StringRef > StableDirs)
void applyDiscoveredDependencies(CompilerInvocation &CI)
Apply any changes implied by the discovered dependencies to the given invocation, (e....
void attachToPreprocessor(Preprocessor &PP) override
void attachToASTReader(ASTReader &R) override
void updateDependentsNotInStableDirs(PrebuiltModulesAttrsMap &PrebuiltModulesMap)
When a module is discovered to not be in stable directories, traverse & update all modules that depen...
void setVFS(llvm::StringSet<> &&VFS)
Update the VFSMap to the one discovered from serializing the AST file.
bool isInStableDir() const
Read-only access to whether the module is made up of dependencies in stable directories.
void addDependent(StringRef ModuleFile)
Add a direct dependent module file, so it can be updated if the current module is from stable directo...
void setInStableDir(bool V=false)
Update whether the prebuilt module resolves entirely in a stable directories.
const llvm::StringSet & getVFS() const
Read-only access to vfs map files.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
bool areOptionsInStableDir(const ArrayRef< StringRef > Directories, const HeaderSearchOptions &HSOpts)
Determine if options collected from a module's compilation can safely be considered as stable.
@ VFS
Remove unused -ivfsoverlay arguments.
ModuleOutputKind
An output from a module compilation, such as the path of the module file.
@ DiagnosticSerializationFile
The path of the serialized diagnostic file (.dia), if any.
@ DependencyFile
The path of the dependency file (.d), if any.
@ DependencyTargets
The null-separated list of names to use as the targets in the dependency file, if any.
@ ModuleFile
The module file (.pcm). Required.
llvm::StringMap< PrebuiltModuleASTAttrs > PrebuiltModulesAttrsMap
Attributes loaded from AST files of prebuilt modules collected prior to ModuleDepCollector creation.
bool isPathInStableDir(const ArrayRef< StringRef > Directories, const StringRef Input)
Determine if Input can be resolved within a stable directory.
void resetBenignCodeGenOptions(frontend::ActionKind ProgramAction, const LangOptions &LangOpts, CodeGenOptions &CGOpts)
Resets codegen options that don't affect modules/PCH.
The JSON file list parser is used to communicate input to InstallAPI.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
Definition FileEntry.h:208
ArrayRef< IdentifierLoc > ModuleIdPath
A sequence of identifier/location pairs used to describe a particular module or submodule,...
@ Other
Other implicit parameter.
Definition Decl.h:1761
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
hash_code hash_value(const clang::dependencies::ModuleID &ID)
std::vector< std::string > ModuleMapFileDeps
A collection of absolute paths to module map files that this module needs to know about.
bool IsInStableDirectories
Whether this module is fully composed of file & module inputs from locations likely to stay the same ...
ModuleID ID
The identifier of the module.
bool IgnoreCWD
Whether current working directory is ignored.
void forEachFileDep(llvm::function_ref< void(StringRef)> Cb) const
Invokes Cb for all file dependencies of this module.
std::vector< PrebuiltModuleDep > PrebuiltModuleDeps
A collection of prebuilt modular dependencies this module directly depends on, not including transiti...
llvm::SmallVector< Module::LinkLibrary, 2 > LinkLibraries
The set of libraries or frameworks to link against when an entity from this module is used.
std::vector< ModuleID > ClangModuleDeps
A list of module identifiers this module directly depends on, not including transitive dependencies.
const std::vector< std::string > & getBuildArguments() const
Get (or compute) the compiler invocation that can be used to build this module.
std::string ClangModuleMapFile
The path to the modulemap file which defines this module.
bool IsSystem
Whether this is a "system" module.
This is used to identify a specific module.
bool operator==(const ModuleID &Other) const
std::string ModuleName
The name of the module.
std::string ContextHash
The context hash of a module represents the compiler options that affect the resulting command-line i...
bool operator<(const ModuleID &Other) const
P1689ModuleInfo - Represents the needed information of standard C++20 modules for P1689 format.
std::string SourcePath
Optional. The source path to the module.
bool IsStdCXXModuleInterface
If this module is a standard c++ interface unit.
std::string ModuleName
The name of the module. This may include : for partitions.
static bool isEqual(const ModuleID &LHS, const ModuleID &RHS)