================ @@ -110,56 +145,113 @@ static std::string computeBaseSysRoot(const Driver &D, bool IncludeTriple) { return std::string(SysRootDir); } -BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple, - const ArgList &Args) - : ToolChain(D, Triple, Args), - SysRoot(computeBaseSysRoot(D, /*IncludeTriple=*/true)) { - getProgramPaths().push_back(getDriver().Dir); - - findMultilibs(D, Triple, Args); - SmallString<128> SysRoot(computeSysRoot()); - if (!SysRoot.empty()) { - for (const Multilib &M : getOrderedMultilibs()) { - SmallString<128> Dir(SysRoot); - llvm::sys::path::append(Dir, M.osSuffix(), "lib"); - getFilePaths().push_back(std::string(Dir)); - getLibraryPaths().push_back(std::string(Dir)); - } - } +// This logic is adapted from RISCVToolChain.cpp as part of the ongoing effort +// to merge RISCVToolChain into the Baremetal toolchain. It infers the presence +// of a valid GCC toolchain by checking whether the `crt0.o` file exists in the +// `bin/../<target-triple>/lib` directory +static bool detectGCCToolchainAdjacent(const Driver &D) { + SmallString<128> GCCDir; + llvm::sys::path::append(GCCDir, D.Dir, "..", D.getTargetTriple(), + "lib/crt0.o"); + return llvm::sys::fs::exists(GCCDir); } -/// Is the triple {aarch64.aarch64_be}-none-elf? -static bool isAArch64BareMetal(const llvm::Triple &Triple) { - if (Triple.getArch() != llvm::Triple::aarch64 && - Triple.getArch() != llvm::Triple::aarch64_be) - return false; +// If no sysroot is provided the driver will first attempt to infer it from the +// values of `--gcc-install-dir` or `--gcc-toolchain`, which specify the +// location of a GCC toolchain. +// If neither flag is used, the sysroot defaults to either: +// - `bin/../<target-triple>` +// - `bin/../lib/clang-runtimes/<target-triple>` +// +// To use the `clang-runtimes` path, ensure that `../<target-triple>/lib/crt0.o` +// does not exist relative to the driver. +std::string BareMetal::computeSysRoot() const { + // Use Baremetal::sysroot if it has already been set. + if (!SysRoot.empty()) + return SysRoot; + + // Use the sysroot specified via the `--sysroot` command-line flag, if + // provided. + const Driver &D = getDriver(); + if (!D.SysRoot.empty()) + return D.SysRoot; - if (Triple.getVendor() != llvm::Triple::UnknownVendor) - return false; + // Attempt to infer sysroot from a valid GCC installation. + // If no valid GCC installation, check for a GCC toolchain alongside Clang. + SmallString<128> inferredSysRoot; + if (GCCInstallation.isValid()) { + llvm::sys::path::append(inferredSysRoot, GCCInstallation.getParentLibPath(), + "..", GCCInstallation.getTriple().str()); + } else if (detectGCCToolchainAdjacent(D)) { + // Use the triple as provided to the driver. Unlike the parsed triple + // this has not been normalized to always contain every field. + llvm::sys::path::append(inferredSysRoot, D.Dir, "..", D.getTargetTriple()); + } - if (Triple.getOS() != llvm::Triple::UnknownOS) - return false; + // If a valid path was inferred and exists, use it + if (!inferredSysRoot.empty() && llvm::sys::fs::exists(inferredSysRoot)) + return std::string(inferredSysRoot); - return Triple.getEnvironmentName() == "elf"; + // Use the clang-runtimes path. + return computeClangRuntimesSysRoot(D, /*IncludeTriple*/ true); } -static bool isRISCVBareMetal(const llvm::Triple &Triple) { - if (!Triple.isRISCV()) - return false; - - if (Triple.getVendor() != llvm::Triple::UnknownVendor) - return false; - - if (Triple.getOS() != llvm::Triple::UnknownOS) - return false; - - return Triple.getEnvironmentName() == "elf"; +static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs, + const Multilib &Multilib, + StringRef InstallPath, + ToolChain::path_list &Paths) { + if (const auto &PathsCallback = Multilibs.filePathsCallback()) + for (const auto &Path : PathsCallback(Multilib)) + addPathIfExists(D, InstallPath + Path, Paths); } -/// Is the triple powerpc[64][le]-*-none-eabi? -static bool isPPCBareMetal(const llvm::Triple &Triple) { - return Triple.isPPC() && Triple.getOS() == llvm::Triple::UnknownOS && - Triple.getEnvironment() == llvm::Triple::EABI; +// GCC mutltilibs will only work for those targets that have their multlib +// structure encoded into GCCInstallation. Baremetal toolchain supports ARM, +// AArch64, RISCV and PPC and of these only RISCV have GCC multilibs hardcoded +// in GCCInstallation. +BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Generic_ELF(D, Triple, Args) { + GCCInstallation.init(Triple, Args); ---------------- quic-garvgupt wrote:
During the initialization of GCCInstallation at line 215, the toolchain is validated based on the following flags, in decreasing order of precedence: --gcc-install-dir, --gcc-toolchain, the adjacent bin/../ path, --sysroot, and finally /usr (for Debian-based systems). Previously, for RISC-V targets, only the first two options were considered when determining a valid GCCInstallation. It appears that this behavior changed when support for GCCInstallation was added. In the latest patchset, I have restored the intended behavior: a valid GCC installation will only be recognized if it is specified via --gcc-toolchain, --gcc-install-dir, or located adjacent to Clang in the bin/.../<target-triple> path. https://github.com/llvm/llvm-project/pull/121829 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits