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

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 }
}

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 16 (6 by maintainers)

Commits related to this issue

Most upvoted comments

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

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!

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

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.

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!