use bindgen::callbacks::{self, IntKind};
use std::{env, path::PathBuf};
const HELPER_PREFIX: &str = "RUST_CONST_HELPER";
const VERSION_PREFIX: &str = "__LINUX_VERSION";
#[derive(Debug)]
struct Callbacks;
impl callbacks::ParseCallbacks for Callbacks {
fn generated_name_override(&self, item: callbacks::ItemInfo<'_>) -> Option<String> {
item.name
.starts_with(HELPER_PREFIX)
.then(|| item.name[HELPER_PREFIX.len() + 1..].into())
}
fn item_name(&self, item: callbacks::ItemInfo) -> Option<String> {
match item.name {
name if name.starts_with("btrfs_ioctl_vol_args_v2") => match name {
"btrfs_ioctl_vol_args_v2__bindgen_ty_2" => Some("vol_args_v2_volume"),
"btrfs_ioctl_vol_args_v2__bindgen_ty_1" => Some("vol_args_v2_qgroup"),
"btrfs_ioctl_vol_args_v2__bindgen_ty_1__bindgen_ty_1" => {
Some("vol_args_v2_qgroup_opts")
}
_ => None,
},
_ => None,
}
.map(Into::into)
}
fn int_macro(&self, name: &str, _value: i64) -> Option<IntKind> {
match name {
"BTRFS_DEVICE_PATH_NAME_MAX"
| "BTRFS_FSID_SIZE"
| "BTRFS_LABEL_SIZE"
| "BTRFS_PATH_NAME_MAX"
| "BTRFS_UUID_SIZE"
| "BTRFS_UUID_UNPARSED_SIZE"
| "BTRFS_VOL_NAME_MAX" => Some(IntKind::Custom {
name: "usize",
is_signed: false,
}),
"BTRFS_CSUM_SIZE"
| "BTRFS_IOCTL_MAGIC"
| "BTRFS_MAX_METADATA_BLOCKSIZE"
| "BTRFS_SAME_DATA_DIFFERS" => None,
_ if name.ends_with("KEY")
|| name.starts_with("BTRFS_SUBVOL_SYNC")
|| name.starts_with("BTRFS_ENCODED_IO") =>
{
None
}
_ if name.starts_with("BTRFS_FT") => Some(IntKind::U8),
_ => Some(IntKind::U64),
}
}
}
#[derive(Debug)]
struct VersionCallbacks;
impl callbacks::ParseCallbacks for VersionCallbacks {
fn will_parse_macro(&self, name: &str) -> callbacks::MacroParsingBehavior {
if let Some(v) = name.strip_prefix(VERSION_PREFIX) {
println!("cargo::rustc-cfg=VERSION{v}");
}
callbacks::MacroParsingBehavior::Ignore
}
}
fn main() {
println!("cargo::rustc-check-cfg=cfg(VERSION_6_15)");
println!("cargo::rustc-check-cfg=cfg(VERSION_6_13)");
println!("cargo::rustc-check-cfg=cfg(VERSION_6_3)");
println!("cargo::rustc-check-cfg=cfg(VERSION_6_2)");
println!("cargo::rustc-check-cfg=cfg(VERSION_3_12)");
println!("cargo::rerun-if-changed=bindings/wrapper.h");
println!("cargo::rerun-if-changed=bindings/version.h");
bindgen::Builder::default()
.header("bindings/version.h")
.parse_callbacks(Box::new(VersionCallbacks))
.generate()
.expect("Unable to determine version");
let bindings = bindgen::Builder::default()
.header("bindings/wrapper.h")
.allowlist_item(r"(?i-u:btrfs).*")
.anon_fields_prefix("inner")
.derive_default(false)
.derive_debug(false)
.disable_nested_struct_naming()
.parse_callbacks(Box::new(Callbacks))
.prepend_enum_name(false)
.generate()
.expect("Unable to generate bindings");
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_dir.join("generated.rs"))
.expect("Unable to write bindings");
}