1 //! [Flexible target specification.](https://github.com/rust-lang/rfcs/pull/131)
3 //! Rust targets a wide variety of usecases, and in the interest of flexibility,
4 //! allows new target triples to be defined in configuration files. Most users
5 //! will not need to care about these, but this is invaluable when porting Rust
6 //! to a new platform, and allows for an unprecedented level of control over how
7 //! the compiler works.
9 //! # Using custom targets
11 //! A target triple, as passed via `rustc --target=TRIPLE`, will first be
12 //! compared against the list of built-in targets. This is to ease distributing
13 //! rustc (no need for configuration files) and also to hold these built-in
14 //! targets as immutable and sacred. If `TRIPLE` is not one of the built-in
15 //! targets, rustc will check if a file named `TRIPLE` exists. If it does, it
16 //! will be loaded as the target configuration. If the file does not exist,
17 //! rustc will search each directory in the environment variable
18 //! `RUST_TARGET_PATH` for a file named `TRIPLE.json`. The first one found will
19 //! be loaded. If no file is found in any of those directories, a fatal error
22 //! Projects defining their own targets should use
23 //! `--target=path/to/my-awesome-platform.json` instead of adding to
24 //! `RUST_TARGET_PATH`.
26 //! # Defining a new target
28 //! Targets are defined using [JSON](https://json.org/). The `Target` struct in
29 //! this module defines the format the JSON file should take, though each
30 //! underscore in the field names should be replaced with a hyphen (`-`) in the
31 //! JSON file. Some fields are required in every target specification, such as
32 //! `llvm-target`, `target-endian`, `target-pointer-width`, `data-layout`,
33 //! `arch`, and `os`. In general, options passed to rustc with `-C` override
34 //! the target's settings, though `target-feature` and `link-args` will *add*
35 //! to the list specified by the target, rather than replace.
37 use crate::abi
::call
::Conv
;
38 use crate::abi
::{Endian, Integer, Size, TargetDataLayout, TargetDataLayoutErrors}
;
39 use crate::json
::{Json, ToJson}
;
40 use crate::spec
::abi
::{lookup as lookup_abi, Abi}
;
41 use crate::spec
::crt_objects
::{CrtObjects, LinkSelfContainedDefault}
;
42 use rustc_data_structures
::stable_hasher
::{HashStable, StableHasher}
;
43 use rustc_serialize
::{Decodable, Decoder, Encodable, Encoder}
;
44 use rustc_span
::symbol
::{sym, Symbol}
;
45 use serde_json
::Value
;
47 use std
::collections
::BTreeMap
;
48 use std
::hash
::{Hash, Hasher}
;
49 use std
::ops
::{Deref, DerefMut}
;
50 use std
::path
::{Path, PathBuf}
;
51 use std
::str::FromStr
;
54 use rustc_macros
::HashStable_Generic
;
74 mod linux_uclibc_base
;
87 mod windows_gnullvm_base
;
88 mod windows_msvc_base
;
89 mod windows_uwp_gnu_base
;
90 mod windows_uwp_msvc_base
;
92 /// Linker is called through a C/C++ compiler.
93 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
100 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
106 /// All linkers have some kinds of command line interfaces and rustc needs to know which commands
107 /// to use with each of them. So we cluster all such interfaces into a (somewhat arbitrary) number
108 /// of classes that we call "linker flavors".
110 /// Technically, it's not even necessary, we can nearly always infer the flavor from linker name
111 /// and target properties like `is_like_windows`/`is_like_osx`/etc. However, the PRs originally
112 /// introducing `-Clinker-flavor` (#40018 and friends) were aiming to reduce this kind of inference
113 /// and provide something certain and explicitly specified instead, and that design goal is still
116 /// The second goal is to keep the number of flavors to the minimum if possible.
117 /// LLD somewhat forces our hand here because that linker is self-sufficient only if its executable
118 /// (`argv[0]`) is named in specific way, otherwise it doesn't work and requires a
119 /// `-flavor LLD_FLAVOR` argument to choose which logic to use. Our shipped `rust-lld` in
120 /// particular is not named in such specific way, so it needs the flavor option, so we make our
121 /// linker flavors sufficiently fine-grained to satisfy LLD without inferring its flavor from other
122 /// target properties, in accordance with the first design goal.
124 /// The first component of the flavor is tightly coupled with the compilation target,
125 /// while the `Cc` and `Lld` flags can vary withing the same target.
126 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
127 pub enum LinkerFlavor
{
128 /// Unix-like linker with GNU extensions (both naked and compiler-wrapped forms).
129 /// Besides similar "default" Linux/BSD linkers this also includes Windows/GNU linker,
130 /// which is somewhat different because it doesn't produce ELFs.
132 /// Unix-like linker for Apple targets (both naked and compiler-wrapped forms).
133 /// Extracted from the "umbrella" `Unix` flavor due to its corresponding LLD flavor.
135 /// Unix-like linker for Wasm targets (both naked and compiler-wrapped forms).
136 /// Extracted from the "umbrella" `Unix` flavor due to its corresponding LLD flavor.
137 /// Non-LLD version does not exist, so the lld flag is currently hardcoded here.
139 /// Basic Unix-like linker for "any other Unix" targets (Solaris/illumos, L4Re, MSP430, etc),
140 /// possibly with non-GNU extensions (both naked and compiler-wrapped forms).
141 /// LLD doesn't support any of these.
143 /// MSVC-style linker for Windows and UEFI, LLD supports it.
145 /// Emscripten Compiler Frontend, a wrapper around `WasmLld(Cc::Yes)` that has a different
146 /// interface and produces some additional JavaScript output.
148 // Below: other linker-like tools with unique interfaces for exotic targets.
149 /// Linker tool for BPF.
151 /// Linker tool for Nvidia PTX.
155 /// Linker flavors available externally through command line (`-Clinker-flavor`)
156 /// or json target specifications.
157 /// FIXME: This set has accumulated historically, bring it more in line with the internal
158 /// linker flavors (`LinkerFlavor`).
159 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
160 pub enum LinkerFlavorCli
{
170 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
179 pub fn as_str(&self) -> &'
static str {
181 LldFlavor
::Wasm
=> "wasm",
182 LldFlavor
::Ld64
=> "darwin",
183 LldFlavor
::Ld
=> "gnu",
184 LldFlavor
::Link
=> "link",
188 fn from_str(s
: &str) -> Option
<Self> {
190 "darwin" => LldFlavor
::Ld64
,
191 "gnu" => LldFlavor
::Ld
,
192 "link" => LldFlavor
::Link
,
193 "wasm" => LldFlavor
::Wasm
,
199 impl ToJson
for LldFlavor
{
200 fn to_json(&self) -> Json
{
201 self.as_str().to_json()
206 pub fn from_cli(cli
: LinkerFlavorCli
, target
: &TargetOptions
) -> LinkerFlavor
{
207 Self::from_cli_impl(cli
, target
.linker_flavor
.lld_flavor(), target
.linker_flavor
.is_gnu())
210 /// The passed CLI flavor is preferred over other args coming from the default target spec,
211 /// so this function can produce a flavor that is incompatible with the current target.
212 /// FIXME: Produce errors when `-Clinker-flavor` is set to something incompatible
213 /// with the current target.
214 fn from_cli_impl(cli
: LinkerFlavorCli
, lld_flavor
: LldFlavor
, is_gnu
: bool
) -> LinkerFlavor
{
216 LinkerFlavorCli
::Gcc
=> match lld_flavor
{
217 LldFlavor
::Ld
if is_gnu
=> LinkerFlavor
::Gnu(Cc
::Yes
, Lld
::No
),
218 LldFlavor
::Ld64
=> LinkerFlavor
::Darwin(Cc
::Yes
, Lld
::No
),
219 LldFlavor
::Wasm
=> LinkerFlavor
::WasmLld(Cc
::Yes
),
220 LldFlavor
::Ld
| LldFlavor
::Link
=> LinkerFlavor
::Unix(Cc
::Yes
),
222 LinkerFlavorCli
::Ld
=> match lld_flavor
{
223 LldFlavor
::Ld
if is_gnu
=> LinkerFlavor
::Gnu(Cc
::No
, Lld
::No
),
224 LldFlavor
::Ld64
=> LinkerFlavor
::Darwin(Cc
::No
, Lld
::No
),
225 LldFlavor
::Ld
| LldFlavor
::Wasm
| LldFlavor
::Link
=> LinkerFlavor
::Unix(Cc
::No
),
227 LinkerFlavorCli
::Lld(LldFlavor
::Ld
) => LinkerFlavor
::Gnu(Cc
::No
, Lld
::Yes
),
228 LinkerFlavorCli
::Lld(LldFlavor
::Ld64
) => LinkerFlavor
::Darwin(Cc
::No
, Lld
::Yes
),
229 LinkerFlavorCli
::Lld(LldFlavor
::Wasm
) => LinkerFlavor
::WasmLld(Cc
::No
),
230 LinkerFlavorCli
::Lld(LldFlavor
::Link
) => LinkerFlavor
::Msvc(Lld
::Yes
),
231 LinkerFlavorCli
::Msvc
=> LinkerFlavor
::Msvc(Lld
::No
),
232 LinkerFlavorCli
::Em
=> LinkerFlavor
::EmCc
,
233 LinkerFlavorCli
::BpfLinker
=> LinkerFlavor
::Bpf
,
234 LinkerFlavorCli
::PtxLinker
=> LinkerFlavor
::Ptx
,
238 fn to_cli(self) -> LinkerFlavorCli
{
240 LinkerFlavor
::Gnu(Cc
::Yes
, _
)
241 | LinkerFlavor
::Darwin(Cc
::Yes
, _
)
242 | LinkerFlavor
::WasmLld(Cc
::Yes
)
243 | LinkerFlavor
::Unix(Cc
::Yes
) => LinkerFlavorCli
::Gcc
,
244 LinkerFlavor
::Gnu(_
, Lld
::Yes
) => LinkerFlavorCli
::Lld(LldFlavor
::Ld
),
245 LinkerFlavor
::Darwin(_
, Lld
::Yes
) => LinkerFlavorCli
::Lld(LldFlavor
::Ld64
),
246 LinkerFlavor
::WasmLld(..) => LinkerFlavorCli
::Lld(LldFlavor
::Wasm
),
247 LinkerFlavor
::Gnu(..) | LinkerFlavor
::Darwin(..) | LinkerFlavor
::Unix(..) => {
250 LinkerFlavor
::Msvc(Lld
::Yes
) => LinkerFlavorCli
::Lld(LldFlavor
::Link
),
251 LinkerFlavor
::Msvc(..) => LinkerFlavorCli
::Msvc
,
252 LinkerFlavor
::EmCc
=> LinkerFlavorCli
::Em
,
253 LinkerFlavor
::Bpf
=> LinkerFlavorCli
::BpfLinker
,
254 LinkerFlavor
::Ptx
=> LinkerFlavorCli
::PtxLinker
,
258 pub fn lld_flavor(self) -> LldFlavor
{
260 LinkerFlavor
::Gnu(..)
261 | LinkerFlavor
::Unix(..)
264 | LinkerFlavor
::Ptx
=> LldFlavor
::Ld
,
265 LinkerFlavor
::Darwin(..) => LldFlavor
::Ld64
,
266 LinkerFlavor
::WasmLld(..) => LldFlavor
::Wasm
,
267 LinkerFlavor
::Msvc(..) => LldFlavor
::Link
,
271 pub fn is_gnu(self) -> bool
{
272 matches
!(self, LinkerFlavor
::Gnu(..))
276 macro_rules
! linker_flavor_cli_impls
{
277 ($
(($
($flavor
:tt
)*) $string
:literal
)*) => (
278 impl LinkerFlavorCli
{
279 pub const fn one_of() -> &'
static str {
280 concat
!("one of: ", $
($string
, " ",)*)
283 pub fn from_str(s
: &str) -> Option
<LinkerFlavorCli
> {
285 $
($string
=> $
($flavor
)*,)*
290 pub fn desc(&self) -> &str {
292 $
($
($flavor
)* => $string
,)*
299 linker_flavor_cli_impls
! {
300 (LinkerFlavorCli
::Gcc
) "gcc"
301 (LinkerFlavorCli
::Ld
) "ld"
302 (LinkerFlavorCli
::Lld(LldFlavor
::Ld
)) "ld.lld"
303 (LinkerFlavorCli
::Lld(LldFlavor
::Ld64
)) "ld64.lld"
304 (LinkerFlavorCli
::Lld(LldFlavor
::Link
)) "lld-link"
305 (LinkerFlavorCli
::Lld(LldFlavor
::Wasm
)) "wasm-ld"
306 (LinkerFlavorCli
::Msvc
) "msvc"
307 (LinkerFlavorCli
::Em
) "em"
308 (LinkerFlavorCli
::BpfLinker
) "bpf-linker"
309 (LinkerFlavorCli
::PtxLinker
) "ptx-linker"
312 impl ToJson
for LinkerFlavorCli
{
313 fn to_json(&self) -> Json
{
314 self.desc().to_json()
318 #[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
319 pub enum PanicStrategy
{
325 pub fn desc(&self) -> &str {
327 PanicStrategy
::Unwind
=> "unwind",
328 PanicStrategy
::Abort
=> "abort",
332 pub const fn desc_symbol(&self) -> Symbol
{
334 PanicStrategy
::Unwind
=> sym
::unwind
,
335 PanicStrategy
::Abort
=> sym
::abort
,
339 pub const fn all() -> [Symbol
; 2] {
340 [Self::Abort
.desc_symbol(), Self::Unwind
.desc_symbol()]
344 impl ToJson
for PanicStrategy
{
345 fn to_json(&self) -> Json
{
347 PanicStrategy
::Abort
=> "abort".to_json(),
348 PanicStrategy
::Unwind
=> "unwind".to_json(),
353 #[derive(Clone, Copy, Debug, PartialEq, Hash)]
354 pub enum RelroLevel
{
362 pub fn desc(&self) -> &str {
364 RelroLevel
::Full
=> "full",
365 RelroLevel
::Partial
=> "partial",
366 RelroLevel
::Off
=> "off",
367 RelroLevel
::None
=> "none",
372 impl FromStr
for RelroLevel
{
375 fn from_str(s
: &str) -> Result
<RelroLevel
, ()> {
377 "full" => Ok(RelroLevel
::Full
),
378 "partial" => Ok(RelroLevel
::Partial
),
379 "off" => Ok(RelroLevel
::Off
),
380 "none" => Ok(RelroLevel
::None
),
386 impl ToJson
for RelroLevel
{
387 fn to_json(&self) -> Json
{
389 RelroLevel
::Full
=> "full".to_json(),
390 RelroLevel
::Partial
=> "partial".to_json(),
391 RelroLevel
::Off
=> "off".to_json(),
392 RelroLevel
::None
=> "None".to_json(),
397 #[derive(Clone, Copy, Debug, PartialEq, Hash)]
398 pub enum MergeFunctions
{
404 impl MergeFunctions
{
405 pub fn desc(&self) -> &str {
407 MergeFunctions
::Disabled
=> "disabled",
408 MergeFunctions
::Trampolines
=> "trampolines",
409 MergeFunctions
::Aliases
=> "aliases",
414 impl FromStr
for MergeFunctions
{
417 fn from_str(s
: &str) -> Result
<MergeFunctions
, ()> {
419 "disabled" => Ok(MergeFunctions
::Disabled
),
420 "trampolines" => Ok(MergeFunctions
::Trampolines
),
421 "aliases" => Ok(MergeFunctions
::Aliases
),
427 impl ToJson
for MergeFunctions
{
428 fn to_json(&self) -> Json
{
430 MergeFunctions
::Disabled
=> "disabled".to_json(),
431 MergeFunctions
::Trampolines
=> "trampolines".to_json(),
432 MergeFunctions
::Aliases
=> "aliases".to_json(),
437 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
438 pub enum RelocModel
{
448 impl FromStr
for RelocModel
{
451 fn from_str(s
: &str) -> Result
<RelocModel
, ()> {
453 "static" => RelocModel
::Static
,
454 "pic" => RelocModel
::Pic
,
455 "pie" => RelocModel
::Pie
,
456 "dynamic-no-pic" => RelocModel
::DynamicNoPic
,
457 "ropi" => RelocModel
::Ropi
,
458 "rwpi" => RelocModel
::Rwpi
,
459 "ropi-rwpi" => RelocModel
::RopiRwpi
,
465 impl ToJson
for RelocModel
{
466 fn to_json(&self) -> Json
{
468 RelocModel
::Static
=> "static",
469 RelocModel
::Pic
=> "pic",
470 RelocModel
::Pie
=> "pie",
471 RelocModel
::DynamicNoPic
=> "dynamic-no-pic",
472 RelocModel
::Ropi
=> "ropi",
473 RelocModel
::Rwpi
=> "rwpi",
474 RelocModel
::RopiRwpi
=> "ropi-rwpi",
480 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
489 impl FromStr
for CodeModel
{
492 fn from_str(s
: &str) -> Result
<CodeModel
, ()> {
494 "tiny" => CodeModel
::Tiny
,
495 "small" => CodeModel
::Small
,
496 "kernel" => CodeModel
::Kernel
,
497 "medium" => CodeModel
::Medium
,
498 "large" => CodeModel
::Large
,
504 impl ToJson
for CodeModel
{
505 fn to_json(&self) -> Json
{
507 CodeModel
::Tiny
=> "tiny",
508 CodeModel
::Small
=> "small",
509 CodeModel
::Kernel
=> "kernel",
510 CodeModel
::Medium
=> "medium",
511 CodeModel
::Large
=> "large",
517 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
525 impl FromStr
for TlsModel
{
528 fn from_str(s
: &str) -> Result
<TlsModel
, ()> {
530 // Note the difference "general" vs "global" difference. The model name is "general",
531 // but the user-facing option name is "global" for consistency with other compilers.
532 "global-dynamic" => TlsModel
::GeneralDynamic
,
533 "local-dynamic" => TlsModel
::LocalDynamic
,
534 "initial-exec" => TlsModel
::InitialExec
,
535 "local-exec" => TlsModel
::LocalExec
,
541 impl ToJson
for TlsModel
{
542 fn to_json(&self) -> Json
{
544 TlsModel
::GeneralDynamic
=> "global-dynamic",
545 TlsModel
::LocalDynamic
=> "local-dynamic",
546 TlsModel
::InitialExec
=> "initial-exec",
547 TlsModel
::LocalExec
=> "local-exec",
553 /// Everything is flattened to a single enum to make the json encoding/decoding less annoying.
554 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
555 pub enum LinkOutputKind
{
556 /// Dynamically linked non position-independent executable.
558 /// Dynamically linked position-independent executable.
560 /// Statically linked non position-independent executable.
562 /// Statically linked position-independent executable.
564 /// Regular dynamic library ("dynamically linked").
566 /// Dynamic library with bundled libc ("statically linked").
568 /// WASI module with a lifetime past the _initialize entry point
572 impl LinkOutputKind
{
573 fn as_str(&self) -> &'
static str {
575 LinkOutputKind
::DynamicNoPicExe
=> "dynamic-nopic-exe",
576 LinkOutputKind
::DynamicPicExe
=> "dynamic-pic-exe",
577 LinkOutputKind
::StaticNoPicExe
=> "static-nopic-exe",
578 LinkOutputKind
::StaticPicExe
=> "static-pic-exe",
579 LinkOutputKind
::DynamicDylib
=> "dynamic-dylib",
580 LinkOutputKind
::StaticDylib
=> "static-dylib",
581 LinkOutputKind
::WasiReactorExe
=> "wasi-reactor-exe",
585 pub(super) fn from_str(s
: &str) -> Option
<LinkOutputKind
> {
587 "dynamic-nopic-exe" => LinkOutputKind
::DynamicNoPicExe
,
588 "dynamic-pic-exe" => LinkOutputKind
::DynamicPicExe
,
589 "static-nopic-exe" => LinkOutputKind
::StaticNoPicExe
,
590 "static-pic-exe" => LinkOutputKind
::StaticPicExe
,
591 "dynamic-dylib" => LinkOutputKind
::DynamicDylib
,
592 "static-dylib" => LinkOutputKind
::StaticDylib
,
593 "wasi-reactor-exe" => LinkOutputKind
::WasiReactorExe
,
599 impl fmt
::Display
for LinkOutputKind
{
600 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
601 f
.write_str(self.as_str())
605 pub type LinkArgs
= BTreeMap
<LinkerFlavor
, Vec
<StaticCow
<str>>>;
606 pub type LinkArgsCli
= BTreeMap
<LinkerFlavorCli
, Vec
<StaticCow
<str>>>;
608 /// Which kind of debuginfo does the target use?
610 /// Useful in determining whether a target supports Split DWARF (a target with
611 /// `DebuginfoKind::Dwarf` and supporting `SplitDebuginfo::Unpacked` for example).
612 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
613 pub enum DebuginfoKind
{
614 /// DWARF debuginfo (such as that used on `x86_64_unknown_linux_gnu`).
617 /// DWARF debuginfo in dSYM files (such as on Apple platforms).
619 /// Program database files (such as on Windows).
624 fn as_str(&self) -> &'
static str {
626 DebuginfoKind
::Dwarf
=> "dwarf",
627 DebuginfoKind
::DwarfDsym
=> "dwarf-dsym",
628 DebuginfoKind
::Pdb
=> "pdb",
633 impl FromStr
for DebuginfoKind
{
636 fn from_str(s
: &str) -> Result
<Self, ()> {
638 "dwarf" => DebuginfoKind
::Dwarf
,
639 "dwarf-dsym" => DebuginfoKind
::DwarfDsym
,
640 "pdb" => DebuginfoKind
::Pdb
,
646 impl ToJson
for DebuginfoKind
{
647 fn to_json(&self) -> Json
{
648 self.as_str().to_json()
652 impl fmt
::Display
for DebuginfoKind
{
653 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
654 f
.write_str(self.as_str())
658 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
659 pub enum SplitDebuginfo
{
660 /// Split debug-information is disabled, meaning that on supported platforms
661 /// you can find all debug information in the executable itself. This is
662 /// only supported for ELF effectively.
664 /// * Windows - not supported
665 /// * macOS - don't run `dsymutil`
666 /// * ELF - `.debug_*` sections
670 /// Split debug-information can be found in a "packed" location separate
671 /// from the final artifact. This is supported on all platforms.
673 /// * Windows - `*.pdb`
674 /// * macOS - `*.dSYM` (run `dsymutil`)
675 /// * ELF - `*.dwp` (run `thorin`)
678 /// Split debug-information can be found in individual object files on the
679 /// filesystem. The main executable may point to the object files.
681 /// * Windows - not supported
682 /// * macOS - supported, scattered object files
683 /// * ELF - supported, scattered `*.dwo` or `*.o` files (see `SplitDwarfKind`)
687 impl SplitDebuginfo
{
688 fn as_str(&self) -> &'
static str {
690 SplitDebuginfo
::Off
=> "off",
691 SplitDebuginfo
::Packed
=> "packed",
692 SplitDebuginfo
::Unpacked
=> "unpacked",
697 impl FromStr
for SplitDebuginfo
{
700 fn from_str(s
: &str) -> Result
<Self, ()> {
702 "off" => SplitDebuginfo
::Off
,
703 "unpacked" => SplitDebuginfo
::Unpacked
,
704 "packed" => SplitDebuginfo
::Packed
,
710 impl ToJson
for SplitDebuginfo
{
711 fn to_json(&self) -> Json
{
712 self.as_str().to_json()
716 impl fmt
::Display
for SplitDebuginfo
{
717 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
718 f
.write_str(self.as_str())
722 #[derive(Clone, Debug, PartialEq, Eq)]
723 pub enum StackProbeType
{
724 /// Don't emit any stack probes.
726 /// It is harmless to use this option even on targets that do not have backend support for
727 /// stack probes as the failure mode is the same as if no stack-probe option was specified in
730 /// Call `__rust_probestack` whenever stack needs to be probed.
732 /// Use inline option for LLVM versions later than specified in `min_llvm_version_for_inline`
733 /// and call `__rust_probestack` otherwise.
734 InlineOrCall { min_llvm_version_for_inline: (u32, u32, u32) }
,
737 impl StackProbeType
{
738 // LLVM X86 targets (ix86 and x86_64) can use inline-asm stack probes starting with LLVM 16.
739 // Notable past issues were rust#83139 (fixed in 14) and rust#84667 (fixed in 16).
740 const X86
: Self = Self::InlineOrCall { min_llvm_version_for_inline: (16, 0, 0) }
;
742 fn from_json(json
: &Json
) -> Result
<Self, String
> {
743 let object
= json
.as_object().ok_or_else(|| "expected a JSON object")?
;
746 .and_then(|o
| o
.as_str())
747 .ok_or_else(|| "expected `kind` to be a string")?
;
749 "none" => Ok(StackProbeType
::None
),
750 "inline" => Ok(StackProbeType
::Inline
),
751 "call" => Ok(StackProbeType
::Call
),
752 "inline-or-call" => {
753 let min_version
= object
754 .get("min-llvm-version-for-inline")
755 .and_then(|o
| o
.as_array())
756 .ok_or_else(|| "expected `min-llvm-version-for-inline` to be an array")?
;
757 let mut iter
= min_version
.into_iter().map(|v
| {
758 let int
= v
.as_u64().ok_or_else(
759 || "expected `min-llvm-version-for-inline` values to be integers",
762 .map_err(|_
| "`min-llvm-version-for-inline` values don't convert to u32")
764 let min_llvm_version_for_inline
= (
765 iter
.next().unwrap_or(Ok(11))?
,
766 iter
.next().unwrap_or(Ok(0))?
,
767 iter
.next().unwrap_or(Ok(0))?
,
769 Ok(StackProbeType
::InlineOrCall { min_llvm_version_for_inline }
)
771 _
=> Err(String
::from(
772 "`kind` expected to be one of `none`, `inline`, `call` or `inline-or-call`",
778 impl ToJson
for StackProbeType
{
779 fn to_json(&self) -> Json
{
780 Json
::Object(match self {
781 StackProbeType
::None
=> {
782 [(String
::from("kind"), "none".to_json())].into_iter().collect()
784 StackProbeType
::Inline
=> {
785 [(String
::from("kind"), "inline".to_json())].into_iter().collect()
787 StackProbeType
::Call
=> {
788 [(String
::from("kind"), "call".to_json())].into_iter().collect()
790 StackProbeType
::InlineOrCall { min_llvm_version_for_inline: (maj, min, patch) }
=> [
791 (String
::from("kind"), "inline-or-call".to_json()),
793 String
::from("min-llvm-version-for-inline"),
794 Json
::Array(vec
![maj
.to_json(), min
.to_json(), patch
.to_json()]),
803 bitflags
::bitflags
! {
804 #[derive(Default, Encodable, Decodable)]
805 pub struct SanitizerSet
: u16 {
806 const ADDRESS
= 1 << 0;
808 const MEMORY
= 1 << 2;
809 const THREAD
= 1 << 3;
810 const HWADDRESS
= 1 << 4;
812 const MEMTAG
= 1 << 6;
813 const SHADOWCALLSTACK
= 1 << 7;
819 /// Return sanitizer's name
821 /// Returns none if the flags is a set of sanitizers numbering not exactly one.
822 pub fn as_str(self) -> Option
<&'
static str> {
824 SanitizerSet
::ADDRESS
=> "address",
825 SanitizerSet
::CFI
=> "cfi",
826 SanitizerSet
::KCFI
=> "kcfi",
827 SanitizerSet
::LEAK
=> "leak",
828 SanitizerSet
::MEMORY
=> "memory",
829 SanitizerSet
::MEMTAG
=> "memtag",
830 SanitizerSet
::SHADOWCALLSTACK
=> "shadow-call-stack",
831 SanitizerSet
::THREAD
=> "thread",
832 SanitizerSet
::HWADDRESS
=> "hwaddress",
838 /// Formats a sanitizer set as a comma separated list of sanitizers' names.
839 impl fmt
::Display
for SanitizerSet
{
840 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
841 let mut first
= true;
843 let name
= s
.as_str().unwrap_or_else(|| panic
!("unrecognized sanitizer {s:?}"));
854 impl IntoIterator
for SanitizerSet
{
855 type Item
= SanitizerSet
;
856 type IntoIter
= std
::vec
::IntoIter
<SanitizerSet
>;
858 fn into_iter(self) -> Self::IntoIter
{
860 SanitizerSet
::ADDRESS
,
864 SanitizerSet
::MEMORY
,
865 SanitizerSet
::MEMTAG
,
866 SanitizerSet
::SHADOWCALLSTACK
,
867 SanitizerSet
::THREAD
,
868 SanitizerSet
::HWADDRESS
,
872 .filter(|&s
| self.contains(s
))
878 impl<CTX
> HashStable
<CTX
> for SanitizerSet
{
879 fn hash_stable(&self, ctx
: &mut CTX
, hasher
: &mut StableHasher
) {
880 self.bits().hash_stable(ctx
, hasher
);
884 impl ToJson
for SanitizerSet
{
885 fn to_json(&self) -> Json
{
887 .map(|v
| Some(v
.as_str()?
.to_json()))
888 .collect
::<Option
<Vec
<_
>>>()
894 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
895 pub enum FramePointer
{
896 /// Forces the machine code generator to always preserve the frame pointers.
898 /// Forces the machine code generator to preserve the frame pointers except for the leaf
899 /// functions (i.e. those that don't call other functions).
901 /// Allows the machine code generator to omit the frame pointers.
903 /// This option does not guarantee that the frame pointers will be omitted.
907 impl FromStr
for FramePointer
{
909 fn from_str(s
: &str) -> Result
<Self, ()> {
911 "always" => Self::Always
,
912 "non-leaf" => Self::NonLeaf
,
913 "may-omit" => Self::MayOmit
,
919 impl ToJson
for FramePointer
{
920 fn to_json(&self) -> Json
{
922 Self::Always
=> "always",
923 Self::NonLeaf
=> "non-leaf",
924 Self::MayOmit
=> "may-omit",
930 /// Controls use of stack canaries.
931 #[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)]
932 pub enum StackProtector
{
933 /// Disable stack canary generation.
936 /// On LLVM, mark all generated LLVM functions with the `ssp` attribute (see
937 /// llvm/docs/LangRef.rst). This triggers stack canary generation in
938 /// functions which contain an array of a byte-sized type with more than
942 /// On LLVM, mark all generated LLVM functions with the `sspstrong`
943 /// attribute (see llvm/docs/LangRef.rst). This triggers stack canary
944 /// generation in functions which either contain an array, or which take
945 /// the address of a local variable.
948 /// Generate stack canaries in all functions.
952 impl StackProtector
{
953 fn as_str(&self) -> &'
static str {
955 StackProtector
::None
=> "none",
956 StackProtector
::Basic
=> "basic",
957 StackProtector
::Strong
=> "strong",
958 StackProtector
::All
=> "all",
963 impl FromStr
for StackProtector
{
966 fn from_str(s
: &str) -> Result
<StackProtector
, ()> {
968 "none" => StackProtector
::None
,
969 "basic" => StackProtector
::Basic
,
970 "strong" => StackProtector
::Strong
,
971 "all" => StackProtector
::All
,
977 impl fmt
::Display
for StackProtector
{
978 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
979 f
.write_str(self.as_str())
983 macro_rules
! supported_targets
{
984 ( $
(($triple
:literal
, $module
:ident
),)+ ) => {
987 /// List of supported targets
988 pub const TARGETS
: &[&str] = &[$
($triple
),+];
990 fn load_builtin(target
: &str) -> Option
<Target
> {
991 let mut t
= match target
{
992 $
( $triple
=> $module
::target(), )+
996 debug
!("got builtin target: {:?}", t
);
1004 // Cannot put this into a separate file without duplication, make an exception.
1006 #[test] // `#[test]`
1008 tests_impl
::test_target(super::$module
::target());
1015 supported_targets
! {
1016 ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu
),
1017 ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32
),
1018 ("i686-unknown-linux-gnu", i686_unknown_linux_gnu
),
1019 ("i586-unknown-linux-gnu", i586_unknown_linux_gnu
),
1020 ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu
),
1021 ("mips-unknown-linux-gnu", mips_unknown_linux_gnu
),
1022 ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64
),
1023 ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64
),
1024 ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu
),
1025 ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu
),
1026 ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64
),
1027 ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64
),
1028 ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu
),
1029 ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu
),
1030 ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe
),
1031 ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl
),
1032 ("powerpc64-ibm-aix", powerpc64_ibm_aix
),
1033 ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu
),
1034 ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl
),
1035 ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu
),
1036 ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl
),
1037 ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu
),
1038 ("s390x-unknown-linux-musl", s390x_unknown_linux_musl
),
1039 ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu
),
1040 ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu
),
1041 ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi
),
1042 ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf
),
1043 ("armeb-unknown-linux-gnueabi", armeb_unknown_linux_gnueabi
),
1044 ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi
),
1045 ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf
),
1046 ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi
),
1047 ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi
),
1048 ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi
),
1049 ("armv5te-unknown-linux-uclibceabi", armv5te_unknown_linux_uclibceabi
),
1050 ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi
),
1051 ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf
),
1052 ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf
),
1053 ("thumbv7neon-unknown-linux-musleabihf", thumbv7neon_unknown_linux_musleabihf
),
1054 ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi
),
1055 ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf
),
1056 ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu
),
1057 ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl
),
1058 ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl
),
1059 ("i686-unknown-linux-musl", i686_unknown_linux_musl
),
1060 ("i586-unknown-linux-musl", i586_unknown_linux_musl
),
1061 ("mips-unknown-linux-musl", mips_unknown_linux_musl
),
1062 ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl
),
1063 ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64
),
1064 ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64
),
1065 ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl
),
1067 ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc
),
1068 ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc
),
1070 ("i686-linux-android", i686_linux_android
),
1071 ("x86_64-linux-android", x86_64_linux_android
),
1072 ("arm-linux-androideabi", arm_linux_androideabi
),
1073 ("armv7-linux-androideabi", armv7_linux_androideabi
),
1074 ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi
),
1075 ("aarch64-linux-android", aarch64_linux_android
),
1077 ("aarch64-unknown-freebsd", aarch64_unknown_freebsd
),
1078 ("armv6-unknown-freebsd", armv6_unknown_freebsd
),
1079 ("armv7-unknown-freebsd", armv7_unknown_freebsd
),
1080 ("i686-unknown-freebsd", i686_unknown_freebsd
),
1081 ("powerpc-unknown-freebsd", powerpc_unknown_freebsd
),
1082 ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd
),
1083 ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd
),
1084 ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd
),
1085 ("x86_64-unknown-freebsd", x86_64_unknown_freebsd
),
1087 ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly
),
1089 ("aarch64-unknown-openbsd", aarch64_unknown_openbsd
),
1090 ("i686-unknown-openbsd", i686_unknown_openbsd
),
1091 ("powerpc-unknown-openbsd", powerpc_unknown_openbsd
),
1092 ("powerpc64-unknown-openbsd", powerpc64_unknown_openbsd
),
1093 ("riscv64gc-unknown-openbsd", riscv64gc_unknown_openbsd
),
1094 ("sparc64-unknown-openbsd", sparc64_unknown_openbsd
),
1095 ("x86_64-unknown-openbsd", x86_64_unknown_openbsd
),
1097 ("aarch64-unknown-netbsd", aarch64_unknown_netbsd
),
1098 ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf
),
1099 ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf
),
1100 ("i686-unknown-netbsd", i686_unknown_netbsd
),
1101 ("powerpc-unknown-netbsd", powerpc_unknown_netbsd
),
1102 ("sparc64-unknown-netbsd", sparc64_unknown_netbsd
),
1103 ("x86_64-unknown-netbsd", x86_64_unknown_netbsd
),
1105 ("i686-unknown-haiku", i686_unknown_haiku
),
1106 ("x86_64-unknown-haiku", x86_64_unknown_haiku
),
1108 ("aarch64-apple-darwin", aarch64_apple_darwin
),
1109 ("x86_64-apple-darwin", x86_64_apple_darwin
),
1110 ("i686-apple-darwin", i686_apple_darwin
),
1112 // FIXME(#106649): Remove aarch64-fuchsia in favor of aarch64-unknown-fuchsia
1113 ("aarch64-fuchsia", aarch64_fuchsia
),
1114 ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia
),
1115 // FIXME(#106649): Remove x86_64-fuchsia in favor of x86_64-unknown-fuchsia
1116 ("x86_64-fuchsia", x86_64_fuchsia
),
1117 ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia
),
1119 ("avr-unknown-gnu-atmega328", avr_unknown_gnu_atmega328
),
1121 ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc
),
1123 ("aarch64-unknown-redox", aarch64_unknown_redox
),
1124 ("x86_64-unknown-redox", x86_64_unknown_redox
),
1126 ("i386-apple-ios", i386_apple_ios
),
1127 ("x86_64-apple-ios", x86_64_apple_ios
),
1128 ("aarch64-apple-ios", aarch64_apple_ios
),
1129 ("armv7-apple-ios", armv7_apple_ios
),
1130 ("armv7s-apple-ios", armv7s_apple_ios
),
1131 ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi
),
1132 ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi
),
1133 ("aarch64-apple-ios-sim", aarch64_apple_ios_sim
),
1134 ("aarch64-apple-tvos", aarch64_apple_tvos
),
1135 ("x86_64-apple-tvos", x86_64_apple_tvos
),
1137 ("armv7k-apple-watchos", armv7k_apple_watchos
),
1138 ("arm64_32-apple-watchos", arm64_32_apple_watchos
),
1139 ("x86_64-apple-watchos-sim", x86_64_apple_watchos_sim
),
1140 ("aarch64-apple-watchos-sim", aarch64_apple_watchos_sim
),
1142 ("armebv7r-none-eabi", armebv7r_none_eabi
),
1143 ("armebv7r-none-eabihf", armebv7r_none_eabihf
),
1144 ("armv7r-none-eabi", armv7r_none_eabi
),
1145 ("armv7r-none-eabihf", armv7r_none_eabihf
),
1147 ("x86_64-pc-solaris", x86_64_pc_solaris
),
1148 ("x86_64-sun-solaris", x86_64_sun_solaris
),
1149 ("sparcv9-sun-solaris", sparcv9_sun_solaris
),
1151 ("x86_64-unknown-illumos", x86_64_unknown_illumos
),
1153 ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu
),
1154 ("i686-pc-windows-gnu", i686_pc_windows_gnu
),
1155 ("i686-uwp-windows-gnu", i686_uwp_windows_gnu
),
1156 ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu
),
1158 ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm
),
1159 ("x86_64-pc-windows-gnullvm", x86_64_pc_windows_gnullvm
),
1161 ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc
),
1162 ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc
),
1163 ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc
),
1164 ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc
),
1165 ("i686-pc-windows-msvc", i686_pc_windows_msvc
),
1166 ("i686-uwp-windows-msvc", i686_uwp_windows_msvc
),
1167 ("i586-pc-windows-msvc", i586_pc_windows_msvc
),
1168 ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc
),
1169 ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc
),
1171 ("asmjs-unknown-emscripten", asmjs_unknown_emscripten
),
1172 ("wasm32-unknown-emscripten", wasm32_unknown_emscripten
),
1173 ("wasm32-unknown-unknown", wasm32_unknown_unknown
),
1174 ("wasm32-wasi", wasm32_wasi
),
1175 ("wasm64-unknown-unknown", wasm64_unknown_unknown
),
1177 ("thumbv6m-none-eabi", thumbv6m_none_eabi
),
1178 ("thumbv7m-none-eabi", thumbv7m_none_eabi
),
1179 ("thumbv7em-none-eabi", thumbv7em_none_eabi
),
1180 ("thumbv7em-none-eabihf", thumbv7em_none_eabihf
),
1181 ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi
),
1182 ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi
),
1183 ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf
),
1185 ("armv7a-none-eabi", armv7a_none_eabi
),
1186 ("armv7a-none-eabihf", armv7a_none_eabihf
),
1188 ("msp430-none-elf", msp430_none_elf
),
1190 ("aarch64-unknown-hermit", aarch64_unknown_hermit
),
1191 ("x86_64-unknown-hermit", x86_64_unknown_hermit
),
1193 ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf
),
1194 ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf
),
1195 ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf
),
1196 ("riscv32imc-esp-espidf", riscv32imc_esp_espidf
),
1197 ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf
),
1198 ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf
),
1199 ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu
),
1200 ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl
),
1201 ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf
),
1202 ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf
),
1203 ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu
),
1204 ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl
),
1206 ("aarch64-unknown-none", aarch64_unknown_none
),
1207 ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat
),
1209 ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx
),
1211 ("x86_64-unknown-uefi", x86_64_unknown_uefi
),
1212 ("i686-unknown-uefi", i686_unknown_uefi
),
1213 ("aarch64-unknown-uefi", aarch64_unknown_uefi
),
1215 ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda
),
1217 ("i686-wrs-vxworks", i686_wrs_vxworks
),
1218 ("x86_64-wrs-vxworks", x86_64_wrs_vxworks
),
1219 ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf
),
1220 ("aarch64-wrs-vxworks", aarch64_wrs_vxworks
),
1221 ("powerpc-wrs-vxworks", powerpc_wrs_vxworks
),
1222 ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe
),
1223 ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks
),
1225 ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3
),
1226 ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi
),
1227 ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf
),
1229 ("mipsel-sony-psp", mipsel_sony_psp
),
1230 ("mipsel-sony-psx", mipsel_sony_psx
),
1231 ("mipsel-unknown-none", mipsel_unknown_none
),
1232 ("thumbv4t-none-eabi", thumbv4t_none_eabi
),
1233 ("armv4t-none-eabi", armv4t_none_eabi
),
1234 ("thumbv5te-none-eabi", thumbv5te_none_eabi
),
1235 ("armv5te-none-eabi", armv5te_none_eabi
),
1237 ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu
),
1238 ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32
),
1239 ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32
),
1241 ("bpfeb-unknown-none", bpfeb_unknown_none
),
1242 ("bpfel-unknown-none", bpfel_unknown_none
),
1244 ("armv6k-nintendo-3ds", armv6k_nintendo_3ds
),
1246 ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding
),
1248 ("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf
),
1250 ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi
),
1251 ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf
),
1253 ("x86_64-unknown-none", x86_64_unknown_none
),
1255 ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl
),
1257 ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx_710
),
1258 ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710
),
1261 /// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]>
1264 ::std
::borrow
::Cow
::Borrowed(&[])
1266 ($
($x
:expr
),+ $
(,)?
) => {
1267 ::std
::borrow
::Cow
::Borrowed(&[
1269 ::std
::borrow
::Cow
::Borrowed($x
),
1277 /// Warnings encountered when parsing the target `json`.
1279 /// Includes fields that weren't recognized and fields that don't have the expected type.
1280 #[derive(Debug, PartialEq)]
1281 pub struct TargetWarnings
{
1282 unused_fields
: Vec
<String
>,
1283 incorrect_type
: Vec
<String
>,
1286 impl TargetWarnings
{
1287 pub fn empty() -> Self {
1288 Self { unused_fields: Vec::new(), incorrect_type: Vec::new() }
1291 pub fn warning_messages(&self) -> Vec
<String
> {
1292 let mut warnings
= vec
![];
1293 if !self.unused_fields
.is_empty() {
1294 warnings
.push(format
!(
1295 "target json file contains unused fields: {}",
1296 self.unused_fields
.join(", ")
1299 if !self.incorrect_type
.is_empty() {
1300 warnings
.push(format
!(
1301 "target json file contains fields whose value doesn't have the correct json type: {}",
1302 self.incorrect_type
.join(", ")
1309 /// Everything `rustc` knows about how to compile for a specific target.
1311 /// Every field here must be specified, and has no default value.
1312 #[derive(PartialEq, Clone, Debug)]
1314 /// Target triple to pass to LLVM.
1315 pub llvm_target
: StaticCow
<str>,
1316 /// Number of bits in a pointer. Influences the `target_pointer_width` `cfg` variable.
1317 pub pointer_width
: u32,
1318 /// Architecture to use for ABI considerations. Valid options include: "x86",
1319 /// "x86_64", "arm", "aarch64", "mips", "powerpc", "powerpc64", and others.
1320 pub arch
: StaticCow
<str>,
1321 /// [Data layout](https://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
1322 pub data_layout
: StaticCow
<str>,
1323 /// Optional settings with defaults.
1324 pub options
: TargetOptions
,
1328 pub fn parse_data_layout(&self) -> Result
<TargetDataLayout
, TargetDataLayoutErrors
<'_
>> {
1329 let mut dl
= TargetDataLayout
::parse_from_llvm_datalayout_string(&self.data_layout
)?
;
1331 // Perform consistency checks against the Target information.
1332 if dl
.endian
!= self.endian
{
1333 return Err(TargetDataLayoutErrors
::InconsistentTargetArchitecture
{
1334 dl
: dl
.endian
.as_str(),
1335 target
: self.endian
.as_str(),
1339 let target_pointer_width
: u64 = self.pointer_width
.into();
1340 if dl
.pointer_size
.bits() != target_pointer_width
{
1341 return Err(TargetDataLayoutErrors
::InconsistentTargetPointerWidth
{
1342 pointer_size
: dl
.pointer_size
.bits(),
1343 target
: self.pointer_width
,
1347 dl
.c_enum_min_size
= match Integer
::from_size(Size
::from_bits(self.c_enum_min_bits
)) {
1349 Err(err
) => return Err(TargetDataLayoutErrors
::InvalidBitsSize { err }
),
1356 pub trait HasTargetSpec
{
1357 fn target_spec(&self) -> &Target
;
1360 impl HasTargetSpec
for Target
{
1362 fn target_spec(&self) -> &Target
{
1367 type StaticCow
<T
> = Cow
<'
static, T
>;
1369 /// Optional aspects of a target specification.
1371 /// This has an implementation of `Default`, see each field for what the default is. In general,
1372 /// these try to take "minimal defaults" that don't assume anything about the runtime they run in.
1374 /// `TargetOptions` as a separate structure is mostly an implementation detail of `Target`
1375 /// construction, all its fields logically belong to `Target` and available from `Target`
1376 /// through `Deref` impls.
1377 #[derive(PartialEq, Clone, Debug)]
1378 pub struct TargetOptions
{
1379 /// Whether the target is built-in or loaded from a custom target specification.
1380 pub is_builtin
: bool
,
1382 /// Used as the `target_endian` `cfg` variable. Defaults to little endian.
1384 /// Width of c_int type. Defaults to "32".
1385 pub c_int_width
: StaticCow
<str>,
1386 /// OS name to use for conditional compilation (`target_os`). Defaults to "none".
1387 /// "none" implies a bare metal target without `std` library.
1388 /// A couple of targets having `std` also use "unknown" as an `os` value,
1389 /// but they are exceptions.
1390 pub os
: StaticCow
<str>,
1391 /// Environment name to use for conditional compilation (`target_env`). Defaults to "".
1392 pub env
: StaticCow
<str>,
1393 /// ABI name to distinguish multiple ABIs on the same OS and architecture. For instance, `"eabi"`
1394 /// or `"eabihf"`. Defaults to "".
1395 pub abi
: StaticCow
<str>,
1396 /// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown".
1397 pub vendor
: StaticCow
<str>,
1399 /// Linker to invoke
1400 pub linker
: Option
<StaticCow
<str>>,
1401 /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
1402 /// on the command line. Defaults to `LinkerFlavor::Gnu(Cc::Yes, Lld::No)`.
1403 pub linker_flavor
: LinkerFlavor
,
1404 linker_flavor_json
: LinkerFlavorCli
,
1405 lld_flavor_json
: LldFlavor
,
1406 linker_is_gnu_json
: bool
,
1408 /// Objects to link before and after all other object code.
1409 pub pre_link_objects
: CrtObjects
,
1410 pub post_link_objects
: CrtObjects
,
1411 /// Same as `(pre|post)_link_objects`, but when self-contained linking mode is enabled.
1412 pub pre_link_objects_self_contained
: CrtObjects
,
1413 pub post_link_objects_self_contained
: CrtObjects
,
1414 pub link_self_contained
: LinkSelfContainedDefault
,
1416 /// Linker arguments that are passed *before* any user-defined libraries.
1417 pub pre_link_args
: LinkArgs
,
1418 pre_link_args_json
: LinkArgsCli
,
1419 /// Linker arguments that are unconditionally passed after any
1420 /// user-defined but before post-link objects. Standard platform
1421 /// libraries that should be always be linked to, usually go here.
1422 pub late_link_args
: LinkArgs
,
1423 late_link_args_json
: LinkArgsCli
,
1424 /// Linker arguments used in addition to `late_link_args` if at least one
1425 /// Rust dependency is dynamically linked.
1426 pub late_link_args_dynamic
: LinkArgs
,
1427 late_link_args_dynamic_json
: LinkArgsCli
,
1428 /// Linker arguments used in addition to `late_link_args` if all Rust
1429 /// dependencies are statically linked.
1430 pub late_link_args_static
: LinkArgs
,
1431 late_link_args_static_json
: LinkArgsCli
,
1432 /// Linker arguments that are unconditionally passed *after* any
1433 /// user-defined libraries.
1434 pub post_link_args
: LinkArgs
,
1435 post_link_args_json
: LinkArgsCli
,
1437 /// Optional link script applied to `dylib` and `executable` crate types.
1438 /// This is a string containing the script, not a path. Can only be applied
1439 /// to linkers where linker flavor matches `LinkerFlavor::Gnu(..)`.
1440 pub link_script
: Option
<StaticCow
<str>>,
1441 /// Environment variables to be set for the linker invocation.
1442 pub link_env
: StaticCow
<[(StaticCow
<str>, StaticCow
<str>)]>,
1443 /// Environment variables to be removed for the linker invocation.
1444 pub link_env_remove
: StaticCow
<[StaticCow
<str>]>,
1446 /// Extra arguments to pass to the external assembler (when used)
1447 pub asm_args
: StaticCow
<[StaticCow
<str>]>,
1449 /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults
1451 pub cpu
: StaticCow
<str>,
1452 /// Default target features to pass to LLVM. These features will *always* be
1453 /// passed, and cannot be disabled even via `-C`. Corresponds to `llc
1454 /// -mattr=$features`.
1455 pub features
: StaticCow
<str>,
1456 /// Whether dynamic linking is available on this target. Defaults to false.
1457 pub dynamic_linking
: bool
,
1458 /// If dynamic linking is available, whether only cdylibs are supported.
1459 pub only_cdylib
: bool
,
1460 /// Whether executables are available on this target. Defaults to true.
1461 pub executables
: bool
,
1462 /// Relocation model to use in object file. Corresponds to `llc
1463 /// -relocation-model=$relocation_model`. Defaults to `Pic`.
1464 pub relocation_model
: RelocModel
,
1465 /// Code model to use. Corresponds to `llc -code-model=$code_model`.
1466 /// Defaults to `None` which means "inherited from the base LLVM target".
1467 pub code_model
: Option
<CodeModel
>,
1468 /// TLS model to use. Options are "global-dynamic" (default), "local-dynamic", "initial-exec"
1469 /// and "local-exec". This is similar to the -ftls-model option in GCC/Clang.
1470 pub tls_model
: TlsModel
,
1471 /// Do not emit code that uses the "red zone", if the ABI has one. Defaults to false.
1472 pub disable_redzone
: bool
,
1473 /// Frame pointer mode for this target. Defaults to `MayOmit`.
1474 pub frame_pointer
: FramePointer
,
1475 /// Emit each function in its own section. Defaults to true.
1476 pub function_sections
: bool
,
1477 /// String to prepend to the name of every dynamic library. Defaults to "lib".
1478 pub dll_prefix
: StaticCow
<str>,
1479 /// String to append to the name of every dynamic library. Defaults to ".so".
1480 pub dll_suffix
: StaticCow
<str>,
1481 /// String to append to the name of every executable.
1482 pub exe_suffix
: StaticCow
<str>,
1483 /// String to prepend to the name of every static library. Defaults to "lib".
1484 pub staticlib_prefix
: StaticCow
<str>,
1485 /// String to append to the name of every static library. Defaults to ".a".
1486 pub staticlib_suffix
: StaticCow
<str>,
1487 /// Values of the `target_family` cfg set for this target.
1489 /// Common options are: "unix", "windows". Defaults to no families.
1491 /// See <https://doc.rust-lang.org/reference/conditional-compilation.html#target_family>.
1492 pub families
: StaticCow
<[StaticCow
<str>]>,
1493 /// Whether the target toolchain's ABI supports returning small structs as an integer.
1494 pub abi_return_struct_as_int
: bool
,
1495 /// Whether the target toolchain is like AIX's. Linker options on AIX are special and it uses
1496 /// XCOFF as binary format. Defaults to false.
1497 pub is_like_aix
: bool
,
1498 /// Whether the target toolchain is like macOS's. Only useful for compiling against iOS/macOS,
1499 /// in particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false.
1500 /// Also indiates whether to use Apple-specific ABI changes, such as extending function
1501 /// parameters to 32-bits.
1502 pub is_like_osx
: bool
,
1503 /// Whether the target toolchain is like Solaris's.
1504 /// Only useful for compiling against Illumos/Solaris,
1505 /// as they have a different set of linker flags. Defaults to false.
1506 pub is_like_solaris
: bool
,
1507 /// Whether the target is like Windows.
1508 /// This is a combination of several more specific properties represented as a single flag:
1509 /// - The target uses a Windows ABI,
1510 /// - uses PE/COFF as a format for object code,
1511 /// - uses Windows-style dllexport/dllimport for shared libraries,
1512 /// - uses import libraries and .def files for symbol exports,
1513 /// - executables support setting a subsystem.
1514 pub is_like_windows
: bool
,
1515 /// Whether the target is like MSVC.
1516 /// This is a combination of several more specific properties represented as a single flag:
1517 /// - The target has all the properties from `is_like_windows`
1518 /// (for in-tree targets "is_like_msvc ⇒ is_like_windows" is ensured by a unit test),
1519 /// - has some MSVC-specific Windows ABI properties,
1520 /// - uses a link.exe-like linker,
1521 /// - uses CodeView/PDB for debuginfo and natvis for its visualization,
1522 /// - uses SEH-based unwinding,
1523 /// - supports control flow guard mechanism.
1524 pub is_like_msvc
: bool
,
1525 /// Whether a target toolchain is like WASM.
1526 pub is_like_wasm
: bool
,
1527 /// Whether a target toolchain is like Android, implying a Linux kernel and a Bionic libc
1528 pub is_like_android
: bool
,
1529 /// Default supported version of DWARF on this platform.
1530 /// Useful because some platforms (osx, bsd) only want up to DWARF2.
1531 pub default_dwarf_version
: u32,
1532 /// The MinGW toolchain has a known issue that prevents it from correctly
1533 /// handling COFF object files with more than 2<sup>15</sup> sections. Since each weak
1534 /// symbol needs its own COMDAT section, weak linkage implies a large
1535 /// number sections that easily exceeds the given limit for larger
1536 /// codebases. Consequently we want a way to disallow weak linkage on some
1538 pub allows_weak_linkage
: bool
,
1539 /// Whether the linker support rpaths or not. Defaults to false.
1540 pub has_rpath
: bool
,
1541 /// Whether to disable linking to the default libraries, typically corresponds
1542 /// to `-nodefaultlibs`. Defaults to true.
1543 pub no_default_libraries
: bool
,
1544 /// Dynamically linked executables can be compiled as position independent
1545 /// if the default relocation model of position independent code is not
1546 /// changed. This is a requirement to take advantage of ASLR, as otherwise
1547 /// the functions in the executable are not randomized and can be used
1548 /// during an exploit of a vulnerability in any code.
1549 pub position_independent_executables
: bool
,
1550 /// Executables that are both statically linked and position-independent are supported.
1551 pub static_position_independent_executables
: bool
,
1552 /// Determines if the target always requires using the PLT for indirect
1553 /// library calls or not. This controls the default value of the `-Z plt` flag.
1554 pub needs_plt
: bool
,
1555 /// Either partial, full, or off. Full RELRO makes the dynamic linker
1556 /// resolve all symbols at startup and marks the GOT read-only before
1557 /// starting the program, preventing overwriting the GOT.
1558 pub relro_level
: RelroLevel
,
1559 /// Format that archives should be emitted in. This affects whether we use
1560 /// LLVM to assemble an archive or fall back to the system linker, and
1561 /// currently only "gnu" is used to fall into LLVM. Unknown strings cause
1562 /// the system linker to be used.
1563 pub archive_format
: StaticCow
<str>,
1564 /// Is asm!() allowed? Defaults to true.
1565 pub allow_asm
: bool
,
1566 /// Whether the runtime startup code requires the `main` function be passed
1567 /// `argc` and `argv` values.
1568 pub main_needs_argc_argv
: bool
,
1570 /// Flag indicating whether #[thread_local] is available for this target.
1571 pub has_thread_local
: bool
,
1572 /// This is mainly for easy compatibility with emscripten.
1573 /// If we give emcc .o files that are actually .bc files it
1574 /// will 'just work'.
1575 pub obj_is_bitcode
: bool
,
1576 /// Whether the target requires that emitted object code includes bitcode.
1577 pub forces_embed_bitcode
: bool
,
1578 /// Content of the LLVM cmdline section associated with embedded bitcode.
1579 pub bitcode_llvm_cmdline
: StaticCow
<str>,
1581 /// Don't use this field; instead use the `.min_atomic_width()` method.
1582 pub min_atomic_width
: Option
<u64>,
1584 /// Don't use this field; instead use the `.max_atomic_width()` method.
1585 pub max_atomic_width
: Option
<u64>,
1587 /// Whether the target supports atomic CAS operations natively
1588 pub atomic_cas
: bool
,
1590 /// Panic strategy: "unwind" or "abort"
1591 pub panic_strategy
: PanicStrategy
,
1593 /// Whether or not linking dylibs to a static CRT is allowed.
1594 pub crt_static_allows_dylibs
: bool
,
1595 /// Whether or not the CRT is statically linked by default.
1596 pub crt_static_default
: bool
,
1597 /// Whether or not crt-static is respected by the compiler (or is a no-op).
1598 pub crt_static_respected
: bool
,
1600 /// The implementation of stack probes to use.
1601 pub stack_probes
: StackProbeType
,
1603 /// The minimum alignment for global symbols.
1604 pub min_global_align
: Option
<u64>,
1606 /// Default number of codegen units to use in debug mode
1607 pub default_codegen_units
: Option
<u64>,
1609 /// Whether to generate trap instructions in places where optimization would
1610 /// otherwise produce control flow that falls through into unrelated memory.
1611 pub trap_unreachable
: bool
,
1613 /// This target requires everything to be compiled with LTO to emit a final
1614 /// executable, aka there is no native linker for this target.
1615 pub requires_lto
: bool
,
1617 /// This target has no support for threads.
1618 pub singlethread
: bool
,
1620 /// Whether library functions call lowering/optimization is disabled in LLVM
1621 /// for this target unconditionally.
1622 pub no_builtins
: bool
,
1624 /// The default visibility for symbols in this target should be "hidden"
1625 /// rather than "default"
1626 pub default_hidden_visibility
: bool
,
1628 /// Whether a .debug_gdb_scripts section will be added to the output object file
1629 pub emit_debug_gdb_scripts
: bool
,
1631 /// Whether or not to unconditionally `uwtable` attributes on functions,
1632 /// typically because the platform needs to unwind for things like stack
1634 pub requires_uwtable
: bool
,
1636 /// Whether or not to emit `uwtable` attributes on functions if `-C force-unwind-tables`
1637 /// is not specified and `uwtable` is not required on this target.
1638 pub default_uwtable
: bool
,
1640 /// Whether or not SIMD types are passed by reference in the Rust ABI,
1641 /// typically required if a target can be compiled with a mixed set of
1642 /// target features. This is `true` by default, and `false` for targets like
1643 /// wasm32 where the whole program either has simd or not.
1644 pub simd_types_indirect
: bool
,
1646 /// Pass a list of symbol which should be exported in the dylib to the linker.
1647 pub limit_rdylib_exports
: bool
,
1649 /// If set, have the linker export exactly these symbols, instead of using
1650 /// the usual logic to figure this out from the crate itself.
1651 pub override_export_symbols
: Option
<StaticCow
<[StaticCow
<str>]>>,
1653 /// Determines how or whether the MergeFunctions LLVM pass should run for
1654 /// this target. Either "disabled", "trampolines", or "aliases".
1655 /// The MergeFunctions pass is generally useful, but some targets may need
1656 /// to opt out. The default is "aliases".
1658 /// Workaround for: <https://github.com/rust-lang/rust/issues/57356>
1659 pub merge_functions
: MergeFunctions
,
1661 /// Use platform dependent mcount function
1662 pub mcount
: StaticCow
<str>,
1664 /// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers
1665 pub llvm_abiname
: StaticCow
<str>,
1667 /// Whether or not RelaxElfRelocation flag will be passed to the linker
1668 pub relax_elf_relocations
: bool
,
1670 /// Additional arguments to pass to LLVM, similar to the `-C llvm-args` codegen option.
1671 pub llvm_args
: StaticCow
<[StaticCow
<str>]>,
1673 /// Whether to use legacy .ctors initialization hooks rather than .init_array. Defaults
1674 /// to false (uses .init_array).
1675 pub use_ctors_section
: bool
,
1677 /// Whether the linker is instructed to add a `GNU_EH_FRAME` ELF header
1678 /// used to locate unwinding information is passed
1679 /// (only has effect if the linker is `ld`-like).
1680 pub eh_frame_header
: bool
,
1682 /// Is true if the target is an ARM architecture using thumb v1 which allows for
1683 /// thumb and arm interworking.
1684 pub has_thumb_interworking
: bool
,
1686 /// Which kind of debuginfo is used by this target?
1687 pub debuginfo_kind
: DebuginfoKind
,
1688 /// How to handle split debug information, if at all. Specifying `None` has
1689 /// target-specific meaning.
1690 pub split_debuginfo
: SplitDebuginfo
,
1691 /// Which kinds of split debuginfo are supported by the target?
1692 pub supported_split_debuginfo
: StaticCow
<[SplitDebuginfo
]>,
1694 /// The sanitizers supported by this target
1696 /// Note that the support here is at a codegen level. If the machine code with sanitizer
1697 /// enabled can generated on this target, but the necessary supporting libraries are not
1698 /// distributed with the target, the sanitizer should still appear in this list for the target.
1699 pub supported_sanitizers
: SanitizerSet
,
1701 /// If present it's a default value to use for adjusting the C ABI.
1702 pub default_adjusted_cabi
: Option
<Abi
>,
1704 /// Minimum number of bits in #[repr(C)] enum. Defaults to 32.
1705 pub c_enum_min_bits
: u64,
1707 /// Whether or not the DWARF `.debug_aranges` section should be generated.
1708 pub generate_arange_section
: bool
,
1710 /// Whether the target supports stack canary checks. `true` by default,
1711 /// since this is most common among tier 1 and tier 2 targets.
1712 pub supports_stack_protector
: bool
,
1714 /// The name of entry function.
1715 /// Default value is "main"
1716 pub entry_name
: StaticCow
<str>,
1718 /// The ABI of entry function.
1719 /// Default value is `Conv::C`, i.e. C call convention
1720 pub entry_abi
: Conv
,
1723 /// Add arguments for the given flavor and also for its "twin" flavors
1724 /// that have a compatible command line interface.
1725 fn add_link_args_iter(
1726 link_args
: &mut LinkArgs
,
1727 flavor
: LinkerFlavor
,
1728 args
: impl Iterator
<Item
= StaticCow
<str>> + Clone
,
1730 let mut insert
= |flavor
| link_args
.entry(flavor
).or_default().extend(args
.clone());
1733 LinkerFlavor
::Gnu(cc
, lld
) => {
1734 assert_eq
!(lld
, Lld
::No
);
1735 insert(LinkerFlavor
::Gnu(cc
, Lld
::Yes
));
1737 LinkerFlavor
::Darwin(cc
, lld
) => {
1738 assert_eq
!(lld
, Lld
::No
);
1739 insert(LinkerFlavor
::Darwin(cc
, Lld
::Yes
));
1741 LinkerFlavor
::Msvc(lld
) => {
1742 assert_eq
!(lld
, Lld
::No
);
1743 insert(LinkerFlavor
::Msvc(Lld
::Yes
));
1745 LinkerFlavor
::WasmLld(..)
1746 | LinkerFlavor
::Unix(..)
1747 | LinkerFlavor
::EmCc
1749 | LinkerFlavor
::Ptx
=> {}
1753 fn add_link_args(link_args
: &mut LinkArgs
, flavor
: LinkerFlavor
, args
: &[&'
static str]) {
1754 add_link_args_iter(link_args
, flavor
, args
.iter().copied().map(Cow
::Borrowed
))
1757 impl TargetOptions
{
1758 fn link_args(flavor
: LinkerFlavor
, args
: &[&'
static str]) -> LinkArgs
{
1759 let mut link_args
= LinkArgs
::new();
1760 add_link_args(&mut link_args
, flavor
, args
);
1764 fn add_pre_link_args(&mut self, flavor
: LinkerFlavor
, args
: &[&'
static str]) {
1765 add_link_args(&mut self.pre_link_args
, flavor
, args
);
1768 fn add_post_link_args(&mut self, flavor
: LinkerFlavor
, args
: &[&'
static str]) {
1769 add_link_args(&mut self.post_link_args
, flavor
, args
);
1772 fn update_from_cli(&mut self) {
1773 self.linker_flavor
= LinkerFlavor
::from_cli_impl(
1774 self.linker_flavor_json
,
1775 self.lld_flavor_json
,
1776 self.linker_is_gnu_json
,
1778 for (args
, args_json
) in [
1779 (&mut self.pre_link_args
, &self.pre_link_args_json
),
1780 (&mut self.late_link_args
, &self.late_link_args_json
),
1781 (&mut self.late_link_args_dynamic
, &self.late_link_args_dynamic_json
),
1782 (&mut self.late_link_args_static
, &self.late_link_args_static_json
),
1783 (&mut self.post_link_args
, &self.post_link_args_json
),
1786 for (flavor
, args_json
) in args_json
{
1787 // Cannot use `from_cli` due to borrow checker.
1788 let linker_flavor
= LinkerFlavor
::from_cli_impl(
1790 self.lld_flavor_json
,
1791 self.linker_is_gnu_json
,
1793 // Normalize to no lld to avoid asserts.
1794 let linker_flavor
= match linker_flavor
{
1795 LinkerFlavor
::Gnu(cc
, _
) => LinkerFlavor
::Gnu(cc
, Lld
::No
),
1796 LinkerFlavor
::Darwin(cc
, _
) => LinkerFlavor
::Darwin(cc
, Lld
::No
),
1797 LinkerFlavor
::Msvc(_
) => LinkerFlavor
::Msvc(Lld
::No
),
1800 if !args
.contains_key(&linker_flavor
) {
1801 add_link_args_iter(args
, linker_flavor
, args_json
.iter().cloned());
1807 fn update_to_cli(&mut self) {
1808 self.linker_flavor_json
= self.linker_flavor
.to_cli();
1809 self.lld_flavor_json
= self.linker_flavor
.lld_flavor();
1810 self.linker_is_gnu_json
= self.linker_flavor
.is_gnu();
1811 for (args
, args_json
) in [
1812 (&self.pre_link_args
, &mut self.pre_link_args_json
),
1813 (&self.late_link_args
, &mut self.late_link_args_json
),
1814 (&self.late_link_args_dynamic
, &mut self.late_link_args_dynamic_json
),
1815 (&self.late_link_args_static
, &mut self.late_link_args_static_json
),
1816 (&self.post_link_args
, &mut self.post_link_args_json
),
1819 args
.iter().map(|(flavor
, args
)| (flavor
.to_cli(), args
.clone())).collect();
1824 impl Default
for TargetOptions
{
1825 /// Creates a set of "sane defaults" for any target. This is still
1826 /// incomplete, and if used for compilation, will certainly not work.
1827 fn default() -> TargetOptions
{
1830 endian
: Endian
::Little
,
1831 c_int_width
: "32".into(),
1835 vendor
: "unknown".into(),
1836 linker
: option_env
!("CFG_DEFAULT_LINKER").map(|s
| s
.into()),
1837 linker_flavor
: LinkerFlavor
::Gnu(Cc
::Yes
, Lld
::No
),
1838 linker_flavor_json
: LinkerFlavorCli
::Gcc
,
1839 lld_flavor_json
: LldFlavor
::Ld
,
1840 linker_is_gnu_json
: true,
1843 cpu
: "generic".into(),
1844 features
: "".into(),
1845 dynamic_linking
: false,
1848 relocation_model
: RelocModel
::Pic
,
1850 tls_model
: TlsModel
::GeneralDynamic
,
1851 disable_redzone
: false,
1852 frame_pointer
: FramePointer
::MayOmit
,
1853 function_sections
: true,
1854 dll_prefix
: "lib".into(),
1855 dll_suffix
: ".so".into(),
1856 exe_suffix
: "".into(),
1857 staticlib_prefix
: "lib".into(),
1858 staticlib_suffix
: ".a".into(),
1860 abi_return_struct_as_int
: false,
1863 is_like_solaris
: false,
1864 is_like_windows
: false,
1865 is_like_msvc
: false,
1866 is_like_wasm
: false,
1867 is_like_android
: false,
1868 default_dwarf_version
: 4,
1869 allows_weak_linkage
: true,
1871 no_default_libraries
: true,
1872 position_independent_executables
: false,
1873 static_position_independent_executables
: false,
1875 relro_level
: RelroLevel
::None
,
1876 pre_link_objects
: Default
::default(),
1877 post_link_objects
: Default
::default(),
1878 pre_link_objects_self_contained
: Default
::default(),
1879 post_link_objects_self_contained
: Default
::default(),
1880 link_self_contained
: LinkSelfContainedDefault
::False
,
1881 pre_link_args
: LinkArgs
::new(),
1882 pre_link_args_json
: LinkArgsCli
::new(),
1883 late_link_args
: LinkArgs
::new(),
1884 late_link_args_json
: LinkArgsCli
::new(),
1885 late_link_args_dynamic
: LinkArgs
::new(),
1886 late_link_args_dynamic_json
: LinkArgsCli
::new(),
1887 late_link_args_static
: LinkArgs
::new(),
1888 late_link_args_static_json
: LinkArgsCli
::new(),
1889 post_link_args
: LinkArgs
::new(),
1890 post_link_args_json
: LinkArgsCli
::new(),
1892 link_env_remove
: cvs
![],
1893 archive_format
: "gnu".into(),
1894 main_needs_argc_argv
: true,
1896 has_thread_local
: false,
1897 obj_is_bitcode
: false,
1898 forces_embed_bitcode
: false,
1899 bitcode_llvm_cmdline
: "".into(),
1900 min_atomic_width
: None
,
1901 max_atomic_width
: None
,
1903 panic_strategy
: PanicStrategy
::Unwind
,
1904 crt_static_allows_dylibs
: false,
1905 crt_static_default
: false,
1906 crt_static_respected
: false,
1907 stack_probes
: StackProbeType
::None
,
1908 min_global_align
: None
,
1909 default_codegen_units
: None
,
1910 trap_unreachable
: true,
1911 requires_lto
: false,
1912 singlethread
: false,
1914 default_hidden_visibility
: false,
1915 emit_debug_gdb_scripts
: true,
1916 requires_uwtable
: false,
1917 default_uwtable
: false,
1918 simd_types_indirect
: true,
1919 limit_rdylib_exports
: true,
1920 override_export_symbols
: None
,
1921 merge_functions
: MergeFunctions
::Aliases
,
1922 mcount
: "mcount".into(),
1923 llvm_abiname
: "".into(),
1924 relax_elf_relocations
: false,
1926 use_ctors_section
: false,
1927 eh_frame_header
: true,
1928 has_thumb_interworking
: false,
1929 debuginfo_kind
: Default
::default(),
1930 split_debuginfo
: Default
::default(),
1931 // `Off` is supported by default, but targets can remove this manually, e.g. Windows.
1932 supported_split_debuginfo
: Cow
::Borrowed(&[SplitDebuginfo
::Off
]),
1933 supported_sanitizers
: SanitizerSet
::empty(),
1934 default_adjusted_cabi
: None
,
1935 c_enum_min_bits
: 32,
1936 generate_arange_section
: true,
1937 supports_stack_protector
: true,
1938 entry_name
: "main".into(),
1944 /// `TargetOptions` being a separate type is basically an implementation detail of `Target` that is
1945 /// used for providing defaults. Perhaps there's a way to merge `TargetOptions` into `Target` so
1946 /// this `Deref` implementation is no longer necessary.
1947 impl Deref
for Target
{
1948 type Target
= TargetOptions
;
1951 fn deref(&self) -> &Self::Target
{
1955 impl DerefMut
for Target
{
1957 fn deref_mut(&mut self) -> &mut Self::Target
{
1963 /// Given a function ABI, turn it into the correct ABI for this target.
1964 pub fn adjust_abi(&self, abi
: Abi
) -> Abi
{
1966 Abi
::C { .. }
=> self.default_adjusted_cabi
.unwrap_or(abi
),
1967 Abi
::System { unwind }
if self.is_like_windows
&& self.arch
== "x86" => {
1968 Abi
::Stdcall { unwind }
1970 Abi
::System { unwind }
=> Abi
::C { unwind }
,
1971 Abi
::EfiApi
if self.arch
== "arm" => Abi
::Aapcs { unwind: false }
,
1972 Abi
::EfiApi
if self.arch
== "x86_64" => Abi
::Win64 { unwind: false }
,
1973 Abi
::EfiApi
=> Abi
::C { unwind: false }
,
1975 // See commentary in `is_abi_supported`.
1976 Abi
::Stdcall { .. }
| Abi
::Thiscall { .. }
if self.arch
== "x86" => abi
,
1977 Abi
::Stdcall { unwind }
| Abi
::Thiscall { unwind }
=> Abi
::C { unwind }
,
1978 Abi
::Fastcall { .. }
if self.arch
== "x86" => abi
,
1979 Abi
::Vectorcall { .. }
if ["x86", "x86_64"].contains(&&self.arch
[..]) => abi
,
1980 Abi
::Fastcall { unwind }
| Abi
::Vectorcall { unwind }
=> Abi
::C { unwind }
,
1986 /// Returns a None if the UNSUPPORTED_CALLING_CONVENTIONS lint should be emitted
1987 pub fn is_abi_supported(&self, abi
: Abi
) -> Option
<bool
> {
2000 ["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch
[..])
2002 X86Interrupt
=> ["x86", "x86_64"].contains(&&self.arch
[..]),
2003 Aapcs { .. }
=> "arm" == self.arch
,
2004 CCmseNonSecureCall
=> ["arm", "aarch64"].contains(&&self.arch
[..]),
2005 Win64 { .. }
| SysV64 { .. }
=> self.arch
== "x86_64",
2006 PtxKernel
=> self.arch
== "nvptx64",
2007 Msp430Interrupt
=> self.arch
== "msp430",
2008 AmdGpuKernel
=> self.arch
== "amdgcn",
2009 AvrInterrupt
| AvrNonBlockingInterrupt
=> self.arch
== "avr",
2010 Wasm
=> ["wasm32", "wasm64"].contains(&&self.arch
[..]),
2011 Thiscall { .. }
=> self.arch
== "x86",
2012 // On windows these fall-back to platform native calling convention (C) when the
2013 // architecture is not supported.
2015 // This is I believe a historical accident that has occurred as part of Microsoft
2016 // striving to allow most of the code to "just" compile when support for 64-bit x86
2017 // was added and then later again, when support for ARM architectures was added.
2019 // This is well documented across MSDN. Support for this in Rust has been added in
2020 // #54576. This makes much more sense in context of Microsoft's C++ than it does in
2021 // Rust, but there isn't much leeway remaining here to change it back at the time this
2022 // comment has been written.
2024 // Following are the relevant excerpts from the MSDN documentation.
2026 // > The __vectorcall calling convention is only supported in native code on x86 and
2027 // x64 processors that include Streaming SIMD Extensions 2 (SSE2) and above.
2029 // > On ARM machines, __vectorcall is accepted and ignored by the compiler.
2031 // -- https://docs.microsoft.com/en-us/cpp/cpp/vectorcall?view=msvc-160
2033 // > On ARM and x64 processors, __stdcall is accepted and ignored by the compiler;
2035 // -- https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-160
2037 // > In most cases, keywords or compiler switches that specify an unsupported
2038 // > convention on a particular platform are ignored, and the platform default
2039 // > convention is used.
2041 // -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
2042 Stdcall { .. }
| Fastcall { .. }
| Vectorcall { .. }
if self.is_like_windows
=> true,
2043 // Outside of Windows we want to only support these calling conventions for the
2044 // architectures for which these calling conventions are actually well defined.
2045 Stdcall { .. }
| Fastcall { .. }
if self.arch
== "x86" => true,
2046 Vectorcall { .. }
if ["x86", "x86_64"].contains(&&self.arch
[..]) => true,
2047 // Return a `None` for other cases so that we know to emit a future compat lint.
2048 Stdcall { .. }
| Fastcall { .. }
| Vectorcall { .. }
=> return None
,
2052 /// Minimum integer size in bits that this target can perform atomic
2054 pub fn min_atomic_width(&self) -> u64 {
2055 self.min_atomic_width
.unwrap_or(8)
2058 /// Maximum integer size in bits that this target can perform atomic
2060 pub fn max_atomic_width(&self) -> u64 {
2061 self.max_atomic_width
.unwrap_or_else(|| self.pointer_width
.into())
2064 /// Loads a target descriptor from a JSON object.
2065 pub fn from_json(obj
: Json
) -> Result
<(Target
, TargetWarnings
), String
> {
2066 // While ugly, this code must remain this way to retain
2067 // compatibility with existing JSON fields and the internal
2068 // expected naming of the Target and TargetOptions structs.
2069 // To ensure compatibility is retained, the built-in targets
2070 // are round-tripped through this code to catch cases where
2071 // the JSON parser is not updated to match the structs.
2073 let mut obj
= match obj
{
2074 Value
::Object(obj
) => obj
,
2075 _
=> return Err("Expected JSON object for target")?
,
2078 let mut get_req_field
= |name
: &str| {
2080 .and_then(|j
| j
.as_str().map(str::to_string
))
2081 .ok_or_else(|| format
!("Field {name} in target specification is required"))
2084 let mut base
= Target
{
2085 llvm_target
: get_req_field("llvm-target")?
.into(),
2086 pointer_width
: get_req_field("target-pointer-width")?
2088 .map_err(|_
| "target-pointer-width must be an integer".to_string())?
,
2089 data_layout
: get_req_field("data-layout")?
.into(),
2090 arch
: get_req_field("arch")?
.into(),
2091 options
: Default
::default(),
2094 let mut incorrect_type
= vec
![];
2097 ($key_name
:ident
) => ( {
2098 let name
= (stringify
!($key_name
)).replace("_", "-");
2099 if let Some(s
) = obj
.remove(&name
).and_then(|s
| s
.as_str().map(str::to_string
).map(Cow
::from
)) {
2103 ($key_name
:ident
= $json_name
:expr
) => ( {
2104 let name
= $json_name
;
2105 if let Some(s
) = obj
.remove(name
).and_then(|s
| s
.as_str().map(str::to_string
).map(Cow
::from
)) {
2109 ($key_name
:ident
, bool
) => ( {
2110 let name
= (stringify
!($key_name
)).replace("_", "-");
2111 if let Some(s
) = obj
.remove(&name
).and_then(|b
| b
.as_bool()) {
2115 ($key_name
:ident
= $json_name
:expr
, bool
) => ( {
2116 let name
= $json_name
;
2117 if let Some(s
) = obj
.remove(name
).and_then(|b
| b
.as_bool()) {
2121 ($key_name
:ident
, u64) => ( {
2122 let name
= (stringify
!($key_name
)).replace("_", "-");
2123 if let Some(s
) = obj
.remove(&name
).and_then(|j
| Json
::as_u64(&j
)) {
2127 ($key_name
:ident
, u32) => ( {
2128 let name
= (stringify
!($key_name
)).replace("_", "-");
2129 if let Some(s
) = obj
.remove(&name
).and_then(|b
| b
.as_u64()) {
2131 return Err("Not a valid DWARF version number".into());
2133 base
.$key_name
= s
as u32;
2136 ($key_name
:ident
, Option
<u64>) => ( {
2137 let name
= (stringify
!($key_name
)).replace("_", "-");
2138 if let Some(s
) = obj
.remove(&name
).and_then(|b
| b
.as_u64()) {
2139 base
.$key_name
= Some(s
);
2142 ($key_name
:ident
, MergeFunctions
) => ( {
2143 let name
= (stringify
!($key_name
)).replace("_", "-");
2144 obj
.remove(&name
).and_then(|o
| o
.as_str().and_then(|s
| {
2145 match s
.parse
::<MergeFunctions
>() {
2146 Ok(mergefunc
) => base
.$key_name
= mergefunc
,
2147 _
=> return Some(Err(format
!("'{}' is not a valid value for \
2148 merge-functions. Use 'disabled', \
2149 'trampolines', or 'aliases'.",
2153 })).unwrap_or(Ok(()))
2155 ($key_name
:ident
, RelocModel
) => ( {
2156 let name
= (stringify
!($key_name
)).replace("_", "-");
2157 obj
.remove(&name
).and_then(|o
| o
.as_str().and_then(|s
| {
2158 match s
.parse
::<RelocModel
>() {
2159 Ok(relocation_model
) => base
.$key_name
= relocation_model
,
2160 _
=> return Some(Err(format
!("'{}' is not a valid relocation model. \
2161 Run `rustc --print relocation-models` to \
2162 see the list of supported values.", s
))),
2165 })).unwrap_or(Ok(()))
2167 ($key_name
:ident
, CodeModel
) => ( {
2168 let name
= (stringify
!($key_name
)).replace("_", "-");
2169 obj
.remove(&name
).and_then(|o
| o
.as_str().and_then(|s
| {
2170 match s
.parse
::<CodeModel
>() {
2171 Ok(code_model
) => base
.$key_name
= Some(code_model
),
2172 _
=> return Some(Err(format
!("'{}' is not a valid code model. \
2173 Run `rustc --print code-models` to \
2174 see the list of supported values.", s
))),
2177 })).unwrap_or(Ok(()))
2179 ($key_name
:ident
, TlsModel
) => ( {
2180 let name
= (stringify
!($key_name
)).replace("_", "-");
2181 obj
.remove(&name
).and_then(|o
| o
.as_str().and_then(|s
| {
2182 match s
.parse
::<TlsModel
>() {
2183 Ok(tls_model
) => base
.$key_name
= tls_model
,
2184 _
=> return Some(Err(format
!("'{}' is not a valid TLS model. \
2185 Run `rustc --print tls-models` to \
2186 see the list of supported values.", s
))),
2189 })).unwrap_or(Ok(()))
2191 ($key_name
:ident
, PanicStrategy
) => ( {
2192 let name
= (stringify
!($key_name
)).replace("_", "-");
2193 obj
.remove(&name
).and_then(|o
| o
.as_str().and_then(|s
| {
2195 "unwind" => base
.$key_name
= PanicStrategy
::Unwind
,
2196 "abort" => base
.$key_name
= PanicStrategy
::Abort
,
2197 _
=> return Some(Err(format
!("'{}' is not a valid value for \
2198 panic-strategy. Use 'unwind' or 'abort'.",
2202 })).unwrap_or(Ok(()))
2204 ($key_name
:ident
, RelroLevel
) => ( {
2205 let name
= (stringify
!($key_name
)).replace("_", "-");
2206 obj
.remove(&name
).and_then(|o
| o
.as_str().and_then(|s
| {
2207 match s
.parse
::<RelroLevel
>() {
2208 Ok(level
) => base
.$key_name
= level
,
2209 _
=> return Some(Err(format
!("'{}' is not a valid value for \
2210 relro-level. Use 'full', 'partial, or 'off'.",
2214 })).unwrap_or(Ok(()))
2216 ($key_name
:ident
, DebuginfoKind
) => ( {
2217 let name
= (stringify
!($key_name
)).replace("_", "-");
2218 obj
.remove(&name
).and_then(|o
| o
.as_str().and_then(|s
| {
2219 match s
.parse
::<DebuginfoKind
>() {
2220 Ok(level
) => base
.$key_name
= level
,
2221 _
=> return Some(Err(
2222 format
!("'{s}' is not a valid value for debuginfo-kind. Use 'dwarf', \
2223 'dwarf-dsym' or 'pdb'.")
2227 })).unwrap_or(Ok(()))
2229 ($key_name
:ident
, SplitDebuginfo
) => ( {
2230 let name
= (stringify
!($key_name
)).replace("_", "-");
2231 obj
.remove(&name
).and_then(|o
| o
.as_str().and_then(|s
| {
2232 match s
.parse
::<SplitDebuginfo
>() {
2233 Ok(level
) => base
.$key_name
= level
,
2234 _
=> return Some(Err(format
!("'{}' is not a valid value for \
2235 split-debuginfo. Use 'off' or 'dsymutil'.",
2239 })).unwrap_or(Ok(()))
2241 ($key_name
:ident
, list
) => ( {
2242 let name
= (stringify
!($key_name
)).replace("_", "-");
2243 if let Some(j
) = obj
.remove(&name
) {
2244 if let Some(v
) = j
.as_array() {
2245 base
.$key_name
= v
.iter()
2246 .map(|a
| a
.as_str().unwrap().to_string().into())
2249 incorrect_type
.push(name
)
2253 ($key_name
:ident
, opt_list
) => ( {
2254 let name
= (stringify
!($key_name
)).replace("_", "-");
2255 if let Some(j
) = obj
.remove(&name
) {
2256 if let Some(v
) = j
.as_array() {
2257 base
.$key_name
= Some(v
.iter()
2258 .map(|a
| a
.as_str().unwrap().to_string().into())
2261 incorrect_type
.push(name
)
2265 ($key_name
:ident
, falliable_list
) => ( {
2266 let name
= (stringify
!($key_name
)).replace("_", "-");
2267 obj
.remove(&name
).and_then(|j
| {
2268 if let Some(v
) = j
.as_array() {
2269 match v
.iter().map(|a
| FromStr
::from_str(a
.as_str().unwrap())).collect() {
2270 Ok(l
) => { base.$key_name = l }
,
2271 // FIXME: `falliable_list` can't re-use the `key!` macro for list
2272 // elements and the error messages from that macro, so it has a bad
2273 // generic message instead
2274 Err(_
) => return Some(Err(
2275 format
!("`{:?}` is not a valid value for `{}`", j
, name
)
2279 incorrect_type
.push(name
)
2282 }).unwrap_or(Ok(()))
2284 ($key_name
:ident
, optional
) => ( {
2285 let name
= (stringify
!($key_name
)).replace("_", "-");
2286 if let Some(o
) = obj
.remove(&name
) {
2289 .map(|s
| s
.to_string().into());
2292 ($key_name
:ident
= $json_name
:expr
, LldFlavor
) => ( {
2293 let name
= $json_name
;
2294 obj
.remove(name
).and_then(|o
| o
.as_str().and_then(|s
| {
2295 if let Some(flavor
) = LldFlavor
::from_str(&s
) {
2296 base
.$key_name
= flavor
;
2298 return Some(Err(format
!(
2299 "'{}' is not a valid value for lld-flavor. \
2300 Use 'darwin', 'gnu', 'link' or 'wasm'.",
2304 })).unwrap_or(Ok(()))
2306 ($key_name
:ident
= $json_name
:expr
, LinkerFlavor
) => ( {
2307 let name
= $json_name
;
2308 obj
.remove(name
).and_then(|o
| o
.as_str().and_then(|s
| {
2309 match LinkerFlavorCli
::from_str(s
) {
2310 Some(linker_flavor
) => base
.$key_name
= linker_flavor
,
2311 _
=> return Some(Err(format
!("'{}' is not a valid value for linker-flavor. \
2312 Use {}", s
, LinkerFlavorCli
::one_of()))),
2315 })).unwrap_or(Ok(()))
2317 ($key_name
:ident
, StackProbeType
) => ( {
2318 let name
= (stringify
!($key_name
)).replace("_", "-");
2319 obj
.remove(&name
).and_then(|o
| match StackProbeType
::from_json(&o
) {
2325 format
!("`{:?}` is not a valid value for `{}`: {}", o
, name
, s
)
2327 }).unwrap_or(Ok(()))
2329 ($key_name
:ident
, SanitizerSet
) => ( {
2330 let name
= (stringify
!($key_name
)).replace("_", "-");
2331 if let Some(o
) = obj
.remove(&name
) {
2332 if let Some(a
) = o
.as_array() {
2334 base
.$key_name
|= match s
.as_str() {
2335 Some("address") => SanitizerSet
::ADDRESS
,
2336 Some("cfi") => SanitizerSet
::CFI
,
2337 Some("kcfi") => SanitizerSet
::KCFI
,
2338 Some("leak") => SanitizerSet
::LEAK
,
2339 Some("memory") => SanitizerSet
::MEMORY
,
2340 Some("memtag") => SanitizerSet
::MEMTAG
,
2341 Some("shadow-call-stack") => SanitizerSet
::SHADOWCALLSTACK
,
2342 Some("thread") => SanitizerSet
::THREAD
,
2343 Some("hwaddress") => SanitizerSet
::HWADDRESS
,
2344 Some(s
) => return Err(format
!("unknown sanitizer {}", s
)),
2345 _
=> return Err(format
!("not a string: {:?}", s
)),
2349 incorrect_type
.push(name
)
2352 Ok
::<(), String
>(())
2355 ($key_name
:ident
= $json_name
:expr
, link_self_contained
) => ( {
2356 let name
= $json_name
;
2357 obj
.remove(name
).and_then(|o
| o
.as_str().and_then(|s
| {
2358 match s
.parse
::<LinkSelfContainedDefault
>() {
2359 Ok(lsc_default
) => base
.$key_name
= lsc_default
,
2360 _
=> return Some(Err(format
!("'{}' is not a valid `-Clink-self-contained` default. \
2361 Use 'false', 'true', 'musl' or 'mingw'", s
))),
2364 })).unwrap_or(Ok(()))
2366 ($key_name
:ident
= $json_name
:expr
, link_objects
) => ( {
2367 let name
= $json_name
;
2368 if let Some(val
) = obj
.remove(name
) {
2369 let obj
= val
.as_object().ok_or_else(|| format
!("{}: expected a \
2370 JSON object with fields per CRT object kind.", name
))?
;
2371 let mut args
= CrtObjects
::new();
2373 let kind
= LinkOutputKind
::from_str(&k
).ok_or_else(|| {
2374 format
!("{}: '{}' is not a valid value for CRT object kind. \
2375 Use '(dynamic,static)-(nopic,pic)-exe' or \
2376 '(dynamic,static)-dylib' or 'wasi-reactor-exe'", name
, k
)
2379 let v
= v
.as_array().ok_or_else(||
2380 format
!("{}.{}: expected a JSON array", name
, k
)
2381 )?
.iter().enumerate()
2383 let s
= s
.as_str().ok_or_else(||
2384 format
!("{}.{}[{}]: expected a JSON string", name
, k
, i
))?
;
2385 Ok(s
.to_string().into())
2387 .collect
::<Result
<Vec
<_
>, String
>>()?
;
2389 args
.insert(kind
, v
);
2391 base
.$key_name
= args
;
2394 ($key_name
:ident
= $json_name
:expr
, link_args
) => ( {
2395 let name
= $json_name
;
2396 if let Some(val
) = obj
.remove(name
) {
2397 let obj
= val
.as_object().ok_or_else(|| format
!("{}: expected a \
2398 JSON object with fields per linker-flavor.", name
))?
;
2399 let mut args
= LinkArgsCli
::new();
2401 let flavor
= LinkerFlavorCli
::from_str(&k
).ok_or_else(|| {
2402 format
!("{}: '{}' is not a valid value for linker-flavor. \
2403 Use 'em', 'gcc', 'ld' or 'msvc'", name
, k
)
2406 let v
= v
.as_array().ok_or_else(||
2407 format
!("{}.{}: expected a JSON array", name
, k
)
2408 )?
.iter().enumerate()
2410 let s
= s
.as_str().ok_or_else(||
2411 format
!("{}.{}[{}]: expected a JSON string", name
, k
, i
))?
;
2412 Ok(s
.to_string().into())
2414 .collect
::<Result
<Vec
<_
>, String
>>()?
;
2416 args
.insert(flavor
, v
);
2418 base
.$key_name
= args
;
2421 ($key_name
:ident
, env
) => ( {
2422 let name
= (stringify
!($key_name
)).replace("_", "-");
2423 if let Some(o
) = obj
.remove(&name
) {
2424 if let Some(a
) = o
.as_array() {
2426 if let Some(s
) = o
.as_str() {
2427 let p
= s
.split('
='
).collect
::<Vec
<_
>>();
2429 let k
= p
[0].to_string();
2430 let v
= p
[1].to_string();
2431 base
.$key_name
.to_mut().push((k
.into(), v
.into()));
2436 incorrect_type
.push(name
)
2440 ($key_name
:ident
, Option
<Abi
>) => ( {
2441 let name
= (stringify
!($key_name
)).replace("_", "-");
2442 obj
.remove(&name
).and_then(|o
| o
.as_str().and_then(|s
| {
2443 match lookup_abi(s
) {
2444 Some(abi
) => base
.$key_name
= Some(abi
),
2445 _
=> return Some(Err(format
!("'{}' is not a valid value for abi", s
))),
2448 })).unwrap_or(Ok(()))
2450 ($key_name
:ident
, TargetFamilies
) => ( {
2451 if let Some(value
) = obj
.remove("target-family") {
2452 if let Some(v
) = value
.as_array() {
2453 base
.$key_name
= v
.iter()
2454 .map(|a
| a
.as_str().unwrap().to_string().into())
2456 } else if let Some(v
) = value
.as_str() {
2457 base
.$key_name
= vec
![v
.to_string().into()].into();
2461 ($key_name
:ident
, Conv
) => ( {
2462 let name
= (stringify
!($key_name
)).replace("_", "-");
2463 obj
.remove(&name
).and_then(|o
| o
.as_str().and_then(|s
| {
2464 match Conv
::from_str(s
) {
2469 Err(e
) => Some(Err(e
))
2471 })).unwrap_or(Ok(()))
2475 if let Some(j
) = obj
.remove("target-endian") {
2476 if let Some(s
) = j
.as_str() {
2477 base
.endian
= s
.parse()?
;
2479 incorrect_type
.push("target-endian".into())
2483 if let Some(fp
) = obj
.remove("frame-pointer") {
2484 if let Some(s
) = fp
.as_str() {
2485 base
.frame_pointer
= s
2487 .map_err(|()| format
!("'{s}' is not a valid value for frame-pointer"))?
;
2489 incorrect_type
.push("frame-pointer".into())
2493 key
!(is_builtin
, bool
);
2494 key
!(c_int_width
= "target-c-int-width");
2499 key
!(linker
, optional
);
2500 key
!(linker_flavor_json
= "linker-flavor", LinkerFlavor
)?
;
2501 key
!(lld_flavor_json
= "lld-flavor", LldFlavor
)?
;
2502 key
!(linker_is_gnu_json
= "linker-is-gnu", bool
);
2503 key
!(pre_link_objects
= "pre-link-objects", link_objects
);
2504 key
!(post_link_objects
= "post-link-objects", link_objects
);
2505 key
!(pre_link_objects_self_contained
= "pre-link-objects-fallback", link_objects
);
2506 key
!(post_link_objects_self_contained
= "post-link-objects-fallback", link_objects
);
2507 key
!(link_self_contained
= "crt-objects-fallback", link_self_contained
)?
;
2508 key
!(pre_link_args_json
= "pre-link-args", link_args
);
2509 key
!(late_link_args_json
= "late-link-args", link_args
);
2510 key
!(late_link_args_dynamic_json
= "late-link-args-dynamic", link_args
);
2511 key
!(late_link_args_static_json
= "late-link-args-static", link_args
);
2512 key
!(post_link_args_json
= "post-link-args", link_args
);
2513 key
!(link_script
, optional
);
2514 key
!(link_env
, env
);
2515 key
!(link_env_remove
, list
);
2516 key
!(asm_args
, list
);
2519 key
!(dynamic_linking
, bool
);
2520 key
!(only_cdylib
, bool
);
2521 key
!(executables
, bool
);
2522 key
!(relocation_model
, RelocModel
)?
;
2523 key
!(code_model
, CodeModel
)?
;
2524 key
!(tls_model
, TlsModel
)?
;
2525 key
!(disable_redzone
, bool
);
2526 key
!(function_sections
, bool
);
2530 key
!(staticlib_prefix
);
2531 key
!(staticlib_suffix
);
2532 key
!(families
, TargetFamilies
);
2533 key
!(abi_return_struct_as_int
, bool
);
2534 key
!(is_like_aix
, bool
);
2535 key
!(is_like_osx
, bool
);
2536 key
!(is_like_solaris
, bool
);
2537 key
!(is_like_windows
, bool
);
2538 key
!(is_like_msvc
, bool
);
2539 key
!(is_like_wasm
, bool
);
2540 key
!(is_like_android
, bool
);
2541 key
!(default_dwarf_version
, u32);
2542 key
!(allows_weak_linkage
, bool
);
2543 key
!(has_rpath
, bool
);
2544 key
!(no_default_libraries
, bool
);
2545 key
!(position_independent_executables
, bool
);
2546 key
!(static_position_independent_executables
, bool
);
2547 key
!(needs_plt
, bool
);
2548 key
!(relro_level
, RelroLevel
)?
;
2549 key
!(archive_format
);
2550 key
!(allow_asm
, bool
);
2551 key
!(main_needs_argc_argv
, bool
);
2552 key
!(has_thread_local
, bool
);
2553 key
!(obj_is_bitcode
, bool
);
2554 key
!(forces_embed_bitcode
, bool
);
2555 key
!(bitcode_llvm_cmdline
);
2556 key
!(max_atomic_width
, Option
<u64>);
2557 key
!(min_atomic_width
, Option
<u64>);
2558 key
!(atomic_cas
, bool
);
2559 key
!(panic_strategy
, PanicStrategy
)?
;
2560 key
!(crt_static_allows_dylibs
, bool
);
2561 key
!(crt_static_default
, bool
);
2562 key
!(crt_static_respected
, bool
);
2563 key
!(stack_probes
, StackProbeType
)?
;
2564 key
!(min_global_align
, Option
<u64>);
2565 key
!(default_codegen_units
, Option
<u64>);
2566 key
!(trap_unreachable
, bool
);
2567 key
!(requires_lto
, bool
);
2568 key
!(singlethread
, bool
);
2569 key
!(no_builtins
, bool
);
2570 key
!(default_hidden_visibility
, bool
);
2571 key
!(emit_debug_gdb_scripts
, bool
);
2572 key
!(requires_uwtable
, bool
);
2573 key
!(default_uwtable
, bool
);
2574 key
!(simd_types_indirect
, bool
);
2575 key
!(limit_rdylib_exports
, bool
);
2576 key
!(override_export_symbols
, opt_list
);
2577 key
!(merge_functions
, MergeFunctions
)?
;
2578 key
!(mcount
= "target-mcount");
2580 key
!(relax_elf_relocations
, bool
);
2581 key
!(llvm_args
, list
);
2582 key
!(use_ctors_section
, bool
);
2583 key
!(eh_frame_header
, bool
);
2584 key
!(has_thumb_interworking
, bool
);
2585 key
!(debuginfo_kind
, DebuginfoKind
)?
;
2586 key
!(split_debuginfo
, SplitDebuginfo
)?
;
2587 key
!(supported_split_debuginfo
, falliable_list
)?
;
2588 key
!(supported_sanitizers
, SanitizerSet
)?
;
2589 key
!(default_adjusted_cabi
, Option
<Abi
>)?
;
2590 key
!(c_enum_min_bits
, u64);
2591 key
!(generate_arange_section
, bool
);
2592 key
!(supports_stack_protector
, bool
);
2594 key
!(entry_abi
, Conv
)?
;
2596 if base
.is_builtin
{
2597 // This can cause unfortunate ICEs later down the line.
2598 return Err("may not set is_builtin for targets not built-in".into());
2600 base
.update_from_cli();
2602 // Each field should have been read using `Json::remove` so any keys remaining are unused.
2603 let remaining_keys
= obj
.keys();
2606 TargetWarnings { unused_fields: remaining_keys.cloned().collect(), incorrect_type }
,
2610 /// Load a built-in target
2611 pub fn expect_builtin(target_triple
: &TargetTriple
) -> Target
{
2612 match *target_triple
{
2613 TargetTriple
::TargetTriple(ref target_triple
) => {
2614 load_builtin(target_triple
).expect("built-in target")
2616 TargetTriple
::TargetJson { .. }
=> {
2617 panic
!("built-in targets doesn't support target-paths")
2622 /// Search for a JSON file specifying the given target triple.
2624 /// If none is found in `$RUST_TARGET_PATH`, look for a file called `target.json` inside the
2625 /// sysroot under the target-triple's `rustlib` directory. Note that it could also just be a
2626 /// bare filename already, so also check for that. If one of the hardcoded targets we know
2627 /// about, just return it directly.
2629 /// The error string could come from any of the APIs called, including filesystem access and
2632 target_triple
: &TargetTriple
,
2634 ) -> Result
<(Target
, TargetWarnings
), String
> {
2638 fn load_file(path
: &Path
) -> Result
<(Target
, TargetWarnings
), String
> {
2639 let contents
= fs
::read_to_string(path
).map_err(|e
| e
.to_string())?
;
2640 let obj
= serde_json
::from_str(&contents
).map_err(|e
| e
.to_string())?
;
2641 Target
::from_json(obj
)
2644 match *target_triple
{
2645 TargetTriple
::TargetTriple(ref target_triple
) => {
2646 // check if triple is in list of built-in targets
2647 if let Some(t
) = load_builtin(target_triple
) {
2648 return Ok((t
, TargetWarnings
::empty()));
2651 // search for a file named `target_triple`.json in RUST_TARGET_PATH
2653 let mut target
= target_triple
.to_string();
2654 target
.push_str(".json");
2655 PathBuf
::from(target
)
2658 let target_path
= env
::var_os("RUST_TARGET_PATH").unwrap_or_default();
2660 for dir
in env
::split_paths(&target_path
) {
2661 let p
= dir
.join(&path
);
2663 return load_file(&p
);
2667 // Additionally look in the sysroot under `lib/rustlib/<triple>/target.json`
2669 let rustlib_path
= crate::target_rustlib_path(sysroot
, target_triple
);
2670 let p
= PathBuf
::from_iter([
2672 Path
::new(&rustlib_path
),
2673 Path
::new("target.json"),
2676 return load_file(&p
);
2679 Err(format
!("Could not find specification for target {target_triple:?}"))
2681 TargetTriple
::TargetJson { ref contents, .. }
=> {
2682 let obj
= serde_json
::from_str(contents
).map_err(|e
| e
.to_string())?
;
2683 Target
::from_json(obj
)
2689 impl ToJson
for Target
{
2690 fn to_json(&self) -> Json
{
2691 let mut d
= serde_json
::Map
::new();
2692 let default: TargetOptions
= Default
::default();
2693 let mut target
= self.clone();
2694 target
.update_to_cli();
2696 macro_rules
! target_val
{
2698 let name
= (stringify
!($attr
)).replace("_", "-");
2699 d
.insert(name
, target
.$attr
.to_json());
2703 macro_rules
! target_option_val
{
2705 let name
= (stringify
!($attr
)).replace("_", "-");
2706 if default.$attr
!= target
.$attr
{
2707 d
.insert(name
, target
.$attr
.to_json());
2710 ($attr
:ident
, $json_name
:expr
) => {{
2711 let name
= $json_name
;
2712 if default.$attr
!= target
.$attr
{
2713 d
.insert(name
.into(), target
.$attr
.to_json());
2716 (link_args
- $attr
:ident
, $json_name
:expr
) => {{
2717 let name
= $json_name
;
2718 if default.$attr
!= target
.$attr
{
2722 .map(|(k
, v
)| (k
.desc().to_string(), v
.clone()))
2723 .collect
::<BTreeMap
<_
, _
>>();
2724 d
.insert(name
.to_string(), obj
.to_json());
2727 (env
- $attr
:ident
) => {{
2728 let name
= (stringify
!($attr
)).replace("_", "-");
2729 if default.$attr
!= target
.$attr
{
2733 .map(|&(ref k
, ref v
)| format
!("{k}={v}"))
2734 .collect
::<Vec
<_
>>();
2735 d
.insert(name
, obj
.to_json());
2740 target_val
!(llvm_target
);
2741 d
.insert("target-pointer-width".to_string(), self.pointer_width
.to_string().to_json());
2743 target_val
!(data_layout
);
2745 target_option_val
!(is_builtin
);
2746 target_option_val
!(endian
, "target-endian");
2747 target_option_val
!(c_int_width
, "target-c-int-width");
2748 target_option_val
!(os
);
2749 target_option_val
!(env
);
2750 target_option_val
!(abi
);
2751 target_option_val
!(vendor
);
2752 target_option_val
!(linker
);
2753 target_option_val
!(linker_flavor_json
, "linker-flavor");
2754 target_option_val
!(lld_flavor_json
, "lld-flavor");
2755 target_option_val
!(linker_is_gnu_json
, "linker-is-gnu");
2756 target_option_val
!(pre_link_objects
);
2757 target_option_val
!(post_link_objects
);
2758 target_option_val
!(pre_link_objects_self_contained
, "pre-link-objects-fallback");
2759 target_option_val
!(post_link_objects_self_contained
, "post-link-objects-fallback");
2760 target_option_val
!(link_self_contained
, "crt-objects-fallback");
2761 target_option_val
!(link_args
- pre_link_args_json
, "pre-link-args");
2762 target_option_val
!(link_args
- late_link_args_json
, "late-link-args");
2763 target_option_val
!(link_args
- late_link_args_dynamic_json
, "late-link-args-dynamic");
2764 target_option_val
!(link_args
- late_link_args_static_json
, "late-link-args-static");
2765 target_option_val
!(link_args
- post_link_args_json
, "post-link-args");
2766 target_option_val
!(link_script
);
2767 target_option_val
!(env
- link_env
);
2768 target_option_val
!(link_env_remove
);
2769 target_option_val
!(asm_args
);
2770 target_option_val
!(cpu
);
2771 target_option_val
!(features
);
2772 target_option_val
!(dynamic_linking
);
2773 target_option_val
!(only_cdylib
);
2774 target_option_val
!(executables
);
2775 target_option_val
!(relocation_model
);
2776 target_option_val
!(code_model
);
2777 target_option_val
!(tls_model
);
2778 target_option_val
!(disable_redzone
);
2779 target_option_val
!(frame_pointer
);
2780 target_option_val
!(function_sections
);
2781 target_option_val
!(dll_prefix
);
2782 target_option_val
!(dll_suffix
);
2783 target_option_val
!(exe_suffix
);
2784 target_option_val
!(staticlib_prefix
);
2785 target_option_val
!(staticlib_suffix
);
2786 target_option_val
!(families
, "target-family");
2787 target_option_val
!(abi_return_struct_as_int
);
2788 target_option_val
!(is_like_aix
);
2789 target_option_val
!(is_like_osx
);
2790 target_option_val
!(is_like_solaris
);
2791 target_option_val
!(is_like_windows
);
2792 target_option_val
!(is_like_msvc
);
2793 target_option_val
!(is_like_wasm
);
2794 target_option_val
!(is_like_android
);
2795 target_option_val
!(default_dwarf_version
);
2796 target_option_val
!(allows_weak_linkage
);
2797 target_option_val
!(has_rpath
);
2798 target_option_val
!(no_default_libraries
);
2799 target_option_val
!(position_independent_executables
);
2800 target_option_val
!(static_position_independent_executables
);
2801 target_option_val
!(needs_plt
);
2802 target_option_val
!(relro_level
);
2803 target_option_val
!(archive_format
);
2804 target_option_val
!(allow_asm
);
2805 target_option_val
!(main_needs_argc_argv
);
2806 target_option_val
!(has_thread_local
);
2807 target_option_val
!(obj_is_bitcode
);
2808 target_option_val
!(forces_embed_bitcode
);
2809 target_option_val
!(bitcode_llvm_cmdline
);
2810 target_option_val
!(min_atomic_width
);
2811 target_option_val
!(max_atomic_width
);
2812 target_option_val
!(atomic_cas
);
2813 target_option_val
!(panic_strategy
);
2814 target_option_val
!(crt_static_allows_dylibs
);
2815 target_option_val
!(crt_static_default
);
2816 target_option_val
!(crt_static_respected
);
2817 target_option_val
!(stack_probes
);
2818 target_option_val
!(min_global_align
);
2819 target_option_val
!(default_codegen_units
);
2820 target_option_val
!(trap_unreachable
);
2821 target_option_val
!(requires_lto
);
2822 target_option_val
!(singlethread
);
2823 target_option_val
!(no_builtins
);
2824 target_option_val
!(default_hidden_visibility
);
2825 target_option_val
!(emit_debug_gdb_scripts
);
2826 target_option_val
!(requires_uwtable
);
2827 target_option_val
!(default_uwtable
);
2828 target_option_val
!(simd_types_indirect
);
2829 target_option_val
!(limit_rdylib_exports
);
2830 target_option_val
!(override_export_symbols
);
2831 target_option_val
!(merge_functions
);
2832 target_option_val
!(mcount
, "target-mcount");
2833 target_option_val
!(llvm_abiname
);
2834 target_option_val
!(relax_elf_relocations
);
2835 target_option_val
!(llvm_args
);
2836 target_option_val
!(use_ctors_section
);
2837 target_option_val
!(eh_frame_header
);
2838 target_option_val
!(has_thumb_interworking
);
2839 target_option_val
!(debuginfo_kind
);
2840 target_option_val
!(split_debuginfo
);
2841 target_option_val
!(supported_split_debuginfo
);
2842 target_option_val
!(supported_sanitizers
);
2843 target_option_val
!(c_enum_min_bits
);
2844 target_option_val
!(generate_arange_section
);
2845 target_option_val
!(supports_stack_protector
);
2846 target_option_val
!(entry_name
);
2847 target_option_val
!(entry_abi
);
2849 if let Some(abi
) = self.default_adjusted_cabi
{
2850 d
.insert("default-adjusted-cabi".into(), Abi
::name(abi
).to_json());
2857 /// Either a target triple string or a path to a JSON file.
2858 #[derive(Clone, Debug)]
2859 pub enum TargetTriple
{
2860 TargetTriple(String
),
2862 /// Warning: This field may only be used by rustdoc. Using it anywhere else will lead to
2863 /// inconsistencies as it is discarded during serialization.
2864 path_for_rustdoc
: PathBuf
,
2870 // Use a manual implementation to ignore the path field
2871 impl PartialEq
for TargetTriple
{
2872 fn eq(&self, other
: &Self) -> bool
{
2873 match (self, other
) {
2874 (Self::TargetTriple(l0
), Self::TargetTriple(r0
)) => l0
== r0
,
2876 Self::TargetJson { path_for_rustdoc: _, triple: l_triple, contents: l_contents }
,
2877 Self::TargetJson { path_for_rustdoc: _, triple: r_triple, contents: r_contents }
,
2878 ) => l_triple
== r_triple
&& l_contents
== r_contents
,
2884 // Use a manual implementation to ignore the path field
2885 impl Hash
for TargetTriple
{
2886 fn hash
<H
: Hasher
>(&self, state
: &mut H
) -> () {
2888 TargetTriple
::TargetTriple(triple
) => {
2892 TargetTriple
::TargetJson { path_for_rustdoc: _, triple, contents }
=> {
2895 contents
.hash(state
)
2901 // Use a manual implementation to prevent encoding the target json file path in the crate metadata
2902 impl<S
: Encoder
> Encodable
<S
> for TargetTriple
{
2903 fn encode(&self, s
: &mut S
) {
2905 TargetTriple
::TargetTriple(triple
) => s
.emit_enum_variant(0, |s
| s
.emit_str(triple
)),
2906 TargetTriple
::TargetJson { path_for_rustdoc: _, triple, contents }
=> s
2907 .emit_enum_variant(1, |s
| {
2909 s
.emit_str(contents
)
2915 impl<D
: Decoder
> Decodable
<D
> for TargetTriple
{
2916 fn decode(d
: &mut D
) -> Self {
2917 match d
.read_usize() {
2918 0 => TargetTriple
::TargetTriple(d
.read_str().to_owned()),
2919 1 => TargetTriple
::TargetJson
{
2920 path_for_rustdoc
: PathBuf
::new(),
2921 triple
: d
.read_str().to_owned(),
2922 contents
: d
.read_str().to_owned(),
2925 panic
!("invalid enum variant tag while decoding `TargetTriple`, expected 0..2");
2932 /// Creates a target triple from the passed target triple string.
2933 pub fn from_triple(triple
: &str) -> Self {
2934 TargetTriple
::TargetTriple(triple
.into())
2937 /// Creates a target triple from the passed target path.
2938 pub fn from_path(path
: &Path
) -> Result
<Self, io
::Error
> {
2939 let canonicalized_path
= path
.canonicalize()?
;
2940 let contents
= std
::fs
::read_to_string(&canonicalized_path
).map_err(|err
| {
2942 io
::ErrorKind
::InvalidInput
,
2943 format
!("target path {canonicalized_path:?} is not a valid file: {err}"),
2946 let triple
= canonicalized_path
2948 .expect("target path must not be empty")
2950 .expect("target path must be valid unicode")
2952 Ok(TargetTriple
::TargetJson { path_for_rustdoc: canonicalized_path, triple, contents }
)
2955 /// Returns a string triple for this target.
2957 /// If this target is a path, the file name (without extension) is returned.
2958 pub fn triple(&self) -> &str {
2960 TargetTriple
::TargetTriple(ref triple
)
2961 | TargetTriple
::TargetJson { ref triple, .. }
=> triple
,
2965 /// Returns an extended string triple for this target.
2967 /// If this target is a path, a hash of the path is appended to the triple returned
2969 pub fn debug_triple(&self) -> String
{
2970 use std
::collections
::hash_map
::DefaultHasher
;
2973 TargetTriple
::TargetTriple(triple
) => triple
.to_owned(),
2974 TargetTriple
::TargetJson { path_for_rustdoc: _, triple, contents: content }
=> {
2975 let mut hasher
= DefaultHasher
::new();
2976 content
.hash(&mut hasher
);
2977 let hash
= hasher
.finish();
2978 format
!("{triple}-{hash}")
2984 impl fmt
::Display
for TargetTriple
{
2985 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
2986 write
!(f
, "{}", self.debug_triple())