xref: /relibc/build.rs (revision cdbbd4a426c81cb3dd83db87ee992d59f667f7c5)
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 '_'
7 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 
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 
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     cc::Build::new()
57         .flag("-nostdinc")
58         .flag("-nostdlib")
59         .include(&format!("{}/include", crate_dir))
60         .flag("-fno-stack-protector")
61         .flag("-Wno-expansion-to-defined")
62         .files(
63             fs::read_dir("src/c")
64                 .expect("src/c directory missing")
65                 .map(|res| res.expect("read_dir error").path()),
66         )
67         .compile("relibc_c");
68 
69     println!("cargo:rustc-link-lib=static=relibc_c");
70 }
71