Rust-bindgen: wasm32 target does not generate class functions.

Created on 15 Jun 2017  路  16Comments  路  Source: rust-lang/rust-bindgen

Input C/C++ Header

class Foo {
public:
    void bar();
};

Bindgen Invocation

$ bindgen test.h -- -x c++ -target wasm32

Actual Results

/* automatically generated by rust-bindgen */

#[repr(C)]
#[derive(Debug, Copy)]
pub struct Foo {
    pub _address: u8,
}
#[test]
fn bindgen_test_layout_Foo() {
    assert_eq!(::std::mem::size_of::<Foo>() , 1usize , concat ! (
               "Size of: " , stringify ! ( Foo ) ));
    assert_eq! (::std::mem::align_of::<Foo>() , 1usize , concat ! (
                "Alignment of " , stringify ! ( Foo ) ));
}
impl Clone for Foo {
    fn clone(&self) -> Self { *self }
}

Expected Results

Something similar to the following. Generated with $ bindgen test.h -- -x c++ on x86_64.

/* automatically generated by rust-bindgen */

#[repr(C)]
#[derive(Debug, Copy)]
pub struct Foo {
    pub _address: u8,
}
#[test]
fn bindgen_test_layout_Foo() {
    assert_eq!(::std::mem::size_of::<Foo>() , 1usize , concat ! (
               "Size of: " , stringify ! ( Foo ) ));
    assert_eq! (::std::mem::align_of::<Foo>() , 1usize , concat ! (
                "Alignment of " , stringify ! ( Foo ) ));
}
extern "C" {
    #[link_name = "_ZN3Foo3barEv"]
    pub fn Foo_bar(this: *mut Foo);
}
impl Clone for Foo {
    fn clone(&self) -> Self { *self }
}
impl Foo {
    #[inline]
    pub unsafe fn bar(&mut self) { Foo_bar(self) }
}

RUST_LOG=bindgen Output

INFO:bindgen: Clang Version: clang version 4.0.0 (https://github.com/kripken/emscripten-fastcomp-clang/ ac7f972a03d729dddd614882b634da3884962263) (https://github.com/kripken/emscripten-fastcomp/ 042f4a81b1d95123ef6798ffc1457da3217d44bc) (emscripten 1.37.12 : 1.37.12)
WARN:bindgen: Using clang (4, 0), expected (3, 9)
DEBUG:bindgen::ir::context: BindgenContext::add_item(Item { id: ItemId(0), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Module(Module { name: Some("root"), kind: Normal, children_ids: [] }), detect_derive_debug_cycle: Cell { value: false }, detect_derive_copy_cycle: Cell { value: false } }, declaration: None, loc: None
DEBUG:bindgen::ir::item: Item::from_ty_with_id: ItemId(1)
        ty = Type(Foo, kind: Record, cconv: 100, decl: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo")), canon: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo"))),
        location = Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo"))
