diff options
-rw-r--r-- | src/chooser.rs | 3 | ||||
-rw-r--r-- | src/lib.rs | 5 | ||||
-rw-r--r-- | src/main.rs | 29 | ||||
-rw-r--r-- | src/options.rs | 9 | ||||
-rw-r--r-- | tests/tests.rs | 2 |
5 files changed, 41 insertions, 7 deletions
diff --git a/src/chooser.rs b/src/chooser.rs index bf610b28..29090a42 100644 --- a/src/chooser.rs +++ b/src/chooser.rs @@ -3,10 +3,11 @@ pub use ir::enum_ty::{EnumVariantCustomBehavior, EnumVariantValue}; pub use ir::int::IntKind; use std::fmt; +use std::panic::UnwindSafe; /// A trait to allow configuring different kinds of types in different /// situations. -pub trait TypeChooser: fmt::Debug { +pub trait TypeChooser: fmt::Debug + UnwindSafe { /// The integer kind an integer macro should have, given a name and the /// value of that macro, or `None` if you want the default to be chosen. fn int_macro(&self, _name: &str, _value: i64) -> Option<IntKind> { @@ -554,6 +554,11 @@ pub struct BindgenOptions { pub objc_extern_crate: bool, } +/// TODO(emilio): This is sort of a lie (see the error message that results from +/// removing this), but since we don't share references across panic boundaries +/// it's ok. +impl ::std::panic::UnwindSafe for BindgenOptions {} + impl BindgenOptions { fn build(&mut self) { self.whitelisted_vars.build(); diff --git a/src/main.rs b/src/main.rs index 9b037ef8..68f3d0a8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ extern crate rustc_serialize; use bindgen::clang_version; use std::env; +use std::panic; mod options; use options::builder_from_flags; @@ -41,9 +42,21 @@ pub fn main() { } match builder_from_flags(bind_args.into_iter()) { - Ok((builder, output)) => { - let mut bindings = builder.generate() - .expect("Unable to generate bindings"); + Ok((builder, output, verbose)) => { + + let builder_result = + panic::catch_unwind(|| + builder.generate().expect("Unable to generate bindings") + ); + + if builder_result.is_err() { + if verbose { + print_verbose_err(); + } + std::process::exit(1); + } + + let mut bindings = builder_result.unwrap(); bindings.write(output) .expect("Unable to write output"); bindings.write_dummy_uses() @@ -55,3 +68,13 @@ pub fn main() { } }; } + +fn print_verbose_err() { + println!("Bindgen unexpectedly panicked"); + println!("This may be caused by one of the known-unsupported \ + things (https://github.com/servo/rust-bindgen#c), \ + please modify the bindgen flags to work around it as \ + described in https://github.com/servo/rust-bindgen#c"); + println!("Otherwise, please file an issue at \ + https://github.com/servo/rust-bindgen/issues/new"); +} diff --git a/src/options.rs b/src/options.rs index 8d11be2d..5231ad24 100644 --- a/src/options.rs +++ b/src/options.rs @@ -5,7 +5,7 @@ use std::io::{self, Error, ErrorKind}; /// Construct a new [`Builder`](./struct.Builder.html) from command line flags. pub fn builder_from_flags<I>(args: I) - -> Result<(Builder, Box<io::Write>), io::Error> + -> Result<(Builder, Box<io::Write>, bool), io::Error> where I: Iterator<Item = String>, { let matches = App::new("bindgen") @@ -175,6 +175,9 @@ pub fn builder_from_flags<I>(args: I) .takes_value(true) .multiple(true) .number_of_values(1), + Arg::with_name("verbose") + .long("verbose") + .help("Print verbose error messages"), ]) // .args() .get_matches_from(args); @@ -346,5 +349,7 @@ pub fn builder_from_flags<I>(args: I) Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write> }; - Ok((builder, output)) + let verbose = matches.is_present("verbose"); + + Ok((builder, output, verbose)) } diff --git a/tests/tests.rs b/tests/tests.rs index 5b0ccd11..bc853a33 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -117,7 +117,7 @@ fn create_bindgen_builder(header: &PathBuf) -> Result<Option<Builder>, Error> { .chain(flags.into_iter()); builder_from_flags(args) - .map(|(builder, _)| Some(builder.no_unstable_rust())) + .map(|(builder, _, _)| Some(builder.no_unstable_rust())) } macro_rules! test_header { |