use std::env; use crate::spec::{LinkArgs, TargetOptions}; pub fn opts() -> TargetOptions { // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6 // either the linker will complain if it is used or the binary will end up // segfaulting at runtime when run on 10.6. Rust by default supports macOS // 10.7+, but there is a standard environment variable, // MACOSX_DEPLOYMENT_TARGET, which is used to signal targeting older // versions of macOS. For example compiling on 10.10 with // MACOSX_DEPLOYMENT_TARGET set to 10.6 will cause the linker to generate // warnings about the usage of ELF TLS. // // Here we detect what version is being requested, defaulting to 10.7. ELF // TLS is flagged as enabled if it looks to be supported. let version = macos_deployment_target(); TargetOptions { // macOS has -dead_strip, which doesn't rely on function_sections function_sections: false, dynamic_linking: true, executables: true, target_family: Some("unix".to_string()), is_like_osx: true, has_rpath: true, dll_prefix: "lib".to_string(), dll_suffix: ".dylib".to_string(), archive_format: "bsd".to_string(), pre_link_args: LinkArgs::new(), has_elf_tls: version >= (10, 7), abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, .. Default::default() } } fn macos_deployment_target() -> (u32, u32) { let deployment_target = env::var("MACOSX_DEPLOYMENT_TARGET").ok(); let version = deployment_target.as_ref().and_then(|s| { let mut i = s.splitn(2, '.'); i.next().and_then(|a| i.next().map(|b| (a, b))) }).and_then(|(a, b)| { a.parse::().and_then(|a| b.parse::().map(|b| (a, b))).ok() }); version.unwrap_or((10, 7)) } pub fn macos_llvm_target(arch: &str) -> String { let (major, minor) = macos_deployment_target(); format!("{}-apple-macosx{}.{}.0", arch, major, minor) }