diff --git a/example/build.rs b/example/build.rs index 913b415..16a7372 100644 --- a/example/build.rs +++ b/example/build.rs @@ -4,6 +4,7 @@ fn main() { // Ensure this matches the versions set in your `Package.swift` file. SwiftLinker::new("10.15") .with_ios("11") + .with_visionos("1") .with_package("swift-lib", "./swift-lib/") .link(); } diff --git a/src-rs/build.rs b/src-rs/build.rs index 41abd7a..10270d7 100644 --- a/src-rs/build.rs +++ b/src-rs/build.rs @@ -29,9 +29,17 @@ struct SwiftEnv { } impl SwiftEnv { - fn new(minimum_macos_version: &str, minimum_ios_version: Option<&str>) -> Self { + fn new( + minimum_macos_version: &str, + minimum_ios_version: Option<&str>, + minimum_visionos_version: Option<&str>, + ) -> Self { let rust_target = RustTarget::from_env(); - let target = rust_target.swift_target_triple(minimum_macos_version, minimum_ios_version); + let target = rust_target.swift_target_triple( + minimum_macos_version, + minimum_ios_version, + minimum_visionos_version, + ); let swift_target_info_str = Command::new("swift") .args(["-target", &target, "-print-target-info"]) @@ -47,6 +55,7 @@ impl SwiftEnv { enum RustTargetOS { MacOS, IOS, + VisionOS, } impl RustTargetOS { @@ -54,6 +63,7 @@ impl RustTargetOS { match env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() { "macos" => RustTargetOS::MacOS, "ios" => RustTargetOS::IOS, + "visionos" => RustTargetOS::VisionOS, _ => panic!("unexpected target operating system"), } } @@ -62,6 +72,7 @@ impl RustTargetOS { match self { Self::MacOS => "macosx", Self::IOS => "ios", + Self::VisionOS => "xros", } } } @@ -71,6 +82,7 @@ impl Display for RustTargetOS { match self { Self::MacOS => write!(f, "macos"), Self::IOS => write!(f, "ios"), + Self::VisionOS => write!(f, "visionos"), } } } @@ -80,18 +92,23 @@ enum SwiftSDK { MacOS, IOS, IOSSimulator, + VisionOS, + VisionOSSimulator, } impl SwiftSDK { fn from_os(os: &RustTargetOS) -> Self { let target = env::var("TARGET").unwrap(); let simulator = target.ends_with("ios-sim") + || target.ends_with("visionos-sim") || (target.starts_with("x86_64") && target.ends_with("ios")); match os { RustTargetOS::MacOS => Self::MacOS, RustTargetOS::IOS if simulator => Self::IOSSimulator, RustTargetOS::IOS => Self::IOS, + RustTargetOS::VisionOS if simulator => Self::VisionOSSimulator, + RustTargetOS::VisionOS => Self::VisionOS, } } @@ -100,6 +117,8 @@ impl SwiftSDK { Self::MacOS => "osx", Self::IOS => "ios", Self::IOSSimulator => "iossim", + Self::VisionOS => "xros", + Self::VisionOSSimulator => "xrsimulator", } } } @@ -110,6 +129,8 @@ impl Display for SwiftSDK { Self::MacOS => write!(f, "macosx"), Self::IOSSimulator => write!(f, "iphonesimulator"), Self::IOS => write!(f, "iphoneos"), + Self::VisionOSSimulator => write!(f, "xrsimulator"), + Self::VisionOS => write!(f, "xros"), } } } @@ -133,19 +154,23 @@ impl RustTarget { &self, minimum_macos_version: &str, minimum_ios_version: Option<&str>, + minimum_visionos_version: Option<&str>, ) -> String { let unversioned = self.unversioned_swift_target_triple(); format!( "{unversioned}{}{}", - match (&self.os, minimum_ios_version) { - (RustTargetOS::MacOS, _) => minimum_macos_version, - (RustTargetOS::IOS, Some(version)) => version, - _ => "", + match &self.os { + RustTargetOS::MacOS => minimum_macos_version, + RustTargetOS::IOS => minimum_ios_version.unwrap(), + RustTargetOS::VisionOS => minimum_visionos_version.unwrap(), }, // simulator suffix - matches!(self.sdk, SwiftSDK::IOSSimulator) - .then(|| "-simulator".to_string()) - .unwrap_or_default() + matches!( + self.sdk, + SwiftSDK::IOSSimulator | SwiftSDK::VisionOSSimulator + ) + .then(|| "-simulator".to_string()) + .unwrap_or_default() ) } @@ -172,6 +197,7 @@ pub struct SwiftLinker { packages: Vec, macos_min_version: String, ios_min_version: Option, + visionos_min_version: Option, } impl SwiftLinker { @@ -183,6 +209,7 @@ impl SwiftLinker { packages: vec![], macos_min_version: macos_min_version.to_string(), ios_min_version: None, + visionos_min_version: None, } } @@ -195,6 +222,15 @@ impl SwiftLinker { self } + /// Instructs the [`SwiftLinker`] to also compile for visionOS + /// using the specified minimum visionOS version. + /// + /// Minimum visionOS version must be at least 11. + pub fn with_visionos(mut self, min_version: &str) -> Self { + self.visionos_min_version = Some(min_version.to_string()); + self + } + /// Adds a package to be linked against. /// `name` should match the `name` field in your `Package.swift`, /// and `path` should point to the root of your Swift package relative @@ -212,7 +248,11 @@ impl SwiftLinker { /// This does not (yet) automatically rebuild your Swift files when they are modified, /// you'll need to modify/save your `build.rs` file for that. pub fn link(self) { - let swift_env = SwiftEnv::new(&self.macos_min_version, self.ios_min_version.as_deref()); + let swift_env = SwiftEnv::new( + &self.macos_min_version, + self.ios_min_version.as_deref(), + self.visionos_min_version.as_deref(), + ); #[allow(clippy::uninlined_format_args)] for path in swift_env.paths.runtime_library_paths { @@ -253,8 +293,11 @@ impl SwiftLinker { arch => arch, }; - let swift_target_triple = rust_target - .swift_target_triple(&self.macos_min_version, self.ios_min_version.as_deref()); + let swift_target_triple = rust_target.swift_target_triple( + &self.macos_min_version, + self.ios_min_version.as_deref(), + self.visionos_min_version.as_deref(), + ); command // Build the package (duh) @@ -277,6 +320,8 @@ impl SwiftLinker { .args(["-Xcc", &format!("--target={swift_target_triple}")]) .args(["-Xcxx", &format!("--target={swift_target_triple}")]); + println!("Command `{command:?}`"); + if !command.status().unwrap().success() { panic!("Failed to compile swift package {}", package.name); } diff --git a/src-rs/test-build.rs b/src-rs/test-build.rs index da43c63..b8ca6c2 100644 --- a/src-rs/test-build.rs +++ b/src-rs/test-build.rs @@ -14,6 +14,7 @@ fn main() { SwiftLinker::new("10.15") .with_ios("11") + .with_visionos("1") .with_package("test-swift", "tests/swift-pkg") .link(); }