Skip to content

Commit 8c737ec

Browse files
author
bors-servo
authored
Auto merge of #218 - emilio:use-core, r=fitzgen
Support --use-core and --ctypes-prefix As requested in https://github.com/Yamakaky/rust-bindgen/issues/400#issuecomment-258632805. r? @fitzgen
2 parents 86c3bba + 6611276 commit 8c737ec

File tree

10 files changed

+138
-29
lines changed

10 files changed

+138
-29
lines changed

src/bin/bindgen.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ extern crate log;
88
extern crate clang_sys;
99
extern crate rustc_serialize;
1010

11-
use bindgen::{BindgenOptions, Bindings, ClangVersion, LinkType, clang_version};
11+
use bindgen::{BindgenOptions, Bindings, LinkType, clang_version};
1212
use std::default::Default;
1313
use std::env;
1414
use std::fs;
@@ -67,6 +67,11 @@ Options:
6767
6868
--no-unstable-rust Avoid generating unstable rust.
6969
70+
--use-core Use built-in types from core instead of std.
71+
72+
--ctypes-prefix=<prefix> Use the given prefix before the raw types
73+
instead of ::std::os::raw::.
74+
7075
--opaque-type=<type> Mark a type as opaque.
7176
7277
--blacklist-type=<type> Mark a type as hidden.
@@ -180,6 +185,14 @@ fn parse_args_or_exit(args: Vec<String>) -> (BindgenOptions, Box<io::Write>) {
180185
"--no-unstable-rust" => {
181186
options.unstable_rust = false;
182187
}
188+
"--use-core" => {
189+
options.use_core = true;
190+
}
191+
"--ctypes-prefix" => {
192+
let prefix = iter.next()
193+
.expect("--ctypes-prefix expects a prefix after it");
194+
options.ctypes_prefix = Some(prefix);
195+
}
183196
"--emit-clang-ast" => {
184197
options.emit_ast = true;
185198
}

src/codegen/mod.rs

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -533,14 +533,15 @@ impl<'a> Bitfield<'a> {
533533
let setter_name = ctx.ext_cx()
534534
.ident_of(&format!("set_{}", &field_name));
535535
let mask = ((1usize << width) - 1) << offset;
536+
let prefix = ctx.trait_prefix();
536537
// The transmute is unfortunate, but it's needed for enums in
537538
// bitfields.
538539
let item = quote_item!(ctx.ext_cx(),
539540
impl X {
540541
#[inline]
541542
pub fn $getter_name(&self) -> $field_type {
542543
unsafe {
543-
::std::mem::transmute(
544+
::$prefix::mem::transmute(
544545
(
545546
(self.$field_ident &
546547
($mask as $bitfield_type))
@@ -942,8 +943,9 @@ impl CodeGenerator for CompInfo {
942943
if !template_args_used[i] {
943944
let name = ctx.resolve_type(*ty).name().unwrap();
944945
let ident = ctx.rust_ident(name);
946+
let prefix = ctx.trait_prefix();
945947
let phantom = quote_ty!(ctx.ext_cx(),
946-
::std::marker::PhantomData<$ident>);
948+
::$prefix::marker::PhantomData<$ident>);
947949
let field =
948950
StructFieldBuilder::named(format!("_phantom_{}", i))
949951
.pub_()
@@ -999,10 +1001,11 @@ impl CodeGenerator for CompInfo {
9991001
let fn_name = format!("bindgen_test_layout_{}", canonical_name);
10001002
let fn_name = ctx.rust_ident_raw(&fn_name);
10011003
let ident = ctx.rust_ident_raw(&canonical_name);
1002-
let size_of_expr =
1003-
quote_expr!(ctx.ext_cx(), ::std::mem::size_of::<$ident>());
1004-
let align_of_expr =
1005-
quote_expr!(ctx.ext_cx(), ::std::mem::align_of::<$ident>());
1004+
let prefix = ctx.trait_prefix();
1005+
let size_of_expr = quote_expr!(ctx.ext_cx(),
1006+
::$prefix::mem::size_of::<$ident>());
1007+
let align_of_expr = quote_expr!(ctx.ext_cx(),
1008+
::$prefix::mem::align_of::<$ident>());
10061009
let size = layout.size;
10071010
let align = layout.align;
10081011
let item = quote_item!(ctx.ext_cx(),
@@ -1414,7 +1417,13 @@ impl ItemToRustTy for Item {
14141417

14151418
fn raw_type(ctx: &BindgenContext, name: &str) -> P<ast::Ty> {
14161419
let ident = ctx.rust_ident_raw(&name);
1417-
quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident)
1420+
match ctx.options().ctypes_prefix {
1421+
Some(ref prefix) => {
1422+
let prefix = ctx.rust_ident_raw(prefix);
1423+
quote_ty!(ctx.ext_cx(), $prefix::$ident)
1424+
}
1425+
None => quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident),
1426+
}
14181427
}
14191428

14201429
impl ToRustTy for Type {
@@ -1430,9 +1439,7 @@ impl ToRustTy for Type {
14301439
TypeKind::Void => raw!(c_void),
14311440
// TODO: we should do something smart with nullptr, or maybe *const
14321441
// c_void is enough?
1433-
TypeKind::NullPtr => {
1434-
quote_ty!(ctx.ext_cx(), *const ::std::os::raw::c_void)
1435-
}
1442+
TypeKind::NullPtr => raw!(c_void).to_ptr(true, ctx.span()),
14361443
TypeKind::Int(ik) => {
14371444
match ik {
14381445
IntKind::Bool => aster::ty::TyBuilder::new().bool(),
@@ -1755,35 +1762,37 @@ mod utils {
17551762

17561763
pub fn prepend_union_types(ctx: &BindgenContext,
17571764
result: &mut Vec<P<ast::Item>>) {
1765+
let prefix = ctx.trait_prefix();
17581766
let union_field_decl = quote_item!(ctx.ext_cx(),
17591767
#[derive(Debug)]
17601768
#[repr(C)]
1761-
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
1769+
pub struct __BindgenUnionField<T>(
1770+
::$prefix::marker::PhantomData<T>);
17621771
)
17631772
.unwrap();
17641773

17651774
let union_field_impl = quote_item!(&ctx.ext_cx(),
17661775
impl<T> __BindgenUnionField<T> {
17671776
#[inline]
17681777
pub fn new() -> Self {
1769-
__BindgenUnionField(::std::marker::PhantomData)
1778+
__BindgenUnionField(::$prefix::marker::PhantomData)
17701779
}
17711780

17721781
#[inline]
17731782
pub unsafe fn as_ref(&self) -> &T {
1774-
::std::mem::transmute(self)
1783+
::$prefix::mem::transmute(self)
17751784
}
17761785

17771786
#[inline]
17781787
pub unsafe fn as_mut(&mut self) -> &mut T {
1779-
::std::mem::transmute(self)
1788+
::$prefix::mem::transmute(self)
17801789
}
17811790
}
17821791
)
17831792
.unwrap();
17841793

17851794
let union_field_default_impl = quote_item!(&ctx.ext_cx(),
1786-
impl<T> ::std::default::Default for __BindgenUnionField<T> {
1795+
impl<T> ::$prefix::default::Default for __BindgenUnionField<T> {
17871796
#[inline]
17881797
fn default() -> Self {
17891798
Self::new()
@@ -1793,7 +1802,7 @@ mod utils {
17931802
.unwrap();
17941803

17951804
let union_field_clone_impl = quote_item!(&ctx.ext_cx(),
1796-
impl<T> ::std::clone::Clone for __BindgenUnionField<T> {
1805+
impl<T> ::$prefix::clone::Clone for __BindgenUnionField<T> {
17971806
#[inline]
17981807
fn clone(&self) -> Self {
17991808
Self::new()
@@ -1803,7 +1812,7 @@ mod utils {
18031812
.unwrap();
18041813

18051814
let union_field_copy_impl = quote_item!(&ctx.ext_cx(),
1806-
impl<T> ::std::marker::Copy for __BindgenUnionField<T> {}
1815+
impl<T> ::$prefix::marker::Copy for __BindgenUnionField<T> {}
18071816
)
18081817
.unwrap();
18091818

src/ir/context.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ impl<'ctx> BindgenContext<'ctx> {
221221
/// Mangles a name so it doesn't conflict with any keyword.
222222
pub fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> {
223223
use syntax::parse::token;
224-
let ident = self.rust_ident_raw(&name);
224+
let ident = self.rust_ident_raw(name);
225225
let token = token::Ident(ident);
226226
if token.is_any_keyword() || name.contains("@") ||
227227
name.contains("?") || name.contains("$") ||
@@ -242,9 +242,7 @@ impl<'ctx> BindgenContext<'ctx> {
242242
}
243243

244244
/// Returns a mangled name as a rust identifier.
245-
pub fn rust_ident_raw<S>(&self, name: &S) -> Ident
246-
where S: Borrow<str>,
247-
{
245+
pub fn rust_ident_raw(&self, name: &str) -> Ident {
248246
self.ext_cx().ident_of(name.borrow())
249247
}
250248

@@ -912,6 +910,16 @@ impl<'ctx> BindgenContext<'ctx> {
912910
to_iterate: to_iterate,
913911
}
914912
}
913+
914+
/// Convenient method for getting the prefix to use for most traits in
915+
/// codegen depending on the `use_core` option.
916+
pub fn trait_prefix(&self) -> Ident {
917+
if self.options().use_core {
918+
self.rust_ident_raw("core")
919+
} else {
920+
self.rust_ident_raw("std")
921+
}
922+
}
915923
}
916924

917925
/// An iterator over whitelisted items.

src/ir/ty.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -686,19 +686,21 @@ impl Type {
686686
// process of resolving them.
687687
CXType_MemberPointer |
688688
CXType_Pointer => {
689-
let inner =
690-
Item::from_ty_or_ref(ty.pointee_type().unwrap(), location,
691-
parent_id, ctx);
689+
let inner = Item::from_ty_or_ref(ty.pointee_type().unwrap(),
690+
location,
691+
parent_id,
692+
ctx);
692693
TypeKind::Pointer(inner)
693694
}
694695
CXType_BlockPointer => TypeKind::BlockPointer,
695696
// XXX: RValueReference is most likely wrong, but I don't think we
696697
// can even add bindings for that, so huh.
697698
CXType_RValueReference |
698699
CXType_LValueReference => {
699-
let inner =
700-
Item::from_ty_or_ref(ty.pointee_type().unwrap(), location,
701-
parent_id, ctx);
700+
let inner = Item::from_ty_or_ref(ty.pointee_type().unwrap(),
701+
location,
702+
parent_id,
703+
ctx);
702704
TypeKind::Reference(inner)
703705
}
704706
// XXX DependentSizedArray is wrong

src/lib.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,18 @@ impl Builder {
210210
self
211211
}
212212

213+
/// Use core instead of libstd in the generated bindings.
214+
pub fn use_core(mut self) -> Builder {
215+
self.options.use_core = true;
216+
self
217+
}
218+
219+
/// Use the given prefix for the raw types instead of `::std::os::raw`.
220+
pub fn ctypes_prefix<T: Into<String>>(mut self, prefix: T) -> Builder {
221+
self.options.ctypes_prefix = Some(prefix.into());
222+
self
223+
}
224+
213225
/// Generate the Rust bindings using the options built up thus far.
214226
pub fn generate<'ctx>(self) -> Result<Bindings<'ctx>, ()> {
215227
Bindings::generate(self.options, None)
@@ -273,6 +285,12 @@ pub struct BindgenOptions {
273285
/// cannot.
274286
pub unstable_rust: bool,
275287

288+
/// True if we should avoid using libstd to use libcore instead.
289+
pub use_core: bool,
290+
291+
/// An optional prefix for the "raw" types, like `c_int`, `c_void`...
292+
pub ctypes_prefix: Option<String>,
293+
276294
/// True if we should generate constant names that are **directly** under
277295
/// namespaces.
278296
pub namespaced_constants: bool,
@@ -310,6 +328,8 @@ impl Default for BindgenOptions {
310328
derive_debug: true,
311329
enable_cxx_namespaces: false,
312330
unstable_rust: true,
331+
use_core: false,
332+
ctypes_prefix: None,
313333
namespaced_constants: true,
314334
msvc_mangling: false,
315335
raw_lines: vec![],

tests/expectations/tests/no-std.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
#![no_std]
7+
mod libc { pub type c_int = i32; pub enum c_void {} }
8+
9+
#[repr(C)]
10+
#[derive(Debug, Copy)]
11+
pub struct foo {
12+
pub a: libc::c_int,
13+
pub b: libc::c_int,
14+
pub bar: *mut libc::c_void,
15+
}
16+
#[test]
17+
fn bindgen_test_layout_foo() {
18+
assert_eq!(::core::mem::size_of::<foo>() , 16usize);
19+
assert_eq!(::core::mem::align_of::<foo>() , 8usize);
20+
}
21+
impl Clone for foo {
22+
fn clone(&self) -> Self { *self }
23+
}

tests/expectations/tests/use-core.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
extern crate core;
7+
8+
#[repr(C)]
9+
#[derive(Debug, Copy)]
10+
pub struct foo {
11+
pub a: ::std::os::raw::c_int,
12+
pub b: ::std::os::raw::c_int,
13+
pub bar: *mut ::std::os::raw::c_void,
14+
}
15+
#[test]
16+
fn bindgen_test_layout_foo() {
17+
assert_eq!(::core::mem::size_of::<foo>() , 16usize);
18+
assert_eq!(::core::mem::align_of::<foo>() , 8usize);
19+
}
20+
impl Clone for foo {
21+
fn clone(&self) -> Self { *self }
22+
}

tests/headers/no-std.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// bindgen-flags: --ctypes-prefix "libc" --use-core --raw-line "#![no_std]" --raw-line "mod libc { pub type c_int = i32; pub enum c_void {} }"
2+
struct foo {
3+
int a, b;
4+
void* bar;
5+
};

tests/headers/use-core.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// bindgen-flags: --use-core --raw-line "extern crate core;"
2+
3+
struct foo {
4+
int a, b;
5+
void* bar;
6+
};

tests/tools/run-bindgen.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import sys
99
import subprocess
1010
import tempfile
11+
import shlex
1112

1213
BINDGEN_FLAGS_PREFIX = "// bindgen-flags: "
1314

@@ -94,7 +95,7 @@ def get_bindgen_flags(header_path):
9495
with open(header_path) as f:
9596
for line in f:
9697
if line.startswith(BINDGEN_FLAGS_PREFIX):
97-
flags.extend(line.strip().split(BINDGEN_FLAGS_PREFIX)[1].split(" "))
98+
flags.extend(shlex.split(line.strip().split(BINDGEN_FLAGS_PREFIX)[1]))
9899
break
99100

100101
return flags

0 commit comments

Comments
 (0)