summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml1
-rw-r--r--src/lib.rs12
-rw-r--r--tests/tests.rs33
3 files changed, 46 insertions, 0 deletions
diff --git a/Cargo.toml b/Cargo.toml
index f77d9d40..2f653dcf 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 e3906612..c5bcf494 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<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);")