use super::super::*; use std::assert_matches::assert_matches; // Test target self-consistency and JSON encoding/decoding roundtrip. pub(super) fn test_target(mut target: Target) { let recycled_target = Target::from_json(target.to_json()).map(|(j, _)| j); target.update_to_cli(); target.check_consistency(); assert_eq!(recycled_target, Ok(target)); } impl Target { fn check_consistency(&self) { assert_eq!(self.is_like_osx, self.vendor == "apple"); assert_eq!(self.is_like_solaris, self.os == "solaris" || self.os == "illumos"); assert_eq!(self.is_like_windows, self.os == "windows" || self.os == "uefi"); assert_eq!(self.is_like_wasm, self.arch == "wasm32" || self.arch == "wasm64"); if self.is_like_msvc { assert!(self.is_like_windows); } // Check that default linker flavor is compatible with some other key properties. assert_eq!(self.is_like_osx, matches!(self.linker_flavor, LinkerFlavor::Darwin(..))); assert_eq!(self.is_like_msvc, matches!(self.linker_flavor, LinkerFlavor::Msvc(..))); assert_eq!( self.is_like_wasm && self.os != "emscripten", matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)) ); assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::EmCc)); assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::Bpf)); assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::Ptx)); for args in [ &self.pre_link_args, &self.late_link_args, &self.late_link_args_dynamic, &self.late_link_args_static, &self.post_link_args, ] { for (&flavor, flavor_args) in args { assert!(!flavor_args.is_empty()); // Check that flavors mentioned in link args are compatible with the default flavor. match self.linker_flavor { LinkerFlavor::Gnu(..) => { assert_matches!(flavor, LinkerFlavor::Gnu(..)); } LinkerFlavor::Darwin(..) => { assert_matches!(flavor, LinkerFlavor::Darwin(..)) } LinkerFlavor::WasmLld(..) => { assert_matches!(flavor, LinkerFlavor::WasmLld(..)) } LinkerFlavor::Unix(..) => { assert_matches!(flavor, LinkerFlavor::Unix(..)); } LinkerFlavor::Msvc(..) => { assert_matches!(flavor, LinkerFlavor::Msvc(..)) } LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Ptx => { assert_eq!(flavor, self.linker_flavor) } } // Check that link args for cc and non-cc versions of flavors are consistent. let check_noncc = |noncc_flavor| { if let Some(noncc_args) = args.get(&noncc_flavor) { for arg in flavor_args { if let Some(suffix) = arg.strip_prefix("-Wl,") { assert!(noncc_args.iter().any(|a| a == suffix)); } } } }; match self.linker_flavor { LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld)), LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No)), LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No)), _ => {} } } // Check that link args for lld and non-lld versions of flavors are consistent. for cc in [Cc::No, Cc::Yes] { assert_eq!( args.get(&LinkerFlavor::Gnu(cc, Lld::No)), args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)), ); assert_eq!( args.get(&LinkerFlavor::Darwin(cc, Lld::No)), args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)), ); } assert_eq!( args.get(&LinkerFlavor::Msvc(Lld::No)), args.get(&LinkerFlavor::Msvc(Lld::Yes)), ); } if self.link_self_contained == LinkSelfContainedDefault::False { assert!( self.pre_link_objects_self_contained.is_empty() && self.post_link_objects_self_contained.is_empty() ); } // If your target really needs to deviate from the rules below, // except it and document the reasons. // Keep the default "unknown" vendor instead. assert_ne!(self.vendor, ""); assert_ne!(self.os, ""); if !self.can_use_os_unknown() { // Keep the default "none" for bare metal targets instead. assert_ne!(self.os, "unknown"); } // Check dynamic linking stuff // BPF: when targeting user space vms (like rbpf), those can load dynamic libraries. if self.os == "none" && self.arch != "bpf" { assert!(!self.dynamic_linking); } if self.only_cdylib || self.crt_static_allows_dylibs || !self.late_link_args_dynamic.is_empty() { assert!(self.dynamic_linking); } // Apparently PIC was slow on wasm at some point, see comments in wasm_base.rs if self.dynamic_linking && !(self.is_like_wasm && self.os != "emscripten") { assert_eq!(self.relocation_model, RelocModel::Pic); } if self.position_independent_executables { assert_eq!(self.relocation_model, RelocModel::Pic); } // The UEFI targets do not support dynamic linking but still require PIC (#101377). if self.relocation_model == RelocModel::Pic && self.os != "uefi" { assert!(self.dynamic_linking || self.position_independent_executables); } if self.static_position_independent_executables { assert!(self.position_independent_executables); } if self.position_independent_executables { assert!(self.executables); } // Check crt static stuff if self.crt_static_default || self.crt_static_allows_dylibs { assert!(self.crt_static_respected); } } // Add your target to the whitelist if it has `std` library // and you certainly want "unknown" for the OS name. fn can_use_os_unknown(&self) -> bool { self.llvm_target == "wasm32-unknown-unknown" || self.llvm_target == "wasm64-unknown-unknown" || (self.env == "sgx" && self.vendor == "fortanix") } }