diff --git a/src/lib.rs b/src/lib.rs index e3a2b98b0..7101cf50c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,7 +59,7 @@ use std::collections::HashMap; use std::env; use std::ffi::{OsStr, OsString}; -use std::fmt::{self, Display}; +use std::fmt::{self, Display, Formatter}; use std::fs; use std::io::{self, BufRead, BufReader, Read, Write}; use std::path::{Component, Path, PathBuf}; @@ -168,7 +168,7 @@ impl From for Error { } impl Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}: {}", self.kind, self.message) } } @@ -1522,7 +1522,7 @@ impl Build { cmd.push_opt_unless_duplicate("-DANDROID".into()); } - if !target.contains("apple-ios") { + if !target.contains("apple-ios") && !target.contains("apple-watchos") { cmd.push_cc_arg("-ffunction-sections".into()); cmd.push_cc_arg("-fdata-sections".into()); } @@ -1590,6 +1590,20 @@ impl Build { .into(), ); } + } else if target.contains("watchos-sim") { + 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()); + cmd.args.push( + format!( + "--target={}-apple-watchos{}-simulator", + arch, deployment_target + ) + .into(), + ); + } } else if target.starts_with("riscv64gc-") { cmd.args.push( format!("--target={}", target.replace("riscv64gc", "riscv64")).into(), @@ -1849,8 +1863,8 @@ impl Build { } } - if target.contains("apple-ios") { - self.ios_flags(cmd)?; + if target.contains("apple-ios") || target.contains("apple-watchos") { + self.ios_watchos_flags(cmd)?; } if self.static_flag.unwrap_or(false) { @@ -2043,18 +2057,37 @@ impl Build { Ok(()) } - fn ios_flags(&self, cmd: &mut Tool) -> Result<(), Error> { + fn ios_watchos_flags(&self, cmd: &mut Tool) -> Result<(), Error> { enum ArchSpec { Device(&'static str), Simulator(&'static str), Catalyst(&'static str), } + enum Os { + Ios, + WatchOs, + } + impl Display for Os { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + Os::Ios => f.write_str("iOS"), + Os::WatchOs => f.write_str("WatchOS"), + } + } + } + let target = self.get_target()?; + let os = if target.contains("-watchos") { + Os::WatchOs + } else { + Os::Ios + }; + let arch = target.split('-').nth(0).ok_or_else(|| { Error::new( ErrorKind::ArchitectureInvalid, - "Unknown architecture for iOS target.", + format!("Unknown architecture for {} target.", os).as_str(), ) })?; @@ -2083,6 +2116,7 @@ impl Build { } else if is_sim { match arch { "arm64" | "aarch64" => ArchSpec::Simulator("-arch arm64"), + "x86_64" => ArchSpec::Simulator("-m64"), _ => { return Err(Error::new( ErrorKind::ArchitectureInvalid, @@ -2093,42 +2127,54 @@ impl Build { } else { match arch { "arm" | "armv7" | "thumbv7" => ArchSpec::Device("armv7"), + "armv7k" => ArchSpec::Device("armv7k"), "armv7s" | "thumbv7s" => ArchSpec::Device("armv7s"), "arm64e" => ArchSpec::Device("arm64e"), "arm64" | "aarch64" => ArchSpec::Device("arm64"), + "arm64_32" => ArchSpec::Device("arm64_32"), "i386" | "i686" => ArchSpec::Simulator("-m32"), "x86_64" => ArchSpec::Simulator("-m64"), _ => { return Err(Error::new( ErrorKind::ArchitectureInvalid, - "Unknown architecture for iOS target.", + format!("Unknown architecture for {} target.", os).as_str(), )); } } }; - let min_version = - std::env::var("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or_else(|_| "7.0".into()); + let (sdk_prefix, sim_prefix, min_version) = match os { + 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 sdk = match arch { ArchSpec::Device(arch) => { cmd.args.push("-arch".into()); cmd.args.push(arch.into()); cmd.args - .push(format!("-miphoneos-version-min={}", min_version).into()); - "iphoneos" + .push(format!("-m{}os-version-min={}", sdk_prefix, min_version).into()); + format!("{}os", sdk_prefix) } ArchSpec::Simulator(arch) => { cmd.args.push(arch.into()); cmd.args - .push(format!("-mios-simulator-version-min={}", min_version).into()); - "iphonesimulator" + .push(format!("-m{}simulator-version-min={}", sim_prefix, min_version).into()); + format!("{}simulator", sdk_prefix) } - ArchSpec::Catalyst(_) => "macosx", + ArchSpec::Catalyst(_) => "macosx".to_owned(), }; - self.print(&format!("Detecting iOS SDK path for {}", sdk)); - let sdk_path = self.apple_sdk_root(sdk)?; + self.print(&format!("Detecting {} SDK path for {}", os, sdk)); + let sdk_path = self.apple_sdk_root(sdk.as_str())?; cmd.args.push("-isysroot".into()); cmd.args.push(sdk_path); cmd.args.push("-fembed-bitcode".into()); @@ -2230,6 +2276,8 @@ impl Build { } } else if target.contains("apple-ios") { clang.to_string() + } else if target.contains("apple-watchos") { + clang.to_string() } else if target.contains("android") { autodetect_android_compiler(&target, &host, gnu, clang) } else if target.contains("cloudabi") { @@ -2806,7 +2854,7 @@ impl Build { Err(_) => { return Err(Error::new( ErrorKind::IOError, - "Unable to determine iOS SDK path.", + "Unable to determine Apple SDK path.", )); } };