From b1e566f65e109eaceb78fa06043b092b778d01e5 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sun, 31 Jul 2022 04:44:46 +0900 Subject: [PATCH 1/3] use MACOSX_DEPLOYMENT_TARGET when set --- src/lib.rs | 88 ++++++++++++++++++++++++++++++++++++--------------- tests/test.rs | 18 +++++++++++ 2 files changed, 81 insertions(+), 25 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8dd19e10..67a59150 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2141,8 +2141,8 @@ impl Build { } } - if target.contains("apple-ios") || target.contains("apple-watchos") { - self.ios_watchos_flags(cmd)?; + if target.contains("-apple-") { + self.apple_flags(cmd)?; } if self.static_flag.unwrap_or(false) { @@ -2360,7 +2360,7 @@ impl Build { Ok(()) } - fn ios_watchos_flags(&self, cmd: &mut Tool) -> Result<(), Error> { + fn apple_flags(&self, cmd: &mut Tool) -> Result<(), Error> { enum ArchSpec { Device(&'static str), Simulator(&'static str), @@ -2368,12 +2368,14 @@ impl Build { } enum Os { + MacOs, Ios, WatchOs, } - impl Display for Os { + impl std::fmt::Debug for Os { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { + Os::MacOs => f.write_str("macOS"), Os::Ios => f.write_str("iOS"), Os::WatchOs => f.write_str("WatchOS"), } @@ -2381,16 +2383,22 @@ impl Build { } let target = self.get_target()?; - let os = if target.contains("-watchos") { + let os = if target.contains("-darwin") { + Os::MacOs + } else if target.contains("-watchos") { Os::WatchOs } else { Os::Ios }; + let is_mac = match os { + Os::MacOs => true, + _ => false, + }; - let arch = target.split('-').nth(0).ok_or_else(|| { + let arch_str = target.split('-').nth(0).ok_or_else(|| { Error::new( ErrorKind::ArchitectureInvalid, - format!("Unknown architecture for {} target.", os), + format!("Unknown architecture for {:?} target.", os), ) })?; @@ -2404,11 +2412,22 @@ impl Build { None => false, }; - let arch = if is_catalyst { - match arch { + let arch = if is_mac { + match arch_str { + "i686" => ArchSpec::Device("-m32"), + "x86_64" | "x86_64h" | "aarch64" => ArchSpec::Device("-m64"), + _ => { + return Err(Error::new( + ErrorKind::ArchitectureInvalid, + "Unknown architecture for macOS target.", + )); + } + } + } else if is_catalyst { + match arch_str { "arm64e" => ArchSpec::Catalyst("arm64e"), "arm64" | "aarch64" => ArchSpec::Catalyst("arm64"), - "x86_64" => ArchSpec::Catalyst("-m64"), + "x86_64" | "x86_64h" => ArchSpec::Catalyst("-m64"), _ => { return Err(Error::new( ErrorKind::ArchitectureInvalid, @@ -2417,9 +2436,9 @@ impl Build { } } } else if is_sim { - match arch { + match arch_str { "arm64" | "aarch64" => ArchSpec::Simulator("arm64"), - "x86_64" => ArchSpec::Simulator("-m64"), + "x86_64" | "x86_64h" => ArchSpec::Simulator("-m64"), _ => { return Err(Error::new( ErrorKind::ArchitectureInvalid, @@ -2428,7 +2447,7 @@ impl Build { } } } else { - match arch { + match arch_str { "arm" | "armv7" | "thumbv7" => ArchSpec::Device("armv7"), "armv7k" => ArchSpec::Device("armv7k"), "armv7s" | "thumbv7s" => ArchSpec::Device("armv7s"), @@ -2436,17 +2455,29 @@ impl Build { "arm64" | "aarch64" => ArchSpec::Device("arm64"), "arm64_32" => ArchSpec::Device("arm64_32"), "i386" | "i686" => ArchSpec::Simulator("-m32"), - "x86_64" => ArchSpec::Simulator("-m64"), + "x86_64" | "x86_64h" => ArchSpec::Simulator("-m64"), _ => { return Err(Error::new( ErrorKind::ArchitectureInvalid, - format!("Unknown architecture for {} target.", os), + format!("Unknown architecture for {:?} target.", os), )); } } }; let (sdk_prefix, sim_prefix, min_version) = match os { + Os::MacOs => ( + "macosx", + "", + std::env::var("MACOSX_DEPLOYMENT_TARGET").unwrap_or_else(|_| { + (if arch_str == "aarch64" { + "11.0" + } else { + "10.7" + }) + .into() + }), + ), Os::Ios => ( "iphone", "ios-", @@ -2460,6 +2491,11 @@ impl Build { }; let sdk = match arch { + ArchSpec::Device(_) if is_mac => { + cmd.args + .push(format!("-mmacosx-version-min={}", min_version).into()); + "macosx".to_owned() + } ArchSpec::Device(arch) => { cmd.args.push("-arch".into()); cmd.args.push(arch.into()); @@ -2482,17 +2518,19 @@ impl Build { ArchSpec::Catalyst(_) => "macosx".to_owned(), }; - self.print(&format_args!("Detecting {} SDK path for {}", os, sdk)); - let sdk_path = if let Some(sdkroot) = env::var_os("SDKROOT") { - sdkroot - } else { - self.apple_sdk_root(sdk.as_str())? - }; + if !is_mac { + self.print(&format_args!("Detecting {:?} SDK path for {}", os, sdk)); + let sdk_path = if let Some(sdkroot) = env::var_os("SDKROOT") { + sdkroot + } else { + self.apple_sdk_root(sdk.as_str())? + }; - cmd.args.push("-isysroot".into()); - cmd.args.push(sdk_path); - // TODO: Remove this once Apple stops accepting apps built with Xcode 13 - cmd.args.push("-fembed-bitcode".into()); + cmd.args.push("-isysroot".into()); + cmd.args.push(sdk_path); + // TODO: Remove this once Apple stops accepting apps built with Xcode 13 + cmd.args.push("-fembed-bitcode".into()); + } Ok(()) } diff --git a/tests/test.rs b/tests/test.rs index 7f1ddb21..b1c10c10 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -475,3 +475,21 @@ fn asm_flags() { test.cmd(1).must_have("--abc"); test.cmd(2).must_have("--abc"); } + +#[test] +fn gnu_apple_darwin() { + for (arch, version) in &[("x86_64", "10.7"), ("aarch64", "11.0")] { + let target = format!("{}-apple-darwin", arch); + let test = Test::gnu(); + test.gcc() + .target(&target) + .host(&target) + // Avoid test maintainence when minimum supported OSes change. + .__set_env("MACOSX_DEPLOYMENT_TARGET", version) + .file("foo.c") + .compile("foo"); + + test.cmd(0) + .must_have(format!("-mmacosx-version-min={}", version)); + } +} From e251e13e1b2ffd9b6c0319bc592e06bd1133eeb0 Mon Sep 17 00:00:00 2001 From: BlackHoleFox Date: Thu, 3 Aug 2023 23:46:04 -0500 Subject: [PATCH 2/3] Use rustc's minimum Apple deployment targets when available --- src/lib.rs | 119 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 42 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 67a59150..e5fd0b82 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2367,31 +2367,16 @@ impl Build { Catalyst(&'static str), } - enum Os { - MacOs, - Ios, - WatchOs, - } - impl std::fmt::Debug for Os { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - Os::MacOs => f.write_str("macOS"), - Os::Ios => f.write_str("iOS"), - Os::WatchOs => f.write_str("WatchOS"), - } - } - } - let target = self.get_target()?; let os = if target.contains("-darwin") { - Os::MacOs + AppleOs::MacOs } else if target.contains("-watchos") { - Os::WatchOs + AppleOs::WatchOs } else { - Os::Ios + AppleOs::Ios }; let is_mac = match os { - Os::MacOs => true, + AppleOs::MacOs => true, _ => false, }; @@ -2465,29 +2450,11 @@ impl Build { } }; - let (sdk_prefix, sim_prefix, min_version) = match os { - Os::MacOs => ( - "macosx", - "", - std::env::var("MACOSX_DEPLOYMENT_TARGET").unwrap_or_else(|_| { - (if arch_str == "aarch64" { - "11.0" - } else { - "10.7" - }) - .into() - }), - ), - Os::Ios => ( - "iphone", - "ios-", - std::env::var("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or_else(|_| "7.0".into()), - ), - Os::WatchOs => ( - "watch", - "watch", - std::env::var("WATCHOS_DEPLOYMENT_TARGET").unwrap_or_else(|_| "2.0".into()), - ), + let min_version = self.apple_deployment_version(os, &target, arch_str); + let (sdk_prefix, sim_prefix) = match os { + AppleOs::MacOs => ("macosx", ""), + AppleOs::Ios => ("iphone", "ios-"), + AppleOs::WatchOs => ("watch", "watch"), }; let sdk = match arch { @@ -3437,6 +3404,58 @@ impl Build { Ok(ret) } + fn apple_deployment_version(&self, os: AppleOs, target: &str, arch_str: &str) -> String { + fn rustc_provided_target(rustc: Option<&str>, target: &str) -> Option { + let rustc = rustc?; + let output = Command::new(rustc) + .args(&["--target", target]) + .args(&["--print", "deployment-target"]) + .output() + .ok()?; + + if output.status.success() { + std::str::from_utf8(&output.stdout) + .unwrap() + .strip_prefix("deployment_target=") + .map(|v| v.trim()) + .map(ToString::to_string) + } else { + // rustc is < 1.71 + None + } + } + + let rustc = self.getenv("RUSTC"); + let rustc = rustc.as_deref(); + // note the hardcoded minimums here are subject to change in a future compiler release, + // so the ones rustc knows about are preferred. For any compiler version that has bumped them + // though, `--print deployment-target` will be present and the fallbacks won't be used. + // + // the ordering of env -> rustc -> old defaults is intentional for performance when using + // an explicit target + match os { + AppleOs::MacOs => env::var("MACOSX_DEPLOYMENT_TARGET") + .ok() + .or_else(|| rustc_provided_target(rustc, target)) + .unwrap_or_else(|| { + if arch_str == "aarch64" { + "11.0" + } else { + "10.7" + } + .into() + }), + AppleOs::Ios => env::var("IPHONEOS_DEPLOYMENT_TARGET") + .ok() + .or_else(|| rustc_provided_target(rustc, target)) + .unwrap_or_else(|| "7.0".into()), + AppleOs::WatchOs => env::var("WATCHOS_DEPLOYMENT_TARGET") + .ok() + .or_else(|| rustc_provided_target(rustc, target)) + .unwrap_or_else(|| "2.0".into()), + } + } + fn cuda_file_count(&self) -> usize { self.files .iter() @@ -3824,6 +3843,22 @@ fn command_add_output_file( } } +#[derive(Clone, Copy)] +enum AppleOs { + MacOs, + Ios, + WatchOs, +} +impl std::fmt::Debug for AppleOs { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + AppleOs::MacOs => f.write_str("macOS"), + AppleOs::Ios => f.write_str("iOS"), + AppleOs::WatchOs => f.write_str("WatchOS"), + } + } +} + // Use by default minimum available API level // See note about naming here // https://android.googlesource.com/platform/ndk/+/refs/heads/ndk-release-r21/docs/BuildSystemMaintainers.md#Clang From ba90200ee293d74bcb421acf44ad071074131330 Mon Sep 17 00:00:00 2001 From: BlackHoleFox Date: Thu, 3 Aug 2023 23:47:20 -0500 Subject: [PATCH 3/3] Obtain deployment target consistently Fix the now-unified default watchOS deployment target --- src/lib.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e5fd0b82..f3e921bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1832,8 +1832,8 @@ impl Build { if let Some(arch) = map_darwin_target_from_rust_to_compiler_architecture(target) { - let deployment_target = env::var("IPHONEOS_DEPLOYMENT_TARGET") - .unwrap_or_else(|_| "7.0".into()); + let deployment_target = + self.apple_deployment_version(AppleOs::Ios, target, None); cmd.args.push( format!( "--target={}-apple-ios{}-simulator", @@ -1846,8 +1846,8 @@ impl Build { if let Some(arch) = map_darwin_target_from_rust_to_compiler_architecture(target) { - let deployment_target = env::var("WATCHOS_DEPLOYMENT_TARGET") - .unwrap_or_else(|_| "5.0".into()); + let deployment_target = + self.apple_deployment_version(AppleOs::WatchOs, target, None); cmd.args.push( format!( "--target={}-apple-watchos{}-simulator", @@ -2450,7 +2450,7 @@ impl Build { } }; - let min_version = self.apple_deployment_version(os, &target, arch_str); + let min_version = self.apple_deployment_version(os, &target, Some(arch_str)); let (sdk_prefix, sim_prefix) = match os { AppleOs::MacOs => ("macosx", ""), AppleOs::Ios => ("iphone", "ios-"), @@ -3404,7 +3404,12 @@ impl Build { Ok(ret) } - fn apple_deployment_version(&self, os: AppleOs, target: &str, arch_str: &str) -> String { + fn apple_deployment_version( + &self, + os: AppleOs, + target: &str, + arch_str: Option<&str>, + ) -> String { fn rustc_provided_target(rustc: Option<&str>, target: &str) -> Option { let rustc = rustc?; let output = Command::new(rustc) @@ -3438,7 +3443,7 @@ impl Build { .ok() .or_else(|| rustc_provided_target(rustc, target)) .unwrap_or_else(|| { - if arch_str == "aarch64" { + if arch_str == Some("aarch64") { "11.0" } else { "10.7" @@ -3452,7 +3457,7 @@ impl Build { AppleOs::WatchOs => env::var("WATCHOS_DEPLOYMENT_TARGET") .ok() .or_else(|| rustc_provided_target(rustc, target)) - .unwrap_or_else(|| "2.0".into()), + .unwrap_or_else(|| "5.0".into()), } }