Add BindgenError
diff --git a/src/lib.rs b/src/lib.rs
index f3912e8..4ff72cc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1444,6 +1444,7 @@
}
/// Generate the Rust bindings using the options built up thus far.
+ #[deprecated(since = "0.59.3", note = "please use `gen` instead")]
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) =
@@ -1475,6 +1476,41 @@
}),
);
+ Bindings::generate(self.options).map_err(|_| ())
+ }
+
+ /// Generate the Rust bindings using the options built up thus far, or `Err` on failure.
+ pub fn gen(mut self) -> Result<Bindings, BindgenError> {
+ // Add any extra arguments from the environment to the clang command line.
+ if let Some(extra_clang_args) =
+ get_target_dependent_env_var("BINDGEN_EXTRA_CLANG_ARGS")
+ {
+ // 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.extra_input_headers = self.input_headers;
+ self.options.clang_args.extend(
+ self.options.extra_input_headers.iter().flat_map(|header| {
+ iter::once("-include".into())
+ .chain(iter::once(header.to_string()))
+ }),
+ );
+
+ self.options.input_unsaved_files.extend(
+ self.input_header_contents
+ .drain(..)
+ .map(|(name, contents)| {
+ clang::UnsavedFile::new(&name, &contents)
+ }),
+ );
+
Bindings::generate(self.options)
}
@@ -2146,6 +2182,28 @@
#[cfg(not(feature = "runtime"))]
fn ensure_libclang_is_loaded() {}
+/// Error type for rust-bindgen.
+#[derive(Debug)]
+pub enum BindgenError {
+ /// Any provided header was invalid.
+ InvalidHeader(String),
+ /// Clang diagnosed an error.
+ ClangDiagnostic(String),
+}
+
+impl std::fmt::Display for BindgenError {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ BindgenError::InvalidHeader(message) => {
+ write!(f, "invalid header: {}", message)
+ }
+ BindgenError::ClangDiagnostic(message) => {
+ write!(f, "clang diagnosed error: {}", message)
+ }
+ }
+ }
+}
+
/// Generated Rust bindings.
#[derive(Debug)]
pub struct Bindings {
@@ -2202,7 +2260,7 @@
/// Generate bindings for the given options.
pub(crate) fn generate(
mut options: BindgenOptions,
- ) -> Result<Bindings, ()> {
+ ) -> Result<Bindings, BindgenError> {
ensure_libclang_is_loaded();
#[cfg(feature = "runtime")]
@@ -2322,20 +2380,23 @@
if let Some(h) = options.input_header.as_ref() {
if let Ok(md) = std::fs::metadata(h) {
if md.is_dir() {
- eprintln!("error: '{}' is a folder", h);
- return Err(());
+ return Err(BindgenError::InvalidHeader(format!(
+ "error: '{}' is a folder",
+ h
+ )));
}
if !can_read(&md.permissions()) {
- eprintln!(
+ return Err(BindgenError::InvalidHeader(format!(
"error: insufficient permissions to read '{}'",
h
- );
- return Err(());
+ )));
}
options.clang_args.push(h.clone())
} else {
- eprintln!("error: header '{}' does not exist.", h);
- return Err(());
+ return Err(BindgenError::InvalidHeader(format!(
+ "error: header '{}' does not exist.",
+ h
+ )));
}
}
@@ -2556,19 +2617,24 @@
}
/// Parse the Clang AST into our `Item` internal representation.
-fn parse(context: &mut BindgenContext) -> Result<(), ()> {
+fn parse(context: &mut BindgenContext) -> Result<(), BindgenError> {
use clang_sys::*;
- let mut any_error = false;
+ let mut error = None;
for d in context.translation_unit().diags().iter() {
let msg = d.format();
let is_err = d.severity() >= CXDiagnostic_Error;
- eprintln!("{}, err: {}", msg, is_err);
- any_error |= is_err;
+ if is_err {
+ let error = error.get_or_insert_with(String::new);
+ error.push_str(&msg);
+ error.push('\n');
+ } else {
+ eprintln!("clang diag: {}", msg);
+ }
}
- if any_error {
- return Err(());
+ if let Some(message) = error {
+ return Err(BindgenError::ClangDiagnostic(message));
}
let cursor = context.translation_unit().cursor();