xref: /openbsd-src/gnu/llvm/clang/lib/Driver/ToolChains/Hurd.cpp (revision a9ac8606c53d55cee9c3a39778b249c51df111ef)
1e5dd7070Spatrick //===--- Hurd.cpp - Hurd ToolChain Implementations --------*- C++ -*-===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick 
9e5dd7070Spatrick #include "Hurd.h"
10e5dd7070Spatrick #include "CommonArgs.h"
11e5dd7070Spatrick #include "clang/Config/config.h"
12e5dd7070Spatrick #include "clang/Driver/Driver.h"
13e5dd7070Spatrick #include "clang/Driver/Options.h"
14e5dd7070Spatrick #include "llvm/Support/Path.h"
15e5dd7070Spatrick #include "llvm/Support/VirtualFileSystem.h"
16e5dd7070Spatrick 
17e5dd7070Spatrick using namespace clang::driver;
18e5dd7070Spatrick using namespace clang::driver::toolchains;
19e5dd7070Spatrick using namespace clang;
20e5dd7070Spatrick using namespace llvm::opt;
21e5dd7070Spatrick 
22e5dd7070Spatrick using tools::addPathIfExists;
23e5dd7070Spatrick 
24e5dd7070Spatrick /// Get our best guess at the multiarch triple for a target.
25e5dd7070Spatrick ///
26e5dd7070Spatrick /// Debian-based systems are starting to use a multiarch setup where they use
27e5dd7070Spatrick /// a target-triple directory in the library and header search paths.
28e5dd7070Spatrick /// Unfortunately, this triple does not align with the vanilla target triple,
29e5dd7070Spatrick /// so we provide a rough mapping here.
getMultiarchTriple(const Driver & D,const llvm::Triple & TargetTriple,StringRef SysRoot) const30e5dd7070Spatrick std::string Hurd::getMultiarchTriple(const Driver &D,
31e5dd7070Spatrick                                      const llvm::Triple &TargetTriple,
32e5dd7070Spatrick                                      StringRef SysRoot) const {
33e5dd7070Spatrick   if (TargetTriple.getArch() == llvm::Triple::x86) {
34e5dd7070Spatrick     // We use the existence of '/lib/<triple>' as a directory to detect some
35e5dd7070Spatrick     // common hurd triples that don't quite match the Clang triple for both
36e5dd7070Spatrick     // 32-bit and 64-bit targets. Multiarch fixes its install triples to these
37e5dd7070Spatrick     // regardless of what the actual target triple is.
38e5dd7070Spatrick     if (D.getVFS().exists(SysRoot + "/lib/i386-gnu"))
39e5dd7070Spatrick       return "i386-gnu";
40e5dd7070Spatrick   }
41e5dd7070Spatrick 
42e5dd7070Spatrick   // For most architectures, just use whatever we have rather than trying to be
43e5dd7070Spatrick   // clever.
44e5dd7070Spatrick   return TargetTriple.str();
45e5dd7070Spatrick }
46e5dd7070Spatrick 
getOSLibDir(const llvm::Triple & Triple,const ArgList & Args)47e5dd7070Spatrick static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
48e5dd7070Spatrick   // It happens that only x86 and PPC use the 'lib32' variant of oslibdir, and
49e5dd7070Spatrick   // using that variant while targeting other architectures causes problems
50e5dd7070Spatrick   // because the libraries are laid out in shared system roots that can't cope
51e5dd7070Spatrick   // with a 'lib32' library search path being considered. So we only enable
52e5dd7070Spatrick   // them when we know we may need it.
53e5dd7070Spatrick   //
54e5dd7070Spatrick   // FIXME: This is a bit of a hack. We should really unify this code for
55e5dd7070Spatrick   // reasoning about oslibdir spellings with the lib dir spellings in the
56e5dd7070Spatrick   // GCCInstallationDetector, but that is a more significant refactoring.
57e5dd7070Spatrick 
58e5dd7070Spatrick   if (Triple.getArch() == llvm::Triple::x86)
59e5dd7070Spatrick     return "lib32";
60e5dd7070Spatrick 
61e5dd7070Spatrick   return Triple.isArch32Bit() ? "lib" : "lib64";
62e5dd7070Spatrick }
63e5dd7070Spatrick 
Hurd(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)64389bb291Spatrick Hurd::Hurd(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
65e5dd7070Spatrick     : Generic_ELF(D, Triple, Args) {
66ec727ea7Spatrick   GCCInstallation.init(Triple, Args);
67ec727ea7Spatrick   Multilibs = GCCInstallation.getMultilibs();
68ec727ea7Spatrick   SelectedMultilib = GCCInstallation.getMultilib();
69e5dd7070Spatrick   std::string SysRoot = computeSysRoot();
70ec727ea7Spatrick   ToolChain::path_list &PPaths = getProgramPaths();
71ec727ea7Spatrick 
72ec727ea7Spatrick   Generic_GCC::PushPPaths(PPaths);
73ec727ea7Spatrick 
74ec727ea7Spatrick   // The selection of paths to try here is designed to match the patterns which
75ec727ea7Spatrick   // the GCC driver itself uses, as this is part of the GCC-compatible driver.
76ec727ea7Spatrick   // This was determined by running GCC in a fake filesystem, creating all
77ec727ea7Spatrick   // possible permutations of these directories, and seeing which ones it added
78ec727ea7Spatrick   // to the link paths.
79e5dd7070Spatrick   path_list &Paths = getFilePaths();
80e5dd7070Spatrick 
81ec727ea7Spatrick   const std::string OSLibDir = std::string(getOSLibDir(Triple, Args));
82e5dd7070Spatrick   const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
83e5dd7070Spatrick 
84e5dd7070Spatrick #ifdef ENABLE_LINKER_BUILD_ID
85e5dd7070Spatrick   ExtraOpts.push_back("--build-id");
86e5dd7070Spatrick #endif
87e5dd7070Spatrick 
88ec727ea7Spatrick   Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
89ec727ea7Spatrick 
90ec727ea7Spatrick   // Similar to the logic for GCC above, if we currently running Clang inside
91ec727ea7Spatrick   // of the requested system root, add its parent library paths to
92ec727ea7Spatrick   // those searched.
93e5dd7070Spatrick   // FIXME: It's not clear whether we should use the driver's installed
94e5dd7070Spatrick   // directory ('Dir' below) or the ResourceDir.
95e5dd7070Spatrick   if (StringRef(D.Dir).startswith(SysRoot)) {
96e5dd7070Spatrick     addPathIfExists(D, D.Dir + "/../lib/" + MultiarchTriple, Paths);
97e5dd7070Spatrick     addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);
98e5dd7070Spatrick   }
99e5dd7070Spatrick 
100e5dd7070Spatrick   addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
101e5dd7070Spatrick   addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
102e5dd7070Spatrick 
103e5dd7070Spatrick   addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
104e5dd7070Spatrick   addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
105e5dd7070Spatrick 
106ec727ea7Spatrick   Generic_GCC::AddMultiarchPaths(D, SysRoot, OSLibDir, Paths);
107ec727ea7Spatrick 
108ec727ea7Spatrick   // Similar to the logic for GCC above, if we are currently running Clang
109ec727ea7Spatrick   // inside of the requested system root, add its parent library path to those
110ec727ea7Spatrick   // searched.
111e5dd7070Spatrick   // FIXME: It's not clear whether we should use the driver's installed
112e5dd7070Spatrick   // directory ('Dir' below) or the ResourceDir.
113e5dd7070Spatrick   if (StringRef(D.Dir).startswith(SysRoot))
114e5dd7070Spatrick     addPathIfExists(D, D.Dir + "/../lib", Paths);
115e5dd7070Spatrick 
116e5dd7070Spatrick   addPathIfExists(D, SysRoot + "/lib", Paths);
117e5dd7070Spatrick   addPathIfExists(D, SysRoot + "/usr/lib", Paths);
118e5dd7070Spatrick }
119e5dd7070Spatrick 
HasNativeLLVMSupport() const120e5dd7070Spatrick bool Hurd::HasNativeLLVMSupport() const { return true; }
121e5dd7070Spatrick 
buildLinker() const122e5dd7070Spatrick Tool *Hurd::buildLinker() const { return new tools::gnutools::Linker(*this); }
123e5dd7070Spatrick 
buildAssembler() const124e5dd7070Spatrick Tool *Hurd::buildAssembler() const {
125e5dd7070Spatrick   return new tools::gnutools::Assembler(*this);
126e5dd7070Spatrick }
127e5dd7070Spatrick 
getDynamicLinker(const ArgList & Args) const128e5dd7070Spatrick std::string Hurd::getDynamicLinker(const ArgList &Args) const {
129e5dd7070Spatrick   if (getArch() == llvm::Triple::x86)
130e5dd7070Spatrick     return "/lib/ld.so";
131e5dd7070Spatrick 
132e5dd7070Spatrick   llvm_unreachable("unsupported architecture");
133e5dd7070Spatrick }
134e5dd7070Spatrick 
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const135e5dd7070Spatrick void Hurd::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
136e5dd7070Spatrick                                      ArgStringList &CC1Args) const {
137e5dd7070Spatrick   const Driver &D = getDriver();
138e5dd7070Spatrick   std::string SysRoot = computeSysRoot();
139e5dd7070Spatrick 
140e5dd7070Spatrick   if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
141e5dd7070Spatrick     return;
142e5dd7070Spatrick 
143e5dd7070Spatrick   if (!DriverArgs.hasArg(options::OPT_nostdlibinc))
144e5dd7070Spatrick     addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
145e5dd7070Spatrick 
146e5dd7070Spatrick   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
147e5dd7070Spatrick     SmallString<128> P(D.ResourceDir);
148e5dd7070Spatrick     llvm::sys::path::append(P, "include");
149e5dd7070Spatrick     addSystemInclude(DriverArgs, CC1Args, P);
150e5dd7070Spatrick   }
151e5dd7070Spatrick 
152e5dd7070Spatrick   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
153e5dd7070Spatrick     return;
154e5dd7070Spatrick 
155e5dd7070Spatrick   // Check for configure-time C include directories.
156e5dd7070Spatrick   StringRef CIncludeDirs(C_INCLUDE_DIRS);
157e5dd7070Spatrick   if (CIncludeDirs != "") {
158e5dd7070Spatrick     SmallVector<StringRef, 5> Dirs;
159e5dd7070Spatrick     CIncludeDirs.split(Dirs, ":");
160e5dd7070Spatrick     for (StringRef Dir : Dirs) {
161e5dd7070Spatrick       StringRef Prefix =
162ec727ea7Spatrick           llvm::sys::path::is_absolute(Dir) ? "" : StringRef(SysRoot);
163e5dd7070Spatrick       addExternCSystemInclude(DriverArgs, CC1Args, Prefix + Dir);
164e5dd7070Spatrick     }
165e5dd7070Spatrick     return;
166e5dd7070Spatrick   }
167e5dd7070Spatrick 
168e5dd7070Spatrick   // Lacking those, try to detect the correct set of system includes for the
169e5dd7070Spatrick   // target triple.
170ec727ea7Spatrick 
171ec727ea7Spatrick   AddMultilibIncludeArgs(DriverArgs, CC1Args);
172ec727ea7Spatrick 
173*a9ac8606Spatrick   // On systems using multiarch, add /usr/include/$triple before
174*a9ac8606Spatrick   // /usr/include.
175*a9ac8606Spatrick   std::string MultiarchIncludeDir = getMultiarchTriple(D, getTriple(), SysRoot);
176*a9ac8606Spatrick   if (!MultiarchIncludeDir.empty() &&
177*a9ac8606Spatrick       D.getVFS().exists(SysRoot + "/usr/include/" + MultiarchIncludeDir))
178*a9ac8606Spatrick     addExternCSystemInclude(DriverArgs, CC1Args,
179*a9ac8606Spatrick                             SysRoot + "/usr/include/" + MultiarchIncludeDir);
180e5dd7070Spatrick 
181e5dd7070Spatrick   // Add an include of '/include' directly. This isn't provided by default by
182e5dd7070Spatrick   // system GCCs, but is often used with cross-compiling GCCs, and harmless to
183e5dd7070Spatrick   // add even when Clang is acting as-if it were a system compiler.
184e5dd7070Spatrick   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
185e5dd7070Spatrick 
186e5dd7070Spatrick   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
187e5dd7070Spatrick }
188389bb291Spatrick 
addLibStdCxxIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const189*a9ac8606Spatrick void Hurd::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
190*a9ac8606Spatrick                                     llvm::opt::ArgStringList &CC1Args) const {
191*a9ac8606Spatrick   // We need a detected GCC installation on Linux to provide libstdc++'s
192*a9ac8606Spatrick   // headers in odd Linuxish places.
193*a9ac8606Spatrick   if (!GCCInstallation.isValid())
194*a9ac8606Spatrick     return;
195*a9ac8606Spatrick 
196*a9ac8606Spatrick   StringRef TripleStr = GCCInstallation.getTriple().str();
197*a9ac8606Spatrick   StringRef DebianMultiarch =
198*a9ac8606Spatrick       GCCInstallation.getTriple().getArch() == llvm::Triple::x86 ? "i386-gnu"
199*a9ac8606Spatrick                                                                  : TripleStr;
200*a9ac8606Spatrick 
201*a9ac8606Spatrick   addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args, DebianMultiarch);
202*a9ac8606Spatrick }
203*a9ac8606Spatrick 
addExtraOpts(llvm::opt::ArgStringList & CmdArgs) const204389bb291Spatrick void Hurd::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {
205389bb291Spatrick   for (const auto &Opt : ExtraOpts)
206389bb291Spatrick     CmdArgs.push_back(Opt.c_str());
207389bb291Spatrick }
208