diff options
-rwxr-xr-x | src/bin/bindgen.rs | 15 | ||||
-rwxr-xr-x | src/clang.rs | 25 | ||||
-rwxr-xr-x | src/codegen/mod.rs | 43 | ||||
-rw-r--r-- | src/ir/context.rs | 16 | ||||
-rw-r--r-- | src/ir/item.rs | 11 | ||||
-rw-r--r-- | src/ir/ty.rs | 23 | ||||
-rwxr-xr-x | src/lib.rs | 20 | ||||
-rw-r--r-- | tests/expectations/tests/no-std.rs | 23 | ||||
-rw-r--r-- | tests/expectations/tests/use-core.rs | 22 | ||||
-rw-r--r-- | tests/headers/no-std.h | 5 | ||||
-rw-r--r-- | tests/headers/use-core.h | 6 | ||||
-rwxr-xr-x | tests/tools/run-bindgen.py | 3 |
12 files changed, 170 insertions, 42 deletions
diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs index 0c3d97cf..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; @@ -69,6 +69,11 @@ Options: --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. @@ -182,6 +187,14 @@ 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; } diff --git a/src/clang.rs b/src/clang.rs index a11e2924..c6af517c 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 7d470be4..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(), @@ -1768,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(); @@ -1779,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() @@ -1806,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() @@ -1816,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/item.rs b/src/ir/item.rs index a07ee1f3..c6d80a08 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -331,6 +331,12 @@ impl Item { self.kind().expect_type() } + /// Get a reference to this item's underlying `Type`, or `None` if this is + /// some other kind of item. + pub fn as_type(&self) -> Option<&Type> { + self.kind().as_type() + } + /// Get a reference to this item's underlying `Function`. Panic if this is /// some other kind of item. pub fn expect_function(&self) -> &Function { @@ -531,6 +537,11 @@ impl Item { ctx.opaque_by_name(&self.real_canonical_name(ctx, false, true)) } + /// Is this a reference to another type? + pub fn is_type_ref(&self) -> bool { + self.as_type().map_or(false, |ty| ty.is_type_ref()) + } + /// Get the canonical name without taking into account the replaces /// annotation. /// diff --git a/src/ir/ty.rs b/src/ir/ty.rs index be749268..77dc61be 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -136,6 +136,15 @@ impl Type { self.is_const } + /// Is this a reference to another type? + pub fn is_type_ref(&self) -> bool { + match self.kind { + TypeKind::ResolvedTypeRef(_) | + TypeKind::UnresolvedTypeRef(_, _, _) => true, + _ => false, + } + } + /// What is the layout of this type? pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> { use std::mem; @@ -677,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, @@ -687,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 @@ -216,6 +216,18 @@ impl Builder { 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) @@ -279,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, @@ -319,6 +337,8 @@ 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, diff --git a/tests/expectations/tests/no-std.rs b/tests/expectations/tests/no-std.rs new file mode 100644 index 00000000..f50a889d --- /dev/null +++ b/tests/expectations/tests/no-std.rs @@ -0,0 +1,23 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + +#![no_std] +mod libc { pub type c_int = i32; pub enum c_void {} } + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub a: libc::c_int, + pub b: libc::c_int, + pub bar: *mut libc::c_void, +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::core::mem::size_of::<foo>() , 16usize); + assert_eq!(::core::mem::align_of::<foo>() , 8usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/tests/expectations/tests/use-core.rs b/tests/expectations/tests/use-core.rs new file mode 100644 index 00000000..484105ea --- /dev/null +++ b/tests/expectations/tests/use-core.rs @@ -0,0 +1,22 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + +extern crate core; + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub a: ::std::os::raw::c_int, + pub b: ::std::os::raw::c_int, + pub bar: *mut ::std::os::raw::c_void, +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::core::mem::size_of::<foo>() , 16usize); + assert_eq!(::core::mem::align_of::<foo>() , 8usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/tests/headers/no-std.h b/tests/headers/no-std.h new file mode 100644 index 00000000..7bee9657 --- /dev/null +++ b/tests/headers/no-std.h @@ -0,0 +1,5 @@ +// bindgen-flags: --ctypes-prefix "libc" --use-core --raw-line "#![no_std]" --raw-line "mod libc { pub type c_int = i32; pub enum c_void {} }" +struct foo { + int a, b; + void* bar; +}; diff --git a/tests/headers/use-core.h b/tests/headers/use-core.h new file mode 100644 index 00000000..535d2b15 --- /dev/null +++ b/tests/headers/use-core.h @@ -0,0 +1,6 @@ +// bindgen-flags: --use-core --raw-line "extern crate core;" + +struct foo { + int a, b; + void* bar; +}; diff --git a/tests/tools/run-bindgen.py b/tests/tools/run-bindgen.py index aad210da..519e6891 100755 --- a/tests/tools/run-bindgen.py +++ b/tests/tools/run-bindgen.py @@ -8,6 +8,7 @@ import os import sys import subprocess import tempfile +import shlex BINDGEN_FLAGS_PREFIX = "// bindgen-flags: " @@ -94,7 +95,7 @@ def get_bindgen_flags(header_path): with open(header_path) as f: for line in f: if line.startswith(BINDGEN_FLAGS_PREFIX): - flags.extend(line.strip().split(BINDGEN_FLAGS_PREFIX)[1].split(" ")) + flags.extend(shlex.split(line.strip().split(BINDGEN_FLAGS_PREFIX)[1])) break return flags |