@@ -110,20 +110,81 @@ static std::string computeBaseSysRoot(const Driver &D, bool IncludeTriple) {
110110 return std::string (SysRootDir);
111111}
112112
113+ static bool hasGCCToolChainAlongSideClang (const Driver &D) {
114+ SmallString<128 > GCCDir;
115+ llvm::sys::path::append (GCCDir, D.Dir , " .." , D.getTargetTriple (),
116+ " lib/crt0.o" );
117+ return llvm::sys::fs::exists (GCCDir);
118+ }
119+
120+ std::string BareMetal::computeSysRoot () const {
121+ if (!SysRoot.empty ())
122+ return SysRoot;
123+
124+ const Driver &D = getDriver ();
125+ if (!D.SysRoot .empty ())
126+ return D.SysRoot ;
127+
128+ // Verify the GCC installation from -gcc-install-dir, --gcc-toolchain, or
129+ // alongside clang. If valid, form the sysroot. Otherwise, check
130+ // lib/clang-runtimes above the driver.
131+ SmallString<128 > SysRootDir;
132+ if (GCCInstallation.isValid ()) {
133+ StringRef LibDir = GCCInstallation.getParentLibPath ();
134+ StringRef TripleStr = GCCInstallation.getTriple ().str ();
135+ llvm::sys::path::append (SysRootDir, LibDir, " .." , TripleStr);
136+ } else if (hasGCCToolChainAlongSideClang (D)) {
137+ // Use the triple as provided to the driver. Unlike the parsed triple
138+ // this has not been normalized to always contain every field.
139+ llvm::sys::path::append (SysRootDir, D.Dir , " .." , D.getTargetTriple ());
140+ }
141+
142+ if (llvm::sys::fs::exists (SysRootDir))
143+ return std::string (SysRootDir);
144+ return computeBaseSysRoot (D, /* IncludeTriple*/ true );
145+ }
146+
147+ static void addMultilibsFilePaths (const Driver &D, const MultilibSet &Multilibs,
148+ const Multilib &Multilib,
149+ StringRef InstallPath,
150+ ToolChain::path_list &Paths) {
151+ if (const auto &PathsCallback = Multilibs.filePathsCallback ())
152+ for (const auto &Path : PathsCallback (Multilib))
153+ addPathIfExists (D, InstallPath + Path, Paths);
154+ }
155+
113156BareMetal::BareMetal (const Driver &D, const llvm::Triple &Triple,
114157 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));
158+ : Generic_ELF(D, Triple, Args) {
159+ GCCInstallation.init (Triple, Args);
160+ SysRoot = computeSysRoot ();
161+ if (GCCInstallation.isValid ()) {
162+ Multilibs = GCCInstallation.getMultilibs ();
163+ SelectedMultilibs.assign ({GCCInstallation.getMultilib ()});
164+ path_list &Paths = getFilePaths ();
165+ // Add toolchain/multilib specific file paths.
166+ addMultilibsFilePaths (D, Multilibs, SelectedMultilibs.back (),
167+ GCCInstallation.getInstallPath (), Paths);
168+ getFilePaths ().push_back (GCCInstallation.getInstallPath ().str ());
169+ ToolChain::path_list &PPaths = getProgramPaths ();
170+ // Multilib cross-compiler GCC installations put ld in a triple-prefixed
171+ // directory off of the parent of the GCC installation.
172+ PPaths.push_back (Twine (GCCInstallation.getParentLibPath () + " /../" +
173+ GCCInstallation.getTriple ().str () + " /bin" )
174+ .str ());
175+ PPaths.push_back ((GCCInstallation.getParentLibPath () + " /../bin" ).str ());
176+ getFilePaths ().push_back (SysRoot + " /lib" );
177+ } else {
178+ getProgramPaths ().push_back (getDriver ().Dir );
179+ findMultilibs (D, Triple, Args);
180+ const SmallString<128 > SysRootDir (computeSysRoot ());
181+ if (!SysRootDir.empty ()) {
182+ for (const Multilib &M : getOrderedMultilibs ()) {
183+ SmallString<128 > Dir (SysRootDir);
184+ llvm::sys::path::append (Dir, M.osSuffix (), " lib" );
185+ getFilePaths ().push_back (std::string (Dir));
186+ getLibraryPaths ().push_back (std::string (Dir));
187+ }
127188 }
128189 }
129190}
@@ -265,8 +326,6 @@ Tool *BareMetal::buildStaticLibTool() const {
265326 return new tools::baremetal::StaticLibTool (*this );
266327}
267328
268- std::string BareMetal::computeSysRoot () const { return SysRoot; }
269-
270329BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs () const {
271330 // Get multilibs in reverse order because they're ordered most-specific last.
272331 if (!SelectedMultilibs.empty ())
@@ -294,10 +353,10 @@ void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
294353 if (std::optional<std::string> Path = getStdlibIncludePath ())
295354 addSystemInclude (DriverArgs, CC1Args, *Path);
296355
297- const SmallString<128 > SysRoot (computeSysRoot ());
298- if (!SysRoot .empty ()) {
356+ const SmallString<128 > SysRootDir (computeSysRoot ());
357+ if (!SysRootDir .empty ()) {
299358 for (const Multilib &M : getOrderedMultilibs ()) {
300- SmallString<128 > Dir (SysRoot );
359+ SmallString<128 > Dir (SysRootDir );
301360 llvm::sys::path::append (Dir, M.includeSuffix ());
302361 llvm::sys::path::append (Dir, " include" );
303362 addSystemInclude (DriverArgs, CC1Args, Dir.str ());
@@ -311,6 +370,19 @@ void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
311370 CC1Args.push_back (" -nostdsysteminc" );
312371}
313372
373+ void BareMetal::addLibStdCxxIncludePaths (
374+ const llvm::opt::ArgList &DriverArgs,
375+ llvm::opt::ArgStringList &CC1Args) const {
376+ if (!GCCInstallation.isValid ())
377+ return ;
378+ const GCCVersion &Version = GCCInstallation.getVersion ();
379+ StringRef TripleStr = GCCInstallation.getTriple ().str ();
380+ const Multilib &Multilib = GCCInstallation.getMultilib ();
381+ addLibStdCXXIncludePaths (computeSysRoot () + " /include/c++/" + Version.Text ,
382+ TripleStr, Multilib.includeSuffix (), DriverArgs,
383+ CC1Args);
384+ }
385+
314386void BareMetal::AddClangCXXStdlibIncludeArgs (const ArgList &DriverArgs,
315387 ArgStringList &CC1Args) const {
316388 if (DriverArgs.hasArg (options::OPT_nostdinc, options::OPT_nostdlibinc,
@@ -341,23 +413,23 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
341413 };
342414
343415 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 ;
416+ case ToolChain::CST_Libcxx: {
417+ SmallString<128 > P (D.Dir );
418+ llvm::sys::path::append (P, " .." , " include" );
419+ AddCXXIncludePath (P);
420+ break ;
421+ }
422+ case ToolChain::CST_Libstdcxx:
423+ addLibStdCxxIncludePaths (DriverArgs, CC1Args);
424+ break ;
353425 }
354426
355- std::string SysRoot (computeSysRoot ());
356- if (SysRoot .empty ())
427+ std::string SysRootDir (computeSysRoot ());
428+ if (SysRootDir .empty ())
357429 return ;
358430
359431 for (const Multilib &M : getOrderedMultilibs ()) {
360- SmallString<128 > Dir (SysRoot );
432+ SmallString<128 > Dir (SysRootDir );
361433 llvm::sys::path::append (Dir, M.gccSuffix ());
362434 switch (GetCXXStdlibType (DriverArgs)) {
363435 case ToolChain::CST_Libcxx: {
0 commit comments