-
Notifications
You must be signed in to change notification settings - Fork 2
/
build.rs
73 lines (63 loc) · 2.72 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
use regex::Regex;
use std::{env, fs};
use std::path::PathBuf;
// These do not contain any fields that are copied from user to kernel, so they can be initialized to zero.
const READ0_IOCTL: [&str; 8] = [
"SNDRV_CTL_IOCTL_CARD_INFO",
"SNDRV_CTL_IOCTL_PVERSION",
"SNDRV_PCM_IOCTL_INFO",
"SNDRV_PCM_IOCTL_PVERSION",
"SNDRV_RAWMIDI_IOCTL_INFO",
"SNDRV_RAWMIDI_IOCTL_PVERSION",
"SNDRV_TIMER_IOCTL_INFO",
"SNDRV_TIMER_IOCTL_PVERSION"
];
fn do_regex(outfile: PathBuf) {
// Same as wrapper.h
let files = ["/usr/include/sound/asound.h", "/usr/include/sound/asequencer.h", "/usr/include/sound/tlv.h"];
let mut out2 = String::new();
for file in &files {
let asoundh = fs::read_to_string(file).unwrap();
// Handle stuff like: #define SNDRV_PCM_STATE_OPEN ((snd_pcm_state_t) 0)
// which bindgen does not handle (yet)
for m in Regex::new(r"#define\s+(\w+)\s+\(\((\w+)\)\s*(\d+)\)").unwrap().captures_iter(&asoundh) {
// eprintln!("{:?}", &m);
out2 += &format!("pub const {}: {} = {};\n", &m[1], &m[2], &m[3]);
}
// Convert stuff like: #define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
for m in Regex::new(r"#define\s+(\w+)\s+_IO([WR]*)\s*\(([^,)]+),\s*([^,)]+),?\s*([^,)]*)\)").unwrap().captures_iter(&asoundh) {
let rw = match &m[2] {
"" => "none",
"R" => if READ0_IOCTL.iter().any(|&x| x == &m[1]) { "read0" } else { "read" },
"W" => "write",
"WR" => "readwrite",
_ => panic!("RW = {}", &m[2])
};
let data: &str =
if rw == "none" { "" }
else if &m[5] == "int" { "std::os::raw::c_int" }
else if m[5].starts_with("struct ") { &m[5][7..] }
else { &m[5] };
out2 += &format!("ioctl_sys::ioctl!(try {} {} with b{}, {}{}{});\n", rw, &m[1], &m[3], &m[4],
if rw == "none" { "" } else { "; "}, data);
}
}
fs::write(outfile, out2).unwrap();
}
fn main() {
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
do_regex(out_path.join("regex.rs"));
let bindings = bindgen::Builder::default()
.size_t_is_usize(true)
.whitelist_type("snd_.*")
.whitelist_var("SNDRV_.*")
// .blacklist_type("_bindgen_ty_.*") // Blacklisting these bogus types will remove SNDRV vars as well
.layout_tests(false)
.header("wrapper.h")
.generate()
.expect("Unable to generate bindings");
// Write the bindings to the $OUT_DIR/bindings.rs file.
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}