@@ -33,6 +33,40 @@ using namespace clang::driver;
33
33
using namespace clang ::driver::tools;
34
34
using namespace clang ::driver::toolchains;
35
35
36
+ // / Is the triple {aarch64.aarch64_be}-none-elf?
37
+ static bool isAArch64BareMetal (const llvm::Triple &Triple) {
38
+ if (Triple.getArch () != llvm::Triple::aarch64 &&
39
+ Triple.getArch () != llvm::Triple::aarch64_be)
40
+ return false ;
41
+
42
+ if (Triple.getVendor () != llvm::Triple::UnknownVendor)
43
+ return false ;
44
+
45
+ if (Triple.getOS () != llvm::Triple::UnknownOS)
46
+ return false ;
47
+
48
+ return Triple.getEnvironmentName () == " elf" ;
49
+ }
50
+
51
+ static bool isRISCVBareMetal (const llvm::Triple &Triple) {
52
+ if (!Triple.isRISCV ())
53
+ return false ;
54
+
55
+ if (Triple.getVendor () != llvm::Triple::UnknownVendor)
56
+ return false ;
57
+
58
+ if (Triple.getOS () != llvm::Triple::UnknownOS)
59
+ return false ;
60
+
61
+ return Triple.getEnvironmentName () == " elf" ;
62
+ }
63
+
64
+ // / Is the triple powerpc[64][le]-*-none-eabi?
65
+ static bool isPPCBareMetal (const llvm::Triple &Triple) {
66
+ return Triple.isPPC () && Triple.getOS () == llvm::Triple::UnknownOS &&
67
+ Triple.getEnvironment () == llvm::Triple::EABI;
68
+ }
69
+
36
70
static bool findRISCVMultilibs (const Driver &D,
37
71
const llvm::Triple &TargetTriple,
38
72
const ArgList &Args, DetectedMultilibs &Result) {
@@ -110,56 +144,99 @@ static std::string computeBaseSysRoot(const Driver &D, bool IncludeTriple) {
110
144
return std::string (SysRootDir);
111
145
}
112
146
113
- BareMetal::BareMetal (const Driver &D, const llvm::Triple &Triple,
114
- const ArgList &Args)
115
- : ToolChain(D, Triple, Args),
116
- SysRoot(computeBaseSysRoot(D, /* IncludeTriple=*/ true )) {
117
- getProgramPaths ().push_back (getDriver ().Dir );
118
-
119
- findMultilibs (D, Triple, Args);
120
- SmallString<128 > SysRoot (computeSysRoot ());
121
- if (!SysRoot.empty ()) {
122
- for (const Multilib &M : getOrderedMultilibs ()) {
123
- SmallString<128 > Dir (SysRoot);
124
- llvm::sys::path::append (Dir, M.osSuffix (), " lib" );
125
- getFilePaths ().push_back (std::string (Dir));
126
- getLibraryPaths ().push_back (std::string (Dir));
127
- }
128
- }
147
+ static bool hasGCCToolChainAlongSideClang (const Driver &D) {
148
+ SmallString<128 > GCCDir;
149
+ llvm::sys::path::append (GCCDir, D.Dir , " .." , D.getTargetTriple (),
150
+ " lib/crt0.o" );
151
+ return llvm::sys::fs::exists (GCCDir);
129
152
}
130
153
131
- // / Is the triple {aarch64.aarch64_be}-none-elf?
132
- static bool isAArch64BareMetal (const llvm::Triple &Triple) {
133
- if (Triple.getArch () != llvm::Triple::aarch64 &&
134
- Triple.getArch () != llvm::Triple::aarch64_be)
135
- return false ;
154
+ // Users can specify their GCC toolchain using `-gcc-install-dir` or
155
+ // `--gcc-toolchain`. If no sysroot is explicitly provided, the driver will
156
+ // attempt to infer it from the values of the above flags.
157
+ //
158
+ // If neither flag is used, the sysroot defaults to either:
159
+ // - `bin/../<target-triple>`
160
+ // - `bin/../lib/clang-runtimes/<target-triple>`
161
+ //
162
+ // To use the `clang-runtimes` path, ensure that `../<target-triple>/lib/crt0.o`
163
+ // does not exist relative to the driver.
164
+ std::string BareMetal::computeSysRoot () const {
165
+ if (!SysRoot.empty ())
166
+ return SysRoot;
136
167
137
- if (Triple.getVendor () != llvm::Triple::UnknownVendor)
138
- return false ;
168
+ const Driver &D = getDriver ();
169
+ if (!D.SysRoot .empty ())
170
+ return D.SysRoot ;
139
171
140
- if (Triple.getOS () != llvm::Triple::UnknownOS)
141
- return false ;
172
+ // Verify the GCC installation from -gcc-install-dir, --gcc-toolchain, or
173
+ // alongside clang. If valid, form the sysroot. Otherwise, check
174
+ // lib/clang-runtimes above the driver.
175
+ SmallString<128 > SysRootDir;
176
+ if (GCCInstallation.isValid ()) {
177
+ StringRef LibDir = GCCInstallation.getParentLibPath ();
178
+ StringRef TripleStr = GCCInstallation.getTriple ().str ();
179
+ llvm::sys::path::append (SysRootDir, LibDir, " .." , TripleStr);
180
+ } else if (hasGCCToolChainAlongSideClang (D)) {
181
+ // Use the triple as provided to the driver. Unlike the parsed triple
182
+ // this has not been normalized to always contain every field.
183
+ llvm::sys::path::append (SysRootDir, D.Dir , " .." , D.getTargetTriple ());
184
+ }
142
185
143
- return Triple.getEnvironmentName () == " elf" ;
186
+ if (llvm::sys::fs::exists (SysRootDir))
187
+ return std::string (SysRootDir);
188
+ return computeBaseSysRoot (D, /* IncludeTriple*/ true );
144
189
}
145
190
146
- static bool isRISCVBareMetal (const llvm::Triple &Triple) {
147
- if (!Triple.isRISCV ())
148
- return false ;
149
-
150
- if (Triple.getVendor () != llvm::Triple::UnknownVendor)
151
- return false ;
152
-
153
- if (Triple.getOS () != llvm::Triple::UnknownOS)
154
- return false ;
155
-
156
- return Triple.getEnvironmentName () == " elf" ;
191
+ static void addMultilibsFilePaths (const Driver &D, const MultilibSet &Multilibs,
192
+ const Multilib &Multilib,
193
+ StringRef InstallPath,
194
+ ToolChain::path_list &Paths) {
195
+ if (const auto &PathsCallback = Multilibs.filePathsCallback ())
196
+ for (const auto &Path : PathsCallback (Multilib))
197
+ addPathIfExists (D, InstallPath + Path, Paths);
157
198
}
158
199
159
- // / Is the triple powerpc[64][le]-*-none-eabi?
160
- static bool isPPCBareMetal (const llvm::Triple &Triple) {
161
- return Triple.isPPC () && Triple.getOS () == llvm::Triple::UnknownOS &&
162
- Triple.getEnvironment () == llvm::Triple::EABI;
200
+ // GCC mutltilibs will only work for those targets that have their multlib
201
+ // structure encoded into GCCInstallation. Baremetal toolchain support ARM,
202
+ // AArch64, RISCV and PPC and of them only RISCV have GCC multilibs hardcoded
203
+ // in GCCInstallation.
204
+ BareMetal::BareMetal (const Driver &D, const llvm::Triple &Triple,
205
+ const ArgList &Args)
206
+ : Generic_ELF(D, Triple, Args) {
207
+ GCCInstallation.init (Triple, Args);
208
+ SysRoot = computeSysRoot ();
209
+ if (GCCInstallation.isValid ()) {
210
+ if (!isRISCVBareMetal (Triple))
211
+ D.Diag (clang::diag::warn_drv_multilib_not_available_for_target);
212
+ Multilibs = GCCInstallation.getMultilibs ();
213
+ SelectedMultilibs.assign ({GCCInstallation.getMultilib ()});
214
+ path_list &Paths = getFilePaths ();
215
+ // Add toolchain/multilib specific file paths.
216
+ addMultilibsFilePaths (D, Multilibs, SelectedMultilibs.back (),
217
+ GCCInstallation.getInstallPath (), Paths);
218
+ getFilePaths ().push_back (GCCInstallation.getInstallPath ().str ());
219
+ ToolChain::path_list &PPaths = getProgramPaths ();
220
+ // Multilib cross-compiler GCC installations put ld in a triple-prefixed
221
+ // directory off of the parent of the GCC installation.
222
+ PPaths.push_back (Twine (GCCInstallation.getParentLibPath () + " /../" +
223
+ GCCInstallation.getTriple ().str () + " /bin" )
224
+ .str ());
225
+ PPaths.push_back ((GCCInstallation.getParentLibPath () + " /../bin" ).str ());
226
+ getFilePaths ().push_back (SysRoot + " /lib" );
227
+ } else {
228
+ getProgramPaths ().push_back (getDriver ().Dir );
229
+ findMultilibs (D, Triple, Args);
230
+ const SmallString<128 > SysRootDir (computeSysRoot ());
231
+ if (!SysRootDir.empty ()) {
232
+ for (const Multilib &M : getOrderedMultilibs ()) {
233
+ SmallString<128 > Dir (SysRootDir);
234
+ llvm::sys::path::append (Dir, M.osSuffix (), " lib" );
235
+ getFilePaths ().push_back (std::string (Dir));
236
+ getLibraryPaths ().push_back (std::string (Dir));
237
+ }
238
+ }
239
+ }
163
240
}
164
241
165
242
static void
@@ -244,7 +321,7 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
244
321
Multilibs = Result.Multilibs ;
245
322
MultilibMacroDefines.append (CustomFlagMacroDefines.begin (),
246
323
CustomFlagMacroDefines.end ());
247
- } else if (isRISCVBareMetal (Triple)) {
324
+ } else if (isRISCVBareMetal (Triple) && ! hasGCCToolChainAlongSideClang (D) ) {
248
325
if (findRISCVMultilibs (D, Triple, Args, Result)) {
249
326
SelectedMultilibs = Result.SelectedMultilibs ;
250
327
Multilibs = Result.Multilibs ;
@@ -265,8 +342,6 @@ Tool *BareMetal::buildStaticLibTool() const {
265
342
return new tools::baremetal::StaticLibTool (*this );
266
343
}
267
344
268
- std::string BareMetal::computeSysRoot () const { return SysRoot; }
269
-
270
345
BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs () const {
271
346
// Get multilibs in reverse order because they're ordered most-specific last.
272
347
if (!SelectedMultilibs.empty ())
@@ -294,10 +369,10 @@ void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
294
369
if (std::optional<std::string> Path = getStdlibIncludePath ())
295
370
addSystemInclude (DriverArgs, CC1Args, *Path);
296
371
297
- const SmallString<128 > SysRoot (computeSysRoot ());
298
- if (!SysRoot .empty ()) {
372
+ const SmallString<128 > SysRootDir (computeSysRoot ());
373
+ if (!SysRootDir .empty ()) {
299
374
for (const Multilib &M : getOrderedMultilibs ()) {
300
- SmallString<128 > Dir (SysRoot );
375
+ SmallString<128 > Dir (SysRootDir );
301
376
llvm::sys::path::append (Dir, M.includeSuffix ());
302
377
llvm::sys::path::append (Dir, " include" );
303
378
addSystemInclude (DriverArgs, CC1Args, Dir.str ());
@@ -311,6 +386,19 @@ void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
311
386
CC1Args.push_back (" -nostdsysteminc" );
312
387
}
313
388
389
+ void BareMetal::addLibStdCxxIncludePaths (
390
+ const llvm::opt::ArgList &DriverArgs,
391
+ llvm::opt::ArgStringList &CC1Args) const {
392
+ if (!GCCInstallation.isValid ())
393
+ return ;
394
+ const GCCVersion &Version = GCCInstallation.getVersion ();
395
+ StringRef TripleStr = GCCInstallation.getTriple ().str ();
396
+ const Multilib &Multilib = GCCInstallation.getMultilib ();
397
+ addLibStdCXXIncludePaths (computeSysRoot () + " /include/c++/" + Version.Text ,
398
+ TripleStr, Multilib.includeSuffix (), DriverArgs,
399
+ CC1Args);
400
+ }
401
+
314
402
void BareMetal::AddClangCXXStdlibIncludeArgs (const ArgList &DriverArgs,
315
403
ArgStringList &CC1Args) const {
316
404
if (DriverArgs.hasArg (options::OPT_nostdinc, options::OPT_nostdlibinc,
@@ -341,23 +429,23 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
341
429
};
342
430
343
431
switch (GetCXXStdlibType (DriverArgs)) {
344
- case ToolChain::CST_Libcxx: {
345
- SmallString<128 > P (D.Dir );
346
- llvm::sys::path::append (P, " .." , " include" );
347
- AddCXXIncludePath (P);
348
- break ;
349
- }
350
- case ToolChain::CST_Libstdcxx:
351
- // We only support libc++ toolchain installation.
352
- break ;
432
+ case ToolChain::CST_Libcxx: {
433
+ SmallString<128 > P (D.Dir );
434
+ llvm::sys::path::append (P, " .." , " include" );
435
+ AddCXXIncludePath (P);
436
+ break ;
437
+ }
438
+ case ToolChain::CST_Libstdcxx:
439
+ addLibStdCxxIncludePaths (DriverArgs, CC1Args);
440
+ break ;
353
441
}
354
442
355
- std::string SysRoot (computeSysRoot ());
356
- if (SysRoot .empty ())
443
+ std::string SysRootDir (computeSysRoot ());
444
+ if (SysRootDir .empty ())
357
445
return ;
358
446
359
447
for (const Multilib &M : getOrderedMultilibs ()) {
360
- SmallString<128 > Dir (SysRoot );
448
+ SmallString<128 > Dir (SysRootDir );
361
449
llvm::sys::path::append (Dir, M.gccSuffix ());
362
450
switch (GetCXXStdlibType (DriverArgs)) {
363
451
case ToolChain::CST_Libcxx: {
0 commit comments