diff options
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/lib.rs | 12 | ||||
-rw-r--r-- | tests/tests.rs | 33 |
3 files changed, 46 insertions, 0 deletions
@@ -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 } @@ -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<Bindings, ()> { + // 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 0966f877..65da0656 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -310,6 +310,39 @@ macro_rules! test_header { 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() .header_contents("test.h", "int foo(const char* a);") |