Created
June 22, 2018 15:25
-
-
Save Moxinilian/5cb29863dd13e9f1ebc879a6ffde9fe2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate bindgen; | |
fn isysroot_path(platform: &str) -> Result<String,std::io::Error>{ | |
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 frameworks_path(platform: &str) -> Result<String, std::io::Error> { | |
// While macOS has its system frameworks located at "/System/Library/Frameworks" | |
// for actually linking against them (especially for cross-compilation) once | |
// has to refer to the frameworks as found within "Xcode.app/Contents/Developer/…". | |
use std::process::Command; | |
let output = Command::new("xcode-select").arg("-p").output()?.stdout; | |
let prefix_str = std::str::from_utf8(&output).expect("invalid output from `xcode-select`"); | |
let prefix = prefix_str.trim_right(); | |
let infix = format!("Platforms/{}.platform/Developer/SDKs/{}.sdk", platform, platform); | |
let suffix = "System/Library/Frameworks"; | |
let directory = format!("{}/{}/{}", prefix, infix, suffix); | |
println!("Framework Directory: {}", directory); | |
Ok(directory) | |
} | |
fn build(target: &str, platform: &str, sdk_path: &str, frameworks_path: &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 | |
// frameworks and in turn share types. To ensure all types are compatible across each | |
// framework, we feed all headers to bindgen at once. | |
// | |
// Only link to each framework and include their headers if their features are enabled and they | |
// are available on the target os. | |
use std::env; | |
use std::path::PathBuf; | |
let mut frameworks = vec![]; | |
let mut headers = vec![]; | |
#[cfg(feature = "audio_toolbox")] | |
{ | |
println!("cargo:rustc-link-lib=framework=AudioToolbox"); | |
frameworks.push("AudioToolbox"); | |
headers.push("AudioToolbox.framework/Headers/AudioToolbox.h"); | |
} | |
#[cfg(feature = "audio_unit")] | |
{ | |
println!("cargo:rustc-link-lib=framework=AudioUnit"); | |
frameworks.push("AudioUnit"); | |
headers.push("AudioUnit.framework/Headers/AudioUnit.h"); | |
} | |
#[cfg(feature = "core_audio")] | |
{ | |
println!("cargo:rustc-link-lib=framework=CoreAudio"); | |
frameworks.push("CoreAudio"); | |
match platform { | |
"MacOSX" => headers.push("CoreAudio.framework/Headers/CoreAudio.h"), | |
"iPhoneOS" | "iPhoneSimulator" => headers.push("CoreAudio.framework/Headers/CoreAudioTypes.h"), | |
_ => unreachable!(), | |
} | |
} | |
#[cfg(feature = "open_al")] | |
{ | |
println!("cargo:rustc-link-lib=framework=OpenAL"); | |
frameworks.push("OpenAL"); | |
headers.push("OpenAL.framework/Headers/al.h"); | |
headers.push("OpenAL.framework/Headers/alc.h"); | |
} | |
#[cfg(feature = "core_midi")] | |
{ | |
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"); | |
} | |
} | |
#[cfg(feature = "av_foundation")] | |
{ | |
if (platform == "MacOSX") { | |
panic!("framework AVFoundation is not supported by Apple on this platform"); | |
} else { | |
println!("cargo:rustc-link-lib=framework=AVFoundation"); | |
frameworks.push("AVFoundation"); | |
headers.push("AVFoundation.framework/Headers/AVFoundation.h"); | |
} | |
} | |
// Get the cargo out directory. | |
let out_dir = PathBuf::from(env::var("OUT_DIR") | |
.expect("env variable OUT_DIR not found")); | |
// Begin building the bindgen params. | |
let mut builder = bindgen::Builder::default(); | |
// Set SDK Path and Frameworks Path | |
builder = builder | |
.clang_arg("-isysroot").clang_arg(sdk_path) | |
.clang_arg(format!("-F/{}", frameworks_path)); | |
// Add all headers. | |
for relative_path in headers { | |
let absolute_path = format!("{}/{}", frameworks_path, relative_path); | |
println!("{}", absolute_path); | |
builder = builder.header(absolute_path); | |
} | |
println!("Target: {}", target); | |
println!("Platform: {}", platform); | |
println!("SDK Path: {}", sdk_path); | |
println!("Frameworks Path: {}", frameworks_path); | |
// Generate the bindings. | |
let bindings = builder | |
.clang_arg("-target").clang_arg(target) | |
.trust_clang_mangling(false) | |
.derive_default(true) | |
// Debug Code | |
//.clang_arg("-v") | |
//.dump_preprocessed_input() | |
.generate() | |
.expect("unable to generate bindings"); | |
// Write them to the crate root. | |
bindings.write_to_file(out_dir.join("coreaudio.rs")) | |
.expect("could not write bindings"); | |
} | |
fn main() { | |
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 from cargo?)") | |
}; | |
if let Ok(sdk_path) = isysroot_path(&platform.to_lowercase()) { | |
if let Ok(frameworks_path) = frameworks_path(platform) { | |
build(&target, platform, &sdk_path, &frameworks_path); | |
} else { | |
eprintln!("coreaudio-sys could not find frameworks path"); | |
} | |
} else { | |
eprintln!("coreaudio-sys could not find sdk path"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment