diff --git a/build.rs b/build.rs index efac340..0f06785 100644 --- a/build.rs +++ b/build.rs @@ -15,6 +15,25 @@ fn osx_version() -> Result { Ok(version.to_owned()) } +fn isysroot_path(platform: &str) -> Result { + use std::process::Command; + + let output = Command::new("xcrun") + .arg("--sdk") + .arg(platform) + .arg("--show-sdk-path") + .output()? + .stdout; + + let sdk_path = + std::str::from_utf8(&output).expect("invalid output from `xcrun --show-sdk-path`"); + let directory = String::from(sdk_path.trim()); + + println!("SDK Directory: {}", directory); + + Ok(directory) +} + fn parse_version(version: &str) -> Option { version .split(".") @@ -23,7 +42,7 @@ fn parse_version(version: &str) -> Option { .and_then(|m| m.parse::().ok()) } -fn frameworks_path() -> Result { +fn frameworks_path(platform: &str) -> Result { // For 10.13 and higher: // // While macOS has its system frameworks located at "/System/Library/Frameworks" @@ -40,18 +59,13 @@ fn frameworks_path() -> Result { let prefix_str = std::str::from_utf8(&output).expect("invalid output from `xcode-select`"); let prefix = prefix_str.trim_right(); - let platform = if cfg!(target_os = "macos") { - "MacOSX" - } else if cfg!(target_os = "ios") { - "iPhoneOS" - } else { - unreachable!(); - }; - let infix = if prefix == "/Library/Developer/CommandLineTools" { format!("SDKs/{}.sdk", platform) } else { - format!("Platforms/{}.platform/Developer/SDKs/{}.sdk", platform, platform) + format!( + "Platforms/{}.platform/Developer/SDKs/{}.sdk", + platform, platform + ) }; let suffix = "System/Library/Frameworks"; @@ -63,7 +77,7 @@ fn frameworks_path() -> Result { } } -fn build(frameworks_path: &str) { +fn build(frameworks_path: &str, sysroot: &str, platform: &str, target: &str) { // Generate one large set of bindings for all frameworks. // // We do this rather than generating a module per framework as some frameworks depend on other @@ -97,7 +111,13 @@ fn build(frameworks_path: &str) { { println!("cargo:rustc-link-lib=framework=CoreAudio"); frameworks.push("CoreAudio"); - headers.push("CoreAudio.framework/Headers/CoreAudio.h"); + match platform { + "MacOSX" => headers.push("CoreAudio.framework/Headers/CoreAudio.h"), + "iPhoneOS" | "iPhoneSimulator" => { + headers.push("CoreAudio.framework/Headers/CoreAudioTypes.h") + } + _ => unreachable!(), + } } #[cfg(feature = "open_al")] @@ -110,9 +130,13 @@ fn build(frameworks_path: &str) { #[cfg(all(feature = "core_midi", target_os = "macos"))] { - println!("cargo:rustc-link-lib=framework=CoreMIDI"); - frameworks.push("CoreMIDI"); - headers.push("CoreMIDI.framework/Headers/CoreMIDI.h"); + if (platform == "MacOSX") { + println!("cargo:rustc-link-lib=framework=CoreMIDI"); + frameworks.push("CoreMIDI"); + headers.push("CoreMIDI.framework/Headers/CoreMIDI.h"); + } else { + panic!("framework CoreMIDI is not supported by Apple on this platform"); + } } // Get the cargo out directory. @@ -121,7 +145,10 @@ fn build(frameworks_path: &str) { // Begin building the bindgen params. let mut builder = bindgen::Builder::default(); - builder = builder.clang_arg(format!("-F/{}", frameworks_path)); + builder = builder + .clang_arg(format!("-F/{}", frameworks_path)) + .clang_arg("-isysroot") + .clang_arg(sysroot); // Add all headers. for relative_path in headers { @@ -137,6 +164,8 @@ fn build(frameworks_path: &str) { // Generate the bindings. let bindings = builder + .clang_arg("-target") + .clang_arg(target) .trust_clang_mangling(false) .derive_default(true) .rustfmt_bindings(false) @@ -149,16 +178,28 @@ fn build(frameworks_path: &str) { .expect("could not write bindings"); } -#[cfg(any(target_os = "macos", target_os = "ios"))] fn main() { - if let Ok(directory) = frameworks_path() { - build(&directory); + let (target, platform) = match std::env::var("TARGET") { + Ok(val) => match val.as_ref() { + "x86_64-apple-darwin" | "i686-apple-darwin" => (val, "MacOSX"), + "aarch64-apple-ios" => (String::from("arm64-apple-ios"), "iPhoneOS"), + "armv7-apple-ios" | "armv7s-apple-ios" | "i386-apple-ios" | "x86_64-apple-ios" => { + (val, "iPhoneOS") + } + _ => panic!("coreaudio-sys requires macos or ios target. Found: {}", val), + }, + Err(_e) => { + panic!("TARGET environment variable not found (are you running this outside of cargo?)") + } + }; + + if let Ok(directory) = frameworks_path(platform) { + if let Ok(sysroot) = isysroot_path(&platform.to_lowercase()) { + build(&directory, &sysroot, platform, &target); + } else { + eprintln!("coreaudio-sys could not find sysroot path"); + } } else { eprintln!("coreaudio-sys could not find frameworks path"); } } - -#[cfg(not(any(target_os = "macos", target_os = "ios")))] -fn main() { - eprintln!("coreaudio-sys requires macos or ios target"); -}