Skip to content

Commit

Permalink
Merge pull request #662 from vladimir-ea/watch_os
Browse files Browse the repository at this point in the history
Add support for Apple WatchOS
  • Loading branch information
m-ou-se authored Jul 6, 2022
2 parents f2e1b1c + f461a55 commit 53272c5
Showing 1 changed file with 66 additions and 18 deletions.
84 changes: 66 additions & 18 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -168,7 +168,7 @@ impl From<io::Error> 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)
}
}
Expand Down Expand Up @@ -1529,7 +1529,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());
}
Expand Down Expand Up @@ -1597,6 +1597,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(),
Expand Down Expand Up @@ -1856,8 +1870,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) {
Expand Down Expand Up @@ -2050,18 +2064,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(),
)
})?;

Expand Down Expand Up @@ -2090,6 +2123,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,
Expand All @@ -2100,42 +2134,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());
Expand Down Expand Up @@ -2237,6 +2283,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") {
Expand Down Expand Up @@ -2813,7 +2861,7 @@ impl Build {
Err(_) => {
return Err(Error::new(
ErrorKind::IOError,
"Unable to determine iOS SDK path.",
"Unable to determine Apple SDK path.",
));
}
};
Expand Down

0 comments on commit 53272c5

Please sign in to comment.