1 //===--- Hurd.cpp - Hurd ToolChain Implementations --------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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"
17 using namespace clang::driver
;
18 using namespace clang::driver::toolchains
;
19 using namespace clang
;
20 using namespace llvm::opt
;
22 using tools::addPathIfExists
;
24 /// Get our best guess at the multiarch triple for a target.
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.
30 std::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"))
42 // For most architectures, just use whatever we have rather than trying to be
44 return TargetTriple
.str();
47 static 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.
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.
58 if (Triple
.getArch() == llvm::Triple::x86
)
61 return Triple
.isArch32Bit() ? "lib" : "lib64";
64 Hurd::Hurd(const Driver
&D
, const llvm::Triple
&Triple
, const ArgList
&Args
)
65 : Generic_ELF(D
, Triple
, Args
) {
66 GCCInstallation
.init(Triple
, Args
);
67 Multilibs
= GCCInstallation
.getMultilibs();
68 SelectedMultilib
= GCCInstallation
.getMultilib();
69 std::string SysRoot
= computeSysRoot();
70 ToolChain::path_list
&PPaths
= getProgramPaths();
72 Generic_GCC::PushPPaths(PPaths
);
74 // The selection of paths to try here is designed to match the patterns which
75 // the GCC driver itself uses, as this is part of the GCC-compatible driver.
76 // This was determined by running GCC in a fake filesystem, creating all
77 // possible permutations of these directories, and seeing which ones it added
79 path_list
&Paths
= getFilePaths();
81 const std::string OSLibDir
= std::string(getOSLibDir(Triple
, Args
));
82 const std::string MultiarchTriple
= getMultiarchTriple(D
, Triple
, SysRoot
);
84 #ifdef ENABLE_LINKER_BUILD_ID
85 ExtraOpts
.push_back("--build-id");
88 Generic_GCC::AddMultilibPaths(D
, SysRoot
, OSLibDir
, MultiarchTriple
, Paths
);
90 // Similar to the logic for GCC above, if we currently running Clang inside
91 // of the requested system root, add its parent library paths to
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/" + MultiarchTriple
, Paths
);
97 addPathIfExists(D
, D
.Dir
+ "/../" + OSLibDir
, Paths
);
100 addPathIfExists(D
, SysRoot
+ "/lib/" + MultiarchTriple
, Paths
);
101 addPathIfExists(D
, SysRoot
+ "/lib/../" + OSLibDir
, Paths
);
103 addPathIfExists(D
, SysRoot
+ "/usr/lib/" + MultiarchTriple
, Paths
);
104 addPathIfExists(D
, SysRoot
+ "/usr/lib/../" + OSLibDir
, Paths
);
106 Generic_GCC::AddMultiarchPaths(D
, SysRoot
, OSLibDir
, Paths
);
108 // Similar to the logic for GCC above, if we are currently running Clang
109 // inside of the requested system root, add its parent library path to those
111 // FIXME: It's not clear whether we should use the driver's installed
112 // directory ('Dir' below) or the ResourceDir.
113 if (StringRef(D
.Dir
).startswith(SysRoot
))
114 addPathIfExists(D
, D
.Dir
+ "/../lib", Paths
);
116 addPathIfExists(D
, SysRoot
+ "/lib", Paths
);
117 addPathIfExists(D
, SysRoot
+ "/usr/lib", Paths
);
120 bool Hurd::HasNativeLLVMSupport() const { return true; }
122 Tool
*Hurd::buildLinker() const { return new tools::gnutools::Linker(*this); }
124 Tool
*Hurd::buildAssembler() const {
125 return new tools::gnutools::Assembler(*this);
128 std::string
Hurd::getDynamicLinker(const ArgList
&Args
) const {
129 if (getArch() == llvm::Triple::x86
)
132 llvm_unreachable("unsupported architecture");
135 void Hurd::AddClangSystemIncludeArgs(const ArgList
&DriverArgs
,
136 ArgStringList
&CC1Args
) const {
137 const Driver
&D
= getDriver();
138 std::string SysRoot
= computeSysRoot();
140 if (DriverArgs
.hasArg(clang::driver::options::OPT_nostdinc
))
143 if (!DriverArgs
.hasArg(options::OPT_nostdlibinc
))
144 addSystemInclude(DriverArgs
, CC1Args
, SysRoot
+ "/usr/local/include");
146 if (!DriverArgs
.hasArg(options::OPT_nobuiltininc
)) {
147 SmallString
<128> P(D
.ResourceDir
);
148 llvm::sys::path::append(P
, "include");
149 addSystemInclude(DriverArgs
, CC1Args
, P
);
152 if (DriverArgs
.hasArg(options::OPT_nostdlibinc
))
155 // Check for configure-time C include directories.
156 StringRef
CIncludeDirs(C_INCLUDE_DIRS
);
157 if (CIncludeDirs
!= "") {
158 SmallVector
<StringRef
, 5> Dirs
;
159 CIncludeDirs
.split(Dirs
, ":");
160 for (StringRef Dir
: Dirs
) {
162 llvm::sys::path::is_absolute(Dir
) ? "" : StringRef(SysRoot
);
163 addExternCSystemInclude(DriverArgs
, CC1Args
, Prefix
+ Dir
);
168 // Lacking those, try to detect the correct set of system includes for the
171 AddMultilibIncludeArgs(DriverArgs
, CC1Args
);
173 // On systems using multiarch, add /usr/include/$triple before
175 std::string MultiarchIncludeDir
= getMultiarchTriple(D
, getTriple(), SysRoot
);
176 if (!MultiarchIncludeDir
.empty() &&
177 D
.getVFS().exists(SysRoot
+ "/usr/include/" + MultiarchIncludeDir
))
178 addExternCSystemInclude(DriverArgs
, CC1Args
,
179 SysRoot
+ "/usr/include/" + MultiarchIncludeDir
);
181 // Add an include of '/include' directly. This isn't provided by default by
182 // system GCCs, but is often used with cross-compiling GCCs, and harmless to
183 // add even when Clang is acting as-if it were a system compiler.
184 addExternCSystemInclude(DriverArgs
, CC1Args
, SysRoot
+ "/include");
186 addExternCSystemInclude(DriverArgs
, CC1Args
, SysRoot
+ "/usr/include");
189 void Hurd::addLibStdCxxIncludePaths(const llvm::opt::ArgList
&DriverArgs
,
190 llvm::opt::ArgStringList
&CC1Args
) const {
191 // We need a detected GCC installation on Linux to provide libstdc++'s
192 // headers in odd Linuxish places.
193 if (!GCCInstallation
.isValid())
196 StringRef TripleStr
= GCCInstallation
.getTriple().str();
197 StringRef DebianMultiarch
=
198 GCCInstallation
.getTriple().getArch() == llvm::Triple::x86
? "i386-gnu"
201 addGCCLibStdCxxIncludePaths(DriverArgs
, CC1Args
, DebianMultiarch
);
204 void Hurd::addExtraOpts(llvm::opt::ArgStringList
&CmdArgs
) const {
205 for (const auto &Opt
: ExtraOpts
)
206 CmdArgs
.push_back(Opt
.c_str());