use std::{ collections::HashSet, env, path::PathBuf, sync::{Arc, RwLock}, }; use bindgen::callbacks::{MacroParsingBehavior, ParseCallbacks}; // build script heavily inspired by proj-sys crate // some parts of code from rust-bindgen // currently the latest in apt on Github Actions const MINIMUM_ECCODES_VERSION: &str = "2.24.0"; const PROBLEMATIC_MACROS: [&str; 5] = [ "FP_NAN", "FP_INFINITE", "FP_ZERO", "FP_SUBNORMAL", "FP_NORMAL", ]; #[derive(Debug)] struct MacroCallback { macros: Arc>>, } impl ParseCallbacks for MacroCallback { fn will_parse_macro(&self, name: &str) -> MacroParsingBehavior { self.macros.write().unwrap().insert(name.into()); if PROBLEMATIC_MACROS.contains(&name) { return MacroParsingBehavior::Ignore; } MacroParsingBehavior::Default } } fn main() { if cfg!(feature = "docs") { return; }; let lib_result = pkg_config::Config::new() .atleast_version(MINIMUM_ECCODES_VERSION) .probe("eccodes"); let include_path = match lib_result { Ok(pk) => { eprintln!( "Found installed ecCodes library to link at: {:?}", pk.link_paths[0] ); println!("cargo:rustc-link-search={:?}", pk.link_paths[0]); println!("cargo:rustc-link-lib=eccodes"); pk.include_paths[0].clone() } Err(err) => { panic!( "Cannot find existing ecCodes library. Please check the README for information how to correctly install ecCodes. Additional error information: {}", err ); } }; //bindgen magic to avoid duplicate math.h type definitions let macros = Arc::new(RwLock::new(HashSet::new())); let tests = cfg!(feature = "tests"); let bindings = bindgen::Builder::default() .clang_arg(format!("-I{}", include_path.to_string_lossy())) .trust_clang_mangling(false) .header("wrapper.h") .layout_tests(tests) //avoiding tests with UB .parse_callbacks(Box::new(MacroCallback { macros })) .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("Failed to write bindings to file"); }