DEBUG:bindgen::ir::context: builtin_or_resolved_ty: Type(Foo, kind: Record, cconv: 100, decl: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo")), canon: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo"))), Some(Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo"))), None
DEBUG:bindgen::ir::context: Not resolved, maybe builtin?
DEBUG:bindgen::ir::context: builtin_or_resolved_ty: Type(Foo, kind: Record, cconv: 100, decl: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo")), canon: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo"))), Some(Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo"))), None
DEBUG:bindgen::ir::context: Not resolved, maybe builtin?
DEBUG:bindgen::ir::ty: from_clang_ty: ItemId(1), ty: Type(Foo, kind: Record, cconv: 100, decl: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo")), canon: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo"))), loc: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo"))
DEBUG:bindgen::ir::ty: currently_parsed_types: [PartialType { decl: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo")), id: ItemId(1) }]
DEBUG:bindgen::ir::comp: CompInfo::from_ty(Struct, Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo")))
DEBUG:bindgen::ir::function: Function::parse(Cursor(bar kind: CXXMethod, loc: test.h:3:10, usr: Some("c:@S@Foo@F@bar#")), Type(void (), kind: FunctionProto, cconv: 1, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)))
DEBUG:bindgen::ir::item: Item::from_ty_with_id: ItemId(2)
        ty = Type(void (), kind: FunctionProto, cconv: 1, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)),
        location = Cursor(bar kind: CXXMethod, loc: test.h:3:10, usr: Some("c:@S@Foo@F@bar#"))
DEBUG:bindgen::ir::context: builtin_or_resolved_ty: Type(void (), kind: FunctionProto, cconv: 1, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)), Some(Cursor(bar kind: CXXMethod, loc: test.h:3:10, usr: Some("c:@S@Foo@F@bar#"))), Some(ItemId(1))
DEBUG:bindgen::ir::context: Not resolved, maybe builtin?
DEBUG:bindgen::ir::context: builtin_or_resolved_ty: Type(void (), kind: FunctionProto, cconv: 1, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)), Some(Cursor(bar kind: CXXMethod, loc: test.h:3:10, usr: Some("c:@S@Foo@F@bar#"))), Some(ItemId(1))
DEBUG:bindgen::ir::context: Not resolved, maybe builtin?
DEBUG:bindgen::ir::ty: from_clang_ty: ItemId(2), ty: Type(void (), kind: FunctionProto, cconv: 1, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)), loc: Cursor(bar kind: CXXMethod, loc: test.h:3:10, usr: Some("c:@S@Foo@F@bar#"))
DEBUG:bindgen::ir::ty: currently_parsed_types: [PartialType { decl: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo")), id: ItemId(1) }]
DEBUG:bindgen::ir::function: FunctionSig::from_ty Type(void (), kind: FunctionProto, cconv: 1, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)) Cursor(bar kind: CXXMethod, loc: test.h:3:10, usr: Some("c:@S@Foo@F@bar#"))
DEBUG:bindgen::ir::item: Item::from_ty_with_id: ItemId(3)
        ty = Type(Foo, kind: Record, cconv: 100, decl: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo")), canon: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo"))),
        location = Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo"))
