1 use std::env;
2
3 use crate::spec::{SplitDebuginfo, TargetOptions};
4
opts(os: &str) -> TargetOptions5 pub fn opts(os: &str) -> TargetOptions {
6 // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
7 // either the linker will complain if it is used or the binary will end up
8 // segfaulting at runtime when run on 10.6. Rust by default supports macOS
9 // 10.7+, but there is a standard environment variable,
10 // MACOSX_DEPLOYMENT_TARGET, which is used to signal targeting older
11 // versions of macOS. For example compiling on 10.10 with
12 // MACOSX_DEPLOYMENT_TARGET set to 10.6 will cause the linker to generate
13 // warnings about the usage of ELF TLS.
14 //
15 // Here we detect what version is being requested, defaulting to 10.7. ELF
16 // TLS is flagged as enabled if it looks to be supported.
17 let version = macos_deployment_target();
18
19 TargetOptions {
20 os: os.to_string(),
21 vendor: "apple".to_string(),
22 // macOS has -dead_strip, which doesn't rely on function_sections
23 function_sections: false,
24 dynamic_linking: true,
25 linker_is_gnu: false,
26 executables: true,
27 families: vec!["unix".to_string()],
28 is_like_osx: true,
29 dwarf_version: Some(2),
30 has_rpath: true,
31 dll_suffix: ".dylib".to_string(),
32 archive_format: "darwin".to_string(),
33 has_elf_tls: version >= (10, 7),
34 abi_return_struct_as_int: true,
35 emit_debug_gdb_scripts: false,
36 eh_frame_header: false,
37
38 // The historical default for macOS targets is to run `dsymutil` which
39 // generates a packed version of debuginfo split from the main file.
40 split_debuginfo: SplitDebuginfo::Packed,
41
42 // This environment variable is pretty magical but is intended for
43 // producing deterministic builds. This was first discovered to be used
44 // by the `ar` tool as a way to control whether or not mtime entries in
45 // the archive headers were set to zero or not. It appears that
46 // eventually the linker got updated to do the same thing and now reads
47 // this environment variable too in recent versions.
48 //
49 // For some more info see the commentary on #47086
50 link_env: vec![("ZERO_AR_DATE".to_string(), "1".to_string())],
51
52 ..Default::default()
53 }
54 }
55
deployment_target(var_name: &str) -> Option<(u32, u32)>56 fn deployment_target(var_name: &str) -> Option<(u32, u32)> {
57 let deployment_target = env::var(var_name).ok();
58 deployment_target
59 .as_ref()
60 .and_then(|s| s.split_once('.'))
61 .and_then(|(a, b)| a.parse::<u32>().and_then(|a| b.parse::<u32>().map(|b| (a, b))).ok())
62 }
63
macos_deployment_target() -> (u32, u32)64 fn macos_deployment_target() -> (u32, u32) {
65 deployment_target("MACOSX_DEPLOYMENT_TARGET").unwrap_or((10, 7))
66 }
67
macos_llvm_target(arch: &str) -> String68 pub fn macos_llvm_target(arch: &str) -> String {
69 let (major, minor) = macos_deployment_target();
70 format!("{}-apple-macosx{}.{}.0", arch, major, minor)
71 }
72
macos_link_env_remove() -> Vec<String>73 pub fn macos_link_env_remove() -> Vec<String> {
74 let mut env_remove = Vec::with_capacity(2);
75 // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which
76 // may occur when we're linking a custom build script while targeting iOS for example.
77 if let Ok(sdkroot) = env::var("SDKROOT") {
78 if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") {
79 env_remove.push("SDKROOT".to_string())
80 }
81 }
82 // Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at
83 // "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld",
84 // although this is apparently ignored when using the linker at "/usr/bin/ld".
85 env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".to_string());
86 env_remove
87 }
88
ios_deployment_target() -> (u32, u32)89 fn ios_deployment_target() -> (u32, u32) {
90 deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((7, 0))
91 }
92
ios_sim_llvm_target(arch: &str) -> String93 pub fn ios_sim_llvm_target(arch: &str) -> String {
94 let (major, minor) = ios_deployment_target();
95 format!("{}-apple-ios{}.{}.0-simulator", arch, major, minor)
96 }
97