#[cfg(feature = "system")] use registry::{Data, Hive, Security}; use std::env; use std::fs::File; use std::io::Write; use std::path::{Path, PathBuf}; static HEADER: &str = r#" #include #include #include "#; #[cfg(not(feature = "system"))] fn local() -> String { let project_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); println!( "cargo:rustc-link-search={}", project_dir.join("winfsp/lib").to_string_lossy() ); "--include-directory=winfsp/inc".into() } #[cfg(feature = "system")] fn system() -> String { let winfsp_install = Hive::LocalMachine .open("SOFTWARE\\WOW6432Node\\WinFsp", Security::Read) .ok() .and_then(|u| u.value("InstallDir").ok()) .expect("WinFsp installation directory not found."); let directory = match winfsp_install { Data::String(string) => string.to_string_lossy(), _ => panic!("unexpected install directory"), }; println!("cargo:rustc-link-search={}/lib", directory); format!("--include-directory={}/inc", directory) } fn main() { let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); // host needs to be windows if cfg!(feature = "docsrs") { println!("cargo:warning=WinFSP does not build on any operating system but Windows. This feature is meant for docs.rs only. It will not link when compiled into a binary."); File::create(out_dir.join("bindings.rs")).unwrap(); return; } if !cfg!(windows) { panic!("WinFSP is only supported on Windows."); } #[cfg(feature = "system")] let link_include = system(); #[cfg(not(feature = "system"))] let link_include = local(); println!("cargo:rustc-link-lib=dylib=delayimp"); if cfg!(target_os = "windows") && cfg!(target_arch = "x86_64") && cfg!(target_env = "msvc") { println!("cargo:rustc-link-lib=dylib=winfsp-x64"); println!("cargo:rustc-link-arg=/DELAYLOAD:winfsp-x64.dll"); } else if cfg!(target_os = "windows") && cfg!(target_arch = "i686") && cfg!(target_env = "msvc") { println!("cargo:rustc-link-lib=dylib=winfsp-x86"); println!("cargo:rustc-link-arg=/DELAYLOAD:winfsp-x86.dll"); } else if cfg!(target_arch = "aarch64") { println!("cargo:rustc-link-lib=dylib=winfsp-a64"); println!("cargo:rustc-link-arg=/DELAYLOAD:winfsp-a64.dll"); } else { panic!("unsupported triple {}", env::var("TARGET").unwrap()) } let bindings_path_str = out_dir.join("bindings.rs"); if !Path::new(&bindings_path_str).exists() { let gen_h_path = out_dir.join("gen.h"); let mut gen_h = File::create(&gen_h_path).expect("could not create file"); gen_h .write_all(HEADER.as_bytes()) .expect("could not write header file"); let bindings = bindgen::Builder::default() .header(gen_h_path.to_str().unwrap()) .derive_default(true) .blocklist_type("_?P?IMAGE_TLS_DIRECTORY.*") .allowlist_function("Fsp.*") .allowlist_type("FSP.*") .allowlist_type("Fsp.*") .allowlist_var("FSP_.*") .allowlist_var("Fsp.*") .allowlist_var("CTL_CODE") .clang_arg("-DUNICODE") .clang_arg(link_include); let bindings = if cfg!(target_os = "windows") && cfg!(target_arch = "x86_64") && cfg!(target_env = "msvc") { bindings.clang_arg("--target=x86_64-pc-windows-msvc") } else if cfg!(target_os = "windows") && cfg!(target_arch = "i686") && cfg!(target_env = "msvc") { bindings.clang_arg("--target=i686-pc-windows-msvc") } else if cfg!(target_os = "windows") && cfg!(target_arch = "aarch64") && cfg!(target_env = "msvc") { bindings.clang_arg("--target=aarch64-pc-windows-msvc") } else { panic!("unsupported triple {}", env::var("TARGET").unwrap()) }; let bindings = bindings .parse_callbacks(Box::new(bindgen::CargoCallbacks)) .generate() .expect("Unable to generate bindings"); bindings .write_to_file(out_dir.join("bindings.rs")) .expect("Couldn't write bindings!"); } }