DEBUG:bindgen::ir::context: builtin_or_resolved_ty: Type(Foo, kind: Record, cconv: 100, decl: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo")), canon: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo"))), Some(Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo"))), None
DEBUG:bindgen::ir::context: Not resolved, maybe builtin?
DEBUG:bindgen::ir::item: Avoiding recursion parsing type: Type(Foo, kind: Record, cconv: 100, decl: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo")), canon: Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo")))
DEBUG:bindgen::ir::context: BindgenContext::add_item(Item { id: ItemId(4), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: None, layout: None, kind: Pointer(ItemId(1)), is_const: false, detect_has_vtable_cycle: Cell { value: false } }), detect_derive_debug_cycle: Cell { value: false }, detect_derive_copy_cycle: Cell { value: false } }, declaration: None, loc: None
DEBUG:bindgen::ir::item: from_ty_or_ref_with_id: ItemId(5) Type(void, kind: Void, cconv: 100, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)), Cursor(bar kind: CXXMethod, loc: test.h:3:10, usr: Some("c:@S@Foo@F@bar#")), None
DEBUG:bindgen::ir::context: builtin_or_resolved_ty: Type(void, kind: Void, cconv: 100, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)), Some(Cursor(bar kind: CXXMethod, loc: test.h:3:10, usr: Some("c:@S@Foo@F@bar#"))), None
DEBUG:bindgen::ir::context: Not resolved, maybe builtin?
DEBUG:bindgen::ir::context: add_builtin_item: item = Item { id: ItemId(6), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: Some("void"), layout: None, kind: Void, is_const: false, detect_has_vtable_cycle: Cell { value: false } }), detect_derive_debug_cycle: Cell { value: false }, detect_derive_copy_cycle: Cell { value: false } }
DEBUG:bindgen::ir::item: ItemId(6) already resolved: Cursor(bar kind: CXXMethod, loc: test.h:3:10, usr: Some("c:@S@Foo@F@bar#"))
DEBUG:bindgen::ir::context: BindgenContext::add_item(Item { id: ItemId(2), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(1), kind: Type(Type { name: None, layout: Some(Layout { size: 1, align: 4, packed: false }), kind: Function(FunctionSig { return_type: ItemId(6), argument_types: [(Some("this"), ItemId(4))], is_variadic: false, abi: Known(C) }), is_const: false, detect_has_vtable_cycle: Cell { value: false } }), detect_derive_debug_cycle: Cell { value: false }, detect_derive_copy_cycle: Cell { value: false } }, declaration: Some(Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)), loc: Some(Cursor(bar kind: CXXMethod, loc: test.h:3:10, usr: Some("c:@S@Foo@F@bar#")))
DEBUG:bindgen::ir::context: Invalid declaration Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None) found for type Type { name: None, layout: Some(Layout { size: 1, align: 4, packed: false }), kind: Function(FunctionSig { return_type: ItemId(6), argument_types: [(Some("this"), ItemId(4))], is_variadic: false, abi: Known(C) }), is_const: false, detect_has_vtable_cycle: Cell { value: false } }
DEBUG:bindgen::ir::context: BindgenContext::add_item(Item { id: ItemId(1), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: Some("Foo"), layout: Some(Layout { size: 1, align: 1, packed: false }), kind: Comp(CompInfo { kind: Struct, fields: BeforeComputingBitfieldUnits([]), template_params: [], methods: [], constructors: [], destructor: None, base_members: [], inner_types: [], inner_vars: [], has_vtable: false, has_destructor: false, has_nonempty_base: false, has_non_type_template_params: false, packed: false, found_unknown_attr: false, detect_derive_debug_cycle: Cell { value: false }, detect_derive_default_cycle: Cell { value: false }, detect_has_destructor_cycle: Cell { value: false }, is_forward_declaration: false }), is_const: false, detect_has_vtable_cycle: Cell { value: false } }), detect_derive_debug_cycle: Cell { value: false }, detect_derive_copy_cycle: Cell { value: false } }, declaration: Some(Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo"))), loc: Some(Cursor(Foo kind: ClassDecl, loc: test.h:1:7, usr: Some("c:@S@Foo")))
DEBUG:bindgen::ir::context: No replacements to process
TRACE:bindgen::ir::named: constrain ItemId(6)
TRACE:bindgen::ir::named:   initially, used set is {}
TRACE:bindgen::ir::named:     other item: join with successors' usage
TRACE:bindgen::ir::named:   finally, used set is {}
TRACE:bindgen::ir::named: constrain ItemId(1)
TRACE:bindgen::ir::named:   initially, used set is {}
TRACE:bindgen::ir::named:     other item: join with successors' usage
TRACE:bindgen::ir::named:   finally, used set is {}
TRACE:bindgen::ir::named: constrain ItemId(4)
TRACE:bindgen::ir::named:   initially, used set is {}
TRACE:bindgen::ir::named:     other item: join with successors' usage
TRACE:bindgen::ir::named:       union with ItemId(1)'s usage: []
TRACE:bindgen::ir::named:   finally, used set is {}
TRACE:bindgen::ir::named: constrain ItemId(4)
TRACE:bindgen::ir::named:   initially, used set is {}
TRACE:bindgen::ir::named:     other item: join with successors' usage
TRACE:bindgen::ir::named:       union with ItemId(1)'s usage: []
TRACE:bindgen::ir::named:   finally, used set is {}
TRACE:bindgen::ir::named: constrain ItemId(6)
TRACE:bindgen::ir::named:   initially, used set is {}
TRACE:bindgen::ir::named:     other item: join with successors' usage
TRACE:bindgen::ir::named:   finally, used set is {}
TRACE:bindgen::ir::named: constrain ItemId(2)
TRACE:bindgen::ir::named:   initially, used set is {}
TRACE:bindgen::ir::named:     other item: join with successors' usage
TRACE:bindgen::ir::named:       union with ItemId(6)'s usage: []
TRACE:bindgen::ir::named:       union with ItemId(4)'s usage: []
TRACE:bindgen::ir::named:   finally, used set is {}
TRACE:bindgen::ir::named: constrain ItemId(1)
TRACE:bindgen::ir::named:   initially, used set is {}
TRACE:bindgen::ir::named:     other item: join with successors' usage
TRACE:bindgen::ir::named:   finally, used set is {}
TRACE:bindgen::ir::named: constrain ItemId(0)
TRACE:bindgen::ir::named:   initially, used set is {}
TRACE:bindgen::ir::named:     other item: join with successors' usage
TRACE:bindgen::ir::named:   finally, used set is {}
DEBUG:bindgen::codegen: codegen: BindgenOptions { hidden_types: RegexSet { items: [], set: Some(RegexSet([])) }, opaque_types: RegexSet { items: [], set: Some(RegexSet([])) }, whitelisted_types: RegexSet { items: [], set: Some(RegexSet([])) }, whitelisted_functions: RegexSet { items: [], set: Some(RegexSet([])) }, whitelisted_vars: RegexSet { items: [], set: Some(RegexSet([])) }, bitfield_enums: RegexSet { items: [], set: Some(RegexSet([])) }, constified_enums: RegexSet { items: [], set: Some(RegexSet([])) }, builtins: false, links: [], emit_ast: false, emit_ir: false, emit_ir_graphviz: None, enable_cxx_namespaces: false, disable_name_namespacing: false, layout_tests: true, derive_debug: true, derive_default: false, unstable_rust: true, use_core: false, ctypes_prefix: None, namespaced_constants: true, msvc_mangling: false, convert_floats: true, raw_lines: [], clang_args: ["-x", "c++", "-target", "wasm32", "-isystem", "/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0", "-isystem", "/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/x86_64-linux-gnu/c++/5.4.0", "-isystem", "/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/backward", "-isystem", "/usr/local/include", "-isystem", "/home/kkim/fips-projects/fips-sdks/linux/emsdk-portable/clang/fastcomp/build_incoming_64/bin/../lib/clang/4.0.0/include", "-isystem", "/usr/include/x86_64-linux-gnu", "-isystem", "/usr/include", "test.h"], input_header: Some("test.h"), input_unsaved_files: [], dummy_uses: None, parse_callbacks: None, codegen_config: CodegenConfig { functions: true, types: true, vars: true, methods: true, constructors: true, destructors: true }, conservative_inline_namespaces: false, generate_comments: true, generate_inline_functions: false, whitelist_recursively: true, objc_extern_crate: false, enable_mangling: true, prepend_enum_name: true }
DEBUG:bindgen::codegen: <Item as CodeGenerator>::codegen: self = Item { id: ItemId(0), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Module(Module { name: Some("root"), kind: Normal, children_ids: [ItemId(4), ItemId(1)] }), detect_derive_debug_cycle: Cell { value: false }, detect_derive_copy_cycle: Cell { value: false } }
DEBUG:bindgen::codegen: <Module as CodeGenerator>::codegen: item = Item { id: ItemId(0), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Module(Module { name: Some("root"), kind: Normal, children_ids: [ItemId(4), ItemId(1)] }), detect_derive_debug_cycle: Cell { value: false }, detect_derive_copy_cycle: Cell { value: false } }
DEBUG:bindgen::codegen: <Item as CodeGenerator>::codegen: self = Item { id: ItemId(4), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: None, layout: None, kind: Pointer(ItemId(1)), is_const: false, detect_has_vtable_cycle: Cell { value: false } }), detect_derive_debug_cycle: Cell { value: false }, detect_derive_copy_cycle: Cell { value: false } }
DEBUG:bindgen::codegen: <Type as CodeGenerator>::codegen: item = Item { id: ItemId(4), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: None, layout: None, kind: Pointer(ItemId(1)), is_const: false, detect_has_vtable_cycle: Cell { value: false } }), detect_derive_debug_cycle: Cell { value: false }, detect_derive_copy_cycle: Cell { value: false } }
DEBUG:bindgen::codegen: <Item as CodeGenerator>::codegen: self = Item { id: ItemId(1), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: Some("Foo"), layout: Some(Layout { size: 1, align: 1, packed: false }), kind: Comp(CompInfo { kind: Struct, fields: AfterComputingBitfieldUnits([]), template_params: [], methods: [], constructors: [], destructor: None, base_members: [], inner_types: [], inner_vars: [], has_vtable: false, has_destructor: false, has_nonempty_base: false, has_non_type_template_params: false, packed: false, found_unknown_attr: false, detect_derive_debug_cycle: Cell { value: false }, detect_derive_default_cycle: Cell { value: false }, detect_has_destructor_cycle: Cell { value: false }, is_forward_declaration: false }), is_const: false, detect_has_vtable_cycle: Cell { value: false } }), detect_derive_debug_cycle: Cell { value: false }, detect_derive_copy_cycle: Cell { value: false } }
DEBUG:bindgen::codegen: <Type as CodeGenerator>::codegen: item = Item { id: ItemId(1), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: Some("Foo"), layout: Some(Layout { size: 1, align: 1, packed: false }), kind: Comp(CompInfo { kind: Struct, fields: AfterComputingBitfieldUnits([]), template_params: [], methods: [], constructors: [], destructor: None, base_members: [], inner_types: [], inner_vars: [], has_vtable: false, has_destructor: false, has_nonempty_base: false, has_non_type_template_params: false, packed: false, found_unknown_attr: false, detect_derive_debug_cycle: Cell { value: false }, detect_derive_default_cycle: Cell { value: false }, detect_has_destructor_cycle: Cell { value: false }, is_forward_declaration: false }), is_const: false, detect_has_vtable_cycle: Cell { value: false } }), detect_derive_debug_cycle: Cell { value: false }, detect_derive_copy_cycle: Cell { value: false } }
DEBUG:bindgen::codegen: <CompInfo as CodeGenerator>::codegen: item = Item { id: ItemId(1), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: Some("Foo"), layout: Some(Layout { size: 1, align: 1, packed: false }), kind: Comp(CompInfo { kind: Struct, fields: AfterComputingBitfieldUnits([]), template_params: [], methods: [], constructors: [], destructor: None, base_members: [], inner_types: [], inner_vars: [], has_vtable: false, has_destructor: false, has_nonempty_base: false, has_non_type_template_params: false, packed: false, found_unknown_attr: false, detect_derive_debug_cycle: Cell { value: false }, detect_derive_default_cycle: Cell { value: false }, detect_has_destructor_cycle: Cell { value: false }, is_forward_declaration: false }), is_const: false, detect_has_vtable_cycle: Cell { value: false } }), detect_derive_debug_cycle: Cell { value: false }, detect_derive_copy_cycle: Cell { value: false } }
/* automatically generated by rust-bindgen */

