diff --git a/CHANGELOG.md b/CHANGELOG.md index b15d5e1bba..1cb8209733 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,7 +65,7 @@ - [Fixed](#fixed-13) - [0.54.1](#0541) - [Added](#added-12) - - [Changed](#changed-10) + - [Changed](#chainged-10) - [Fixed](#fixed-14) - [0.54.0](#0540) - [Added](#added-13) @@ -174,6 +174,8 @@ * Added the `Builder::emit_diagnostics` method and the `--emit-diagnostics` flag to enable emission of diagnostic messages. * Added support for the `"efiapi"` calling convention. + * Added the `ParseCallbacks::read_env_var` method which runs everytime + `bindgen` reads and environment variable. ## Changed * Static functions with no arguments use `void` as their single argument diff --git a/bindgen/callbacks.rs b/bindgen/callbacks.rs index d85e565565..582446687c 100644 --- a/bindgen/callbacks.rs +++ b/bindgen/callbacks.rs @@ -102,6 +102,10 @@ pub trait ParseCallbacks: fmt::Debug { /// This will be called on every file inclusion, with the full path of the included file. fn include_file(&self, _filename: &str) {} + /// This will be called every time `bindgen` reads an environment variable whether it has any + /// content or not. + fn read_env_var(&self, _key: &str) {} + /// This will be called to determine whether a particular blocklisted type /// implements a trait or not. This will be used to implement traits on /// other types containing the blocklisted type. diff --git a/bindgen/lib.rs b/bindgen/lib.rs index cd0a06c942..5b54f45ad1 100644 --- a/bindgen/lib.rs +++ b/bindgen/lib.rs @@ -68,10 +68,12 @@ use parse::ParseError; use std::borrow::Cow; use std::collections::hash_map::Entry; use std::env; +use std::ffi::OsStr; use std::fs::{File, OpenOptions}; use std::io::{self, Write}; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; +use std::rc::Rc; use std::str::FromStr; // Some convenient typedefs for a fast hash map and hash set. @@ -278,13 +280,18 @@ pub fn builder() -> Builder { Default::default() } -fn get_extra_clang_args() -> Vec { +fn get_extra_clang_args( + parse_callbacks: &[Rc], +) -> Vec { // Add any extra arguments from the environment to the clang command line. - let extra_clang_args = - match get_target_dependent_env_var("BINDGEN_EXTRA_CLANG_ARGS") { - None => return vec![], - Some(s) => s, - }; + let extra_clang_args = match get_target_dependent_env_var( + parse_callbacks, + "BINDGEN_EXTRA_CLANG_ARGS", + ) { + None => return vec![], + Some(s) => s, + }; + // Try to parse it with shell quoting. If we fail, make it one single big argument. if let Some(strings) = shlex::split(&extra_clang_args) { return strings; @@ -296,7 +303,9 @@ impl Builder { /// Generate the Rust bindings using the options built up thus far. pub fn generate(mut self) -> Result { // Add any extra arguments from the environment to the clang command line. - self.options.clang_args.extend(get_extra_clang_args()); + self.options + .clang_args + .extend(get_extra_clang_args(&self.options.parse_callbacks)); // Transform input headers to arguments on the clang command line. self.options.clang_args.extend( @@ -379,7 +388,7 @@ impl Builder { cmd.arg(a); } - for a in get_extra_clang_args() { + for a in get_extra_clang_args(&self.options.parse_callbacks) { cmd.arg(a); } @@ -1152,22 +1161,38 @@ pub fn clang_version() -> ClangVersion { } } +fn env_var + AsRef>( + parse_callbacks: &[Rc], + key: K, +) -> Result { + for callback in parse_callbacks { + callback.read_env_var(key.as_ref()); + } + std::env::var(key) +} + /// Looks for the env var `var_${TARGET}`, and falls back to just `var` when it is not found. -fn get_target_dependent_env_var(var: &str) -> Option { - if let Ok(target) = env::var("TARGET") { - if let Ok(v) = env::var(format!("{}_{}", var, target)) { +fn get_target_dependent_env_var( + parse_callbacks: &[Rc], + var: &str, +) -> Option { + if let Ok(target) = env_var(parse_callbacks, "TARGET") { + if let Ok(v) = env_var(parse_callbacks, format!("{}_{}", var, target)) { return Some(v); } - if let Ok(v) = env::var(format!("{}_{}", var, target.replace('-', "_"))) - { + if let Ok(v) = env_var( + parse_callbacks, + format!("{}_{}", var, target.replace('-', "_")), + ) { return Some(v); } } - env::var(var).ok() + + env_var(parse_callbacks, var).ok() } /// A ParseCallbacks implementation that will act on file includes by echoing a rerun-if-changed -/// line +/// line and on env variable usage by echoing a rerun-if-env-changed line /// /// When running inside a `build.rs` script, this can be used to make cargo invalidate the /// generated bindings whenever any of the files included from the header change: @@ -1185,6 +1210,10 @@ impl callbacks::ParseCallbacks for CargoCallbacks { fn include_file(&self, filename: &str) { println!("cargo:rerun-if-changed={}", filename); } + + fn read_env_var(&self, key: &str) { + println!("cargo:rerun-if-env-changed={}", key); + } } /// Test command_line_flag function.