diff options
Diffstat (limited to 'bindgen/lib.rs')
-rw-r--r-- | bindgen/lib.rs | 120 |
1 files changed, 77 insertions, 43 deletions
diff --git a/bindgen/lib.rs b/bindgen/lib.rs index 8c8ffe5c..53747420 100644 --- a/bindgen/lib.rs +++ b/bindgen/lib.rs @@ -78,6 +78,7 @@ doc_mod!(ir, ir_docs); doc_mod!(parse, parse_docs); doc_mod!(regex_set, regex_set_docs); +use codegen::CodegenError; use ir::comment; pub use crate::codegen::{ @@ -108,6 +109,7 @@ pub(crate) use std::collections::hash_map::Entry; /// Default prefix for the anon fields. pub const DEFAULT_ANON_FIELDS_PREFIX: &str = "__bindgen_anon_"; +const DEFAULT_NON_EXTERN_FNS_SUFFIX: &str = "__extern"; fn file_is_cpp(name_file: &str) -> bool { name_file.ends_with(".hpp") || @@ -657,6 +659,23 @@ impl Builder { for callbacks in &self.options.parse_callbacks { output_vector.extend(callbacks.cli_args()); } + if self.options.wrap_static_fns { + output_vector.push("--wrap-static-fns".into()) + } + + if let Some(ref path) = self.options.wrap_static_fns_path { + output_vector.push("--wrap-static-fns-path".into()); + output_vector.push(path.display().to_string()); + } + + if let Some(ref suffix) = self.options.wrap_static_fns_suffix { + output_vector.push("--wrap-static-fns-suffix".into()); + output_vector.push(suffix.clone()); + } + + if cfg!(feature = "experimental") { + output_vector.push("--experimental".into()); + } // Add clang arguments @@ -1553,33 +1572,25 @@ impl Builder { } /// Generate the Rust bindings using the options built up thus far. - pub fn generate(self) -> Result<Bindings, BindgenError> { - let mut options = self.options.clone(); + pub fn generate(mut self) -> Result<Bindings, BindgenError> { // Add any extra arguments from the environment to the clang command line. - options.clang_args.extend(get_extra_clang_args()); + self.options.clang_args.extend(get_extra_clang_args()); // Transform input headers to arguments on the clang command line. - options.clang_args.extend( - options.input_headers - [..options.input_headers.len().saturating_sub(1)] + self.options.clang_args.extend( + self.options.input_headers + [..self.options.input_headers.len().saturating_sub(1)] .iter() .flat_map(|header| ["-include".into(), header.to_string()]), ); let input_unsaved_files = - std::mem::take(&mut options.input_header_contents) + std::mem::take(&mut self.options.input_header_contents) .into_iter() .map(|(name, contents)| clang::UnsavedFile::new(name, contents)) .collect::<Vec<_>>(); - match Bindings::generate(options, input_unsaved_files) { - GenerateResult::Ok(bindings) => Ok(*bindings), - GenerateResult::ShouldRestart { header } => self - .header(header) - .generate_inline_functions(false) - .generate(), - GenerateResult::Err(err) => Err(err), - } + Bindings::generate(self.options, input_unsaved_files) } /// Preprocess and dump the input header files to disk. @@ -1796,6 +1807,32 @@ impl Builder { self.options.wrap_unsafe_ops = doit; self } + + #[cfg(feature = "experimental")] + /// Whether to generate extern wrappers for `static` and `static inline` functions. Defaults to + /// false. + pub fn wrap_static_fns(mut self, doit: bool) -> Self { + self.options.wrap_static_fns = doit; + self + } + + #[cfg(feature = "experimental")] + /// Set the path for the source code file that would be created if any wrapper functions must + /// be generated due to the presence of static functions. + /// + /// Bindgen will automatically add the right extension to the header and source code files. + pub fn wrap_static_fns_path<T: AsRef<Path>>(mut self, path: T) -> Self { + self.options.wrap_static_fns_path = Some(path.as_ref().to_owned()); + self + } + + #[cfg(feature = "experimental")] + /// Set the suffix added to the extern wrapper functions generated for `static` and `static + /// inline` functions. + pub fn wrap_static_fns_suffix<T: AsRef<str>>(mut self, suffix: T) -> Self { + self.options.wrap_static_fns_suffix = Some(suffix.as_ref().to_owned()); + self + } } /// Configuration options for generated bindings. @@ -2136,6 +2173,12 @@ struct BindgenOptions { /// Whether to wrap unsafe operations in unsafe blocks or not. wrap_unsafe_ops: bool, + + wrap_static_fns: bool, + + wrap_static_fns_suffix: Option<String>, + + wrap_static_fns_path: Option<PathBuf>, } impl BindgenOptions { @@ -2328,6 +2371,9 @@ impl Default for BindgenOptions { merge_extern_blocks, abi_overrides, wrap_unsafe_ops, + wrap_static_fns, + wrap_static_fns_suffix, + wrap_static_fns_path, } } } @@ -2358,18 +2404,6 @@ fn ensure_libclang_is_loaded() { #[cfg(not(feature = "runtime"))] fn ensure_libclang_is_loaded() {} -#[derive(Debug)] -enum GenerateResult { - Ok(Box<Bindings>), - /// Error variant raised when bindgen requires to run again with a newly generated header - /// input. - #[allow(dead_code)] - ShouldRestart { - header: String, - }, - Err(BindgenError), -} - /// Error type for rust-bindgen. #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[non_exhaustive] @@ -2382,6 +2416,8 @@ pub enum BindgenError { NotExist(PathBuf), /// Clang diagnosed an error. ClangDiagnostic(String), + /// Code generation reported an error. + Codegen(CodegenError), } impl std::fmt::Display for BindgenError { @@ -2399,6 +2435,9 @@ impl std::fmt::Display for BindgenError { BindgenError::ClangDiagnostic(message) => { write!(f, "clang diagnosed error: {}", message) } + BindgenError::Codegen(err) => { + write!(f, "codegen error: {}", err) + } } } } @@ -2472,7 +2511,7 @@ impl Bindings { pub(crate) fn generate( mut options: BindgenOptions, input_unsaved_files: Vec<clang::UnsavedFile>, - ) -> GenerateResult { + ) -> Result<Bindings, BindgenError> { ensure_libclang_is_loaded(); #[cfg(feature = "runtime")] @@ -2593,21 +2632,17 @@ impl Bindings { let path = Path::new(h); if let Ok(md) = std::fs::metadata(path) { if md.is_dir() { - return GenerateResult::Err(BindgenError::FolderAsHeader( - path.into(), - )); + return Err(BindgenError::FolderAsHeader(path.into())); } if !can_read(&md.permissions()) { - return GenerateResult::Err( - BindgenError::InsufficientPermissions(path.into()), - ); + return Err(BindgenError::InsufficientPermissions( + path.into(), + )); } let h = h.clone(); options.clang_args.push(h); } else { - return GenerateResult::Err(BindgenError::NotExist( - path.into(), - )); + return Err(BindgenError::NotExist(path.into())); } } @@ -2635,18 +2670,17 @@ impl Bindings { { let _t = time::Timer::new("parse").with_output(time_phases); - if let Err(err) = parse(&mut context) { - return GenerateResult::Err(err); - } + parse(&mut context)?; } - let (module, options, warnings) = codegen::codegen(context); + let (module, options, warnings) = + codegen::codegen(context).map_err(BindgenError::Codegen)?; - GenerateResult::Ok(Box::new(Bindings { + Ok(Bindings { options, warnings, module, - })) + }) } /// Write these bindings as source text to a file. |