#[repr(C)]
#[derive(Debug, Copy)]
pub struct Foo {
    pub _address: u8,
}
#[test]
fn bindgen_test_layout_Foo() {
    assert_eq!(::std::mem::size_of::<Foo>() , 1usize , concat ! (
               "Size of: " , stringify ! ( Foo ) ));
    assert_eq! (::std::mem::align_of::<Foo>() , 1usize , concat ! (
                "Alignment of " , stringify ! ( Foo ) ));
}
impl Clone for Foo {
    fn clone(&self) -> Self { *self }
}

A-libclang bug

All 16 comments

Note: -target asmjs-unknown-emscripten seems to be fine. I'm not sure if the correct target string for wasm is -target wasm32...

I think the target should be wasm32-unknown-emscripten, but I can repro with that anyway.

So this is because clang reports a CXVisibility_Hidden for the method with the wasm target, but not with any other, so we bail out at https://github.com/servo/rust-bindgen/blob/master/src/ir/function.rs#L372.

It's unclear to me whether that's a bug on clang itself, or the symbol is really unusable. Commenting out that check makes the file getting generated properly.

@kkimdev, could you try with that check commented out and see if you can call that method or something? We can whitelist the wasm target, I guess, but I'm not super-happy about it.

@emilio Yes I commented out them and now I can link and call the method. I guess we should file a bug to libclang? Below are the steps to reproduce:

