1 extern crate bindgen;
2 #[cfg(feature = "logging")]
3 extern crate env_logger;
4 #[macro_use]
5 #[cfg(feature = "logging")]
6 extern crate log;
7 extern crate clap;
8
9 use bindgen::clang_version;
10 use std::env;
11 use std::panic;
12
13 #[macro_use]
14 #[cfg(not(feature = "logging"))]
15 mod log_stubs;
16
17 mod options;
18 use crate::options::builder_from_flags;
19
clang_version_check()20 fn clang_version_check() {
21 let version = clang_version();
22 let expected_version = if cfg!(feature = "testing_only_libclang_9") {
23 Some((9, 0))
24 } else if cfg!(feature = "testing_only_libclang_5") {
25 Some((5, 0))
26 } else if cfg!(feature = "testing_only_libclang_4") {
27 Some((4, 0))
28 } else if cfg!(feature = "testing_only_libclang_3_9") {
29 Some((3, 9))
30 } else {
31 None
32 };
33
34 info!(
35 "Clang Version: {}, parsed: {:?}",
36 version.full, version.parsed
37 );
38
39 if expected_version.is_some() {
40 assert_eq!(version.parsed, version.parsed);
41 }
42 }
43
main()44 pub fn main() {
45 #[cfg(feature = "logging")]
46 env_logger::init();
47
48 let bind_args: Vec<_> = env::args().collect();
49
50 match builder_from_flags(bind_args.into_iter()) {
51 Ok((builder, output, verbose)) => {
52 clang_version_check();
53 let builder_result = panic::catch_unwind(|| {
54 builder.generate().expect("Unable to generate bindings")
55 });
56
57 if builder_result.is_err() {
58 if verbose {
59 print_verbose_err();
60 }
61 std::process::exit(1);
62 }
63
64 let bindings = builder_result.unwrap();
65 bindings.write(output).expect("Unable to write output");
66 }
67 Err(error) => {
68 println!("{}", error);
69 std::process::exit(1);
70 }
71 };
72 }
73
print_verbose_err()74 fn print_verbose_err() {
75 println!("Bindgen unexpectedly panicked");
76 println!(
77 "This may be caused by one of the known-unsupported \
78 things (https://rust-lang.github.io/rust-bindgen/cpp.html), \
79 please modify the bindgen flags to work around it as \
80 described in https://rust-lang.github.io/rust-bindgen/cpp.html"
81 );
82 println!(
83 "Otherwise, please file an issue at \
84 https://github.com/rust-lang/rust-bindgen/issues/new"
85 );
86 }
87
88 #[cfg(test)]
89 mod test {
build_flags_output_helper(builder: &bindgen::Builder)90 fn build_flags_output_helper(builder: &bindgen::Builder) {
91 let mut command_line_flags = builder.command_line_flags();
92 command_line_flags.insert(0, "bindgen".to_string());
93
94 let flags_quoted: Vec<String> = command_line_flags
95 .iter()
96 .map(|x| format!("{}", shlex::quote(x)))
97 .collect();
98 let flags_str = flags_quoted.join(" ");
99 println!("{}", flags_str);
100
101 let (builder, _output, _verbose) =
102 crate::options::builder_from_flags(command_line_flags.into_iter())
103 .unwrap();
104 builder.generate().expect("failed to generate bindings");
105 }
106
107 #[test]
commandline_multiple_headers()108 fn commandline_multiple_headers() {
109 let bindings = bindgen::Builder::default()
110 .header("tests/headers/char.h")
111 .header("tests/headers/func_ptr.h")
112 .header("tests/headers/16-byte-alignment.h");
113 build_flags_output_helper(&bindings);
114 }
115 }
116