1 use pkg_config::Config;
2 use std::env;
3 use std::path::PathBuf;
4
main()5 fn main() {
6 // Re-run build if any of these change
7 println!("cargo:rerun-if-changed=bindings/wrapper.hpp");
8 println!("cargo:rerun-if-changed=build.rs");
9
10 // We need to configure libchrome and libmodp_b64 settings as well
11 let libchrome = Config::new().probe("libchrome").unwrap();
12 let libchrome_paths = libchrome
13 .include_paths
14 .iter()
15 .map(|p| format!("-I{}", p.to_str().unwrap()))
16 .collect::<Vec<String>>();
17
18 let search_root = env::var("CXX_ROOT_PATH").unwrap();
19 let paths = [
20 "/system/",
21 "/system/btcore",
22 "/system/include",
23 "/system/include/hardware",
24 "/system/log/include",
25 "/system/types",
26 ];
27
28 let bt_searches =
29 paths.iter().map(|tail| format!("-I{}{}", search_root, tail)).collect::<Vec<String>>();
30
31 // Also re-run bindgen if anything in the C++ source changes. Unfortunately the Rust source
32 // files also reside in the same directory so any changes of Rust files (and other non-C files
33 // actually) will cause topshim to be rebuild. The TOPSHIM_SHOULD_REBUILD env variable is a
34 // development tool to speed up build that can be set to "no" if topshim is not expected to be
35 // change.
36 let topshim_should_rebuild = match env::var("TOPSHIM_SHOULD_REBUILD") {
37 Err(_) => true,
38 Ok(should_rebuild) => should_rebuild != "no",
39 };
40 if topshim_should_rebuild {
41 println!("cargo:rerun-if-changed={}/system/", search_root);
42 }
43
44 // "-x" and "c++" must be separate due to a bug
45 let clang_args: Vec<&str> = vec!["-x", "c++", "-std=c++20", "-DTARGET_FLOSS"];
46
47 // The bindgen::Builder is the main entry point
48 // to bindgen, and lets you build up options for
49 // the resulting bindings.
50 let bindings = bindgen::Builder::default()
51 .clang_args(bt_searches)
52 .clang_args(libchrome_paths)
53 .clang_args(clang_args)
54 .enable_cxx_namespaces()
55 .size_t_is_usize(true)
56 .blocklist_function("RawAddress_.*")
57 .blocklist_function(".*Uuid_.*")
58 .allowlist_type("(bt_|bthh_|btgatt_|btsdp|bluetooth_sdp|btsock_|bthf_|btrc_).*")
59 .allowlist_type("sock_connect_signal_t")
60 .allowlist_function("(bt_|bthh_|btgatt_|btsdp|osi_property_get).*")
61 .allowlist_function("hal_util_.*")
62 // We must opaque out std:: in order to prevent bindgen from choking
63 .opaque_type("std::.*")
64 // Whitelist std::string though because we use it a lot
65 .allowlist_type("std::string")
66 .formatter(bindgen::Formatter::Rustfmt)
67 .derive_debug(true)
68 .derive_partialeq(true)
69 .derive_eq(true)
70 .derive_default(true)
71 .header("bindings/wrapper.hpp")
72 .generate()
73 .expect("Unable to generate bindings");
74
75 // Write the bindings to the $OUT_DIR/bindings.rs file.
76 let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
77 bindings.write_to_file(out_path.join("bindings.rs")).expect("Couldn't write bindings!");
78 }
79