test.hpp

int add_one(int x);

test.cpp

int add_one(int x) { return x + 1; }

main.rs

mod test;

fn main() {
    unsafe {
        let x = test::add_one(3);
        println!("{}", x);
    }
}

Commands

rustc main.rs --target=wasm32-unknown-emscripten -o main.bc
bindgen test.hpp -o test.rs -- -target wasm32
emcc test.cpp -o test.bc
emcc main.bc test.bc -o test.html

python -m SimpleHTTPServer
# Navigate http://localhost:8000/test.html

Yes, a bug against llvm or https://github.com/kripken/emscripten would be the best way to proceed I think. I'm not sure where the bug lies exactly, I could dig next week (busy today).

Any update on this? I'm currently facing the same problem actually.

I'm pretty sure this is not our bug, but I can land a workaround, I guess...

The problem here may be that clang seems to be assuming -fvisibility=hidden when building wasm32 targets. This does seem to be common practice in the wasm world, as you can then control what gets exported by setting the visibility attribute.

A workaround for this is to explicitly set the clang arg -fvisibility=default which eliminates this issue at the cost of exporting a large number of symbols to wasm.

You can do this from a typical build.rs script by modifying it to include something like:

    let bindings = bindgen::Builder::default()
        .header("wrapper.h")
        .clang_arg("-fvisibility=default")
        .generate()
        .expect("Unable to generate bindings");

