• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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