extern crate bindgen;
extern crate pkg_config;
use std::env;
use std::iter;
use std::path::PathBuf;
const FUSE_DEFAULT_API_VERSION: u32 = 26;
macro_rules! version {
($version_var:ident, $feature:literal, $version:literal) => {
#[cfg(feature = $feature)]
{
if $version_var.is_some() {
panic!("More than one FUSE API version feature is enabled");
}
$version_var = Some($version);
}
};
}
fn generate_fuse_bindings(header: &str, api_version: u32, fuse_lib: &pkg_config::Library) {
let mut header_path: Option<PathBuf> = None;
for include_path in fuse_lib.include_paths.iter() {
let test_path = include_path.join(header);
if test_path.exists() {
header_path = Some(test_path);
break;
}
}
let header_path = header_path
.unwrap_or_else(|| panic!("Cannot find {}", header))
.to_str()
.unwrap_or_else(|| panic!("Path to {} contains invalid unicode characters", header))
.to_string();
let defines = fuse_lib.defines.iter().map(|(key, val)| match val {
Some(val) => format!("-D{}={}", key, val),
None => format!("-D{}", key),
});
let includes = fuse_lib
.include_paths
.iter()
.map(|dir| format!("-I{}", dir.display()));
let api_define = iter::once(format!("-DFUSE_USE_VERSION={}", api_version));
let compile_flags = defines.chain(includes).chain(api_define);
let mut builder = bindgen::builder()
.clang_args(compile_flags)
.derive_default(true)
.derive_copy(true)
.derive_debug(true)
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.whitelist_recursively(false)
.whitelist_type("(?i)^fuse.*")
.whitelist_function("(?i)^fuse.*")
.whitelist_var("(?i)^fuse.*");
if cfg!(target_os = "macos") {
builder = builder.whitelist_type("setattr_x");
}
let bindings = builder
.header(header_path)
.generate()
.unwrap_or_else(|_| panic!("Failed to generate {} bindings", header));
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let bindings_path = out_dir.join(&header.replace(".h", ".rs"));
bindings
.write_to_file(&bindings_path)
.unwrap_or_else(|_| panic!("Failed to write {}", bindings_path.display()));
}
fn main() {
#[allow(unused_mut)]
let mut api_version: Option<u32> = None;
version!(api_version, "fuse_11", 11);
version!(api_version, "fuse_21", 21);
version!(api_version, "fuse_22", 22);
version!(api_version, "fuse_24", 24);
version!(api_version, "fuse_25", 25);
version!(api_version, "fuse_26", 26);
version!(api_version, "fuse_29", 29);
version!(api_version, "fuse_30", 30);
version!(api_version, "fuse_31", 31);
version!(api_version, "fuse_35", 35);
if api_version.is_none() {
println!(
"cargo:warning=No FUSE API version feature selected. Defaulting to version {}.",
FUSE_DEFAULT_API_VERSION
);
}
let api_version = api_version.unwrap_or(FUSE_DEFAULT_API_VERSION);
let fuse_lib = pkg_config::Config::new()
.probe("fuse")
.expect("Failed to find libfuse");
#[cfg(feature = "fuse_highlevel")]
generate_fuse_bindings("fuse.h", api_version, &fuse_lib);
#[cfg(feature = "fuse_lowlevel")]
generate_fuse_bindings("fuse_lowlevel.h", api_version, &fuse_lib);
}