c2a_bind_utils/
lib.rs

1use std::fs;
2use std::path::PathBuf;
3
4use bindgen::callbacks::ParseCallbacks;
5#[derive(Debug)]
6struct Cb;
7
8impl ParseCallbacks for Cb {
9    fn process_comment(&self, comment: &str) -> Option<String> {
10        let comment = comment.replace("@retval {", "@retval return_value {");
11        let dox = doxygen_rs::transform(&comment)
12            .trim()
13            .replace('[', r"\[")
14            .replace(']', r"\]")
15            .split('\n')
16            .map(|s| s.trim()) // インデントが深いと doctest だと思われる
17            .collect::<Vec<_>>()
18            .join("\n");
19        Some(dox)
20    }
21}
22
23pub fn bind_c2a_builder() -> bindgen::Builder {
24    bindgen::Builder::default()
25        .blocklist_type("max_align_t") // https://github.com/servo/rust-bindgen/issues/550
26        .ctypes_prefix("core::ffi")
27        .use_core()
28        .parse_callbacks(Box::new(Cb))
29        .default_enum_style(bindgen::EnumVariation::NewType {
30            is_bitfield: true,
31            is_global: true,
32        })
33}
34
35pub fn bind_c2a(header_path: PathBuf, gen_rs: PathBuf) {
36    let bind = bind_c2a_builder()
37        .header(header_path.to_str().unwrap())
38        .generate()
39        .expect("Unable to generate bindings!");
40    bind.write_to_file(&gen_rs)
41        .expect("Couldn't write bindings!");
42
43    c2a_link_hack(gen_rs);
44}
45
46pub fn c2a_link_hack(gen_rs: PathBuf) {
47    // link hack
48    let bind = fs::read_to_string(&gen_rs).unwrap();
49    let bind = bind.replace(
50        "extern \"C\" {",
51        "#[cfg_attr(not(feature=\"no-c2a-link\"),link(name = \"C2A\", kind = \"static\", modifiers = \"-bundle\"))]\nextern \"C\" {",
52    );
53    fs::write(gen_rs, bind).unwrap();
54}