/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/Hurd.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
17 | | using namespace clang::driver; |
18 | | using namespace clang::driver::toolchains; |
19 | | using namespace clang; |
20 | | using namespace llvm::opt; |
21 | | |
22 | | using 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. |
30 | | std::string Hurd::getMultiarchTriple(const Driver &D, |
31 | | const llvm::Triple &TargetTriple, |
32 | 9 | StringRef SysRoot) const { |
33 | 9 | 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 | 8 | if (D.getVFS().exists(SysRoot + "/lib/i386-gnu")) |
39 | 6 | return "i386-gnu"; |
40 | 8 | } |
41 | | |
42 | | // For most architectures, just use whatever we have rather than trying to be |
43 | | // clever. |
44 | 3 | return TargetTriple.str(); |
45 | 9 | } |
46 | | |
47 | 5 | 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. |
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 | 5 | if (Triple.getArch() == llvm::Triple::x86) |
59 | 4 | return "lib32"; |
60 | | |
61 | 1 | return Triple.isArch32Bit() ? "lib"0 : "lib64"; |
62 | 5 | } |
63 | | |
64 | | Hurd::Hurd(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) |
65 | 5 | : Generic_ELF(D, Triple, Args) { |
66 | 5 | GCCInstallation.init(Triple, Args); |
67 | 5 | Multilibs = GCCInstallation.getMultilibs(); |
68 | 5 | SelectedMultilibs.assign({GCCInstallation.getMultilib()}); |
69 | 5 | std::string SysRoot = computeSysRoot(); |
70 | 5 | ToolChain::path_list &PPaths = getProgramPaths(); |
71 | | |
72 | 5 | Generic_GCC::PushPPaths(PPaths); |
73 | | |
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 |
78 | | // to the link paths. |
79 | 5 | path_list &Paths = getFilePaths(); |
80 | | |
81 | 5 | const std::string OSLibDir = std::string(getOSLibDir(Triple, Args)); |
82 | 5 | const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot); |
83 | | |
84 | | #ifdef ENABLE_LINKER_BUILD_ID |
85 | | ExtraOpts.push_back("--build-id"); |
86 | | #endif |
87 | | |
88 | 5 | Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths); |
89 | | |
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 |
92 | | // those searched. |
93 | | // FIXME: It's not clear whether we should use the driver's installed |
94 | | // directory ('Dir' below) or the ResourceDir. |
95 | 5 | if (StringRef(D.Dir).startswith(SysRoot)) { |
96 | 2 | addPathIfExists(D, D.Dir + "/../lib/" + MultiarchTriple, Paths); |
97 | 2 | addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths); |
98 | 2 | } |
99 | | |
100 | 5 | addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths); |
101 | 5 | addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths); |
102 | | |
103 | 5 | addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths); |
104 | 5 | addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths); |
105 | | |
106 | 5 | Generic_GCC::AddMultiarchPaths(D, SysRoot, OSLibDir, Paths); |
107 | | |
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 |
110 | | // searched. |
111 | | // FIXME: It's not clear whether we should use the driver's installed |
112 | | // directory ('Dir' below) or the ResourceDir. |
113 | 5 | if (StringRef(D.Dir).startswith(SysRoot)) |
114 | 2 | addPathIfExists(D, D.Dir + "/../lib", Paths); |
115 | | |
116 | 5 | addPathIfExists(D, SysRoot + "/lib", Paths); |
117 | 5 | addPathIfExists(D, SysRoot + "/usr/lib", Paths); |
118 | 5 | } |
119 | | |
120 | 4 | bool Hurd::HasNativeLLVMSupport() const { return true; } |
121 | | |
122 | 4 | Tool *Hurd::buildLinker() const { return new tools::gnutools::Linker(*this); } |
123 | | |
124 | 1 | Tool *Hurd::buildAssembler() const { |
125 | 1 | return new tools::gnutools::Assembler(*this); |
126 | 1 | } |
127 | | |
128 | 2 | std::string Hurd::getDynamicLinker(const ArgList &Args) const { |
129 | 2 | if (getArch() == llvm::Triple::x86) |
130 | 2 | return "/lib/ld.so"; |
131 | | |
132 | 0 | llvm_unreachable("unsupported architecture"); |
133 | 0 | } |
134 | | |
135 | | void Hurd::AddClangSystemIncludeArgs(const ArgList &DriverArgs, |
136 | 5 | ArgStringList &CC1Args) const { |
137 | 5 | const Driver &D = getDriver(); |
138 | 5 | std::string SysRoot = computeSysRoot(); |
139 | | |
140 | 5 | if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc)) |
141 | 1 | return; |
142 | | |
143 | 4 | if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) |
144 | 4 | addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include"); |
145 | | |
146 | 4 | if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { |
147 | 4 | SmallString<128> P(D.ResourceDir); |
148 | 4 | llvm::sys::path::append(P, "include"); |
149 | 4 | addSystemInclude(DriverArgs, CC1Args, P); |
150 | 4 | } |
151 | | |
152 | 4 | if (DriverArgs.hasArg(options::OPT_nostdlibinc)) |
153 | 0 | return; |
154 | | |
155 | | // Check for configure-time C include directories. |
156 | 4 | StringRef CIncludeDirs(C_INCLUDE_DIRS); |
157 | 4 | if (CIncludeDirs != "") { |
158 | 0 | SmallVector<StringRef, 5> Dirs; |
159 | 0 | CIncludeDirs.split(Dirs, ":"); |
160 | 0 | for (StringRef Dir : Dirs) { |
161 | 0 | StringRef Prefix = |
162 | 0 | llvm::sys::path::is_absolute(Dir) ? "" : StringRef(SysRoot); |
163 | 0 | addExternCSystemInclude(DriverArgs, CC1Args, Prefix + Dir); |
164 | 0 | } |
165 | 0 | return; |
166 | 0 | } |
167 | | |
168 | | // Lacking those, try to detect the correct set of system includes for the |
169 | | // target triple. |
170 | | |
171 | 4 | AddMultilibIncludeArgs(DriverArgs, CC1Args); |
172 | | |
173 | | // On systems using multiarch, add /usr/include/$triple before |
174 | | // /usr/include. |
175 | 4 | std::string MultiarchIncludeDir = getMultiarchTriple(D, getTriple(), SysRoot); |
176 | 4 | if (!MultiarchIncludeDir.empty() && |
177 | 4 | D.getVFS().exists(SysRoot + "/usr/include/" + MultiarchIncludeDir)) |
178 | 3 | addExternCSystemInclude(DriverArgs, CC1Args, |
179 | 3 | SysRoot + "/usr/include/" + MultiarchIncludeDir); |
180 | | |
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 | 4 | addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include"); |
185 | | |
186 | 4 | addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include"); |
187 | 4 | } |
188 | | |
189 | | void Hurd::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, |
190 | 4 | 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 | 4 | if (!GCCInstallation.isValid()) |
194 | 0 | return; |
195 | | |
196 | 4 | StringRef TripleStr = GCCInstallation.getTriple().str(); |
197 | 4 | StringRef DebianMultiarch = |
198 | 4 | GCCInstallation.getTriple().getArch() == llvm::Triple::x86 ? "i386-gnu" |
199 | 4 | : TripleStr0 ; |
200 | | |
201 | 4 | addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args, DebianMultiarch); |
202 | 4 | } |
203 | | |
204 | 4 | void Hurd::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const { |
205 | 4 | for (const auto &Opt : ExtraOpts) |
206 | 0 | CmdArgs.push_back(Opt.c_str()); |
207 | 4 | } |