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](http://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::spec::abi::{lookup as lookup_abi, Abi};
38 use crate::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
39 use rustc_serialize::json::{Json, ToJson};
40 use std::collections::BTreeMap;
41 use std::path::{Path, PathBuf};
42 use std::str::FromStr;
45 use rustc_macros::HashStable_Generic;
57 mod freestanding_base;
61 mod hermit_kernel_base;
65 mod linux_kernel_base;
78 mod windows_msvc_base;
79 mod windows_uwp_gnu_base;
80 mod windows_uwp_msvc_base;
82 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
83 pub enum LinkerFlavor {
92 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
101 fn from_str(s: &str) -> Option<Self> {
103 "darwin" => LldFlavor::Ld64,
104 "gnu" => LldFlavor::Ld,
105 "link" => LldFlavor::Link,
106 "wasm" => LldFlavor::Wasm,
112 impl ToJson for LldFlavor {
113 fn to_json(&self) -> Json {
115 LldFlavor::Ld64 => "darwin",
116 LldFlavor::Ld => "gnu",
117 LldFlavor::Link => "link",
118 LldFlavor::Wasm => "wasm",
124 impl ToJson for LinkerFlavor {
125 fn to_json(&self) -> Json {
126 self.desc().to_json()
129 macro_rules! flavor_mappings {
130 ($((($($flavor:tt)*), $string:expr),)*) => (
132 pub const fn one_of() -> &'static str {
133 concat!("one of: ", $($string, " ",)*)
136 pub fn from_str(s: &str) -> Option<Self> {
138 $($string => $($flavor)*,)*
143 pub fn desc(&self) -> &str {
145 $($($flavor)* => $string,)*
153 ((LinkerFlavor::Em), "em"),
154 ((LinkerFlavor::Gcc), "gcc"),
155 ((LinkerFlavor::Ld), "ld"),
156 ((LinkerFlavor::Msvc), "msvc"),
157 ((LinkerFlavor::PtxLinker), "ptx-linker"),
158 ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
159 ((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"),
160 ((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"),
161 ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
164 #[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
165 pub enum PanicStrategy {
171 pub fn desc(&self) -> &str {
173 PanicStrategy::Unwind => "unwind",
174 PanicStrategy::Abort => "abort",
179 impl ToJson for PanicStrategy {
180 fn to_json(&self) -> Json {
182 PanicStrategy::Abort => "abort".to_json(),
183 PanicStrategy::Unwind => "unwind".to_json(),
188 #[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable)]
189 pub enum RelroLevel {
197 pub fn desc(&self) -> &str {
199 RelroLevel::Full => "full",
200 RelroLevel::Partial => "partial",
201 RelroLevel::Off => "off",
202 RelroLevel::None => "none",
207 impl FromStr for RelroLevel {
210 fn from_str(s: &str) -> Result<RelroLevel, ()> {
212 "full" => Ok(RelroLevel::Full),
213 "partial" => Ok(RelroLevel::Partial),
214 "off" => Ok(RelroLevel::Off),
215 "none" => Ok(RelroLevel::None),
221 impl ToJson for RelroLevel {
222 fn to_json(&self) -> Json {
224 RelroLevel::Full => "full".to_json(),
225 RelroLevel::Partial => "partial".to_json(),
226 RelroLevel::Off => "off".to_json(),
227 RelroLevel::None => "None".to_json(),
232 #[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable)]
233 pub enum MergeFunctions {
239 impl MergeFunctions {
240 pub fn desc(&self) -> &str {
242 MergeFunctions::Disabled => "disabled",
243 MergeFunctions::Trampolines => "trampolines",
244 MergeFunctions::Aliases => "aliases",
249 impl FromStr for MergeFunctions {
252 fn from_str(s: &str) -> Result<MergeFunctions, ()> {
254 "disabled" => Ok(MergeFunctions::Disabled),
255 "trampolines" => Ok(MergeFunctions::Trampolines),
256 "aliases" => Ok(MergeFunctions::Aliases),
262 impl ToJson for MergeFunctions {
263 fn to_json(&self) -> Json {
265 MergeFunctions::Disabled => "disabled".to_json(),
266 MergeFunctions::Trampolines => "trampolines".to_json(),
267 MergeFunctions::Aliases => "aliases".to_json(),
272 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
273 pub enum RelocModel {
282 impl FromStr for RelocModel {
285 fn from_str(s: &str) -> Result<RelocModel, ()> {
287 "static" => RelocModel::Static,
288 "pic" => RelocModel::Pic,
289 "dynamic-no-pic" => RelocModel::DynamicNoPic,
290 "ropi" => RelocModel::Ropi,
291 "rwpi" => RelocModel::Rwpi,
292 "ropi-rwpi" => RelocModel::RopiRwpi,
298 impl ToJson for RelocModel {
299 fn to_json(&self) -> Json {
301 RelocModel::Static => "static",
302 RelocModel::Pic => "pic",
303 RelocModel::DynamicNoPic => "dynamic-no-pic",
304 RelocModel::Ropi => "ropi",
305 RelocModel::Rwpi => "rwpi",
306 RelocModel::RopiRwpi => "ropi-rwpi",
312 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
321 impl FromStr for CodeModel {
324 fn from_str(s: &str) -> Result<CodeModel, ()> {
326 "tiny" => CodeModel::Tiny,
327 "small" => CodeModel::Small,
328 "kernel" => CodeModel::Kernel,
329 "medium" => CodeModel::Medium,
330 "large" => CodeModel::Large,
336 impl ToJson for CodeModel {
337 fn to_json(&self) -> Json {
339 CodeModel::Tiny => "tiny",
340 CodeModel::Small => "small",
341 CodeModel::Kernel => "kernel",
342 CodeModel::Medium => "medium",
343 CodeModel::Large => "large",
349 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
357 impl FromStr for TlsModel {
360 fn from_str(s: &str) -> Result<TlsModel, ()> {
362 // Note the difference "general" vs "global" difference. The model name is "general",
363 // but the user-facing option name is "global" for consistency with other compilers.
364 "global-dynamic" => TlsModel::GeneralDynamic,
365 "local-dynamic" => TlsModel::LocalDynamic,
366 "initial-exec" => TlsModel::InitialExec,
367 "local-exec" => TlsModel::LocalExec,
373 impl ToJson for TlsModel {
374 fn to_json(&self) -> Json {
376 TlsModel::GeneralDynamic => "global-dynamic",
377 TlsModel::LocalDynamic => "local-dynamic",
378 TlsModel::InitialExec => "initial-exec",
379 TlsModel::LocalExec => "local-exec",
385 /// Everything is flattened to a single enum to make the json encoding/decoding less annoying.
386 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
387 pub enum LinkOutputKind {
388 /// Dynamically linked non position-independent executable.
390 /// Dynamically linked position-independent executable.
392 /// Statically linked non position-independent executable.
394 /// Statically linked position-independent executable.
396 /// Regular dynamic library ("dynamically linked").
398 /// Dynamic library with bundled libc ("statically linked").
402 impl LinkOutputKind {
403 fn as_str(&self) -> &'static str {
405 LinkOutputKind::DynamicNoPicExe => "dynamic-nopic-exe",
406 LinkOutputKind::DynamicPicExe => "dynamic-pic-exe",
407 LinkOutputKind::StaticNoPicExe => "static-nopic-exe",
408 LinkOutputKind::StaticPicExe => "static-pic-exe",
409 LinkOutputKind::DynamicDylib => "dynamic-dylib",
410 LinkOutputKind::StaticDylib => "static-dylib",
414 pub(super) fn from_str(s: &str) -> Option<LinkOutputKind> {
416 "dynamic-nopic-exe" => LinkOutputKind::DynamicNoPicExe,
417 "dynamic-pic-exe" => LinkOutputKind::DynamicPicExe,
418 "static-nopic-exe" => LinkOutputKind::StaticNoPicExe,
419 "static-pic-exe" => LinkOutputKind::StaticPicExe,
420 "dynamic-dylib" => LinkOutputKind::DynamicDylib,
421 "static-dylib" => LinkOutputKind::StaticDylib,
427 impl fmt::Display for LinkOutputKind {
428 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
429 f.write_str(self.as_str())
433 pub enum LoadTargetError {
434 BuiltinTargetNotFound(String),
438 pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<String>>;
439 pub type TargetResult = Result<Target, String>;
441 macro_rules! supported_targets {
442 ( $(($( $triple:literal, )+ $module:ident ),)+ ) => {
445 /// List of supported targets
446 const TARGETS: &[&str] = &[$($($triple),+),+];
448 fn load_specific(target: &str) -> Result<Target, LoadTargetError> {
452 let mut t = $module::target()
453 .map_err(LoadTargetError::Other)?;
454 t.options.is_builtin = true;
456 // round-trip through the JSON parser to ensure at
457 // run-time that the parser works correctly
458 t = Target::from_json(t.to_json())
459 .map_err(LoadTargetError::Other)?;
460 debug!("got builtin target: {:?}", t);
464 _ => Err(LoadTargetError::BuiltinTargetNotFound(
465 format!("Unable to find target: {}", target)))
469 pub fn get_targets() -> impl Iterator<Item = String> {
470 TARGETS.iter().filter_map(|t| -> Option<String> {
472 .and(Ok(t.to_string()))
481 // Cannot put this into a separate file without duplication, make an exception.
485 tests_impl::test_target(super::$module::target());
493 ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
494 ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
495 ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
496 ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
497 ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
498 ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
499 ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
500 ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
501 ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
502 ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
503 ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
504 ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
505 ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
506 ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
507 ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
508 ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
509 ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
510 ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
511 ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
512 ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
513 ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
514 ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
515 ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
516 ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
517 ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
518 ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
519 ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
520 ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
521 ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi),
522 ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi),
523 ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
524 ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf),
525 ("thumbv7neon-unknown-linux-musleabihf", thumbv7neon_unknown_linux_musleabihf),
526 ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi),
527 ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
528 ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
529 ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
530 ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
531 ("i686-unknown-linux-musl", i686_unknown_linux_musl),
532 ("i586-unknown-linux-musl", i586_unknown_linux_musl),
533 ("mips-unknown-linux-musl", mips_unknown_linux_musl),
534 ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
535 ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
536 ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
537 ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
539 ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
540 ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
542 ("i686-linux-android", i686_linux_android),
543 ("x86_64-linux-android", x86_64_linux_android),
544 ("arm-linux-androideabi", arm_linux_androideabi),
545 ("armv7-linux-androideabi", armv7_linux_androideabi),
546 ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
547 ("aarch64-linux-android", aarch64_linux_android),
549 ("x86_64-linux-kernel", x86_64_linux_kernel),
551 ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
552 ("armv6-unknown-freebsd", armv6_unknown_freebsd),
553 ("armv7-unknown-freebsd", armv7_unknown_freebsd),
554 ("i686-unknown-freebsd", i686_unknown_freebsd),
555 ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
556 ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
558 ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
560 ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
561 ("i686-unknown-openbsd", i686_unknown_openbsd),
562 ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
563 ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
565 ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
566 ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
567 ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
568 ("i686-unknown-netbsd", i686_unknown_netbsd),
569 ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
570 ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
571 ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
572 ("x86_64-rumprun-netbsd", x86_64_rumprun_netbsd),
574 ("i686-unknown-haiku", i686_unknown_haiku),
575 ("x86_64-unknown-haiku", x86_64_unknown_haiku),
577 ("aarch64-apple-darwin", aarch64_apple_darwin),
578 ("x86_64-apple-darwin", x86_64_apple_darwin),
579 ("i686-apple-darwin", i686_apple_darwin),
581 ("aarch64-fuchsia", aarch64_fuchsia),
582 ("x86_64-fuchsia", x86_64_fuchsia),
584 ("avr-unknown-unknown", avr_unknown_unknown),
586 ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
588 ("aarch64-unknown-redox", aarch64_unknown_redox),
589 ("x86_64-unknown-redox", x86_64_unknown_redox),
591 ("i386-apple-ios", i386_apple_ios),
592 ("x86_64-apple-ios", x86_64_apple_ios),
593 ("aarch64-apple-ios", aarch64_apple_ios),
594 ("armv7-apple-ios", armv7_apple_ios),
595 ("armv7s-apple-ios", armv7s_apple_ios),
596 ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
597 ("aarch64-apple-tvos", aarch64_apple_tvos),
598 ("x86_64-apple-tvos", x86_64_apple_tvos),
600 ("armebv7r-none-eabi", armebv7r_none_eabi),
601 ("armebv7r-none-eabihf", armebv7r_none_eabihf),
602 ("armv7r-none-eabi", armv7r_none_eabi),
603 ("armv7r-none-eabihf", armv7r_none_eabihf),
605 // `x86_64-pc-solaris` is an alias for `x86_64_sun_solaris` for backwards compatibility reasons.
606 // (See <https://github.com/rust-lang/rust/issues/40531>.)
607 ("x86_64-sun-solaris", "x86_64-pc-solaris", x86_64_sun_solaris),
608 ("sparcv9-sun-solaris", sparcv9_sun_solaris),
610 ("x86_64-unknown-illumos", x86_64_unknown_illumos),
612 ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
613 ("i686-pc-windows-gnu", i686_pc_windows_gnu),
614 ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
615 ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
617 ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
618 ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
619 ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
620 ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
621 ("i686-pc-windows-msvc", i686_pc_windows_msvc),
622 ("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
623 ("i586-pc-windows-msvc", i586_pc_windows_msvc),
624 ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
625 ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc),
627 ("asmjs-unknown-emscripten", asmjs_unknown_emscripten),
628 ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
629 ("wasm32-unknown-unknown", wasm32_unknown_unknown),
630 ("wasm32-wasi", wasm32_wasi),
632 ("thumbv6m-none-eabi", thumbv6m_none_eabi),
633 ("thumbv7m-none-eabi", thumbv7m_none_eabi),
634 ("thumbv7em-none-eabi", thumbv7em_none_eabi),
635 ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
636 ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi),
637 ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
638 ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
640 ("armv7a-none-eabi", armv7a_none_eabi),
641 ("armv7a-none-eabihf", armv7a_none_eabihf),
643 ("msp430-none-elf", msp430_none_elf),
645 ("aarch64-unknown-cloudabi", aarch64_unknown_cloudabi),
646 ("armv7-unknown-cloudabi-eabihf", armv7_unknown_cloudabi_eabihf),
647 ("i686-unknown-cloudabi", i686_unknown_cloudabi),
648 ("x86_64-unknown-cloudabi", x86_64_unknown_cloudabi),
650 ("aarch64-unknown-hermit", aarch64_unknown_hermit),
651 ("x86_64-unknown-hermit", x86_64_unknown_hermit),
652 ("x86_64-unknown-hermit-kernel", x86_64_unknown_hermit_kernel),
654 ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
655 ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
656 ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
657 ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
658 ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
659 ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
661 ("aarch64-unknown-none", aarch64_unknown_none),
662 ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
664 ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
666 ("x86_64-unknown-uefi", x86_64_unknown_uefi),
667 ("i686-unknown-uefi", i686_unknown_uefi),
669 ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
671 ("i686-wrs-vxworks", i686_wrs_vxworks),
672 ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
673 ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
674 ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
675 ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
676 ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
677 ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
679 ("mipsel-sony-psp", mipsel_sony_psp),
680 ("thumbv4t-none-eabi", thumbv4t_none_eabi),
683 /// Everything `rustc` knows about how to compile for a specific target.
685 /// Every field here must be specified, and has no default value.
686 #[derive(PartialEq, Clone, Debug)]
688 /// Target triple to pass to LLVM.
689 pub llvm_target: String,
690 /// String to use as the `target_endian` `cfg` variable.
691 pub target_endian: String,
692 /// String to use as the `target_pointer_width` `cfg` variable.
693 pub target_pointer_width: String,
694 /// Width of c_int type
695 pub target_c_int_width: String,
696 /// OS name to use for conditional compilation.
697 pub target_os: String,
698 /// Environment name to use for conditional compilation.
699 pub target_env: String,
700 /// Vendor name to use for conditional compilation.
701 pub target_vendor: String,
702 /// Architecture to use for ABI considerations. Valid options include: "x86",
703 /// "x86_64", "arm", "aarch64", "mips", "powerpc", "powerpc64", and others.
705 /// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
706 pub data_layout: String,
707 /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
708 /// on the command line.
709 pub linker_flavor: LinkerFlavor,
710 /// Optional settings with defaults.
711 pub options: TargetOptions,
714 pub trait HasTargetSpec {
715 fn target_spec(&self) -> &Target;
718 impl HasTargetSpec for Target {
719 fn target_spec(&self) -> &Target {
724 /// Optional aspects of a target specification.
726 /// This has an implementation of `Default`, see each field for what the default is. In general,
727 /// these try to take "minimal defaults" that don't assume anything about the runtime they run in.
728 #[derive(PartialEq, Clone, Debug)]
729 pub struct TargetOptions {
730 /// Whether the target is built-in or loaded from a custom target specification.
731 pub is_builtin: bool,
734 pub linker: Option<String>,
736 /// LLD flavor used if `lld` (or `rust-lld`) is specified as a linker
737 /// without clarifying its flavor in any way.
738 pub lld_flavor: LldFlavor,
740 /// Linker arguments that are passed *before* any user-defined libraries.
741 pub pre_link_args: LinkArgs,
742 /// Objects to link before and after all other object code.
743 pub pre_link_objects: CrtObjects,
744 pub post_link_objects: CrtObjects,
745 /// Same as `(pre|post)_link_objects`, but when we fail to pull the objects with help of the
746 /// target's native gcc and fall back to the "self-contained" mode and pull them manually.
747 /// See `crt_objects.rs` for some more detailed documentation.
748 pub pre_link_objects_fallback: CrtObjects,
749 pub post_link_objects_fallback: CrtObjects,
750 /// Which logic to use to determine whether to fall back to the "self-contained" mode or not.
751 pub crt_objects_fallback: Option<CrtObjectsFallback>,
753 /// Linker arguments that are unconditionally passed after any
754 /// user-defined but before post-link objects. Standard platform
755 /// libraries that should be always be linked to, usually go here.
756 pub late_link_args: LinkArgs,
757 /// Linker arguments used in addition to `late_link_args` if at least one
758 /// Rust dependency is dynamically linked.
759 pub late_link_args_dynamic: LinkArgs,
760 /// Linker arguments used in addition to `late_link_args` if aall Rust
761 /// dependencies are statically linked.
762 pub late_link_args_static: LinkArgs,
763 /// Linker arguments that are unconditionally passed *after* any
764 /// user-defined libraries.
765 pub post_link_args: LinkArgs,
766 /// Optional link script applied to `dylib` and `executable` crate types.
767 /// This is a string containing the script, not a path. Can only be applied
768 /// to linkers where `linker_is_gnu` is true.
769 pub link_script: Option<String>,
771 /// Environment variables to be set for the linker invocation.
772 pub link_env: Vec<(String, String)>,
773 /// Environment variables to be removed for the linker invocation.
774 pub link_env_remove: Vec<String>,
776 /// Extra arguments to pass to the external assembler (when used)
777 pub asm_args: Vec<String>,
779 /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults
782 /// Default target features to pass to LLVM. These features will *always* be
783 /// passed, and cannot be disabled even via `-C`. Corresponds to `llc
784 /// -mattr=$features`.
785 pub features: String,
786 /// Whether dynamic linking is available on this target. Defaults to false.
787 pub dynamic_linking: bool,
788 /// If dynamic linking is available, whether only cdylibs are supported.
789 pub only_cdylib: bool,
790 /// Whether executables are available on this target. iOS, for example, only allows static
791 /// libraries. Defaults to false.
792 pub executables: bool,
793 /// Relocation model to use in object file. Corresponds to `llc
794 /// -relocation-model=$relocation_model`. Defaults to `Pic`.
795 pub relocation_model: RelocModel,
796 /// Code model to use. Corresponds to `llc -code-model=$code_model`.
797 /// Defaults to `None` which means "inherited from the base LLVM target".
798 pub code_model: Option<CodeModel>,
799 /// TLS model to use. Options are "global-dynamic" (default), "local-dynamic", "initial-exec"
800 /// and "local-exec". This is similar to the -ftls-model option in GCC/Clang.
801 pub tls_model: TlsModel,
802 /// Do not emit code that uses the "red zone", if the ABI has one. Defaults to false.
803 pub disable_redzone: bool,
804 /// Eliminate frame pointers from stack frames if possible. Defaults to true.
805 pub eliminate_frame_pointer: bool,
806 /// Emit each function in its own section. Defaults to true.
807 pub function_sections: bool,
808 /// String to prepend to the name of every dynamic library. Defaults to "lib".
809 pub dll_prefix: String,
810 /// String to append to the name of every dynamic library. Defaults to ".so".
811 pub dll_suffix: String,
812 /// String to append to the name of every executable.
813 pub exe_suffix: String,
814 /// String to prepend to the name of every static library. Defaults to "lib".
815 pub staticlib_prefix: String,
816 /// String to append to the name of every static library. Defaults to ".a".
817 pub staticlib_suffix: String,
818 /// OS family to use for conditional compilation. Valid options: "unix", "windows".
819 pub target_family: Option<String>,
820 /// Whether the target toolchain's ABI supports returning small structs as an integer.
821 pub abi_return_struct_as_int: bool,
822 /// Whether the target toolchain is like macOS's. Only useful for compiling against iOS/macOS,
823 /// in particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false.
824 pub is_like_osx: bool,
825 /// Whether the target toolchain is like Solaris's.
826 /// Only useful for compiling against Illumos/Solaris,
827 /// as they have a different set of linker flags. Defaults to false.
828 pub is_like_solaris: bool,
829 /// Whether the target toolchain is like Windows'. Only useful for compiling against Windows,
830 /// only really used for figuring out how to find libraries, since Windows uses its own
831 /// library naming convention. Defaults to false.
832 pub is_like_windows: bool,
833 pub is_like_msvc: bool,
834 /// Whether the target toolchain is like Android's. Only useful for compiling against Android.
835 /// Defaults to false.
836 pub is_like_android: bool,
837 /// Whether the target toolchain is like Emscripten's. Only useful for compiling with
838 /// Emscripten toolchain.
839 /// Defaults to false.
840 pub is_like_emscripten: bool,
841 /// Whether the target toolchain is like Fuchsia's.
842 pub is_like_fuchsia: bool,
843 /// Whether the linker support GNU-like arguments such as -O. Defaults to false.
844 pub linker_is_gnu: bool,
845 /// The MinGW toolchain has a known issue that prevents it from correctly
846 /// handling COFF object files with more than 2<sup>15</sup> sections. Since each weak
847 /// symbol needs its own COMDAT section, weak linkage implies a large
848 /// number sections that easily exceeds the given limit for larger
849 /// codebases. Consequently we want a way to disallow weak linkage on some
851 pub allows_weak_linkage: bool,
852 /// Whether the linker support rpaths or not. Defaults to false.
854 /// Whether to disable linking to the default libraries, typically corresponds
855 /// to `-nodefaultlibs`. Defaults to true.
856 pub no_default_libraries: bool,
857 /// Dynamically linked executables can be compiled as position independent
858 /// if the default relocation model of position independent code is not
859 /// changed. This is a requirement to take advantage of ASLR, as otherwise
860 /// the functions in the executable are not randomized and can be used
861 /// during an exploit of a vulnerability in any code.
862 pub position_independent_executables: bool,
863 /// Executables that are both statically linked and position-independent are supported.
864 pub static_position_independent_executables: bool,
865 /// Determines if the target always requires using the PLT for indirect
866 /// library calls or not. This controls the default value of the `-Z plt` flag.
868 /// Either partial, full, or off. Full RELRO makes the dynamic linker
869 /// resolve all symbols at startup and marks the GOT read-only before
870 /// starting the program, preventing overwriting the GOT.
871 pub relro_level: RelroLevel,
872 /// Format that archives should be emitted in. This affects whether we use
873 /// LLVM to assemble an archive or fall back to the system linker, and
874 /// currently only "gnu" is used to fall into LLVM. Unknown strings cause
875 /// the system linker to be used.
876 pub archive_format: String,
877 /// Is asm!() allowed? Defaults to true.
879 /// Whether the runtime startup code requires the `main` function be passed
880 /// `argc` and `argv` values.
881 pub main_needs_argc_argv: bool,
883 /// Flag indicating whether ELF TLS (e.g., #[thread_local]) is available for
885 pub has_elf_tls: bool,
886 // This is mainly for easy compatibility with emscripten.
887 // If we give emcc .o files that are actually .bc files it
889 pub obj_is_bitcode: bool,
890 /// Whether the target requires that emitted object code includes bitcode.
891 pub forces_embed_bitcode: bool,
892 /// Content of the LLVM cmdline section associated with embedded bitcode.
893 pub bitcode_llvm_cmdline: String,
895 /// Don't use this field; instead use the `.min_atomic_width()` method.
896 pub min_atomic_width: Option<u64>,
898 /// Don't use this field; instead use the `.max_atomic_width()` method.
899 pub max_atomic_width: Option<u64>,
901 /// Whether the target supports atomic CAS operations natively
902 pub atomic_cas: bool,
904 /// Panic strategy: "unwind" or "abort"
905 pub panic_strategy: PanicStrategy,
907 /// A list of ABIs unsupported by the current target. Note that generic ABIs
908 /// are considered to be supported on all platforms and cannot be marked
910 pub unsupported_abis: Vec<Abi>,
912 /// Whether or not linking dylibs to a static CRT is allowed.
913 pub crt_static_allows_dylibs: bool,
914 /// Whether or not the CRT is statically linked by default.
915 pub crt_static_default: bool,
916 /// Whether or not crt-static is respected by the compiler (or is a no-op).
917 pub crt_static_respected: bool,
919 /// Whether or not stack probes (__rust_probestack) are enabled
920 pub stack_probes: bool,
922 /// The minimum alignment for global symbols.
923 pub min_global_align: Option<u64>,
925 /// Default number of codegen units to use in debug mode
926 pub default_codegen_units: Option<u64>,
928 /// Whether to generate trap instructions in places where optimization would
929 /// otherwise produce control flow that falls through into unrelated memory.
930 pub trap_unreachable: bool,
932 /// This target requires everything to be compiled with LTO to emit a final
933 /// executable, aka there is no native linker for this target.
934 pub requires_lto: bool,
936 /// This target has no support for threads.
937 pub singlethread: bool,
939 /// Whether library functions call lowering/optimization is disabled in LLVM
940 /// for this target unconditionally.
941 pub no_builtins: bool,
943 /// The default visibility for symbols in this target should be "hidden"
944 /// rather than "default"
945 pub default_hidden_visibility: bool,
947 /// Whether a .debug_gdb_scripts section will be added to the output object file
948 pub emit_debug_gdb_scripts: bool,
950 /// Whether or not to unconditionally `uwtable` attributes on functions,
951 /// typically because the platform needs to unwind for things like stack
953 pub requires_uwtable: bool,
955 /// Whether or not SIMD types are passed by reference in the Rust ABI,
956 /// typically required if a target can be compiled with a mixed set of
957 /// target features. This is `true` by default, and `false` for targets like
958 /// wasm32 where the whole program either has simd or not.
959 pub simd_types_indirect: bool,
961 /// Pass a list of symbol which should be exported in the dylib to the linker.
962 pub limit_rdylib_exports: bool,
964 /// If set, have the linker export exactly these symbols, instead of using
965 /// the usual logic to figure this out from the crate itself.
966 pub override_export_symbols: Option<Vec<String>>,
968 /// Determines how or whether the MergeFunctions LLVM pass should run for
969 /// this target. Either "disabled", "trampolines", or "aliases".
970 /// The MergeFunctions pass is generally useful, but some targets may need
971 /// to opt out. The default is "aliases".
973 /// Workaround for: https://github.com/rust-lang/rust/issues/57356
974 pub merge_functions: MergeFunctions,
976 /// Use platform dependent mcount function
977 pub target_mcount: String,
979 /// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers
980 pub llvm_abiname: String,
982 /// Whether or not RelaxElfRelocation flag will be passed to the linker
983 pub relax_elf_relocations: bool,
985 /// Additional arguments to pass to LLVM, similar to the `-C llvm-args` codegen option.
986 pub llvm_args: Vec<String>,
988 /// Whether to use legacy .ctors initialization hooks rather than .init_array. Defaults
989 /// to false (uses .init_array).
990 pub use_ctors_section: bool,
992 /// Whether the linker is instructed to add a `GNU_EH_FRAME` ELF header
993 /// used to locate unwinding information is passed
994 /// (only has effect if the linker is `ld`-like).
995 pub eh_frame_header: bool,
998 impl Default for TargetOptions {
999 /// Creates a set of "sane defaults" for any target. This is still
1000 /// incomplete, and if used for compilation, will certainly not work.
1001 fn default() -> TargetOptions {
1004 linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()),
1005 lld_flavor: LldFlavor::Ld,
1006 pre_link_args: LinkArgs::new(),
1007 post_link_args: LinkArgs::new(),
1009 asm_args: Vec::new(),
1010 cpu: "generic".to_string(),
1011 features: String::new(),
1012 dynamic_linking: false,
1015 relocation_model: RelocModel::Pic,
1017 tls_model: TlsModel::GeneralDynamic,
1018 disable_redzone: false,
1019 eliminate_frame_pointer: true,
1020 function_sections: true,
1021 dll_prefix: "lib".to_string(),
1022 dll_suffix: ".so".to_string(),
1023 exe_suffix: String::new(),
1024 staticlib_prefix: "lib".to_string(),
1025 staticlib_suffix: ".a".to_string(),
1026 target_family: None,
1027 abi_return_struct_as_int: false,
1029 is_like_solaris: false,
1030 is_like_windows: false,
1031 is_like_android: false,
1032 is_like_emscripten: false,
1033 is_like_msvc: false,
1034 is_like_fuchsia: false,
1035 linker_is_gnu: false,
1036 allows_weak_linkage: true,
1038 no_default_libraries: true,
1039 position_independent_executables: false,
1040 static_position_independent_executables: false,
1042 relro_level: RelroLevel::None,
1043 pre_link_objects: Default::default(),
1044 post_link_objects: Default::default(),
1045 pre_link_objects_fallback: Default::default(),
1046 post_link_objects_fallback: Default::default(),
1047 crt_objects_fallback: None,
1048 late_link_args: LinkArgs::new(),
1049 late_link_args_dynamic: LinkArgs::new(),
1050 late_link_args_static: LinkArgs::new(),
1051 link_env: Vec::new(),
1052 link_env_remove: Vec::new(),
1053 archive_format: "gnu".to_string(),
1054 main_needs_argc_argv: true,
1057 obj_is_bitcode: false,
1058 forces_embed_bitcode: false,
1059 bitcode_llvm_cmdline: String::new(),
1060 min_atomic_width: None,
1061 max_atomic_width: None,
1063 panic_strategy: PanicStrategy::Unwind,
1064 unsupported_abis: vec![],
1065 crt_static_allows_dylibs: false,
1066 crt_static_default: false,
1067 crt_static_respected: false,
1068 stack_probes: false,
1069 min_global_align: None,
1070 default_codegen_units: None,
1071 trap_unreachable: true,
1072 requires_lto: false,
1073 singlethread: false,
1075 default_hidden_visibility: false,
1076 emit_debug_gdb_scripts: true,
1077 requires_uwtable: false,
1078 simd_types_indirect: true,
1079 limit_rdylib_exports: true,
1080 override_export_symbols: None,
1081 merge_functions: MergeFunctions::Aliases,
1082 target_mcount: "mcount".to_string(),
1083 llvm_abiname: "".to_string(),
1084 relax_elf_relocations: false,
1086 use_ctors_section: false,
1087 eh_frame_header: true,
1093 /// Given a function ABI, turn it into the correct ABI for this target.
1094 pub fn adjust_abi(&self, abi: Abi) -> Abi {
1097 if self.options.is_like_windows && self.arch == "x86" {
1103 // These ABI kinds are ignored on non-x86 Windows targets.
1104 // See https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
1105 // and the individual pages for __stdcall et al.
1106 Abi::Stdcall | Abi::Fastcall | Abi::Vectorcall | Abi::Thiscall => {
1107 if self.options.is_like_windows && self.arch != "x86" { Abi::C } else { abi }
1110 if self.arch == "x86_64" {
1120 /// Minimum integer size in bits that this target can perform atomic
1122 pub fn min_atomic_width(&self) -> u64 {
1123 self.options.min_atomic_width.unwrap_or(8)
1126 /// Maximum integer size in bits that this target can perform atomic
1128 pub fn max_atomic_width(&self) -> u64 {
1129 self.options.max_atomic_width.unwrap_or_else(|| self.target_pointer_width.parse().unwrap())
1132 pub fn is_abi_supported(&self, abi: Abi) -> bool {
1133 abi.generic() || !self.options.unsupported_abis.contains(&abi)
1136 /// Loads a target descriptor from a JSON object.
1137 pub fn from_json(obj: Json) -> TargetResult {
1138 // While ugly, this code must remain this way to retain
1139 // compatibility with existing JSON fields and the internal
1140 // expected naming of the Target and TargetOptions structs.
1141 // To ensure compatibility is retained, the built-in targets
1142 // are round-tripped through this code to catch cases where
1143 // the JSON parser is not updated to match the structs.
1145 let get_req_field = |name: &str| {
1147 .map(|s| s.as_string())
1148 .and_then(|os| os.map(|s| s.to_string()))
1149 .ok_or_else(|| format!("Field {} in target specification is required", name))
1152 let get_opt_field = |name: &str, default: &str| {
1154 .and_then(|s| s.as_string())
1155 .map(|s| s.to_string())
1156 .unwrap_or_else(|| default.to_string())
1159 let mut base = Target {
1160 llvm_target: get_req_field("llvm-target")?,
1161 target_endian: get_req_field("target-endian")?,
1162 target_pointer_width: get_req_field("target-pointer-width")?,
1163 target_c_int_width: get_req_field("target-c-int-width")?,
1164 data_layout: get_req_field("data-layout")?,
1165 arch: get_req_field("arch")?,
1166 target_os: get_req_field("os")?,
1167 target_env: get_opt_field("env", ""),
1168 target_vendor: get_opt_field("vendor", "unknown"),
1169 linker_flavor: LinkerFlavor::from_str(&*get_req_field("linker-flavor")?)
1170 .ok_or_else(|| format!("linker flavor must be {}", LinkerFlavor::one_of()))?,
1171 options: Default::default(),
1175 ($key_name:ident) => ( {
1176 let name = (stringify!($key_name)).replace("_", "-");
1177 if let Some(s) = obj.find(&name).and_then(Json::as_string) {
1178 base.options.$key_name = s.to_string();
1181 ($key_name:ident, bool) => ( {
1182 let name = (stringify!($key_name)).replace("_", "-");
1183 if let Some(s) = obj.find(&name).and_then(Json::as_boolean) {
1184 base.options.$key_name = s;
1187 ($key_name:ident, Option<u64>) => ( {
1188 let name = (stringify!($key_name)).replace("_", "-");
1189 if let Some(s) = obj.find(&name).and_then(Json::as_u64) {
1190 base.options.$key_name = Some(s);
1193 ($key_name:ident, MergeFunctions) => ( {
1194 let name = (stringify!($key_name)).replace("_", "-");
1195 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1196 match s.parse::<MergeFunctions>() {
1197 Ok(mergefunc) => base.options.$key_name = mergefunc,
1198 _ => return Some(Err(format!("'{}' is not a valid value for \
1199 merge-functions. Use 'disabled', \
1200 'trampolines', or 'aliases'.",
1204 })).unwrap_or(Ok(()))
1206 ($key_name:ident, RelocModel) => ( {
1207 let name = (stringify!($key_name)).replace("_", "-");
1208 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1209 match s.parse::<RelocModel>() {
1210 Ok(relocation_model) => base.options.$key_name = relocation_model,
1211 _ => return Some(Err(format!("'{}' is not a valid relocation model. \
1212 Run `rustc --print relocation-models` to \
1213 see the list of supported values.", s))),
1216 })).unwrap_or(Ok(()))
1218 ($key_name:ident, CodeModel) => ( {
1219 let name = (stringify!($key_name)).replace("_", "-");
1220 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1221 match s.parse::<CodeModel>() {
1222 Ok(code_model) => base.options.$key_name = Some(code_model),
1223 _ => return Some(Err(format!("'{}' is not a valid code model. \
1224 Run `rustc --print code-models` to \
1225 see the list of supported values.", s))),
1228 })).unwrap_or(Ok(()))
1230 ($key_name:ident, TlsModel) => ( {
1231 let name = (stringify!($key_name)).replace("_", "-");
1232 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1233 match s.parse::<TlsModel>() {
1234 Ok(tls_model) => base.options.$key_name = tls_model,
1235 _ => return Some(Err(format!("'{}' is not a valid TLS model. \
1236 Run `rustc --print tls-models` to \
1237 see the list of supported values.", s))),
1240 })).unwrap_or(Ok(()))
1242 ($key_name:ident, PanicStrategy) => ( {
1243 let name = (stringify!($key_name)).replace("_", "-");
1244 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1246 "unwind" => base.options.$key_name = PanicStrategy::Unwind,
1247 "abort" => base.options.$key_name = PanicStrategy::Abort,
1248 _ => return Some(Err(format!("'{}' is not a valid value for \
1249 panic-strategy. Use 'unwind' or 'abort'.",
1253 })).unwrap_or(Ok(()))
1255 ($key_name:ident, RelroLevel) => ( {
1256 let name = (stringify!($key_name)).replace("_", "-");
1257 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1258 match s.parse::<RelroLevel>() {
1259 Ok(level) => base.options.$key_name = level,
1260 _ => return Some(Err(format!("'{}' is not a valid value for \
1261 relro-level. Use 'full', 'partial, or 'off'.",
1265 })).unwrap_or(Ok(()))
1267 ($key_name:ident, list) => ( {
1268 let name = (stringify!($key_name)).replace("_", "-");
1269 if let Some(v) = obj.find(&name).and_then(Json::as_array) {
1270 base.options.$key_name = v.iter()
1271 .map(|a| a.as_string().unwrap().to_string())
1275 ($key_name:ident, opt_list) => ( {
1276 let name = (stringify!($key_name)).replace("_", "-");
1277 if let Some(v) = obj.find(&name).and_then(Json::as_array) {
1278 base.options.$key_name = Some(v.iter()
1279 .map(|a| a.as_string().unwrap().to_string())
1283 ($key_name:ident, optional) => ( {
1284 let name = (stringify!($key_name)).replace("_", "-");
1285 if let Some(o) = obj.find(&name[..]) {
1286 base.options.$key_name = o
1288 .map(|s| s.to_string() );
1291 ($key_name:ident, LldFlavor) => ( {
1292 let name = (stringify!($key_name)).replace("_", "-");
1293 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1294 if let Some(flavor) = LldFlavor::from_str(&s) {
1295 base.options.$key_name = flavor;
1297 return Some(Err(format!(
1298 "'{}' is not a valid value for lld-flavor. \
1299 Use 'darwin', 'gnu', 'link' or 'wasm.",
1303 })).unwrap_or(Ok(()))
1305 ($key_name:ident, LinkerFlavor) => ( {
1306 let name = (stringify!($key_name)).replace("_", "-");
1307 obj.find(&name[..]).and_then(|o| o.as_string().map(|s| {
1308 LinkerFlavor::from_str(&s).ok_or_else(|| {
1309 Err(format!("'{}' is not a valid value for linker-flavor. \
1310 Use 'em', 'gcc', 'ld' or 'msvc.", s))
1312 })).unwrap_or(Ok(()))
1314 ($key_name:ident, crt_objects_fallback) => ( {
1315 let name = (stringify!($key_name)).replace("_", "-");
1316 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1317 match s.parse::<CrtObjectsFallback>() {
1318 Ok(fallback) => base.options.$key_name = Some(fallback),
1319 _ => return Some(Err(format!("'{}' is not a valid CRT objects fallback. \
1320 Use 'musl', 'mingw' or 'wasm'", s))),
1323 })).unwrap_or(Ok(()))
1325 ($key_name:ident, link_objects) => ( {
1326 let name = (stringify!($key_name)).replace("_", "-");
1327 if let Some(val) = obj.find(&name[..]) {
1328 let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
1329 JSON object with fields per CRT object kind.", name))?;
1330 let mut args = CrtObjects::new();
1332 let kind = LinkOutputKind::from_str(&k).ok_or_else(|| {
1333 format!("{}: '{}' is not a valid value for CRT object kind. \
1334 Use '(dynamic,static)-(nopic,pic)-exe' or \
1335 '(dynamic,static)-dylib'", name, k)
1338 let v = v.as_array().ok_or_else(||
1339 format!("{}.{}: expected a JSON array", name, k)
1340 )?.iter().enumerate()
1342 let s = s.as_string().ok_or_else(||
1343 format!("{}.{}[{}]: expected a JSON string", name, k, i))?;
1346 .collect::<Result<Vec<_>, String>>()?;
1348 args.insert(kind, v);
1350 base.options.$key_name = args;
1353 ($key_name:ident, link_args) => ( {
1354 let name = (stringify!($key_name)).replace("_", "-");
1355 if let Some(val) = obj.find(&name[..]) {
1356 let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
1357 JSON object with fields per linker-flavor.", name))?;
1358 let mut args = LinkArgs::new();
1360 let flavor = LinkerFlavor::from_str(&k).ok_or_else(|| {
1361 format!("{}: '{}' is not a valid value for linker-flavor. \
1362 Use 'em', 'gcc', 'ld' or 'msvc'", name, k)
1365 let v = v.as_array().ok_or_else(||
1366 format!("{}.{}: expected a JSON array", name, k)
1367 )?.iter().enumerate()
1369 let s = s.as_string().ok_or_else(||
1370 format!("{}.{}[{}]: expected a JSON string", name, k, i))?;
1373 .collect::<Result<Vec<_>, String>>()?;
1375 args.insert(flavor, v);
1377 base.options.$key_name = args;
1380 ($key_name:ident, env) => ( {
1381 let name = (stringify!($key_name)).replace("_", "-");
1382 if let Some(a) = obj.find(&name[..]).and_then(|o| o.as_array()) {
1384 if let Some(s) = o.as_string() {
1385 let p = s.split('=').collect::<Vec<_>>();
1387 let k = p[0].to_string();
1388 let v = p[1].to_string();
1389 base.options.$key_name.push((k, v));
1397 key!(is_builtin, bool);
1398 key!(linker, optional);
1399 key!(lld_flavor, LldFlavor)?;
1400 key!(pre_link_objects, link_objects);
1401 key!(post_link_objects, link_objects);
1402 key!(pre_link_objects_fallback, link_objects);
1403 key!(post_link_objects_fallback, link_objects);
1404 key!(crt_objects_fallback, crt_objects_fallback)?;
1405 key!(pre_link_args, link_args);
1406 key!(late_link_args, link_args);
1407 key!(late_link_args_dynamic, link_args);
1408 key!(late_link_args_static, link_args);
1409 key!(post_link_args, link_args);
1410 key!(link_script, optional);
1411 key!(link_env, env);
1412 key!(link_env_remove, list);
1413 key!(asm_args, list);
1416 key!(dynamic_linking, bool);
1417 key!(only_cdylib, bool);
1418 key!(executables, bool);
1419 key!(relocation_model, RelocModel)?;
1420 key!(code_model, CodeModel)?;
1421 key!(tls_model, TlsModel)?;
1422 key!(disable_redzone, bool);
1423 key!(eliminate_frame_pointer, bool);
1424 key!(function_sections, bool);
1428 key!(staticlib_prefix);
1429 key!(staticlib_suffix);
1430 key!(target_family, optional);
1431 key!(abi_return_struct_as_int, bool);
1432 key!(is_like_osx, bool);
1433 key!(is_like_solaris, bool);
1434 key!(is_like_windows, bool);
1435 key!(is_like_msvc, bool);
1436 key!(is_like_emscripten, bool);
1437 key!(is_like_android, bool);
1438 key!(is_like_fuchsia, bool);
1439 key!(linker_is_gnu, bool);
1440 key!(allows_weak_linkage, bool);
1441 key!(has_rpath, bool);
1442 key!(no_default_libraries, bool);
1443 key!(position_independent_executables, bool);
1444 key!(static_position_independent_executables, bool);
1445 key!(needs_plt, bool);
1446 key!(relro_level, RelroLevel)?;
1447 key!(archive_format);
1448 key!(allow_asm, bool);
1449 key!(main_needs_argc_argv, bool);
1450 key!(has_elf_tls, bool);
1451 key!(obj_is_bitcode, bool);
1452 key!(forces_embed_bitcode, bool);
1453 key!(bitcode_llvm_cmdline);
1454 key!(max_atomic_width, Option<u64>);
1455 key!(min_atomic_width, Option<u64>);
1456 key!(atomic_cas, bool);
1457 key!(panic_strategy, PanicStrategy)?;
1458 key!(crt_static_allows_dylibs, bool);
1459 key!(crt_static_default, bool);
1460 key!(crt_static_respected, bool);
1461 key!(stack_probes, bool);
1462 key!(min_global_align, Option<u64>);
1463 key!(default_codegen_units, Option<u64>);
1464 key!(trap_unreachable, bool);
1465 key!(requires_lto, bool);
1466 key!(singlethread, bool);
1467 key!(no_builtins, bool);
1468 key!(default_hidden_visibility, bool);
1469 key!(emit_debug_gdb_scripts, bool);
1470 key!(requires_uwtable, bool);
1471 key!(simd_types_indirect, bool);
1472 key!(limit_rdylib_exports, bool);
1473 key!(override_export_symbols, opt_list);
1474 key!(merge_functions, MergeFunctions)?;
1475 key!(target_mcount);
1477 key!(relax_elf_relocations, bool);
1478 key!(llvm_args, list);
1479 key!(use_ctors_section, bool);
1480 key!(eh_frame_header, bool);
1482 // NB: The old name is deprecated, but support for it is retained for
1484 for name in ["abi-blacklist", "unsupported-abis"].iter() {
1485 if let Some(array) = obj.find(name).and_then(Json::as_array) {
1486 for name in array.iter().filter_map(|abi| abi.as_string()) {
1487 match lookup_abi(name) {
1491 "The ABI \"{}\" is considered to be supported on all \
1492 targets and cannot be marked unsupported",
1497 base.options.unsupported_abis.push(abi)
1501 "Unknown ABI \"{}\" in target specification",
1513 /// Search RUST_TARGET_PATH for a JSON file specifying the given target
1514 /// triple. Note that it could also just be a bare filename already, so also
1515 /// check for that. If one of the hardcoded targets we know about, just
1516 /// return it directly.
1518 /// The error string could come from any of the APIs called, including
1519 /// filesystem access and JSON decoding.
1520 pub fn search(target_triple: &TargetTriple) -> Result<Target, String> {
1521 use rustc_serialize::json;
1525 fn load_file(path: &Path) -> Result<Target, String> {
1526 let contents = fs::read(path).map_err(|e| e.to_string())?;
1527 let obj = json::from_reader(&mut &contents[..]).map_err(|e| e.to_string())?;
1528 Target::from_json(obj)
1531 match *target_triple {
1532 TargetTriple::TargetTriple(ref target_triple) => {
1533 // check if triple is in list of supported targets
1534 match load_specific(target_triple) {
1535 Ok(t) => return Ok(t),
1536 Err(LoadTargetError::BuiltinTargetNotFound(_)) => (),
1537 Err(LoadTargetError::Other(e)) => return Err(e),
1540 // search for a file named `target_triple`.json in RUST_TARGET_PATH
1542 let mut target = target_triple.to_string();
1543 target.push_str(".json");
1544 PathBuf::from(target)
1547 let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
1549 // FIXME 16351: add a sane default search path?
1551 for dir in env::split_paths(&target_path) {
1552 let p = dir.join(&path);
1554 return load_file(&p);
1557 Err(format!("Could not find specification for target {:?}", target_triple))
1559 TargetTriple::TargetPath(ref target_path) => {
1560 if target_path.is_file() {
1561 return load_file(&target_path);
1563 Err(format!("Target path {:?} is not a valid file", target_path))
1569 impl ToJson for Target {
1570 fn to_json(&self) -> Json {
1571 let mut d = BTreeMap::new();
1572 let default: TargetOptions = Default::default();
1574 macro_rules! target_val {
1576 let name = (stringify!($attr)).replace("_", "-");
1577 d.insert(name, self.$attr.to_json());
1579 ($attr:ident, $key_name:expr) => {{
1580 let name = $key_name;
1581 d.insert(name.to_string(), self.$attr.to_json());
1585 macro_rules! target_option_val {
1587 let name = (stringify!($attr)).replace("_", "-");
1588 if default.$attr != self.options.$attr {
1589 d.insert(name, self.options.$attr.to_json());
1592 ($attr:ident, $key_name:expr) => {{
1593 let name = $key_name;
1594 if default.$attr != self.options.$attr {
1595 d.insert(name.to_string(), self.options.$attr.to_json());
1598 (link_args - $attr:ident) => {{
1599 let name = (stringify!($attr)).replace("_", "-");
1600 if default.$attr != self.options.$attr {
1605 .map(|(k, v)| (k.desc().to_owned(), v.clone()))
1606 .collect::<BTreeMap<_, _>>();
1607 d.insert(name, obj.to_json());
1610 (env - $attr:ident) => {{
1611 let name = (stringify!($attr)).replace("_", "-");
1612 if default.$attr != self.options.$attr {
1617 .map(|&(ref k, ref v)| k.clone() + "=" + &v)
1618 .collect::<Vec<_>>();
1619 d.insert(name, obj.to_json());
1624 target_val!(llvm_target);
1625 target_val!(target_endian);
1626 target_val!(target_pointer_width);
1627 target_val!(target_c_int_width);
1629 target_val!(target_os, "os");
1630 target_val!(target_env, "env");
1631 target_val!(target_vendor, "vendor");
1632 target_val!(data_layout);
1633 target_val!(linker_flavor);
1635 target_option_val!(is_builtin);
1636 target_option_val!(linker);
1637 target_option_val!(lld_flavor);
1638 target_option_val!(pre_link_objects);
1639 target_option_val!(post_link_objects);
1640 target_option_val!(pre_link_objects_fallback);
1641 target_option_val!(post_link_objects_fallback);
1642 target_option_val!(crt_objects_fallback);
1643 target_option_val!(link_args - pre_link_args);
1644 target_option_val!(link_args - late_link_args);
1645 target_option_val!(link_args - late_link_args_dynamic);
1646 target_option_val!(link_args - late_link_args_static);
1647 target_option_val!(link_args - post_link_args);
1648 target_option_val!(link_script);
1649 target_option_val!(env - link_env);
1650 target_option_val!(link_env_remove);
1651 target_option_val!(asm_args);
1652 target_option_val!(cpu);
1653 target_option_val!(features);
1654 target_option_val!(dynamic_linking);
1655 target_option_val!(only_cdylib);
1656 target_option_val!(executables);
1657 target_option_val!(relocation_model);
1658 target_option_val!(code_model);
1659 target_option_val!(tls_model);
1660 target_option_val!(disable_redzone);
1661 target_option_val!(eliminate_frame_pointer);
1662 target_option_val!(function_sections);
1663 target_option_val!(dll_prefix);
1664 target_option_val!(dll_suffix);
1665 target_option_val!(exe_suffix);
1666 target_option_val!(staticlib_prefix);
1667 target_option_val!(staticlib_suffix);
1668 target_option_val!(target_family);
1669 target_option_val!(abi_return_struct_as_int);
1670 target_option_val!(is_like_osx);
1671 target_option_val!(is_like_solaris);
1672 target_option_val!(is_like_windows);
1673 target_option_val!(is_like_msvc);
1674 target_option_val!(is_like_emscripten);
1675 target_option_val!(is_like_android);
1676 target_option_val!(is_like_fuchsia);
1677 target_option_val!(linker_is_gnu);
1678 target_option_val!(allows_weak_linkage);
1679 target_option_val!(has_rpath);
1680 target_option_val!(no_default_libraries);
1681 target_option_val!(position_independent_executables);
1682 target_option_val!(static_position_independent_executables);
1683 target_option_val!(needs_plt);
1684 target_option_val!(relro_level);
1685 target_option_val!(archive_format);
1686 target_option_val!(allow_asm);
1687 target_option_val!(main_needs_argc_argv);
1688 target_option_val!(has_elf_tls);
1689 target_option_val!(obj_is_bitcode);
1690 target_option_val!(forces_embed_bitcode);
1691 target_option_val!(bitcode_llvm_cmdline);
1692 target_option_val!(min_atomic_width);
1693 target_option_val!(max_atomic_width);
1694 target_option_val!(atomic_cas);
1695 target_option_val!(panic_strategy);
1696 target_option_val!(crt_static_allows_dylibs);
1697 target_option_val!(crt_static_default);
1698 target_option_val!(crt_static_respected);
1699 target_option_val!(stack_probes);
1700 target_option_val!(min_global_align);
1701 target_option_val!(default_codegen_units);
1702 target_option_val!(trap_unreachable);
1703 target_option_val!(requires_lto);
1704 target_option_val!(singlethread);
1705 target_option_val!(no_builtins);
1706 target_option_val!(default_hidden_visibility);
1707 target_option_val!(emit_debug_gdb_scripts);
1708 target_option_val!(requires_uwtable);
1709 target_option_val!(simd_types_indirect);
1710 target_option_val!(limit_rdylib_exports);
1711 target_option_val!(override_export_symbols);
1712 target_option_val!(merge_functions);
1713 target_option_val!(target_mcount);
1714 target_option_val!(llvm_abiname);
1715 target_option_val!(relax_elf_relocations);
1716 target_option_val!(llvm_args);
1717 target_option_val!(use_ctors_section);
1718 target_option_val!(eh_frame_header);
1720 if default.unsupported_abis != self.options.unsupported_abis {
1722 "unsupported-abis".to_string(),
1726 .map(|&name| Abi::name(name).to_json())
1727 .collect::<Vec<_>>()
1736 /// Either a target triple string or a path to a JSON file.
1737 #[derive(PartialEq, Clone, Debug, Hash, Encodable, Decodable)]
1738 pub enum TargetTriple {
1739 TargetTriple(String),
1740 TargetPath(PathBuf),
1744 /// Creates a target triple from the passed target triple string.
1745 pub fn from_triple(triple: &str) -> Self {
1746 TargetTriple::TargetTriple(triple.to_string())
1749 /// Creates a target triple from the passed target path.
1750 pub fn from_path(path: &Path) -> Result<Self, io::Error> {
1751 let canonicalized_path = path.canonicalize()?;
1752 Ok(TargetTriple::TargetPath(canonicalized_path))
1755 /// Returns a string triple for this target.
1757 /// If this target is a path, the file name (without extension) is returned.
1758 pub fn triple(&self) -> &str {
1760 TargetTriple::TargetTriple(ref triple) => triple,
1761 TargetTriple::TargetPath(ref path) => path
1763 .expect("target path must not be empty")
1765 .expect("target path must be valid unicode"),
1769 /// Returns an extended string triple for this target.
1771 /// If this target is a path, a hash of the path is appended to the triple returned
1773 pub fn debug_triple(&self) -> String {
1774 use std::collections::hash_map::DefaultHasher;
1775 use std::hash::{Hash, Hasher};
1777 let triple = self.triple();
1778 if let TargetTriple::TargetPath(ref path) = *self {
1779 let mut hasher = DefaultHasher::new();
1780 path.hash(&mut hasher);
1781 let hash = hasher.finish();
1782 format!("{}-{}", triple, hash)
1789 impl fmt::Display for TargetTriple {
1790 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1791 write!(f, "{}", self.debug_triple())