clang 23.0.0git
ModulesDriver.cpp
Go to the documentation of this file.
1//===--- ModulesDriver.cpp - Driver managed module builds -----------------===//
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/// \file
10/// This file defines functionality to support driver managed builds for
11/// compilations which use Clang modules or standard C++20 named modules.
12///
13//===----------------------------------------------------------------------===//
14
17#include "clang/Basic/LLVM.h"
19#include "clang/Driver/Driver.h"
20#include "clang/Driver/Job.h"
21#include "clang/Driver/Tool.h"
23#include "llvm/Support/JSON.h"
24#include "llvm/Support/Path.h"
25#include "llvm/Support/PrettyStackTrace.h"
26#include "llvm/Support/VirtualFileSystem.h"
27
28using namespace llvm::opt;
29using namespace clang;
30using namespace driver;
31using namespace modules;
32
33namespace clang::driver::modules {
34static bool fromJSON(const llvm::json::Value &Params,
36 llvm::json::Path P) {
37 llvm::json::ObjectMapper O(Params, P);
38 return O.mapOptional("system-include-directories",
39 LocalArgs.SystemIncludeDirs);
40}
41
42static bool fromJSON(const llvm::json::Value &Params,
43 StdModuleManifest::Module &ModuleEntry,
44 llvm::json::Path P) {
45 llvm::json::ObjectMapper O(Params, P);
46 return O.map("is-std-library", ModuleEntry.IsStdlib) &&
47 O.map("logical-name", ModuleEntry.LogicalName) &&
48 O.map("source-path", ModuleEntry.SourcePath) &&
49 O.mapOptional("local-arguments", ModuleEntry.LocalArgs);
50}
51
52static bool fromJSON(const llvm::json::Value &Params,
53 StdModuleManifest &Manifest, llvm::json::Path P) {
54 llvm::json::ObjectMapper O(Params, P);
55 return O.map("modules", Manifest.Modules);
56}
57} // namespace clang::driver::modules
58
59/// Parses the Standard library module manifest from \p Buffer.
61 auto ParsedOrErr = llvm::json::parse(Buffer);
62 if (!ParsedOrErr)
63 return ParsedOrErr.takeError();
64
65 StdModuleManifest Manifest;
66 llvm::json::Path::Root Root;
67 if (!fromJSON(*ParsedOrErr, Manifest, Root))
68 return Root.getError();
69
70 return Manifest;
71}
72
73/// Converts each file path in manifest from relative to absolute.
74///
75/// Each file path in the manifest is expected to be relative the manifest's
76/// location \p ManifestPath itself.
79 StringRef ManifestPath) {
80 StringRef ManifestDir = llvm::sys::path::parent_path(ManifestPath);
81 SmallString<256> TempPath;
82
83 auto PrependManifestDir = [&](StringRef Path) {
84 TempPath = ManifestDir;
85 llvm::sys::path::append(TempPath, Path);
86 return std::string(TempPath);
87 };
88
89 for (auto &Entry : ManifestEntries) {
90 Entry.SourcePath = PrependManifestDir(Entry.SourcePath);
91 if (!Entry.LocalArgs)
92 continue;
93
94 for (auto &IncludeDir : Entry.LocalArgs->SystemIncludeDirs)
95 IncludeDir = PrependManifestDir(IncludeDir);
96 }
97}
98
100driver::modules::readStdModuleManifest(StringRef ManifestPath,
101 llvm::vfs::FileSystem &VFS) {
102 auto MemBufOrErr = VFS.getBufferForFile(ManifestPath);
103 if (!MemBufOrErr)
104 return llvm::createFileError(ManifestPath, MemBufOrErr.getError());
105
106 auto ManifestOrErr = parseManifest((*MemBufOrErr)->getBuffer());
107 if (!ManifestOrErr)
108 return ManifestOrErr.takeError();
109 auto Manifest = std::move(*ManifestOrErr);
110
111 makeManifestPathsAbsolute(Manifest.Modules, ManifestPath);
112 return Manifest;
113}
114
117 InputList &Inputs) {
118 DerivedArgList &Args = C.getArgs();
119 const OptTable &Opts = C.getDriver().getOpts();
120 for (const auto &Entry : ManifestEntries) {
121 auto *InputArg =
122 makeInputArg(Args, Opts, Args.MakeArgString(Entry.SourcePath));
123 Inputs.emplace_back(types::TY_CXXModule, InputArg);
124 }
125}
126
128 llvm::DenseMap<StringRef, const StdModuleManifest::Module *>;
129
130/// Builds a mapping from a module's source path to its entry in the manifest.
133 ManifestEntryLookup ManifestEntryBySource;
134 for (auto &Entry : ManifestEntries) {
135 [[maybe_unused]] const bool Inserted =
136 ManifestEntryBySource.try_emplace(Entry.SourcePath, &Entry).second;
137 assert(Inserted &&
138 "Manifest defines multiple modules with the same source path.");
139 }
140 return ManifestEntryBySource;
141}
142
143/// Returns the manifest entry corresponding to \p Job, or \c nullptr if none
144/// exists.
145static const StdModuleManifest::Module *
147 const ManifestEntryLookup &ManifestEntryBySource) {
148 for (const auto &II : Job.getInputInfos()) {
149 if (const auto It = ManifestEntryBySource.find(II.getFilename());
150 It != ManifestEntryBySource.end())
151 return It->second;
152 }
153 return nullptr;
154}
155
156/// Adds all \p SystemIncludeDirs to the \p CC1Args of \p Job.
157static void
159 ArgStringList &CC1Args,
160 ArrayRef<std::string> SystemIncludeDirs) {
161 const ToolChain &TC = Job.getCreator().getToolChain();
162 const DerivedArgList &TCArgs =
163 C.getArgsForToolChain(&TC, Job.getSource().getOffloadingArch(),
165
166 for (const auto &IncludeDir : SystemIncludeDirs)
167 TC.addSystemInclude(TCArgs, CC1Args, IncludeDir);
168}
169
170static bool isCC1Job(const Command &Job) {
171 return StringRef(Job.getCreator().getName()) == "clang";
172}
173
174/// Apply command-line modifications specific for inputs originating from the
175/// Standard library module manifest.
177 Compilation &C, const ManifestEntryLookup &ManifestEntryBySource,
178 MutableArrayRef<std::unique_ptr<Command>> Jobs) {
179 for (auto &Job : Jobs) {
180 if (!isCC1Job(*Job))
181 continue;
182
183 const auto *Entry = getManifestEntryForCommand(*Job, ManifestEntryBySource);
184 if (!Entry)
185 continue;
186
187 auto CC1Args = Job->getArguments();
188 if (Entry->IsStdlib)
189 CC1Args.push_back("-Wno-reserved-module-identifier");
190 if (Entry->LocalArgs)
191 addSystemIncludeDirsFromManifest(C, *Job, CC1Args,
192 Entry->LocalArgs->SystemIncludeDirs);
193 Job->replaceArguments(CC1Args);
194 }
195}
196
199 llvm::PrettyStackTraceString CrashInfo("Running modules driver.");
200
201 auto Jobs = C.getJobs().takeJobs();
202
203 const auto ManifestEntryBySource = buildManifestLookupMap(ManifestEntries);
204 // Apply manifest-entry specific command-line modifications before the scan as
205 // they might affect it.
206 applyArgsForStdModuleManifestInputs(C, ManifestEntryBySource, Jobs);
207
208 // TODO: Run the dependency scan.
209 // TODO: Prune jobs for modules specified in the manifest that are not
210 // required by any command-line input.
211 // TODO: Reorder and modify jobs based on the discovered dependencies.
212
213 // Add jobs back to the Compilation.
214 for (auto &Job : Jobs)
215 C.addCommand(std::move(Job));
216}
Defines the Diagnostic-related interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static const StdModuleManifest::Module * getManifestEntryForCommand(const Command &Job, const ManifestEntryLookup &ManifestEntryBySource)
Returns the manifest entry corresponding to Job, or nullptr if none exists.
static Expected< StdModuleManifest > parseManifest(StringRef Buffer)
Parses the Standard library module manifest from Buffer.
static void makeManifestPathsAbsolute(MutableArrayRef< StdModuleManifest::Module > ManifestEntries, StringRef ManifestPath)
Converts each file path in manifest from relative to absolute.
static void applyArgsForStdModuleManifestInputs(Compilation &C, const ManifestEntryLookup &ManifestEntryBySource, MutableArrayRef< std::unique_ptr< Command > > Jobs)
Apply command-line modifications specific for inputs originating from the Standard library module man...
static void addSystemIncludeDirsFromManifest(Compilation &C, Command &Job, ArgStringList &CC1Args, ArrayRef< std::string > SystemIncludeDirs)
Adds all SystemIncludeDirs to the CC1Args of Job.
static ManifestEntryLookup buildManifestLookupMap(ArrayRef< StdModuleManifest::Module > ManifestEntries)
Builds a mapping from a module's source path to its entry in the manifest.
static bool isCC1Job(const Command &Job)
llvm::DenseMap< StringRef, const StdModuleManifest::Module * > ManifestEntryLookup
This file defines functionality to support driver managed builds for compilations which use Clang mod...
const char * getOffloadingArch() const
Definition Action.h:213
OffloadKind getOffloadingDeviceKind() const
Definition Action.h:212
Command - An executable path/name and argument vector to execute.
Definition Job.h:106
const Action & getSource() const
getSource - Return the Action which caused the creation of this job.
Definition Job.h:188
const Tool & getCreator() const
getCreator - Return the Tool which caused the creation of this job.
Definition Job.h:191
const std::vector< InputInfo > & getInputInfos() const
Definition Job.h:226
Compilation - A set of tasks to perform for a single driver invocation.
Definition Compilation.h:45
ToolChain - Access to tools for a single platform.
Definition ToolChain.h:92
static void addSystemInclude(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, const Twine &Path)
Utility function to add a system include directory to CC1 arguments.
const ToolChain & getToolChain() const
Definition Tool.h:52
const char * getName() const
Definition Tool.h:48
@ VFS
Remove unused -ivfsoverlay arguments.
void buildStdModuleManifestInputs(ArrayRef< StdModuleManifest::Module > ManifestEntries, Compilation &C, InputList &Inputs)
Constructs compilation inputs for each module listed in the provided Standard library module manifest...
void runModulesDriver(Compilation &C, ArrayRef< StdModuleManifest::Module > ManifestEntries)
Scans the compilation inputs for module dependencies and adjusts the compilation to build and supply ...
llvm::Expected< StdModuleManifest > readStdModuleManifest(llvm::StringRef ManifestPath, llvm::vfs::FileSystem &VFS)
Reads the Standard library module manifest at ManifestPath.
static bool fromJSON(const llvm::json::Value &Params, StdModuleManifest::Module::LocalArguments &LocalArgs, llvm::json::Path P)
llvm::opt::Arg * makeInputArg(llvm::opt::DerivedArgList &Args, const llvm::opt::OptTable &Opts, StringRef Value, bool Claim=true)
Creates and adds a synthesized input argument.
llvm::SmallVector< InputTy, 16 > InputList
A list of inputs and their types for the given arguments.
Definition Types.h:136
The JSON file list parser is used to communicate input to InstallAPI.
std::optional< LocalArguments > LocalArgs
The parsed Standard library module manifest.