diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs index c906efee27..60632f4368 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; @@ -67,6 +67,11 @@ Options: --no-unstable-rust Avoid generating unstable rust. + --use-core Use built-in types from core instead of std. + + --ctypes-prefix= Use the given prefix before the raw types + instead of ::std::os::raw::. + --opaque-type= Mark a type as opaque. --blacklist-type= Mark a type as hidden. @@ -180,6 +185,14 @@ fn parse_args_or_exit(args: Vec) -> (BindgenOptions, Box) { "--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/codegen/mod.rs b/src/codegen/mod.rs index e7fa62eeab..85ac13b5af 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 { 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(), @@ -1755,10 +1762,12 @@ mod utils { pub fn prepend_union_types(ctx: &BindgenContext, result: &mut Vec>) { + let prefix = ctx.trait_prefix(); let union_field_decl = quote_item!(ctx.ext_cx(), #[derive(Debug)] #[repr(C)] - pub struct __BindgenUnionField(::std::marker::PhantomData); + pub struct __BindgenUnionField( + ::$prefix::marker::PhantomData); ) .unwrap(); @@ -1766,24 +1775,24 @@ mod utils { impl __BindgenUnionField { #[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 ::std::default::Default for __BindgenUnionField { + impl ::$prefix::default::Default for __BindgenUnionField { #[inline] fn default() -> Self { Self::new() @@ -1793,7 +1802,7 @@ mod utils { .unwrap(); let union_field_clone_impl = quote_item!(&ctx.ext_cx(), - impl ::std::clone::Clone for __BindgenUnionField { + impl ::$prefix::clone::Clone for __BindgenUnionField { #[inline] fn clone(&self) -> Self { Self::new() @@ -1803,7 +1812,7 @@ mod utils { .unwrap(); let union_field_copy_impl = quote_item!(&ctx.ext_cx(), - impl ::std::marker::Copy for __BindgenUnionField {} + impl ::$prefix::marker::Copy for __BindgenUnionField {} ) .unwrap(); diff --git a/src/ir/context.rs b/src/ir/context.rs index fc06375cc4..f11b387a09 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(&self, name: &S) -> Ident - where S: Borrow, - { + 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 be74926816..78c2d459b9 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -677,9 +677,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 +688,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 diff --git a/src/lib.rs b/src/lib.rs index a0eba4c088..a174d8e3ce 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -210,6 +210,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>(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::generate(self.options, None) @@ -273,6 +285,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, + /// True if we should generate constant names that are **directly** under /// namespaces. pub namespaced_constants: bool, @@ -310,6 +328,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, raw_lines: vec![], diff --git a/tests/expectations/tests/no-std.rs b/tests/expectations/tests/no-std.rs new file mode 100644 index 0000000000..f50a889d4c --- /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::() , 16usize); + assert_eq!(::core::mem::align_of::() , 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 0000000000..484105eaf6 --- /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::() , 16usize); + assert_eq!(::core::mem::align_of::() , 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 0000000000..7bee9657f8 --- /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 0000000000..535d2b1529 --- /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 aad210da53..519e6891af 100755 --- a/tests/tools/run-bindgen.py +++ b/tests/tools/run-bindgen.py @@ -8,6 +8,7 @@ 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