From f29b65993e5726e870cc59ee6484912225af2620 Mon Sep 17 00:00:00 2001 From: jhwgh1968 Date: Wed, 13 Mar 2019 22:28:31 -0500 Subject: [PATCH] Add BINDGEN_EXTRA_CLANG_ARGS env variable --- Cargo.toml | 1 + src/lib.rs | 12 ++++++++++++ tests/tests.rs | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index f77d9d40b0..2f653dcf43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,7 @@ quote = { version = "0.6", default-features = false } regex = "1.0" which = ">=1.0, <3.0" hashbrown = "0.1" +shlex = "0.1" # New validation in 0.3.6 breaks bindgen-integration: # https://github.com/alexcrichton/proc-macro2/commit/489c642. proc-macro2 = { version = "0.4", default-features = false } diff --git a/src/lib.rs b/src/lib.rs index e3906612c9..c5bcf494c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,7 @@ extern crate peeking_take_while; extern crate quote; extern crate proc_macro2; extern crate regex; +extern crate shlex; extern crate which; #[cfg(feature = "logging")] @@ -1168,6 +1169,17 @@ 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. + if let Some(extra_clang_args) = std::env::var("BINDGEN_EXTRA_CLANG_ARGS").ok() { + // 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) { + self.options.clang_args.extend(strings); + } else { + self.options.clang_args.push(extra_clang_args); + }; + } + + // Transform input headers to arguments on the clang command line. self.options.input_header = self.input_headers.pop(); self.options.clang_args.extend( self.input_headers diff --git a/tests/tests.rs b/tests/tests.rs index 0966f8771f..65da0656ba 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -309,6 +309,39 @@ macro_rules! test_header { // This file is generated by build.rs include!(concat!(env!("OUT_DIR"), "/tests.rs")); +#[test] +fn test_clang_env_args() { + std::env::set_var("BINDGEN_EXTRA_CLANG_ARGS", "-D_ENV_ONE=1 -D_ENV_TWO=\"2 -DNOT_THREE=1\""); + let actual = builder() + .header_contents("test.hpp", + "#ifdef _ENV_ONE\nextern const int x[] = { 42 };\n#endif\n\ + #ifdef _ENV_TWO\nextern const int y[] = { 42 };\n#endif\n\ + #ifdef NOT_THREE\nextern const int z[] = { 42 };\n#endif\n") + .generate() + .unwrap() + .to_string(); + + let (actual, stderr) = rustfmt(actual); + println!("{}", stderr); + + let (expected, _) = rustfmt("/* automatically generated by rust-bindgen */ + +extern \"C\" { + #[link_name = \"\\u{1}x\"] + pub static mut x: [::std::os::raw::c_int; 1usize]; +} +extern \"C\" { + #[link_name = \"\\u{1}y\"] + pub static mut y: [::std::os::raw::c_int; 1usize]; +} +".to_string()); + + assert_eq!( + expected, + actual + ); +} + #[test] fn test_header_contents() { let actual = builder()