use pkg_config::{Config, Error};
use std::{
env,
fs::File,
io::Write,
path::{Path, PathBuf},
};
type LibraryConfig = (Vec<String>, Vec<PathBuf>, Vec<PathBuf>, String);
const LIBRARY_NAME: &str = "tss2-fapi";
const LIBRARY_MIN_VERSION: &str = "3.2.0";
fn main() {
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
let tss2_fapi = detect_tss2_library();
let tss2_fapi = tss2_fapi.expect("pkg_config: Required library \"tss2-fapi\" not found!");
assert!(!tss2_fapi.0.is_empty(), "library name is not defined!");
assert!(!tss2_fapi.1.is_empty(), "link path is not defined!");
assert!(!tss2_fapi.2.is_empty(), "include path is not defined!");
assert!(!tss2_fapi.3.is_empty(), "version is not defined!");
for library_name in tss2_fapi.0 {
assert!(!library_name.is_empty(), "library name is empty!");
println!("cargo:rustc-link-lib={}", library_name);
}
for link_path in tss2_fapi.1 {
assert!(link_path.is_dir(), "Link path not found: {:?}", link_path);
println!("cargo:rustc-link-search={}", link_path.to_str().unwrap());
}
let mut bindgen_builder = bindgen::Builder::default();
for inc_path in tss2_fapi.2 {
assert!(inc_path.is_dir(), "Include path not found: {:?}", inc_path);
bindgen_builder = bindgen_builder.clang_arg(format!("-I{}", inc_path.to_str().unwrap()));
}
bindgen_builder
.header_contents("wrapper.h", "#include <tss2_fapi.h>")
.layout_tests(false)
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.generate()
.expect("Unable to generate FAPI bindings")
.write_to_file(out_path.join("tss2_fapi_bindings.rs"))
.expect("Failed to write FAPI bindings!");
if !write_version_string(&out_path.join("tss2_fapi_versinfo.rs"), &tss2_fapi.3) {
panic!("Failed to write library version!");
}
}
fn detect_tss2_library() -> Result<LibraryConfig, Error> {
let env_include_path = env::var("TSS2_INCLUDE_PATH").map(PathBuf::from);
let env_library_path = env::var("TSS2_LIBRARY_PATH").map(PathBuf::from);
if let Ok(include_path) = env_include_path {
if let Ok(library_path) = env_library_path {
let library_version = env::var("TSS2_LIBRARY_VERS").unwrap_or_else(|_| LIBRARY_MIN_VERSION.to_owned());
return Ok((vec![LIBRARY_NAME.to_owned()], vec![library_path], vec![include_path], library_version));
}
}
Config::new()
.cargo_metadata(false)
.atleast_version(LIBRARY_MIN_VERSION)
.probe(LIBRARY_NAME)
.map(|config| (config.libs, config.link_paths, config.include_paths, config.version))
}
fn write_version_string(path: &Path, version_string: &str) -> bool {
let mut tokens = version_string.split('.');
let vers_major = tokens.next().unwrap_or_default().parse::<u16>().expect("Failed to parse version string!");
let vers_minor = tokens.next().unwrap_or_default().parse::<u16>().expect("Failed to parse version string!");
let vers_patch = tokens.next().unwrap_or_default().parse::<u16>().expect("Failed to parse version string!");
let mut file = File::create(path).expect("Failed to create output file for version!");
writeln!(file, r#"pub const TSS2_FAPI_VERSION: &str = "{}.{}.{}";"#, vers_major, vers_minor, vers_patch).is_ok()
}