Path: blob/main/contrib/llvm-project/clang/lib/Driver/ToolChains/Hurd.cpp
35266 views
//===--- Hurd.cpp - Hurd ToolChain Implementations --------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "Hurd.h"9#include "CommonArgs.h"10#include "clang/Config/config.h"11#include "clang/Driver/Driver.h"12#include "clang/Driver/Options.h"13#include "llvm/Support/Path.h"14#include "llvm/Support/VirtualFileSystem.h"1516using namespace clang::driver;17using namespace clang::driver::toolchains;18using namespace clang;19using namespace llvm::opt;2021using tools::addPathIfExists;2223/// Get our best guess at the multiarch triple for a target.24///25/// Debian-based systems are starting to use a multiarch setup where they use26/// a target-triple directory in the library and header search paths.27/// Unfortunately, this triple does not align with the vanilla target triple,28/// so we provide a rough mapping here.29std::string Hurd::getMultiarchTriple(const Driver &D,30const llvm::Triple &TargetTriple,31StringRef SysRoot) const {32switch (TargetTriple.getArch()) {33default:34break;3536case llvm::Triple::x86:37// We use the existence of '/lib/<triple>' as a directory to detect some38// common hurd triples that don't quite match the Clang triple for both39// 32-bit and 64-bit targets. Multiarch fixes its install triples to these40// regardless of what the actual target triple is.41if (D.getVFS().exists(SysRoot + "/lib/i386-gnu"))42return "i386-gnu";43break;4445case llvm::Triple::x86_64:46return "x86_64-gnu";47}4849// For most architectures, just use whatever we have rather than trying to be50// clever.51return TargetTriple.str();52}5354static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {55// It happens that only x86 and PPC use the 'lib32' variant of oslibdir, and56// using that variant while targeting other architectures causes problems57// because the libraries are laid out in shared system roots that can't cope58// with a 'lib32' library search path being considered. So we only enable59// them when we know we may need it.60//61// FIXME: This is a bit of a hack. We should really unify this code for62// reasoning about oslibdir spellings with the lib dir spellings in the63// GCCInstallationDetector, but that is a more significant refactoring.6465if (Triple.getArch() == llvm::Triple::x86)66return "lib32";6768return Triple.isArch32Bit() ? "lib" : "lib64";69}7071Hurd::Hurd(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)72: Generic_ELF(D, Triple, Args) {73GCCInstallation.init(Triple, Args);74Multilibs = GCCInstallation.getMultilibs();75SelectedMultilibs.assign({GCCInstallation.getMultilib()});76std::string SysRoot = computeSysRoot();77ToolChain::path_list &PPaths = getProgramPaths();7879Generic_GCC::PushPPaths(PPaths);8081// The selection of paths to try here is designed to match the patterns which82// the GCC driver itself uses, as this is part of the GCC-compatible driver.83// This was determined by running GCC in a fake filesystem, creating all84// possible permutations of these directories, and seeing which ones it added85// to the link paths.86path_list &Paths = getFilePaths();8788const std::string OSLibDir = std::string(getOSLibDir(Triple, Args));89const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);9091#ifdef ENABLE_LINKER_BUILD_ID92ExtraOpts.push_back("--build-id");93#endif9495Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);9697// Similar to the logic for GCC above, if we currently running Clang inside98// of the requested system root, add its parent library paths to99// those searched.100// FIXME: It's not clear whether we should use the driver's installed101// directory ('Dir' below) or the ResourceDir.102if (StringRef(D.Dir).starts_with(SysRoot)) {103addPathIfExists(D, D.Dir + "/../lib/" + MultiarchTriple, Paths);104addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);105}106107addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);108addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);109110addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);111addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);112113Generic_GCC::AddMultiarchPaths(D, SysRoot, OSLibDir, Paths);114115// Similar to the logic for GCC above, if we are currently running Clang116// inside of the requested system root, add its parent library path to those117// searched.118// FIXME: It's not clear whether we should use the driver's installed119// directory ('Dir' below) or the ResourceDir.120if (StringRef(D.Dir).starts_with(SysRoot))121addPathIfExists(D, D.Dir + "/../lib", Paths);122123addPathIfExists(D, SysRoot + "/lib", Paths);124addPathIfExists(D, SysRoot + "/usr/lib", Paths);125}126127bool Hurd::HasNativeLLVMSupport() const { return true; }128129Tool *Hurd::buildLinker() const { return new tools::gnutools::Linker(*this); }130131Tool *Hurd::buildAssembler() const {132return new tools::gnutools::Assembler(*this);133}134135std::string Hurd::getDynamicLinker(const ArgList &Args) const {136switch (getArch()) {137case llvm::Triple::x86:138return "/lib/ld.so";139case llvm::Triple::x86_64:140return "/lib/ld-x86-64.so.1";141default:142break;143}144145llvm_unreachable("unsupported architecture");146}147148void Hurd::AddClangSystemIncludeArgs(const ArgList &DriverArgs,149ArgStringList &CC1Args) const {150const Driver &D = getDriver();151std::string SysRoot = computeSysRoot();152153if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))154return;155156if (!DriverArgs.hasArg(options::OPT_nostdlibinc))157addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");158159if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {160SmallString<128> P(D.ResourceDir);161llvm::sys::path::append(P, "include");162addSystemInclude(DriverArgs, CC1Args, P);163}164165if (DriverArgs.hasArg(options::OPT_nostdlibinc))166return;167168// Check for configure-time C include directories.169StringRef CIncludeDirs(C_INCLUDE_DIRS);170if (CIncludeDirs != "") {171SmallVector<StringRef, 5> Dirs;172CIncludeDirs.split(Dirs, ":");173for (StringRef Dir : Dirs) {174StringRef Prefix =175llvm::sys::path::is_absolute(Dir) ? "" : StringRef(SysRoot);176addExternCSystemInclude(DriverArgs, CC1Args, Prefix + Dir);177}178return;179}180181// Lacking those, try to detect the correct set of system includes for the182// target triple.183184AddMultilibIncludeArgs(DriverArgs, CC1Args);185186// On systems using multiarch, add /usr/include/$triple before187// /usr/include.188std::string MultiarchIncludeDir = getMultiarchTriple(D, getTriple(), SysRoot);189if (!MultiarchIncludeDir.empty() &&190D.getVFS().exists(SysRoot + "/usr/include/" + MultiarchIncludeDir))191addExternCSystemInclude(DriverArgs, CC1Args,192SysRoot + "/usr/include/" + MultiarchIncludeDir);193194// Add an include of '/include' directly. This isn't provided by default by195// system GCCs, but is often used with cross-compiling GCCs, and harmless to196// add even when Clang is acting as-if it were a system compiler.197addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");198199addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");200}201202void Hurd::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,203llvm::opt::ArgStringList &CC1Args) const {204// We need a detected GCC installation on Linux to provide libstdc++'s205// headers in odd Linuxish places.206if (!GCCInstallation.isValid())207return;208209StringRef TripleStr = GCCInstallation.getTriple().str();210StringRef DebianMultiarch =211GCCInstallation.getTriple().getArch() == llvm::Triple::x86 ? "i386-gnu"212: TripleStr;213214addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args, DebianMultiarch);215}216217void Hurd::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {218for (const auto &Opt : ExtraOpts)219CmdArgs.push_back(Opt.c_str());220}221222223