summaryrefslogtreecommitdiff
path: root/bindgen/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'bindgen/lib.rs')
-rw-r--r--bindgen/lib.rs120
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.