build.rs

  1use serde::Deserialize;
  2use std::{env, path::PathBuf, process::Command};
  3
  4const SWIFT_PACKAGE_NAME: &'static str = "LiveKitBridge";
  5
  6#[derive(Debug, Deserialize)]
  7#[serde(rename_all = "camelCase")]
  8pub struct SwiftTargetInfo {
  9    pub triple: String,
 10    pub unversioned_triple: String,
 11    pub module_triple: String,
 12    pub swift_runtime_compatibility_version: String,
 13    #[serde(rename = "librariesRequireRPath")]
 14    pub libraries_require_rpath: bool,
 15}
 16
 17#[derive(Debug, Deserialize)]
 18#[serde(rename_all = "camelCase")]
 19pub struct SwiftPaths {
 20    pub runtime_library_paths: Vec<String>,
 21    pub runtime_library_import_paths: Vec<String>,
 22    pub runtime_resource_path: String,
 23}
 24
 25#[derive(Debug, Deserialize)]
 26pub struct SwiftTarget {
 27    pub target: SwiftTargetInfo,
 28    pub paths: SwiftPaths,
 29}
 30
 31const MACOS_TARGET_VERSION: &str = "12";
 32
 33fn main() {
 34    let swift_target = get_swift_target();
 35
 36    build_bridge(&swift_target);
 37    link_swift_stdlib(&swift_target);
 38    link_webrtc_framework(&swift_target);
 39}
 40
 41fn build_bridge(swift_target: &SwiftTarget) {
 42    println!("cargo:rerun-if-changed={}/Sources", SWIFT_PACKAGE_NAME);
 43    println!(
 44        "cargo:rerun-if-changed={}/Package.swift",
 45        SWIFT_PACKAGE_NAME
 46    );
 47    println!(
 48        "cargo:rerun-if-changed={}/Package.resolved",
 49        SWIFT_PACKAGE_NAME
 50    );
 51    let swift_package_root = swift_package_root();
 52    if !Command::new("swift")
 53        .arg("build")
 54        .args(&["--configuration", &env::var("PROFILE").unwrap()])
 55        .args(&[
 56            "--triple",
 57            &format!(
 58                "{}{}",
 59                swift_target.target.unversioned_triple, MACOS_TARGET_VERSION
 60            ),
 61        ])
 62        .current_dir(&swift_package_root)
 63        .status()
 64        .unwrap()
 65        .success()
 66    {
 67        panic!(
 68            "Failed to compile swift package in {}",
 69            swift_package_root.display()
 70        );
 71    }
 72
 73    println!(
 74        "cargo:rustc-link-search=native={}",
 75        swift_target.out_dir_path().display()
 76    );
 77    println!("cargo:rustc-link-lib=static={}", SWIFT_PACKAGE_NAME);
 78}
 79
 80fn link_swift_stdlib(swift_target: &SwiftTarget) {
 81    if swift_target.target.libraries_require_rpath {
 82        panic!("Libraries require RPath! Change minimum MacOS value to fix.")
 83    }
 84
 85    swift_target
 86        .paths
 87        .runtime_library_paths
 88        .iter()
 89        .for_each(|path| {
 90            println!("cargo:rustc-link-search=native={}", path);
 91        });
 92}
 93
 94fn link_webrtc_framework(swift_target: &SwiftTarget) {
 95    let swift_out_dir_path = swift_target.out_dir_path();
 96    println!("cargo:rustc-link-lib=framework=WebRTC");
 97    println!(
 98        "cargo:rustc-link-search=framework={}",
 99        swift_out_dir_path.display()
100    );
101
102    let source_path = swift_out_dir_path.join("WebRTC.framework");
103    let target_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("../../../WebRTC.framework");
104    assert!(
105        Command::new("cp")
106            .arg("-r")
107            .args(&[&source_path, &target_path])
108            .status()
109            .unwrap()
110            .success(),
111        "could not copy WebRTC.framework from {:?} to {:?}",
112        source_path,
113        target_path
114    );
115}
116
117fn get_swift_target() -> SwiftTarget {
118    let mut arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
119    if arch == "aarch64" {
120        arch = "arm64".into();
121    }
122    let target = format!("{}-apple-macosx{}", arch, MACOS_TARGET_VERSION);
123
124    let swift_target_info_str = Command::new("swift")
125        .args(&["-target", &target, "-print-target-info"])
126        .output()
127        .unwrap()
128        .stdout;
129
130    serde_json::from_slice(&swift_target_info_str).unwrap()
131}
132
133fn swift_package_root() -> PathBuf {
134    env::current_dir().unwrap().join(SWIFT_PACKAGE_NAME)
135}
136
137impl SwiftTarget {
138    fn out_dir_path(&self) -> PathBuf {
139        swift_package_root()
140            .join(".build")
141            .join(&self.target.unversioned_triple)
142            .join(env::var("PROFILE").unwrap())
143    }
144}