diff --git a/build.rs b/build.rs index 68b2f16..7f71489 100644 --- a/build.rs +++ b/build.rs @@ -1,13 +1,46 @@ use std::env; use std::path::{Path, PathBuf}; -fn generate_bindings<'a>(include_paths: impl Iterator) { +/// Used to exclude autogenerated files in the output dir from `cargo:rerun-if-changed` directives. +#[derive(Debug)] +pub struct CustomCargoCallbacks { + exclude_dir: Option, +} + +impl bindgen::callbacks::ParseCallbacks for CustomCargoCallbacks { + fn header_file(&self, filename: &str) { + if matches!(&self.exclude_dir, Some(exclude_dir) if Path::new(filename).starts_with(exclude_dir)) + { + return; + } + println!("cargo:rerun-if-changed={filename}"); + } + + fn include_file(&self, filename: &str) { + if matches!(&self.exclude_dir, Some(exclude_dir) if Path::new(filename).starts_with(exclude_dir)) + { + return; + } + println!("cargo:rerun-if-changed={filename}"); + } + + fn read_env_var(&self, key: &str) { + println!("cargo:rerun-if-env-changed={key}"); + } +} + +fn generate_bindings<'a>( + exclude_dir: Option, + include_paths: impl IntoIterator, +) { // The bindgen::Builder is the main entry point // to bindgen, and lets you build up options for // the resulting bindings. - let builder = include_paths.fold(bindgen::Builder::default(), |builder, path| { - builder.clang_arg(format!("-I{}", path.to_string_lossy())) - }); + let builder = include_paths + .into_iter() + .fold(bindgen::Builder::default(), |builder, path| { + builder.clang_arg(format!("-I{}", path.to_string_lossy())) + }); let c_bindings = builder // The input header we would like to generate bindings for. // This is a trivial wrapper header so that the HiGHS headers @@ -15,7 +48,7 @@ fn generate_bindings<'a>(include_paths: impl Iterator) { .header("wrapper.h") // Tell cargo to invalidate the built crate whenever any of the // included header files changed. - .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) + .parse_callbacks(Box::new(CustomCargoCallbacks { exclude_dir })) // Finish the builder and generate the bindings. .generate() // Unwrap the Result and panic on failure. @@ -51,7 +84,7 @@ fn build() -> bool { .build(); let include_path = dst.join("include").join("highs"); - generate_bindings(Some(include_path.as_path()).into_iter()); + generate_bindings(Some(dst.clone()), [include_path.as_path()]); println!("cargo:rustc-link-search=native={}/lib", dst.display()); println!("cargo:rustc-link-search=native={}/lib64", dst.display()); @@ -90,7 +123,7 @@ fn discover() -> bool { Err(_e) => return false, }; - generate_bindings(lib.include_paths.iter().map(|p| p.as_path())); + generate_bindings(None, lib.include_paths.iter().map(|p| p.as_path())); true }