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