fn main() {
use std::io::Write;
fn gen_pthread_mutex(out_file: &str) -> std::io::Result<()> {
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_MULTITASK");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_SMP");
let has_multitask = std::env::var_os("CARGO_FEATURE_MULTITASK").is_some();
let has_smp = std::env::var_os("CARGO_FEATURE_SMP").is_some();
let (mutex_size, mutex_init) = if has_multitask {
if has_smp {
(6, "{0, 0, 8, 0, 0, 0}")
} else {
(5, "{0, 8, 0, 0, 0}")
}
} else {
(1, "{0}")
};
let mut output = Vec::new();
writeln!(
output,
"// Generated by ax-posix-api/build.rs — DO NOT edit!"
)?;
writeln!(
output,
r#"
typedef struct {{
long __l[{mutex_size}];
}} pthread_mutex_t;
#define PTHREAD_MUTEX_INITIALIZER {{ .__l = {mutex_init} }}
"#
)?;
std::fs::write(out_file, output)?;
Ok(())
}
fn gen_c_to_rust_bindings(in_file: &str, out_file: &str) {
println!("cargo:rerun-if-changed={in_file}");
let allow_types = [
"stat",
"size_t",
"ssize_t",
"off_t",
"mode_t",
"sock.*",
"fd_set",
"timeval",
"pthread_t",
"pthread_attr_t",
"pthread_mutex_t",
"pthread_mutexattr_t",
"epoll_event",
"iovec",
"clockid_t",
"rlimit",
"aibuf",
];
let allow_vars = [
"CLOCK_.*",
"O_.*",
"AF_.*",
"SOCK_.*",
"IPPROTO_.*",
"FD_.*",
"F_.*",
"_SC_.*",
"EPOLL_CTL_.*",
"EPOLL.*",
"RLIMIT_.*",
"EAI_.*",
"MAXADDRS",
];
#[derive(Debug)]
struct MyCallbacks;
impl bindgen::callbacks::ParseCallbacks for MyCallbacks {
fn include_file(&self, fname: &str) {
if !fname.contains("ax_pthread_mutex.h") {
println!("cargo:rerun-if-changed={fname}");
}
}
}
let target = std::env::var("TARGET").unwrap();
let mut builder = bindgen::Builder::default()
.header(in_file)
.clang_arg("-I./../../ulib/axlibc/include")
.parse_callbacks(Box::new(MyCallbacks))
.derive_default(true)
.size_t_is_usize(false)
.use_core();
if let Some(llvm_target) = target.strip_suffix("-softfloat") {
builder = builder.clang_arg(format!("--target={llvm_target}"));
}
for ty in allow_types {
builder = builder.allowlist_type(ty);
}
for var in allow_vars {
builder = builder.allowlist_var(var);
}
builder
.generate()
.expect("Unable to generate C→Rust bindings")
.write_to_file(out_file)
.expect("Couldn't write bindings!");
}
let axlibc_include = std::path::Path::new("../../ulib/axlibc/include");
if axlibc_include.exists() {
gen_pthread_mutex(axlibc_include.join("ax_pthread_mutex.h").to_str().unwrap()).unwrap();
gen_c_to_rust_bindings("ctypes.h", "src/ctypes_gen.rs");
} else {
eprintln!(
"cargo:warning=axlibc include directory not found, skipping ctypes_gen.rs regeneration"
);
}
}