MSVC C Integer constants are not supported
Input C/C++ Header
#define POOL_FLAG_REQUIRED_START 0x0000000000000001UI64
Bindgen Invocation
builder
.use_core()
.derive_default(true)
.detect_include_paths(false)
.default_enum_style(bindgen::EnumVariation::ModuleConsts)
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.with_codegen_config(CodegenConfig::VARS)
.generate()
.expect("Bindings should succeed to generate")
.write_to_file(out_path.join("constants.rs"))?
Actual Results
generates empty file
Expected Results
pub const POOL_FLAG_REQUIRED_START: u32 = 1;
It seems like the core issue here is that bindgen does not support msvc's integer constants. Removing the UI64 suffix causes the correct generation. Unfortunately, I do not control the headers I am generating bindings too, so cannot just edit the header to use more standard integer literal declarations.
I think none of us has a windows machine to test this so it will be difficult to track down, it could very well be that clang doesn't support this microsoft-specific syntax and if that's the case there's not much we can do as we only use what clang gives us. Maybe you could find a workaround using ParseCallbacks::str_macro to extract this constant, remove the prefix and parse it accordingly so you can append that to your bindings somehow.
It might require activating MSVC-compatible mode in Clang: https://clang.llvm.org/docs/MSVCCompatibility.html
If that's the case, bindgen passes all the arguments after -- to clang. That might help.
After a little bit more digging the issue here seems to be that cexpr (which we use to evaluate macros) is not able to parse and evaluate the macro definition due to the suffix. As this crate is not being maintained actively there's not much we can do right now about this until the ongoing efforts to migrate to cmacro are merged.
Even then, the workaround using str_macro should work.
Even then, the workaround using
str_macroshould work.
It seems that parsing using str_macro doesn't work. str_macro never gets called for the msvc integer constant. When I run using env_logger to capture the internal bindgen INFO logs, i noticed the following line:
bindgen-0.66.1\ir\ty.rs:1000 [WARN] - invalid type Type(, kind: Invalid, cconv: 100, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None))
Rerunning again with trace, the full stderr output:
build.rs:110 [INFO] - cargo:rerun-if-changed=input.h
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\lib.rs:737 [DEBUG] - Generating bindings, libclang at C:\Program Files\LLVM\bin\libclang.dll
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\lib.rs:875 [DEBUG] - Fixed-up options: BindgenOptions { blocklisted_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, blocklisted_functions: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, blocklisted_items: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, blocklisted_files: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, opaque_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, rustfmt_path: None, depfile: None, allowlisted_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, allowlisted_functions: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, allowlisted_vars: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, allowlisted_files: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, default_enum_style: ModuleConsts, bitfield_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, newtype_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, newtype_global_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, rustified_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, rustified_non_exhaustive_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, constified_enum_modules: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, constified_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, default_macro_constant_type: Unsigned, default_alias_style: TypeAlias, type_alias: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, new_type_alias: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, new_type_alias_deref: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, default_non_copy_union_style: BindgenWrapper, bindgen_wrapper_union: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, manually_drop_union: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, builtins: false, emit_ast: false, emit_ir: false, emit_ir_graphviz: None, enable_cxx_namespaces: false, enable_function_attribute_detection: false, disable_name_namespacing: false, disable_nested_struct_naming: false, disable_header_comment: false, layout_tests: true, impl_debug: false, impl_partialeq: false, derive_copy: true, derive_debug: true, derive_default: true, derive_hash: false, derive_partialord: false, derive_ord: false, derive_partialeq: false, derive_eq: false, use_core: true, ctypes_prefix: None, anon_fields_prefix: "__bindgen_anon_", time_phases: false, convert_floats: true, raw_lines: [], module_lines: {}, input_headers: ["input.h"], clang_args: ["input.h"], input_header_contents: [], parse_callbacks: [CargoCallbacks, MSVCIntegerConstantsCallbacks], codegen_config: CodegenConfig(FUNCTIONS | TYPES | VARS | METHODS | CONSTRUCTORS | DESTRUCTORS), conservative_inline_namespaces: false, generate_comments: true, generate_inline_functions: false, allowlist_recursively: true, objc_extern_crate: false, generate_block: false, generate_cstr: false, block_extern_crate: false, enable_mangling: true, detect_include_paths: false, fit_macro_constants: false, prepend_enum_name: true, rust_target: Stable_1_68, rust_features: RustFeatures { static_lifetime_elision: true, untagged_union: true, associated_const: true, builtin_clone_impls: true, repr_align: true, i128_and_u128: true, must_use_function: true, repr_transparent: true, min_const_fn: true, core_ffi_c_void: true, repr_packed_n: true, maybe_uninit: true, non_exhaustive: true, larger_arrays: true, const_cstr: true, core_ffi_c: true, abi_efiapi: true, thiscall_abi: false, vectorcall_abi: false, c_unwind_abi: false }, untagged_union: true, record_matches: true, size_t_is_usize: true, formatter: Rustfmt, rustfmt_configuration_file: None, no_partialeq_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, no_copy_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, no_debug_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, no_default_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, no_hash_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, must_use_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, array_pointers_in_arguments: false, wasm_import_module_name: None, dynamic_library_name: None, dynamic_link_require_all: false, respect_cxx_access_specs: false, translate_enum_integer_types: false, c_naming: false, force_explicit_padding: false, vtable_generation: false, sort_semantically: false, merge_extern_blocks: false, wrap_unsafe_ops: false, abi_overrides: {}, wrap_static_fns: false, wrap_static_fns_suffix: None, wrap_static_fns_path: None, default_visibility: Public, emit_diagnostics: false }
build.rs:14 [INFO] - [will_parse_macro] name: POOL_FLAG_REQUIRED_START
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\item.rs:1594 [DEBUG] - Item::from_ty_with_id: ItemId(1)
ty = Type(, kind: Invalid, cconv: 100, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)),
location = Cursor(POOL_FLAG_REQUIRED_START kind: macro definition, loc: input.h:1:9, usr: Some("c:input.h@8@macro@POOL_FLAG_REQUIRED_START"))
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\context.rs:1866 [DEBUG] - builtin_or_resolved_ty: Type(, kind: Invalid, cconv: 100, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)), Some(Cursor(POOL_FLAG_REQUIRED_START kind: macro definition, loc: input.h:1:9, usr: Some("c:input.h@8@macro@POOL_FLAG_REQUIRED_START"))), ItemId(1), Some(ItemId(0))
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\context.rs:1916 [DEBUG] - Not resolved, maybe builtin?
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\context.rs:1866 [DEBUG] - builtin_or_resolved_ty: Type(, kind: Invalid, cconv: 100, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)), Some(Cursor(POOL_FLAG_REQUIRED_START kind: macro definition, loc: input.h:1:9, usr: Some("c:input.h@8@macro@POOL_FLAG_REQUIRED_START"))), ItemId(1), Some(ItemId(0))
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\context.rs:1916 [DEBUG] - Not resolved, maybe builtin?
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\ty.rs:699 [DEBUG] - from_clang_ty: ItemId(1), ty: Type(, kind: Invalid, cconv: 100, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)), loc: Cursor(POOL_FLAG_REQUIRED_START kind: macro definition, loc: input.h:1:9, usr: Some("c:input.h@8@macro@POOL_FLAG_REQUIRED_START"))
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\ty.rs:703 [DEBUG] - currently_parsed_types: []
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\ty.rs:1000 [WARN] - invalid type Type(, kind: Invalid, cconv: 100, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None))
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\item.rs:1448 [DEBUG] - Unhandled cursor kind 501: Cursor(POOL_FLAG_REQUIRED_START kind: macro definition, loc: input.h:1:9, usr: Some("c:input.h@8@macro@POOL_FLAG_REQUIRED_START"))
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\context.rs:1050 [DEBUG] - No replacements to process
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\has_vtable.rs:154 [TRACE] - constrain ItemId(0)
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\template_params.rs:527 [TRACE] - constrain ItemId(0)
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\template_params.rs:528 [TRACE] - initially, used set is {}
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\template_params.rs:335 [TRACE] - other item: join with successors' usage
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\template_params.rs:565 [TRACE] - finally, used set is {}
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\derive.rs:664 [TRACE] - constrain: ItemId(0)
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\derive.rs:449 [TRACE] - can derive Debug because there are no members
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\derive.rs:114 [TRACE] - inserting ItemId(0) can_derive<Debug>=Yes
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\derive.rs:664 [TRACE] - constrain: ItemId(0)
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\derive.rs:449 [TRACE] - can derive Default because there are no members
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\derive.rs:114 [TRACE] - inserting ItemId(0) can_derive<Default>=Yes
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\derive.rs:664 [TRACE] - constrain: ItemId(0)
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\derive.rs:449 [TRACE] - can derive Copy because there are no members
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\derive.rs:114 [TRACE] - inserting ItemId(0) can_derive<Copy>=Yes
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\has_type_param_in_array.rs:107 [TRACE] - constrain: ItemId(0)
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\analysis\has_type_param_in_array.rs:118 [TRACE] - not a type; ignoring
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\codegen\mod.rs:4688 [DEBUG] - codegen: BindgenOptions { blocklisted_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, blocklisted_functions: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, blocklisted_items: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, blocklisted_files: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, opaque_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, rustfmt_path: None, depfile: None, allowlisted_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, allowlisted_functions: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, allowlisted_vars: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, allowlisted_files: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, default_enum_style: ModuleConsts, bitfield_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, newtype_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, newtype_global_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, rustified_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, rustified_non_exhaustive_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, constified_enum_modules: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, constified_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, default_macro_constant_type: Unsigned, default_alias_style: TypeAlias, type_alias: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, new_type_alias: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, new_type_alias_deref: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, default_non_copy_union_style: BindgenWrapper, bindgen_wrapper_union: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, manually_drop_union: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, builtins: false, emit_ast: false, emit_ir: false, emit_ir_graphviz: None, enable_cxx_namespaces: false, enable_function_attribute_detection: false, disable_name_namespacing: false, disable_nested_struct_naming: false, disable_header_comment: false, layout_tests: true, impl_debug: false, impl_partialeq: false, derive_copy: true, derive_debug: true, derive_default: true, derive_hash: false, derive_partialord: false, derive_ord: false, derive_partialeq: false, derive_eq: false, use_core: true, ctypes_prefix: None, anon_fields_prefix: "__bindgen_anon_", time_phases: false, convert_floats: true, raw_lines: [], module_lines: {}, input_headers: ["input.h"], clang_args: ["input.h"], input_header_contents: [], parse_callbacks: [CargoCallbacks, MSVCIntegerConstantsCallbacks], codegen_config: CodegenConfig(FUNCTIONS | TYPES | VARS | METHODS | CONSTRUCTORS | DESTRUCTORS), conservative_inline_namespaces: false, generate_comments: true, generate_inline_functions: false, allowlist_recursively: true, objc_extern_crate: false, generate_block: false, generate_cstr: false, block_extern_crate: false, enable_mangling: true, detect_include_paths: false, fit_macro_constants: false, prepend_enum_name: true, rust_target: Stable_1_68, rust_features: RustFeatures { static_lifetime_elision: true, untagged_union: true, associated_const: true, builtin_clone_impls: true, repr_align: true, i128_and_u128: true, must_use_function: true, repr_transparent: true, min_const_fn: true, core_ffi_c_void: true, repr_packed_n: true, maybe_uninit: true, non_exhaustive: true, larger_arrays: true, const_cstr: true, core_ffi_c: true, abi_efiapi: true, thiscall_abi: false, vectorcall_abi: false, c_unwind_abi: false }, untagged_union: true, record_matches: true, size_t_is_usize: true, formatter: Rustfmt, rustfmt_configuration_file: None, no_partialeq_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, no_copy_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, no_debug_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, no_default_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, no_hash_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, must_use_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, array_pointers_in_arguments: false, wasm_import_module_name: None, dynamic_library_name: None, dynamic_link_require_all: false, respect_cxx_access_specs: false, translate_enum_integer_types: false, c_naming: false, force_explicit_padding: false, vtable_generation: false, sort_semantically: false, merge_extern_blocks: false, wrap_unsafe_ops: false, abi_overrides: {}, wrap_static_fns: false, wrap_static_fns_suffix: None, wrap_static_fns_path: None, default_visibility: Public, emit_diagnostics: false }
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\codegen\mod.rs:527 [DEBUG] - <Item as CodeGenerator>::codegen: self = Item { id: ItemId(0), local_id: LazyCell { inner: UnsafeCell { .. } }, next_child_local_id: Cell { value: 1 }, canonical_name: LazyCell { inner: UnsafeCell { .. } }, path_for_allowlisting: LazyCell { inner: UnsafeCell { .. } }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, disallow_debug: false, disallow_default: false, must_use_type: false, visibility_kind: None, accessor_kind: None, constify_enum_variant: false, derives: [] }, parent_id: ItemId(0), kind: Module(Module { name: Some("root"), kind: Normal, children: {} }), location: None }
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\codegen\mod.rs:559 [DEBUG] - <Module as CodeGenerator>::codegen: item = Item { id: ItemId(0), local_id: LazyCell { inner: UnsafeCell { .. } }, next_child_local_id: Cell { value: 1 }, canonical_name: LazyCell { inner: UnsafeCell { .. } }, path_for_allowlisting: LazyCell { inner: UnsafeCell { .. } }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, disallow_debug: false, disallow_default: false, must_use_type: false, visibility_kind: None, accessor_kind: None, constify_enum_variant: false, derives: [] }, parent_id: ItemId(0), kind: Module(Module { name: Some("root"), kind: Normal, children: {} }), location: None }
@wmmc88 does this happens even if you pass the mvsc compatibility flags to clang via bindgen?
@pvdrz yes. I passed in the compatibility flags like this:
.clang_arg("-fms-compatibility")
.clang_arg("-fms-extensions")
.clang_arg("-mms-bitfields")
hmmm... that's annoying. Bindgen is basically saying that it cannot find the type definition for that constant iiuc. My best bet is that you also need to include headers with the definition of __int64 for it to be able to get the type definition.
hmm there doesnt seem to be a header with a definition of __int64. AFAIU __int64 is a compiler intrinsic, so it doen't have a header definition anywhere.
I also tried playing around with making __int64 a typedef of other types(ie. typedef signed long long __int64), but that didnt work. I got the following output:
clang diag: input.hpp:6:26: warning: duplicate 'long long' declaration specifier [-Wduplicate-decl-specifier]
clang diag: input.hpp:6:1: warning: typedef requires a name [-Wmissing-declarations]
build.rs:14 [INFO] - [will_parse_macro] name: POOL_FLAG_REQUIRED_START
C:\Users\melvinwang\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bindgen-0.66.1\ir\ty.rs:1000 [WARN] - invalid type Type(, kind: Invalid, cconv: 100, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None))
From those clang diag msgs, it seems that clang itself actually does recognize and can resolve __int64, but the logic inside bindgen still doesnt