Hurd.cpp revision 363496
1//===--- Hurd.cpp - Hurd ToolChain Implementations --------*- C++ -*-===//
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#include "Hurd.h"
10#include "CommonArgs.h"
11#include "clang/Config/config.h"
12#include "clang/Driver/Driver.h"
13#include "clang/Driver/Options.h"
14#include "llvm/Support/Path.h"
15#include "llvm/Support/VirtualFileSystem.h"
16
17using namespace clang::driver;
18using namespace clang::driver::toolchains;
19using namespace clang;
20using namespace llvm::opt;
21
22using tools::addPathIfExists;
23
24/// Get our best guess at the multiarch triple for a target.
25///
26/// Debian-based systems are starting to use a multiarch setup where they use
27/// a target-triple directory in the library and header search paths.
28/// Unfortunately, this triple does not align with the vanilla target triple,
29/// so we provide a rough mapping here.
30std::string Hurd::getMultiarchTriple(const Driver &D,
31                                     const llvm::Triple &TargetTriple,
32                                     StringRef SysRoot) const {
33  if (TargetTriple.getArch() == llvm::Triple::x86) {
34    // We use the existence of '/lib/<triple>' as a directory to detect some
35    // common hurd triples that don't quite match the Clang triple for both
36    // 32-bit and 64-bit targets. Multiarch fixes its install triples to these
37    // regardless of what the actual target triple is.
38    if (D.getVFS().exists(SysRoot + "/lib/i386-gnu"))
39      return "i386-gnu";
40  }
41
42  // For most architectures, just use whatever we have rather than trying to be
43  // clever.
44  return TargetTriple.str();
45}
46
47static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
48  // It happens that only x86 and PPC use the 'lib32' variant of oslibdir, and
49  // using that variant while targeting other architectures causes problems
50  // because the libraries are laid out in shared system roots that can't cope
51  // with a 'lib32' library search path being considered. So we only enable
52  // them when we know we may need it.
53  //
54  // FIXME: This is a bit of a hack. We should really unify this code for
55  // reasoning about oslibdir spellings with the lib dir spellings in the
56  // GCCInstallationDetector, but that is a more significant refactoring.
57
58  if (Triple.getArch() == llvm::Triple::x86)
59    return "lib32";
60
61  return Triple.isArch32Bit() ? "lib" : "lib64";
62}
63
64Hurd::Hurd(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
65    : Generic_ELF(D, Triple, Args) {
66  std::string SysRoot = computeSysRoot();
67  path_list &Paths = getFilePaths();
68
69  const std::string OSLibDir = getOSLibDir(Triple, Args);
70  const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
71
72#ifdef ENABLE_LINKER_BUILD_ID
73  ExtraOpts.push_back("--build-id");
74#endif
75
76  // If we are currently running Clang inside of the requested system root, add
77  // its parent library paths to those searched.
78  // FIXME: It's not clear whether we should use the driver's installed
79  // directory ('Dir' below) or the ResourceDir.
80  if (StringRef(D.Dir).startswith(SysRoot)) {
81    addPathIfExists(D, D.Dir + "/../lib/" + MultiarchTriple, Paths);
82    addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);
83  }
84
85  addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
86  addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
87
88  addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
89  addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
90
91  // If we are currently running Clang inside of the requested system root, add
92  // its parent library path to those searched.
93  // FIXME: It's not clear whether we should use the driver's installed
94  // directory ('Dir' below) or the ResourceDir.
95  if (StringRef(D.Dir).startswith(SysRoot))
96    addPathIfExists(D, D.Dir + "/../lib", Paths);
97
98  addPathIfExists(D, SysRoot + "/lib", Paths);
99  addPathIfExists(D, SysRoot + "/usr/lib", Paths);
100}
101
102bool Hurd::HasNativeLLVMSupport() const { return true; }
103
104Tool *Hurd::buildLinker() const { return new tools::gnutools::Linker(*this); }
105
106Tool *Hurd::buildAssembler() const {
107  return new tools::gnutools::Assembler(*this);
108}
109
110std::string Hurd::computeSysRoot() const {
111  if (!getDriver().SysRoot.empty())
112    return getDriver().SysRoot;
113
114  return std::string();
115}
116
117std::string Hurd::getDynamicLinker(const ArgList &Args) const {
118  if (getArch() == llvm::Triple::x86)
119    return "/lib/ld.so";
120
121  llvm_unreachable("unsupported architecture");
122}
123
124void Hurd::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
125                                     ArgStringList &CC1Args) const {
126  const Driver &D = getDriver();
127  std::string SysRoot = computeSysRoot();
128
129  if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
130    return;
131
132  if (!DriverArgs.hasArg(options::OPT_nostdlibinc))
133    addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
134
135  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
136    SmallString<128> P(D.ResourceDir);
137    llvm::sys::path::append(P, "include");
138    addSystemInclude(DriverArgs, CC1Args, P);
139  }
140
141  if (DriverArgs.hasArg(options::OPT_nostdlibinc))
142    return;
143
144  // Check for configure-time C include directories.
145  StringRef CIncludeDirs(C_INCLUDE_DIRS);
146  if (CIncludeDirs != "") {
147    SmallVector<StringRef, 5> Dirs;
148    CIncludeDirs.split(Dirs, ":");
149    for (StringRef Dir : Dirs) {
150      StringRef Prefix =
151          llvm::sys::path::is_absolute(Dir) ? StringRef(SysRoot) : "";
152      addExternCSystemInclude(DriverArgs, CC1Args, Prefix + Dir);
153    }
154    return;
155  }
156
157  // Lacking those, try to detect the correct set of system includes for the
158  // target triple.
159  if (getTriple().getArch() == llvm::Triple::x86) {
160    std::string Path = SysRoot + "/usr/include/i386-gnu";
161    if (D.getVFS().exists(Path))
162      addExternCSystemInclude(DriverArgs, CC1Args, Path);
163  }
164
165  // Add an include of '/include' directly. This isn't provided by default by
166  // system GCCs, but is often used with cross-compiling GCCs, and harmless to
167  // add even when Clang is acting as-if it were a system compiler.
168  addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
169
170  addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
171}
172
173void Hurd::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {
174  for (const auto &Opt : ExtraOpts)
175    CmdArgs.push_back(Opt.c_str());
176}
177