diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/bin/bindgen.rs | 20 | ||||
-rwxr-xr-x | src/clang.rs | 25 | ||||
-rwxr-xr-x | src/codegen/mod.rs | 68 | ||||
-rw-r--r-- | src/ir/context.rs | 16 | ||||
-rw-r--r-- | src/ir/ty.rs | 14 | ||||
-rwxr-xr-x | src/lib.rs | 30 |
6 files changed, 126 insertions, 47 deletions
diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs index c906efee..2dbb1690 100755 --- a/src/bin/bindgen.rs +++ b/src/bin/bindgen.rs @@ -8,7 +8,7 @@ extern crate log; extern crate clang_sys; extern crate rustc_serialize; -use bindgen::{BindgenOptions, Bindings, ClangVersion, LinkType, clang_version}; +use bindgen::{BindgenOptions, Bindings, LinkType, clang_version}; use std::default::Default; use std::env; use std::fs; @@ -63,10 +63,17 @@ Options: --use-msvc-mangling Handle MSVC C++ ABI mangling; requires that target be set to (i686|x86_64)-pc-win32 + --no-convert-floats Don't convert floats automatically to f32/f64. + --raw-line=<raw> Add a raw line at the beginning of the output. --no-unstable-rust Avoid generating unstable rust. + --use-core Use built-in types from core instead of std. + + --ctypes-prefix=<prefix> Use the given prefix before the raw types + instead of ::std::os::raw::. + --opaque-type=<type> Mark a type as opaque. --blacklist-type=<type> Mark a type as hidden. @@ -180,9 +187,20 @@ fn parse_args_or_exit(args: Vec<String>) -> (BindgenOptions, Box<io::Write>) { "--no-unstable-rust" => { options.unstable_rust = false; } + "--use-core" => { + options.use_core = true; + } + "--ctypes-prefix" => { + let prefix = iter.next() + .expect("--ctypes-prefix expects a prefix after it"); + options.ctypes_prefix = Some(prefix); + } "--emit-clang-ast" => { options.emit_ast = true; } + "--no-convert-floats" => { + options.convert_floats = false; + } "--use-msvc-mangling" => { options.msvc_mangling = true; } diff --git a/src/clang.rs b/src/clang.rs index d9fbd7b8..e6d78123 100755 --- a/src/clang.rs +++ b/src/clang.rs @@ -101,7 +101,9 @@ impl Cursor { /// See documentation for `lexical_parent` for details on semantic vs /// lexical parents. pub fn fallible_semantic_parent(&self) -> Option<Cursor> { - let sp = self.semantic_parent(); + let sp = unsafe { + Cursor { x: clang_getCursorSemanticParent(self.x) } + }; if sp == *self || !sp.is_valid() { return None; } @@ -113,11 +115,7 @@ impl Cursor { /// See documentation for `lexical_parent` for details on semantic vs /// lexical parents. pub fn semantic_parent(&self) -> Cursor { - unsafe { - Cursor { - x: clang_getCursorSemanticParent(self.x), - } - } + self.fallible_semantic_parent().unwrap() } /// Return the number of template arguments used by this cursor's referent, @@ -157,17 +155,18 @@ impl Cursor { /// Is the referent a top level construct? pub fn is_toplevel(&self) -> bool { - let mut semantic_parent = self.semantic_parent(); + let mut semantic_parent = self.fallible_semantic_parent(); - while semantic_parent.kind() == CXCursor_Namespace || - semantic_parent.kind() == CXCursor_NamespaceAlias || - semantic_parent.kind() == CXCursor_NamespaceRef { - semantic_parent = semantic_parent.semantic_parent(); + while semantic_parent.is_some() && + (semantic_parent.unwrap().kind() == CXCursor_Namespace || + semantic_parent.unwrap().kind() == CXCursor_NamespaceAlias || + semantic_parent.unwrap().kind() == CXCursor_NamespaceRef) { + semantic_parent = semantic_parent.unwrap().fallible_semantic_parent(); } let tu = self.translation_unit(); - // Yes, the second can happen with, e.g., macro definitions. - semantic_parent == tu || semantic_parent == tu.semantic_parent() + // Yes, this can happen with, e.g., macro definitions. + semantic_parent == tu.fallible_semantic_parent() } /// Get the kind of referent this cursor is pointing to. diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index e7fa62ee..bf6af82b 100755 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -533,6 +533,7 @@ impl<'a> Bitfield<'a> { let setter_name = ctx.ext_cx() .ident_of(&format!("set_{}", &field_name)); let mask = ((1usize << width) - 1) << offset; + let prefix = ctx.trait_prefix(); // The transmute is unfortunate, but it's needed for enums in // bitfields. let item = quote_item!(ctx.ext_cx(), @@ -540,7 +541,7 @@ impl<'a> Bitfield<'a> { #[inline] pub fn $getter_name(&self) -> $field_type { unsafe { - ::std::mem::transmute( + ::$prefix::mem::transmute( ( (self.$field_ident & ($mask as $bitfield_type)) @@ -942,8 +943,9 @@ impl CodeGenerator for CompInfo { if !template_args_used[i] { let name = ctx.resolve_type(*ty).name().unwrap(); let ident = ctx.rust_ident(name); + let prefix = ctx.trait_prefix(); let phantom = quote_ty!(ctx.ext_cx(), - ::std::marker::PhantomData<$ident>); + ::$prefix::marker::PhantomData<$ident>); let field = StructFieldBuilder::named(format!("_phantom_{}", i)) .pub_() @@ -999,10 +1001,11 @@ impl CodeGenerator for CompInfo { let fn_name = format!("bindgen_test_layout_{}", canonical_name); let fn_name = ctx.rust_ident_raw(&fn_name); let ident = ctx.rust_ident_raw(&canonical_name); - let size_of_expr = - quote_expr!(ctx.ext_cx(), ::std::mem::size_of::<$ident>()); - let align_of_expr = - quote_expr!(ctx.ext_cx(), ::std::mem::align_of::<$ident>()); + let prefix = ctx.trait_prefix(); + let size_of_expr = quote_expr!(ctx.ext_cx(), + ::$prefix::mem::size_of::<$ident>()); + let align_of_expr = quote_expr!(ctx.ext_cx(), + ::$prefix::mem::align_of::<$ident>()); let size = layout.size; let align = layout.align; let item = quote_item!(ctx.ext_cx(), @@ -1414,7 +1417,13 @@ impl ItemToRustTy for Item { fn raw_type(ctx: &BindgenContext, name: &str) -> P<ast::Ty> { let ident = ctx.rust_ident_raw(&name); - quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident) + match ctx.options().ctypes_prefix { + Some(ref prefix) => { + let prefix = ctx.rust_ident_raw(prefix); + quote_ty!(ctx.ext_cx(), $prefix::$ident) + } + None => quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident), + } } impl ToRustTy for Type { @@ -1430,9 +1439,7 @@ impl ToRustTy for Type { TypeKind::Void => raw!(c_void), // TODO: we should do something smart with nullptr, or maybe *const // c_void is enough? - TypeKind::NullPtr => { - quote_ty!(ctx.ext_cx(), *const ::std::os::raw::c_void) - } + TypeKind::NullPtr => raw!(c_void).to_ptr(true, ctx.span()), TypeKind::Int(ik) => { match ik { IntKind::Bool => aster::ty::TyBuilder::new().bool(), @@ -1458,12 +1465,25 @@ impl ToRustTy for Type { } TypeKind::Float(fk) => { use ir::ty::FloatKind; - // TODO: we probably should just take the type layout into - // account? - match fk { - FloatKind::Float => aster::ty::TyBuilder::new().f32(), - FloatKind::Double | FloatKind::LongDouble => { - aster::ty::TyBuilder::new().f64() + if ctx.options().convert_floats { + // TODO: we probably should just take the type layout into + // account? + // + // Also, maybe this one shouldn't be the default? + match fk { + FloatKind::Float => aster::ty::TyBuilder::new().f32(), + FloatKind::Double | FloatKind::LongDouble => { + aster::ty::TyBuilder::new().f64() + } + } + } else { + // FIXME: `c_longdouble` doesn't seem to be defined in some + // systems, so we use `c_double` directly. + match fk { + FloatKind::Float => raw!(c_float), + FloatKind::Double | FloatKind::LongDouble => { + raw!(c_double) + } } } } @@ -1755,10 +1775,12 @@ mod utils { pub fn prepend_union_types(ctx: &BindgenContext, result: &mut Vec<P<ast::Item>>) { + let prefix = ctx.trait_prefix(); let union_field_decl = quote_item!(ctx.ext_cx(), #[derive(Debug)] #[repr(C)] - pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); + pub struct __BindgenUnionField<T>( + ::$prefix::marker::PhantomData<T>); ) .unwrap(); @@ -1766,24 +1788,24 @@ mod utils { impl<T> __BindgenUnionField<T> { #[inline] pub fn new() -> Self { - __BindgenUnionField(::std::marker::PhantomData) + __BindgenUnionField(::$prefix::marker::PhantomData) } #[inline] pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) + ::$prefix::mem::transmute(self) } #[inline] pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) + ::$prefix::mem::transmute(self) } } ) .unwrap(); let union_field_default_impl = quote_item!(&ctx.ext_cx(), - impl<T> ::std::default::Default for __BindgenUnionField<T> { + impl<T> ::$prefix::default::Default for __BindgenUnionField<T> { #[inline] fn default() -> Self { Self::new() @@ -1793,7 +1815,7 @@ mod utils { .unwrap(); let union_field_clone_impl = quote_item!(&ctx.ext_cx(), - impl<T> ::std::clone::Clone for __BindgenUnionField<T> { + impl<T> ::$prefix::clone::Clone for __BindgenUnionField<T> { #[inline] fn clone(&self) -> Self { Self::new() @@ -1803,7 +1825,7 @@ mod utils { .unwrap(); let union_field_copy_impl = quote_item!(&ctx.ext_cx(), - impl<T> ::std::marker::Copy for __BindgenUnionField<T> {} + impl<T> ::$prefix::marker::Copy for __BindgenUnionField<T> {} ) .unwrap(); diff --git a/src/ir/context.rs b/src/ir/context.rs index fc06375c..f11b387a 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -221,7 +221,7 @@ impl<'ctx> BindgenContext<'ctx> { /// Mangles a name so it doesn't conflict with any keyword. pub fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> { use syntax::parse::token; - let ident = self.rust_ident_raw(&name); + let ident = self.rust_ident_raw(name); let token = token::Ident(ident); if token.is_any_keyword() || name.contains("@") || name.contains("?") || name.contains("$") || @@ -242,9 +242,7 @@ impl<'ctx> BindgenContext<'ctx> { } /// Returns a mangled name as a rust identifier. - pub fn rust_ident_raw<S>(&self, name: &S) -> Ident - where S: Borrow<str>, - { + pub fn rust_ident_raw(&self, name: &str) -> Ident { self.ext_cx().ident_of(name.borrow()) } @@ -912,6 +910,16 @@ impl<'ctx> BindgenContext<'ctx> { to_iterate: to_iterate, } } + + /// Convenient method for getting the prefix to use for most traits in + /// codegen depending on the `use_core` option. + pub fn trait_prefix(&self) -> Ident { + if self.options().use_core { + self.rust_ident_raw("core") + } else { + self.rust_ident_raw("std") + } + } } /// An iterator over whitelisted items. diff --git a/src/ir/ty.rs b/src/ir/ty.rs index 2c1e5f8e..77dc61be 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -686,9 +686,10 @@ impl Type { // process of resolving them. CXType_MemberPointer | CXType_Pointer => { - let inner = - Item::from_ty_or_ref(ty.pointee_type().unwrap(), location, - parent_id, ctx); + let inner = Item::from_ty_or_ref(ty.pointee_type().unwrap(), + location, + parent_id, + ctx); TypeKind::Pointer(inner) } CXType_BlockPointer => TypeKind::BlockPointer, @@ -696,9 +697,10 @@ impl Type { // can even add bindings for that, so huh. CXType_RValueReference | CXType_LValueReference => { - let inner = - Item::from_ty_or_ref(ty.pointee_type().unwrap(), location, - parent_id, ctx); + let inner = Item::from_ty_or_ref(ty.pointee_type().unwrap(), + location, + parent_id, + ctx); TypeKind::Reference(inner) } // XXX DependentSizedArray is wrong @@ -204,12 +204,30 @@ impl Builder { self } + /// Avoid converting floats to f32/f64 by default. + pub fn no_convert_floats(mut self) -> Self { + self.options.convert_floats = false; + self + } + /// Avoid generating any unstable Rust in the generated bindings. pub fn no_unstable_rust(mut self) -> Builder { self.options.unstable_rust = false; self } + /// Use core instead of libstd in the generated bindings. + pub fn use_core(mut self) -> Builder { + self.options.use_core = true; + self + } + + /// Use the given prefix for the raw types instead of `::std::os::raw`. + pub fn ctypes_prefix<T: Into<String>>(mut self, prefix: T) -> Builder { + self.options.ctypes_prefix = Some(prefix.into()); + self + } + /// Generate the Rust bindings using the options built up thus far. pub fn generate<'ctx>(self) -> Result<Bindings<'ctx>, ()> { Bindings::generate(self.options, None) @@ -273,6 +291,12 @@ pub struct BindgenOptions { /// cannot. pub unstable_rust: bool, + /// True if we should avoid using libstd to use libcore instead. + pub use_core: bool, + + /// An optional prefix for the "raw" types, like `c_int`, `c_void`... + pub ctypes_prefix: Option<String>, + /// True if we should generate constant names that are **directly** under /// namespaces. pub namespaced_constants: bool, @@ -280,6 +304,9 @@ pub struct BindgenOptions { /// True if we should use MSVC name mangling rules. pub msvc_mangling: bool, + /// Whether we should convert float types to f32/f64 types. + pub convert_floats: bool, + /// The set of raw lines to prepend to the generated Rust code. pub raw_lines: Vec<String>, @@ -310,8 +337,11 @@ impl Default for BindgenOptions { derive_debug: true, enable_cxx_namespaces: false, unstable_rust: true, + use_core: false, + ctypes_prefix: None, namespaced_constants: true, msvc_mangling: false, + convert_floats: true, raw_lines: vec![], clang_args: vec![], input_header: None, |