ygglibc/build.rs

70 lines
1.9 KiB
Rust

use std::{
fs::{self, DirEntry},
path::Path,
};
const RENAMES: &[(&str, &str)] = &[
("CUsizeResult", "size_t"),
("CIsizeResult", "ssize_t"),
("CEofResult", "int"),
("CIntCountResult", "int"),
("CIntZeroResult", "int"),
("CFdResult", "int"),
("COffsetResult", "off_t"),
("CPidResult", "pid_t"),
];
fn include_dir(d: &DirEntry) -> bool {
d.metadata().map(|m| m.is_dir()).unwrap_or(false)
&& d.path()
.iter()
.nth(2)
.map_or(false, |c| c.to_str().map_or(false, |x| !x.starts_with("_")))
}
fn generate_header<P: AsRef<Path>>(config_path: P) {
let config_path = config_path.as_ref();
let relative_path = config_path
.strip_prefix("src/header")
.ok()
.and_then(|p| p.parent())
.and_then(|p| p.to_str())
.unwrap()
.replace("_", "/");
// TODO use outer workspace's target directory?
let header_path = Path::new("target/include")
.join(&relative_path)
.with_extension("h");
let mod_path = config_path.with_file_name("mod.rs");
let mut config = cbindgen::Config::from_file(config_path).unwrap();
config
.export
.rename
.extend(RENAMES.into_iter().map(|&(x, y)| (x.into(), y.into())));
cbindgen::Builder::new()
.with_config(config)
.with_src(mod_path)
.generate()
.unwrap()
.write_to_file(header_path);
}
fn main() {
fs::read_dir("src/header")
.unwrap()
.into_iter()
.filter_map(Result::ok)
.filter(|d| include_dir(d))
.map(|d| d.path().as_path().join("cbindgen.toml"))
.filter(|p| p.exists())
.for_each(|p| {
println!("cargo:rerun-if-changed={:?}", p.parent().unwrap());
println!("cargo:rerun-if-changed={:?}", p);
println!("cargo:rerun-if-changed={:?}", p.with_file_name("mod.rs"));
generate_header(&p);
});
}