extern crate bindgen;
use std::env;
use std::path::PathBuf;
fn get_env<T: From<String>>(var: impl AsRef<str>) -> Option<T> {
println!("cargo:rerun-if-env-changed={}", var.as_ref());
env::var(var.as_ref()).map(Into::into).ok()
}
fn find_library(libname: &str, env_prefix: &str, statik: bool) {
if let Some(lib_dir) = get_env::<PathBuf>(format!("{env_prefix}_LIB_DIR")) {
if !lib_dir.is_dir() {
panic!(
"{libname} library directory does not exist: {}",
lib_dir.display()
);
}
println!("cargo:rustc-link-search=native={}", lib_dir.display());
println!("cargo:rustc-link-lib={libname}");
} else {
pkg_config::Config::new()
.statik(statik)
.probe(libname)
.expect("package not found");
}
}
fn build_includes(deps: &[(&str, &str)]) -> Vec<String> {
deps.iter()
.filter_map(|(_libname, env_prefix)| {
get_env::<String>(format!("{env_prefix}_INCLUDE_DIR")).map(|dir| format!("-I{dir}"))
})
.collect()
}
const LIBNFTABLES_WITH_SUBDEPS: &[(&str, &str)] = &[
("gmp", "GMP"),
("jansson", "JANSSON"),
("libmnl", "LIBMNL"),
("libnftnl", "LIBNFTNL"),
("xtables", "XTABLES"),
("libnftables", "NFTABLES"),
];
const LIBNFTABLES_DEPS: &[(&str, &str)] = &[("libnftables", "NFTABLES")];
fn main() {
let (deps, statik) = match env::var("CARGO_CFG_TARGET_ENV")
.unwrap_or_default()
.as_ref()
{
"musl" => (LIBNFTABLES_WITH_SUBDEPS, true),
_ => (LIBNFTABLES_DEPS, false),
};
for (libname, env_prefix) in deps {
find_library(libname, env_prefix, statik);
}
let bindings = bindgen::Builder::default()
.clang_args(build_includes(deps))
.allowlist_function("nft_.*")
.allowlist_type("nft_.*")
.opaque_type("nft_ctx_set_output")
.opaque_type("nft_ctx_set_error")
.blocklist_type("__uint32_t")
.prepend_enum_name(false)
.header("src/wrapper.h")
.generate()
.expect("Unable to generate bindings");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}