]> git.lizzy.rs Git - rust.git/blob - src/librustc_target/spec/apple_ios_base.rs
Auto merge of #68943 - ecstatic-morse:no-useless-drop-on-enum-variants, r=matthewjasper
[rust.git] / src / librustc_target / spec / apple_ios_base.rs
1 use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
2 use std::env;
3 use std::io;
4 use std::path::Path;
5 use std::process::Command;
6
7 use Arch::*;
8
9 #[allow(non_camel_case_types)]
10 #[derive(Copy, Clone)]
11 pub enum Arch {
12     Armv7,
13     Armv7s,
14     Arm64,
15     I386,
16     X86_64,
17     X86_64_macabi,
18 }
19
20 impl Arch {
21     pub fn to_string(self) -> &'static str {
22         match self {
23             Armv7 => "armv7",
24             Armv7s => "armv7s",
25             Arm64 => "arm64",
26             I386 => "i386",
27             X86_64 => "x86_64",
28             X86_64_macabi => "x86_64",
29         }
30     }
31 }
32
33 pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
34     // Following what clang does
35     // (https://github.com/llvm/llvm-project/blob/
36     // 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
37     // to allow the SDK path to be set. (For clang, xcrun sets
38     // SDKROOT; for rustc, the user or build system can set it, or we
39     // can fall back to checking for xcrun on PATH.)
40     if let Some(sdkroot) = env::var("SDKROOT").ok() {
41         let p = Path::new(&sdkroot);
42         match sdk_name {
43             // Ignore `SDKROOT` if it's clearly set for the wrong platform.
44             "iphoneos"
45                 if sdkroot.contains("iPhoneSimulator.platform")
46                     || sdkroot.contains("MacOSX.platform") =>
47             {
48                 ()
49             }
50             "iphonesimulator"
51                 if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") =>
52             {
53                 ()
54             }
55             "macosx10.15"
56                 if sdkroot.contains("iPhoneOS.platform")
57                     || sdkroot.contains("iPhoneSimulator.platform") =>
58             {
59                 ()
60             }
61             // Ignore `SDKROOT` if it's not a valid path.
62             _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => (),
63             _ => return Ok(sdkroot),
64         }
65     }
66     let res =
67         Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then(
68             |output| {
69                 if output.status.success() {
70                     Ok(String::from_utf8(output.stdout).unwrap())
71                 } else {
72                     let error = String::from_utf8(output.stderr);
73                     let error = format!("process exit with error: {}", error.unwrap());
74                     Err(io::Error::new(io::ErrorKind::Other, &error[..]))
75                 }
76             },
77         );
78
79     match res {
80         Ok(output) => Ok(output.trim().to_string()),
81         Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
82     }
83 }
84
85 fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
86     let sdk_name = match arch {
87         Armv7 | Armv7s | Arm64 => "iphoneos",
88         I386 | X86_64 => "iphonesimulator",
89         X86_64_macabi => "macosx10.15",
90     };
91
92     let arch_name = arch.to_string();
93
94     let sdk_root = get_sdk_root(sdk_name)?;
95
96     let mut args = LinkArgs::new();
97     args.insert(
98         LinkerFlavor::Gcc,
99         vec![
100             "-arch".to_string(),
101             arch_name.to_string(),
102             "-isysroot".to_string(),
103             sdk_root.clone(),
104             "-Wl,-syslibroot".to_string(),
105             sdk_root,
106         ],
107     );
108
109     Ok(args)
110 }
111
112 fn target_cpu(arch: Arch) -> String {
113     match arch {
114         Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
115         Armv7s => "cortex-a9",
116         Arm64 => "cyclone",
117         I386 => "yonah",
118         X86_64 => "core2",
119         X86_64_macabi => "core2",
120     }
121     .to_string()
122 }
123
124 fn link_env_remove(arch: Arch) -> Vec<String> {
125     match arch {
126         Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()],
127         X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()],
128     }
129 }
130
131 pub fn opts(arch: Arch) -> Result<TargetOptions, String> {
132     let pre_link_args = build_pre_link_args(arch)?;
133     Ok(TargetOptions {
134         cpu: target_cpu(arch),
135         dynamic_linking: false,
136         executables: true,
137         pre_link_args,
138         link_env_remove: link_env_remove(arch),
139         has_elf_tls: false,
140         eliminate_frame_pointer: false,
141         ..super::apple_base::opts()
142     })
143 }