Alternatively, if you have control over the C headers that you are running bindgen on, you could set an explicit visibility for those functions that you want to export to wasm:

#define WASM_EXPORT __attribute__ ((visibility("default")))

WASM_EXPORT void wasm_test(void);

At which point the wasm_test symbol should be included in the bindings generated by rust-bindgen regardless of the setting of -fvisibility

Ah, I just poked at #1681 before reading this again, and was going to comment that indeed, the best alternative is passing -fvisibility=default to clang.

This is not a bindgen bug, so closing. But maybe some docs on this would be useful in the book? A PR for that would be appreciated :)

I believe that there may be some lingering issue (that may be related to bindgen). It looks like bindgen prepends \u{1} in front of the link_name, but the wasm build doesn't expect that (I think?). Manually removing the \u{1} from the generated output allows the program to link successfully.

Edit: I forgot to say thank you @emilio for finding this -fvisibility=default workaround!! It helps immensely!

What issue does the wasm build have? Could you file a new issue with a detailed error message?

That is needed to avoid mangling by rustc itself, but maybe wasm is undoing that? There's --distrust-clang-mangling for that, I'd think, but that is a bit of a hammer.

I get a lot of ....rcgu.bc.z is not valid according to llvm-nm, cannot link, then:

warning: unexpected number of arguments 5 in call to '__gxx_personality_v0', should be 1
error: undefined symbol: __Z10Paths_ctorv
warning: To disable errors for undefined symbols use `-s ERROR_ON_UNDEFINED_SYMBOLS=0`
error: undefined symbol: __Z11Path_appendRNSt3__26vectorIN10ClipperLib8IntPointENS_9allocatorIS2_EEEERKS2_
error: undefined symbol: __Z13Path_destructRNSt3__26vectorIN10ClipperLib8IntPointENS_9allocatorIS2_EEEE
... truncated

I am building my C++ code using the cc crate, which outputs a .o file that contains the symbols that do not contain the first character (underscore?). I.e., I have _Z10Paths_ctorv in the actual object file, but __Z10Paths_ctorv in the error message.

@tangmi Have you found a solution for your problem? I'm having the same issue.

Apologies because my memory is a bit hazy, I believe I just added a part to my build.rs to remove the \u{1} (I can't remember if it actually turns into a _?)

@tangmi Thank you for the quick reply. I managed to compile using Rust nightly. 馃

I think my case was some (non-bindgen) part of the compile chain wasn't respecting the fact that LLVM uses \u{1} (I believe it appears as \01 in clang source) to indicate something about name mangling (that names are already mangled?)

Maybe this has been fixed in a newer version of clang? I'm glad nightly works for you, I hope it's a sufficient solution for you!

Was this page helpful?
0 / 5 - 0 ratings