1 extern crate cbindgen;
2 extern crate cc;
3
4 use std::{env, fs, fs::DirEntry, path::Path};
5
6 // include src/header directories that don't start with '_'
include_dir(d: &DirEntry) -> bool7 fn include_dir(d: &DirEntry) -> bool {
8 d.metadata().map(|m| m.is_dir()).unwrap_or(false)
9 && d.path()
10 .iter()
11 .nth(2)
12 .map_or(false, |c| c.to_str().map_or(false, |x| !x.starts_with("_")))
13 }
14
generate_bindings(cbindgen_config_path: &Path)15 fn generate_bindings(cbindgen_config_path: &Path) {
16 let relative_path = cbindgen_config_path
17 .strip_prefix("src/header")
18 .ok()
19 .and_then(|p| p.parent())
20 .and_then(|p| p.to_str())
21 .unwrap()
22 .replace("_", "/");
23 let header_path = Path::new("target/include")
24 .join(&relative_path)
25 .with_extension("h");
26 let mod_path = cbindgen_config_path.with_file_name("mod.rs");
27 let config = cbindgen::Config::from_file(cbindgen_config_path).unwrap();
28 cbindgen::Builder::new()
29 .with_config(config)
30 .with_src(mod_path)
31 .generate()
32 .expect("Unable to generate bindings")
33 .write_to_file(header_path);
34 }
35
main()36 fn main() {
37 let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
38
39 // Generate C includes
40 // - based on contents of src/header/**
41 // - headers written to target/include
42 fs::read_dir(&Path::new("src/header"))
43 .unwrap()
44 .into_iter()
45 .filter_map(Result::ok)
46 .filter(|d| include_dir(d))
47 .map(|d| d.path().as_path().join("cbindgen.toml"))
48 .filter(|p| p.exists())
49 .for_each(|p| {
50 println!("cargo:rerun-if-changed={:?}", p.parent().unwrap());
51 println!("cargo:rerun-if-changed={:?}", p);
52 println!("cargo:rerun-if-changed={:?}", p.with_file_name("mod.rs"));
53 generate_bindings(&p);
54 });
55
56 let mut c = cc::Build::new();
57 c.flag("-nostdinc")
58 .flag("-nostdlib")
59 .include(&format!("{}/include", crate_dir))
60 .include(&format!("{}/target/include", crate_dir))
61 .include(&format!("{}/pthreads-emb", crate_dir))
62 .flag("-fno-stack-protector")
63 .flag("-Wno-expansion-to-defined")
64 .files(
65 fs::read_dir("src/c")
66 .expect("src/c directory missing")
67 .map(|res| res.expect("read_dir error").path()),
68 );
69
70 #[cfg(target_os = "dragonos")]
71 {
72 // for dragonos only
73 c.define("HAVE_MMAP", "0");
74 }
75
76 c.compile("relibc_c");
77
78 println!("cargo:rustc-link-lib=static=relibc_c");
79 }
80