]> git.lizzy.rs Git - rust.git/blob - src/librustc_target/spec/apple_base.rs
Auto merge of #68414 - michaelwoerister:share-drop-glue, r=alexcrichton
[rust.git] / src / librustc_target / spec / apple_base.rs
1 use std::env;
2
3 use crate::spec::{LinkArgs, TargetOptions};
4
5 pub fn opts() -> 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         // macOS has -dead_strip, which doesn't rely on function_sections
21         function_sections: false,
22         dynamic_linking: true,
23         executables: true,
24         target_family: Some("unix".to_string()),
25         is_like_osx: true,
26         has_rpath: true,
27         dll_prefix: "lib".to_string(),
28         dll_suffix: ".dylib".to_string(),
29         archive_format: "bsd".to_string(),
30         pre_link_args: LinkArgs::new(),
31         has_elf_tls: version >= (10, 7),
32         abi_return_struct_as_int: true,
33         emit_debug_gdb_scripts: false,
34         ..Default::default()
35     }
36 }
37
38 fn macos_deployment_target() -> (u32, u32) {
39     let deployment_target = env::var("MACOSX_DEPLOYMENT_TARGET").ok();
40     let version = deployment_target
41         .as_ref()
42         .and_then(|s| {
43             let mut i = s.splitn(2, '.');
44             i.next().and_then(|a| i.next().map(|b| (a, b)))
45         })
46         .and_then(|(a, b)| a.parse::<u32>().and_then(|a| b.parse::<u32>().map(|b| (a, b))).ok());
47
48     version.unwrap_or((10, 7))
49 }
50
51 pub fn macos_llvm_target(arch: &str) -> String {
52     let (major, minor) = macos_deployment_target();
53     format!("{}-apple-macosx{}.{}.0", arch, major, minor)
54 }
55
56 pub fn macos_link_env_remove() -> Vec<String> {
57     let mut env_remove = Vec::with_capacity(2);
58     // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which
59     // may occur when we're linking a custom build script while targeting iOS for example.
60     if let Some(sdkroot) = env::var("SDKROOT").ok() {
61         if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") {
62             env_remove.push("SDKROOT".to_string())
63         }
64     }
65     // Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at
66     // "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld",
67     // although this is apparently ignored when using the linker at "/usr/bin/ld".
68     env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".to_string());
69     env_remove
70 }