Skip to content

Commit f29b659

Browse files
committed
Add BINDGEN_EXTRA_CLANG_ARGS env variable
1 parent 185a5f3 commit f29b659

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ quote = { version = "0.6", default-features = false }
5555
regex = "1.0"
5656
which = ">=1.0, <3.0"
5757
hashbrown = "0.1"
58+
shlex = "0.1"
5859
# New validation in 0.3.6 breaks bindgen-integration:
5960
# https://github.com/alexcrichton/proc-macro2/commit/489c642.
6061
proc-macro2 = { version = "0.4", default-features = false }

src/lib.rs

+12
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ extern crate peeking_take_while;
3131
extern crate quote;
3232
extern crate proc_macro2;
3333
extern crate regex;
34+
extern crate shlex;
3435
extern crate which;
3536

3637
#[cfg(feature = "logging")]
@@ -1168,6 +1169,17 @@ impl Builder {
11681169

11691170
/// Generate the Rust bindings using the options built up thus far.
11701171
pub fn generate(mut self) -> Result<Bindings, ()> {
1172+
// Add any extra arguments from the environment to the clang command line.
1173+
if let Some(extra_clang_args) = std::env::var("BINDGEN_EXTRA_CLANG_ARGS").ok() {
1174+
// Try to parse it with shell quoting. If we fail, make it one single big argument.
1175+
if let Some(strings) = shlex::split(&extra_clang_args) {
1176+
self.options.clang_args.extend(strings);
1177+
} else {
1178+
self.options.clang_args.push(extra_clang_args);
1179+
};
1180+
}
1181+
1182+
// Transform input headers to arguments on the clang command line.
11711183
self.options.input_header = self.input_headers.pop();
11721184
self.options.clang_args.extend(
11731185
self.input_headers

tests/tests.rs

+33
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,39 @@ macro_rules! test_header {
309309
// This file is generated by build.rs
310310
include!(concat!(env!("OUT_DIR"), "/tests.rs"));
311311

312+
#[test]
313+
fn test_clang_env_args() {
314+
std::env::set_var("BINDGEN_EXTRA_CLANG_ARGS", "-D_ENV_ONE=1 -D_ENV_TWO=\"2 -DNOT_THREE=1\"");
315+
let actual = builder()
316+
.header_contents("test.hpp",
317+
"#ifdef _ENV_ONE\nextern const int x[] = { 42 };\n#endif\n\
318+
#ifdef _ENV_TWO\nextern const int y[] = { 42 };\n#endif\n\
319+
#ifdef NOT_THREE\nextern const int z[] = { 42 };\n#endif\n")
320+
.generate()
321+
.unwrap()
322+
.to_string();
323+
324+
let (actual, stderr) = rustfmt(actual);
325+
println!("{}", stderr);
326+
327+
let (expected, _) = rustfmt("/* automatically generated by rust-bindgen */
328+
329+
extern \"C\" {
330+
#[link_name = \"\\u{1}x\"]
331+
pub static mut x: [::std::os::raw::c_int; 1usize];
332+
}
333+
extern \"C\" {
334+
#[link_name = \"\\u{1}y\"]
335+
pub static mut y: [::std::os::raw::c_int; 1usize];
336+
}
337+
".to_string());
338+
339+
assert_eq!(
340+
expected,
341+
actual
342+
);
343+
}
344+
312345
#[test]
313346
fn test_header_contents() {
314347
let actual = builder()

0 commit comments

Comments
 (0)