Skip to content

Commit f978ea4

Browse files
committed
[clang][clang-scan-deps] Aggregate the full dependency information.
Differential Revision: https://reviews.llvm.org/D70268
1 parent f38b543 commit f978ea4

File tree

8 files changed

+648
-155
lines changed

8 files changed

+648
-155
lines changed

clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,69 @@
1111

1212
#include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
1313
#include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
14+
#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
1415
#include "clang/Tooling/JSONCompilationDatabase.h"
16+
#include "llvm/ADT/StringSet.h"
1517
#include <string>
1618

1719
namespace clang{
1820
namespace tooling{
1921
namespace dependencies{
2022

23+
/// The full dependencies and module graph for a specific input.
24+
struct FullDependencies {
25+
/// The name of the C++20 module this translation unit exports. This may
26+
/// include `:` for C++20 module partitons.
27+
///
28+
/// If the translation unit is not a module then this will be empty.
29+
std::string ExportedModuleName;
30+
31+
/// The context hash represents the set of compiler options that may make one
32+
/// version of a module incompatible with another. This includes things like
33+
/// language mode, predefined macros, header search paths, etc...
34+
///
35+
/// Modules with the same name but a different \c ContextHash should be
36+
/// treated as separate modules for the purpose of a build.
37+
std::string ContextHash;
38+
39+
/// A collection of absolute paths to files that this translation unit
40+
/// directly depends on, not including transitive dependencies.
41+
std::vector<std::string> FileDeps;
42+
43+
/// A list of modules this translation unit directly depends on, not including
44+
/// transitive dependencies.
45+
///
46+
/// This may include modules with a different context hash when it can be
47+
/// determined that the differences are benign for this compilation.
48+
std::vector<ClangModuleDep> ClangModuleDeps;
49+
50+
/// A partial addtional set of command line arguments that can be used to
51+
/// build this translation unit.
52+
///
53+
/// Call \c getFullAdditionalCommandLine() to get a command line suitable for
54+
/// appending to the original command line to pass to clang.
55+
std::vector<std::string> AdditionalNonPathCommandLine;
56+
57+
/// Gets the full addtional command line suitable for appending to the
58+
/// original command line to pass to clang.
59+
///
60+
/// \param LookupPCMPath this function is called to fill in `-fmodule-file=`
61+
/// flags and for the `-o` flag. It needs to return a
62+
/// path for where the PCM for the given module is to
63+
/// be located.
64+
/// \param LookupModuleDeps this fucntion is called to collect the full
65+
/// transitive set of dependencies for this
66+
/// compilation.
67+
std::vector<std::string> getAdditionalCommandLine(
68+
std::function<StringRef(ClangModuleDep)> LookupPCMPath,
69+
std::function<const ModuleDeps &(ClangModuleDep)> LookupModuleDeps) const;
70+
};
71+
72+
struct FullDependenciesResult {
73+
FullDependencies FullDeps;
74+
std::vector<ModuleDeps> DiscoveredModules;
75+
};
76+
2177
/// The high-level implementation of the dependency discovery tool that runs on
2278
/// an individual worker thread.
2379
class DependencyScanningTool {
@@ -35,8 +91,23 @@ class DependencyScanningTool {
3591
getDependencyFile(const tooling::CompilationDatabase &Compilations,
3692
StringRef CWD);
3793

94+
/// Collect the full module depenedency graph for the input, ignoring any
95+
/// modules which have already been seen.
96+
///
97+
/// \param AlreadySeen this is used to not report modules that have previously
98+
/// been reported. Use the same `llvm::StringSet<>` for all
99+
/// calls to `getFullDependencies` for a single
100+
/// `DependencyScanningTool` for a single build. Use a
101+
/// different one for different tools, and clear it between
102+
/// builds.
103+
///
104+
/// \returns a \c StringError with the diagnostic output if clang errors
105+
/// occurred, \c FullDependencies otherwise.
106+
llvm::Expected<FullDependenciesResult>
107+
getFullDependencies(const tooling::CompilationDatabase &Compilations,
108+
StringRef CWD, const llvm::StringSet<> &AlreadySeen);
109+
38110
private:
39-
const ScanningOutputFormat Format;
40111
DependencyScanningWorker Worker;
41112
};
42113

clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,82 @@ namespace dependencies {
2828

2929
class DependencyConsumer;
3030

31+
/// This is used to refer to a specific module.
32+
///
33+
/// See \c ModuleDeps for details about what these members mean.
34+
struct ClangModuleDep {
35+
std::string ModuleName;
36+
std::string ContextHash;
37+
};
38+
3139
struct ModuleDeps {
40+
/// The name of the module. This may include `:` for C++20 module partitons,
41+
/// or a header-name for C++20 header units.
3242
std::string ModuleName;
33-
std::string ClangModuleMapFile;
34-
std::string ModulePCMPath;
43+
44+
/// The context hash of a module represents the set of compiler options that
45+
/// may make one version of a module incompatible with another. This includes
46+
/// things like language mode, predefined macros, header search paths, etc...
47+
///
48+
/// Modules with the same name but a different \c ContextHash should be
49+
/// treated as separate modules for the purpose of a build.
3550
std::string ContextHash;
51+
52+
/// The path to the modulemap file which defines this module.
53+
///
54+
/// This can be used to explicitly build this module. This file will
55+
/// additionally appear in \c FileDeps as a dependency.
56+
std::string ClangModuleMapFile;
57+
58+
/// The path to where an implicit build would put the PCM for this module.
59+
std::string ImplicitModulePCMPath;
60+
61+
/// A collection of absolute paths to files that this module directly depends
62+
/// on, not including transitive dependencies.
3663
llvm::StringSet<> FileDeps;
37-
llvm::StringSet<> ClangModuleDeps;
64+
65+
/// A list of modules this module directly depends on, not including
66+
/// transitive dependencies.
67+
///
68+
/// This may include modules with a different context hash when it can be
69+
/// determined that the differences are benign for this compilation.
70+
std::vector<ClangModuleDep> ClangModuleDeps;
71+
72+
/// A partial command line that can be used to build this module.
73+
///
74+
/// Call \c getFullCommandLine() to get a command line suitable for passing to
75+
/// clang.
76+
std::vector<std::string> NonPathCommandLine;
77+
78+
// Used to track which modules that were discovered were directly imported by
79+
// the primary TU.
3880
bool ImportedByMainFile = false;
81+
82+
/// Gets the full command line suitable for passing to clang.
83+
///
84+
/// \param LookupPCMPath this function is called to fill in `-fmodule-file=`
85+
/// flags and for the `-o` flag. It needs to return a
86+
/// path for where the PCM for the given module is to
87+
/// be located.
88+
/// \param LookupModuleDeps this fucntion is called to collect the full
89+
/// transitive set of dependencies for this
90+
/// compilation.
91+
std::vector<std::string> getFullCommandLine(
92+
std::function<StringRef(ClangModuleDep)> LookupPCMPath,
93+
std::function<const ModuleDeps &(ClangModuleDep)> LookupModuleDeps) const;
3994
};
4095

96+
namespace detail {
97+
/// Append the `-fmodule-file=` and `-fmodule-map-file=` arguments for the
98+
/// modules in \c Modules transitively, along with other needed arguments to
99+
/// use explicitly built modules.
100+
void appendCommonModuleArguments(
101+
llvm::ArrayRef<ClangModuleDep> Modules,
102+
std::function<StringRef(ClangModuleDep)> LookupPCMPath,
103+
std::function<const ModuleDeps &(ClangModuleDep)> LookupModuleDeps,
104+
std::vector<std::string> &Result);
105+
} // namespace detail
106+
41107
class ModuleDepCollector;
42108

43109
class ModuleDepCollectorPP final : public PPCallbacks {
@@ -54,6 +120,8 @@ class ModuleDepCollectorPP final : public PPCallbacks {
54120
StringRef SearchPath, StringRef RelativePath,
55121
const Module *Imported,
56122
SrcMgr::CharacteristicKind FileType) override;
123+
void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
124+
const Module *Imported) override;
57125

58126
void EndOfMainFile() override;
59127

@@ -62,16 +130,18 @@ class ModuleDepCollectorPP final : public PPCallbacks {
62130
ModuleDepCollector &MDC;
63131
llvm::DenseSet<const Module *> DirectDeps;
64132

133+
void handleImport(const Module *Imported);
65134
void handleTopLevelModule(const Module *M);
66-
void addAllSubmoduleDeps(const Module *M, ModuleDeps &MD);
67-
void addModuleDep(const Module *M, ModuleDeps &MD);
68-
69-
void addDirectDependencies(const Module *Mod);
135+
void addAllSubmoduleDeps(const Module *M, ModuleDeps &MD,
136+
llvm::DenseSet<const Module *> &AddedModules);
137+
void addModuleDep(const Module *M, ModuleDeps &MD,
138+
llvm::DenseSet<const Module *> &AddedModules);
70139
};
71140

72141
class ModuleDepCollector final : public DependencyCollector {
73142
public:
74-
ModuleDepCollector(CompilerInstance &I, DependencyConsumer &C);
143+
ModuleDepCollector(std::unique_ptr<DependencyOutputOptions> Opts,
144+
CompilerInstance &I, DependencyConsumer &C);
75145

76146
void attachToPreprocessor(Preprocessor &PP) override;
77147
void attachToASTReader(ASTReader &R) override;
@@ -85,6 +155,7 @@ class ModuleDepCollector final : public DependencyCollector {
85155
std::string ContextHash;
86156
std::vector<std::string> MainDeps;
87157
std::unordered_map<std::string, ModuleDeps> Deps;
158+
std::unique_ptr<DependencyOutputOptions> Opts;
88159
};
89160

90161
} // end namespace dependencies

0 commit comments

Comments
 (0)