use serde::Deserialize;
use std::env::var;
use std::process::Command;
fn main() {
#[cfg(docsrs)]
return;
let profile = var("PROFILE").unwrap();
let out_dir = var("OUT_DIR").unwrap();
let info = SwiftTargetInfo::get();
let unversioned_triple = &*info.target.unversioned_triple;
println!("cargo::rerun-if-changed=Package.swift");
println!("cargo::rustc-link-search=native={out_dir}/{unversioned_triple}/{profile}");
for rt_lib_path in &info.paths.runtime_library_paths {
println!("cargo::rustc-link-search=native={}", &**rt_lib_path);
}
#[allow(unused_mut)]
let mut traits = Vec::<&str>::new();
macro_rules! link_pkgs {
{ $($name:literal)* } => {
$(
#[cfg(feature = $name)] {
println!(concat!("cargo::rerun-if-changed=src/", $name));
traits.push($name);
}
)*
}
}
link_pkgs! {
"accessibility"
"dispatch"
"pushkit"
"swift"
}
let traits = traits.join(",");
let has_traits = traits.is_empty();
let traits = &["--traits", &*traits] as &[_];
let success = Command::new("swift")
.arg("build")
.arg("-c")
.arg(&*profile)
.arg("--build-path")
.arg(&*out_dir)
.arg("--disable-default-traits")
.arg("--product")
.arg("apple-apis")
.args(if !has_traits { traits } else { &[] })
.status()
.map(|res| res.success());
let Ok(true) = success else {
panic!("failed to build swift");
};
println!("cargo::rustc-link-lib=static:+whole-archive=apple-apis");
}
#[derive(Deserialize)]
struct SwiftTargetInfo {
#[allow(dead_code)]
target: SwiftTargetInfoTarget,
paths: SwiftTargetInfoPaths
}
#[derive(Deserialize)]
struct SwiftTargetInfoTarget {
#[allow(dead_code)]
#[serde(rename = "unversionedTriple")]
unversioned_triple: String,
}
#[derive(Deserialize)]
struct SwiftTargetInfoPaths {
#[serde(rename = "runtimeLibraryPaths")]
runtime_library_paths: Vec<String>,
}
impl SwiftTargetInfo {
fn get() -> Self {
let info = Command::new("swift")
.arg("-print-target-info")
.output()
.unwrap()
.stdout;
serde_json::from_slice(&info).unwrap()
}
}