summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/bin/bindgen.rs15
-rwxr-xr-xsrc/clang.rs25
-rwxr-xr-xsrc/codegen/mod.rs43
-rw-r--r--src/ir/context.rs16
-rw-r--r--src/ir/item.rs11
-rw-r--r--src/ir/ty.rs23
-rwxr-xr-xsrc/lib.rs20
-rw-r--r--tests/expectations/tests/no-std.rs23
-rw-r--r--tests/expectations/tests/use-core.rs22
-rw-r--r--tests/headers/no-std.h5
-rw-r--r--tests/headers/use-core.h6
-rwxr-xr-xtests/tools/run-bindgen.py3
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
diff --git a/src/lib.rs b/src/lib.rs
index 8d2ff7ad..03dac3cc 100755
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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