Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasm32 target does not generate class functions. #751

Closed
kkimdev opened this issue Jun 15, 2017 · 16 comments
Closed

wasm32 target does not generate class functions. #751

kkimdev opened this issue Jun 15, 2017 · 16 comments

Comments

@kkimdev
Copy link

kkimdev commented Jun 15, 2017

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 }
}
@kkimdev
Copy link
Author

kkimdev commented Jun 15, 2017

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

@emilio
Copy link
Contributor

emilio commented Jun 15, 2017

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

@emilio emilio added the bug label Jun 15, 2017
@emilio
Copy link
Contributor

emilio commented Jun 15, 2017

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.

@kkimdev
Copy link
Author

kkimdev commented Jun 15, 2017

@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

@emilio
Copy link
Contributor

emilio commented Jun 16, 2017

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).

@klefevre
Copy link

klefevre commented Jul 6, 2017

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

@emilio
Copy link
Contributor

emilio commented Jul 7, 2017

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

@jrandall
Copy link

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

@emilio
Copy link
Contributor

emilio commented Nov 19, 2019

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 :)

@emilio emilio closed this as completed Nov 19, 2019
@tangmi
Copy link

tangmi commented Nov 20, 2019

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!

@emilio
Copy link
Contributor

emilio commented Nov 20, 2019

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.

@tangmi
Copy link

tangmi commented Nov 20, 2019

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.

@rafaelcaricio
Copy link

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

@tangmi
Copy link

tangmi commented Sep 21, 2020

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 _?)

@rafaelcaricio
Copy link

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

@tangmi
Copy link

tangmi commented Sep 21, 2020

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants