xref: /relibc/build.rs (revision be35961d82cd98f2a2e61c4f1869271b9f4af571)
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