-
Notifications
You must be signed in to change notification settings - Fork 38
/
build.rs
142 lines (118 loc) · 4.58 KB
/
build.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
extern crate bindgen;
fn sdk_path(target: &str) -> Result<String, std::io::Error> {
// Use environment variable if set
println!("cargo:rerun-if-env-changed=COREAUDIO_SDK_PATH");
if let Ok(path) = std::env::var("COREAUDIO_SDK_PATH") {
return Ok(path);
}
use std::process::Command;
let sdk = if target.contains("apple-darwin") {
"macosx"
} else if target == "x86_64-apple-ios" || target == "i386-apple-ios" {
"iphonesimulator"
} else if target == "aarch64-apple-ios"
|| target == "armv7-apple-ios"
|| target == "armv7s-apple-ios"
{
"iphoneos"
} else {
unreachable!();
};
let output = Command::new("xcrun")
.args(&["--sdk", sdk, "--show-sdk-path"])
.output()?
.stdout;
let prefix_str = std::str::from_utf8(&output).expect("invalid output from `xcrun`");
Ok(prefix_str.trim_end().to_string())
}
fn build(sdk_path: Option<&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
// 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 headers: Vec<&'static str> = vec![];
#[cfg(feature = "audio_toolbox")]
{
println!("cargo:rustc-link-lib=framework=AudioToolbox");
headers.push("AudioToolbox/AudioToolbox.h");
}
#[cfg(feature = "audio_unit")]
{
println!("cargo:rustc-link-lib=framework=AudioToolbox");
headers.push("AudioUnit/AudioUnit.h");
}
#[cfg(feature = "core_audio")]
{
println!("cargo:rustc-link-lib=framework=CoreAudio");
if target.contains("apple-ios") {
headers.push("CoreAudio/CoreAudioTypes.h");
} else {
headers.push("CoreAudio/CoreAudio.h");
}
}
#[cfg(feature = "open_al")]
{
println!("cargo:rustc-link-lib=framework=OpenAL");
headers.push("OpenAL/al.h");
headers.push("OpenAL/alc.h");
}
#[cfg(all(feature = "core_midi"))]
{
if target.contains("apple-darwin") {
println!("cargo:rustc-link-lib=framework=CoreMIDI");
headers.push("CoreMIDI/CoreMIDI.h");
}
}
println!("cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS");
// 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();
// See https://github.com/rust-lang/rust-bindgen/issues/1211
// Technically according to the llvm mailing list, the argument to clang here should be
// -arch arm64 but it looks cleaner to just change the target.
let target = if target == "aarch64-apple-ios" {
"arm64-apple-ios"
} else if target == "aarch64-apple-darwin" {
"arm64-apple-darwin"
} else {
target
};
builder = builder.size_t_is_usize(true);
builder = builder.clang_args(&[&format!("--target={}", target)]);
if let Some(sdk_path) = sdk_path {
builder = builder.clang_args(&["-isysroot", sdk_path]);
}
if target.contains("apple-ios") {
// time.h as has a variable called timezone that conflicts with some of the objective-c
// calls from NSCalendar.h in the Foundation framework. This removes that one variable.
builder = builder.blacklist_item("timezone");
builder = builder.blacklist_item("objc_object");
}
let meta_header: Vec<_> = headers
.iter()
.map(|h| format!("#include <{}>\n", h))
.collect();
builder = builder.header_contents("coreaudio.h", &meta_header.concat());
// Generate the bindings.
builder = builder.trust_clang_mangling(false).derive_default(true);
let bindings = builder.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 = std::env::var("TARGET").unwrap();
if !(target.contains("apple-darwin") || target.contains("apple-ios")) {
panic!("coreaudio-sys requires macos or ios target");
}
let directory = sdk_path(&target).ok();
build(directory.as_ref().map(String::as_ref), &target);
}