1 //===--- Gnu.h - Gnu Tool and 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 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H
10 #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H
13 #include "LazyDetector.h"
15 #include "clang/Driver/Tool.h"
16 #include "clang/Driver/ToolChain.h"
22 struct DetectedMultilibs
{
23 /// The set of multilibs that the detected installation supports.
24 MultilibSet Multilibs
;
26 /// The multilibs appropriate for the given flags.
27 llvm::SmallVector
<Multilib
> SelectedMultilibs
;
29 /// On Biarch systems, this corresponds to the default multilib when
30 /// targeting the non-default multilib. Otherwise, it is empty.
31 std::optional
<Multilib
> BiarchSibling
;
34 bool findMIPSMultilibs(const Driver
&D
, const llvm::Triple
&TargetTriple
,
35 StringRef Path
, const llvm::opt::ArgList
&Args
,
36 DetectedMultilibs
&Result
);
40 /// Directly call GNU Binutils' assembler and linker.
42 class LLVM_LIBRARY_VISIBILITY Assembler
: public Tool
{
44 Assembler(const ToolChain
&TC
) : Tool("GNU::Assembler", "assembler", TC
) {}
46 bool hasIntegratedCPP() const override
{ return false; }
48 void ConstructJob(Compilation
&C
, const JobAction
&JA
,
49 const InputInfo
&Output
, const InputInfoList
&Inputs
,
50 const llvm::opt::ArgList
&TCArgs
,
51 const char *LinkingOutput
) const override
;
54 class LLVM_LIBRARY_VISIBILITY Linker
: public Tool
{
56 Linker(const ToolChain
&TC
) : Tool("GNU::Linker", "linker", TC
) {}
58 bool hasIntegratedCPP() const override
{ return false; }
59 bool isLinkJob() const override
{ return true; }
61 void ConstructJob(Compilation
&C
, const JobAction
&JA
,
62 const InputInfo
&Output
, const InputInfoList
&Inputs
,
63 const llvm::opt::ArgList
&TCArgs
,
64 const char *LinkingOutput
) const override
;
67 class LLVM_LIBRARY_VISIBILITY StaticLibTool
: public Tool
{
69 StaticLibTool(const ToolChain
&TC
)
70 : Tool("GNU::StaticLibTool", "static-lib-linker", TC
) {}
72 bool hasIntegratedCPP() const override
{ return false; }
73 bool isLinkJob() const override
{ return true; }
75 void ConstructJob(Compilation
&C
, const JobAction
&JA
,
76 const InputInfo
&Output
, const InputInfoList
&Inputs
,
77 const llvm::opt::ArgList
&TCArgs
,
78 const char *LinkingOutput
) const override
;
80 } // end namespace gnutools
82 /// gcc - Generic GCC tool implementations.
84 class LLVM_LIBRARY_VISIBILITY Common
: public Tool
{
86 Common(const char *Name
, const char *ShortName
, const ToolChain
&TC
)
87 : Tool(Name
, ShortName
, TC
) {}
89 // A gcc tool has an "integrated" assembler that it will call to produce an
90 // object. Let it use that assembler so that we don't have to deal with
91 // assembly syntax incompatibilities.
92 bool hasIntegratedAssembler() const override
{ return true; }
93 void ConstructJob(Compilation
&C
, const JobAction
&JA
,
94 const InputInfo
&Output
, const InputInfoList
&Inputs
,
95 const llvm::opt::ArgList
&TCArgs
,
96 const char *LinkingOutput
) const override
;
98 /// RenderExtraToolArgs - Render any arguments necessary to force
99 /// the particular tool mode.
100 virtual void RenderExtraToolArgs(const JobAction
&JA
,
101 llvm::opt::ArgStringList
&CmdArgs
) const = 0;
104 class LLVM_LIBRARY_VISIBILITY Preprocessor
: public Common
{
106 Preprocessor(const ToolChain
&TC
)
107 : Common("gcc::Preprocessor", "gcc preprocessor", TC
) {}
109 bool hasGoodDiagnostics() const override
{ return true; }
110 bool hasIntegratedCPP() const override
{ return false; }
112 void RenderExtraToolArgs(const JobAction
&JA
,
113 llvm::opt::ArgStringList
&CmdArgs
) const override
;
116 class LLVM_LIBRARY_VISIBILITY Compiler
: public Common
{
118 Compiler(const ToolChain
&TC
) : Common("gcc::Compiler", "gcc frontend", TC
) {}
120 bool hasGoodDiagnostics() const override
{ return true; }
121 bool hasIntegratedCPP() const override
{ return true; }
123 void RenderExtraToolArgs(const JobAction
&JA
,
124 llvm::opt::ArgStringList
&CmdArgs
) const override
;
127 class LLVM_LIBRARY_VISIBILITY Linker
: public Common
{
129 Linker(const ToolChain
&TC
) : Common("gcc::Linker", "linker (via gcc)", TC
) {}
131 bool hasIntegratedCPP() const override
{ return false; }
132 bool isLinkJob() const override
{ return true; }
134 void RenderExtraToolArgs(const JobAction
&JA
,
135 llvm::opt::ArgStringList
&CmdArgs
) const override
;
137 } // end namespace gcc
138 } // end namespace tools
140 namespace toolchains
{
142 /// Generic_GCC - A tool chain using the 'gcc' command to perform
143 /// all subcommands; this relies on gcc translating the majority of
144 /// command line options.
145 class LLVM_LIBRARY_VISIBILITY Generic_GCC
: public ToolChain
{
147 /// Struct to store and manipulate GCC versions.
149 /// We rely on assumptions about the form and structure of GCC version
150 /// numbers: they consist of at most three '.'-separated components, and each
151 /// component is a non-negative integer except for the last component. For
152 /// the last component we are very flexible in order to tolerate release
153 /// candidates or 'x' wildcards.
155 /// Note that the ordering established among GCCVersions is based on the
156 /// preferred version string to use. For example we prefer versions without
157 /// a hard-coded patch number to those with a hard coded patch number.
159 /// Currently this doesn't provide any logic for textual suffixes to patches
160 /// in the way that (for example) Debian's version format does. If that ever
161 /// becomes necessary, it can be added.
163 /// The unparsed text of the version.
166 /// The parsed major, minor, and patch numbers.
167 int Major
, Minor
, Patch
;
169 /// The text of the parsed major, and major+minor versions.
170 std::string MajorStr
, MinorStr
;
172 /// Any textual suffix on the patch number.
173 std::string PatchSuffix
;
175 static GCCVersion
Parse(StringRef VersionText
);
176 bool isOlderThan(int RHSMajor
, int RHSMinor
, int RHSPatch
,
177 StringRef RHSPatchSuffix
= StringRef()) const;
178 bool operator<(const GCCVersion
&RHS
) const {
179 return isOlderThan(RHS
.Major
, RHS
.Minor
, RHS
.Patch
, RHS
.PatchSuffix
);
181 bool operator>(const GCCVersion
&RHS
) const { return RHS
< *this; }
182 bool operator<=(const GCCVersion
&RHS
) const { return !(*this > RHS
); }
183 bool operator>=(const GCCVersion
&RHS
) const { return !(*this < RHS
); }
186 /// This is a class to find a viable GCC installation for Clang to
189 /// This class tries to find a GCC installation on the system, and report
190 /// information about it. It starts from the host information provided to the
191 /// Driver, and has logic for fuzzing that where appropriate.
192 class GCCInstallationDetector
{
194 llvm::Triple GCCTriple
;
197 // FIXME: These might be better as path objects.
198 std::string GCCInstallPath
;
199 std::string GCCParentLibPath
;
201 /// The primary multilib appropriate for the given flags.
202 Multilib SelectedMultilib
;
203 /// On Biarch systems, this corresponds to the default multilib when
204 /// targeting the non-default multilib. Otherwise, it is empty.
205 std::optional
<Multilib
> BiarchSibling
;
209 // We retain the list of install paths that were considered and rejected in
210 // order to print out detailed information in verbose mode.
211 std::set
<std::string
> CandidateGCCInstallPaths
;
213 /// The set of multilibs that the detected installation supports.
214 MultilibSet Multilibs
;
216 // Gentoo-specific toolchain configurations are stored here.
217 const std::string GentooConfigDir
= "/etc/env.d/gcc";
220 explicit GCCInstallationDetector(const Driver
&D
) : IsValid(false), D(D
) {}
221 void init(const llvm::Triple
&TargetTriple
, const llvm::opt::ArgList
&Args
);
223 /// Check whether we detected a valid GCC install.
224 bool isValid() const { return IsValid
; }
226 /// Get the GCC triple for the detected install.
227 const llvm::Triple
&getTriple() const { return GCCTriple
; }
229 /// Get the detected GCC installation path.
230 StringRef
getInstallPath() const { return GCCInstallPath
; }
232 /// Get the detected GCC parent lib path.
233 StringRef
getParentLibPath() const { return GCCParentLibPath
; }
235 /// Get the detected Multilib
236 const Multilib
&getMultilib() const { return SelectedMultilib
; }
238 /// Get the whole MultilibSet
239 const MultilibSet
&getMultilibs() const { return Multilibs
; }
241 /// Get the biarch sibling multilib (if it exists).
242 /// \return true iff such a sibling exists
243 bool getBiarchSibling(Multilib
&M
) const;
245 /// Get the detected GCC version string.
246 const GCCVersion
&getVersion() const { return Version
; }
248 /// Print information about the detected GCC installation.
249 void print(raw_ostream
&OS
) const;
253 CollectLibDirsAndTriples(const llvm::Triple
&TargetTriple
,
254 const llvm::Triple
&BiarchTriple
,
255 SmallVectorImpl
<StringRef
> &LibDirs
,
256 SmallVectorImpl
<StringRef
> &TripleAliases
,
257 SmallVectorImpl
<StringRef
> &BiarchLibDirs
,
258 SmallVectorImpl
<StringRef
> &BiarchTripleAliases
);
260 void AddDefaultGCCPrefixes(const llvm::Triple
&TargetTriple
,
261 SmallVectorImpl
<std::string
> &Prefixes
,
264 bool ScanGCCForMultilibs(const llvm::Triple
&TargetTriple
,
265 const llvm::opt::ArgList
&Args
,
267 bool NeedsBiarchSuffix
= false);
269 void ScanLibDirForGCCTriple(const llvm::Triple
&TargetArch
,
270 const llvm::opt::ArgList
&Args
,
271 const std::string
&LibDir
,
272 StringRef CandidateTriple
,
273 bool NeedsBiarchSuffix
, bool GCCDirExists
,
274 bool GCCCrossDirExists
);
276 bool ScanGentooConfigs(const llvm::Triple
&TargetTriple
,
277 const llvm::opt::ArgList
&Args
,
278 const SmallVectorImpl
<StringRef
> &CandidateTriples
,
279 const SmallVectorImpl
<StringRef
> &BiarchTriples
);
281 bool ScanGentooGccConfig(const llvm::Triple
&TargetTriple
,
282 const llvm::opt::ArgList
&Args
,
283 StringRef CandidateTriple
,
284 bool NeedsBiarchSuffix
= false);
288 GCCInstallationDetector GCCInstallation
;
289 LazyDetector
<CudaInstallationDetector
> CudaInstallation
;
290 LazyDetector
<RocmInstallationDetector
> RocmInstallation
;
293 Generic_GCC(const Driver
&D
, const llvm::Triple
&Triple
,
294 const llvm::opt::ArgList
&Args
);
295 ~Generic_GCC() override
;
297 void printVerboseInfo(raw_ostream
&OS
) const override
;
300 getDefaultUnwindTableLevel(const llvm::opt::ArgList
&Args
) const override
;
301 bool isPICDefault() const override
;
302 bool isPIEDefault(const llvm::opt::ArgList
&Args
) const override
;
303 bool isPICDefaultForced() const override
;
304 bool IsIntegratedAssemblerDefault() const override
;
305 llvm::opt::DerivedArgList
*
306 TranslateArgs(const llvm::opt::DerivedArgList
&Args
, StringRef BoundArch
,
307 Action::OffloadKind DeviceOffloadKind
) const override
;
310 Tool
*getTool(Action::ActionClass AC
) const override
;
311 Tool
*buildAssembler() const override
;
312 Tool
*buildLinker() const override
;
314 /// \name ToolChain Implementation Helper Functions
317 /// Check whether the target triple's architecture is 64-bits.
318 bool isTarget64Bit() const { return getTriple().isArch64Bit(); }
320 /// Check whether the target triple's architecture is 32-bits.
321 bool isTarget32Bit() const { return getTriple().isArch32Bit(); }
323 void PushPPaths(ToolChain::path_list
&PPaths
);
324 void AddMultilibPaths(const Driver
&D
, const std::string
&SysRoot
,
325 const std::string
&OSLibDir
,
326 const std::string
&MultiarchTriple
,
328 void AddMultiarchPaths(const Driver
&D
, const std::string
&SysRoot
,
329 const std::string
&OSLibDir
, path_list
&Paths
);
330 void AddMultilibIncludeArgs(const llvm::opt::ArgList
&DriverArgs
,
331 llvm::opt::ArgStringList
&CC1Args
) const;
333 // FIXME: This should be final, but the CrossWindows toolchain does weird
334 // things that can't be easily generalized.
335 void AddClangCXXStdlibIncludeArgs(
336 const llvm::opt::ArgList
&DriverArgs
,
337 llvm::opt::ArgStringList
&CC1Args
) const override
;
340 addLibCxxIncludePaths(const llvm::opt::ArgList
&DriverArgs
,
341 llvm::opt::ArgStringList
&CC1Args
) const;
343 addLibStdCxxIncludePaths(const llvm::opt::ArgList
&DriverArgs
,
344 llvm::opt::ArgStringList
&CC1Args
) const;
346 bool addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList
&DriverArgs
,
347 llvm::opt::ArgStringList
&CC1Args
,
348 StringRef DebianMultiarch
) const;
350 bool addLibStdCXXIncludePaths(Twine IncludeDir
, StringRef Triple
,
352 const llvm::opt::ArgList
&DriverArgs
,
353 llvm::opt::ArgStringList
&CC1Args
,
354 bool DetectDebian
= false) const;
359 mutable std::unique_ptr
<tools::gcc::Preprocessor
> Preprocess
;
360 mutable std::unique_ptr
<tools::gcc::Compiler
> Compile
;
363 class LLVM_LIBRARY_VISIBILITY Generic_ELF
: public Generic_GCC
{
364 virtual void anchor();
367 Generic_ELF(const Driver
&D
, const llvm::Triple
&Triple
,
368 const llvm::opt::ArgList
&Args
)
369 : Generic_GCC(D
, Triple
, Args
) {}
371 void addClangTargetOptions(const llvm::opt::ArgList
&DriverArgs
,
372 llvm::opt::ArgStringList
&CC1Args
,
373 Action::OffloadKind DeviceOffloadKind
) const override
;
375 virtual std::string
getDynamicLinker(const llvm::opt::ArgList
&Args
) const {
379 virtual void addExtraOpts(llvm::opt::ArgStringList
&CmdArgs
) const {}
382 } // end namespace toolchains
383 } // end namespace driver
384 } // end namespace clang
386 #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H