1use bindgen::callbacks::TypeKind; 2use bindgen::{ 3 builder, AliasVariation, Builder, CodegenConfig, EnumVariation, 4 MacroTypeVariation, NonCopyUnionStyle, RegexSet, RustTarget, 5 DEFAULT_ANON_FIELDS_PREFIX, RUST_TARGET_STRINGS, 6}; 7use clap::Parser; 8use std::fs::File; 9use std::io::{self, Error, ErrorKind}; 10use std::path::PathBuf; 11 12fn rust_target_help() -> String { 13 format!( 14 "Version of the Rust compiler to target. Valid options are: {:?}. Defaults to {:?}.", 15 RUST_TARGET_STRINGS, 16 String::from(RustTarget::default()) 17 ) 18} 19 20fn parse_codegen_config(what_to_generate: &str) -> io::Result<CodegenConfig> { 21 let mut config = CodegenConfig::empty(); 22 for what in what_to_generate.split(',') { 23 match what { 24 "functions" => config.insert(CodegenConfig::FUNCTIONS), 25 "types" => config.insert(CodegenConfig::TYPES), 26 "vars" => config.insert(CodegenConfig::VARS), 27 "methods" => config.insert(CodegenConfig::METHODS), 28 "constructors" => config.insert(CodegenConfig::CONSTRUCTORS), 29 "destructors" => config.insert(CodegenConfig::DESTRUCTORS), 30 otherwise => { 31 return Err(Error::new( 32 ErrorKind::Other, 33 format!("Unknown generate item: {}", otherwise), 34 )); 35 } 36 } 37 } 38 39 Ok(config) 40} 41 42#[derive(Parser, Debug)] 43#[clap( 44 about = "Generates Rust bindings from C/C++ headers.", 45 override_usage = "bindgen [FLAGS] [OPTIONS] [HEADER] -- [CLANG_ARGS]...", 46 trailing_var_arg = true 47)] 48struct BindgenCommand { 49 /// C or C++ header file. 50 header: Option<String>, 51 /// Path to write depfile to. 52 #[arg(long)] 53 depfile: Option<String>, 54 /// The default style of code used to generate enums. 55 #[arg(long, value_name = "VARIANT")] 56 default_enum_style: Option<EnumVariation>, 57 /// Mark any enum whose name matches <REGEX> as a set of bitfield flags. 58 #[arg(long, value_name = "REGEX")] 59 bitfield_enum: Vec<String>, 60 /// Mark any enum whose name matches <REGEX> as a newtype. 61 #[arg(long, value_name = "REGEX")] 62 newtype_enum: Vec<String>, 63 /// Mark any enum whose name matches <REGEX> as a global newtype. 64 #[arg(long, value_name = "REGEX")] 65 newtype_global_enum: Vec<String>, 66 /// Mark any enum whose name matches <REGEX> as a Rust enum. 67 #[arg(long, value_name = "REGEX")] 68 rustified_enum: Vec<String>, 69 /// Mark any enum whose name matches <REGEX> as a series of constants. 70 #[arg(long, value_name = "REGEX")] 71 constified_enum: Vec<String>, 72 /// Mark any enum whose name matches <regex> as a module of constants. 73 #[arg(long, value_name = "REGEX")] 74 constified_enum_module: Vec<String>, 75 /// The default signed/unsigned type for C macro constants. 76 #[arg(long, value_name = "VARIANT")] 77 default_macro_constant_type: Option<MacroTypeVariation>, 78 /// The default style of code used to generate typedefs. 79 #[arg(long, value_name = "VARIANT")] 80 default_alias_style: Option<AliasVariation>, 81 /// Mark any typedef alias whose name matches <REGEX> to use normal type aliasing. 82 #[arg(long, value_name = "REGEX")] 83 normal_alias: Vec<String>, 84 /// Mark any typedef alias whose name matches <REGEX> to have a new type generated for it. 85 #[arg(long, value_name = "REGEX")] 86 new_type_alias: Vec<String>, 87 /// Mark any typedef alias whose name matches <REGEX> to have a new type with Deref and DerefMut to the inner type. 88 #[arg(long, value_name = "REGEX")] 89 new_type_alias_deref: Vec<String>, 90 /// The default style of code used to generate unions with non-Copy members. Note that ManuallyDrop was first stabilized in Rust 1.20.0. 91 #[arg(long, value_name = "STYLE")] 92 default_non_copy_union_style: Option<NonCopyUnionStyle>, 93 /// Mark any union whose name matches <REGEX> and who has a non-Copy member to use a bindgen-generated wrapper for fields. 94 #[arg(long, value_name = "REGEX")] 95 bindgen_wrapper_union: Vec<String>, 96 /// Mark any union whose name matches <REGEX> and who has a non-Copy member to use ManuallyDrop (stabilized in Rust 1.20.0) for fields. 97 #[arg(long, value_name = "REGEX")] 98 manually_drop_union: Vec<String>, 99 /// Mark <TYPE> as hidden. 100 #[arg(long, value_name = "TYPE")] 101 blocklist_type: Vec<String>, 102 /// Mark <FUNCTION> as hidden. 103 #[arg(long, value_name = "FUNCTION")] 104 blocklist_function: Vec<String>, 105 /// Mark <ITEM> as hidden. 106 #[arg(long, value_name = "ITEM")] 107 blocklist_item: Vec<String>, 108 /// Mark <FILE> as hidden. 109 #[arg(long, value_name = "FILE")] 110 blocklist_file: Vec<String>, 111 /// Avoid generating layout tests for any type. 112 #[arg(long)] 113 no_layout_tests: bool, 114 /// Avoid deriving Copy on any type. 115 #[arg(long)] 116 no_derive_copy: bool, 117 /// Avoid deriving Debug on any type. 118 #[arg(long)] 119 no_derive_debug: bool, 120 /// Avoid deriving Default on any type. 121 #[arg(long, hide = true)] 122 no_derive_default: bool, 123 /// Create a Debug implementation if it cannot be derived automatically. 124 #[arg(long)] 125 impl_debug: bool, 126 /// Create a PartialEq implementation if it cannot be derived automatically. 127 #[arg(long)] 128 impl_partialeq: bool, 129 /// Derive Default on any type. 130 #[arg(long)] 131 with_derive_default: bool, 132 /// Derive Hash on any type.docstring 133 #[arg(long)] 134 with_derive_hash: bool, 135 /// Derive PartialEq on any type. 136 #[arg(long)] 137 with_derive_partialeq: bool, 138 /// Derive PartialOrd on any type. 139 #[arg(long)] 140 with_derive_partialord: bool, 141 /// Derive Eq on any type. 142 #[arg(long)] 143 with_derive_eq: bool, 144 /// Derive Ord on any type. 145 #[arg(long)] 146 with_derive_ord: bool, 147 /// Avoid including doc comments in the output, see: https://github.com/rust-lang/rust-bindgen/issues/426 148 #[arg(long)] 149 no_doc_comments: bool, 150 /// Disable allowlisting types recursively. This will cause bindgen to emit Rust code that won't compile! See the `bindgen::Builder::allowlist_recursively` method's documentation for details. 151 #[arg(long)] 152 no_recursive_allowlist: bool, 153 /// Use extern crate instead of use for objc. 154 #[arg(long)] 155 objc_extern_crate: bool, 156 /// Generate block signatures instead of void pointers. 157 #[arg(long)] 158 generate_block: bool, 159 /// Use extern crate instead of use for block. 160 #[arg(long)] 161 block_extern_crate: bool, 162 /// Do not trust the libclang-provided mangling 163 #[arg(long)] 164 distrust_clang_mangling: bool, 165 /// Output bindings for builtin definitions, e.g. __builtin_va_list. 166 #[arg(long)] 167 builtins: bool, 168 /// Use the given prefix before raw types instead of ::std::os::raw. 169 #[arg(long, value_name = "PREFIX")] 170 ctypes_prefix: Option<String>, 171 /// Use the given prefix for anonymous fields. 172 #[arg(long, default_value = DEFAULT_ANON_FIELDS_PREFIX, value_name = "PREFIX")] 173 anon_fields_prefix: String, 174 /// Time the different bindgen phases and print to stderr 175 #[arg(long)] 176 time_phases: bool, 177 /// Output the Clang AST for debugging purposes. 178 #[arg(long)] 179 emit_clang_ast: bool, 180 /// Output our internal IR for debugging purposes. 181 #[arg(long)] 182 emit_ir: bool, 183 /// Dump graphviz dot file. 184 #[arg(long, value_name = "PATH")] 185 emit_ir_graphviz: Option<String>, 186 /// Enable support for C++ namespaces. 187 #[arg(long)] 188 enable_cxx_namespaces: bool, 189 /// Disable namespacing via mangling, causing bindgen to generate names like `Baz` instead of `foo_bar_Baz` for an input name `foo::bar::Baz`. 190 #[arg(long)] 191 disable_name_namespacing: bool, 192 /// Disable nested struct naming, causing bindgen to generate names like `bar` instead of `foo_bar` for a nested definition `struct foo { struct bar { } b; };`. 193 #[arg(long)] 194 disable_nested_struct_naming: bool, 195 /// Disable support for native Rust unions. 196 #[arg(long)] 197 disable_untagged_union: bool, 198 /// Suppress insertion of bindgen's version identifier into generated bindings. 199 #[arg(long)] 200 disable_header_comment: bool, 201 /// Do not generate bindings for functions or methods. This is useful when you only care about struct layouts.docstring 202 #[arg(long)] 203 ignore_functions: bool, 204 /// Generate only given items, split by commas. Valid values are `functions`,`types`, `vars`, `methods`, `constructors` and `destructors`. 205 #[arg(long, value_parser = parse_codegen_config)] 206 generate: Option<CodegenConfig>, 207 /// Do not generate bindings for methods. 208 #[arg(long)] 209 ignore_methods: bool, 210 /// Do not automatically convert floats to f32/f64. 211 #[arg(long)] 212 no_convert_floats: bool, 213 /// Do not prepend the enum name to constant or newtype variants. 214 #[arg(long)] 215 no_prepend_enum_name: bool, 216 /// Do not try to detect default include paths 217 #[arg(long)] 218 no_include_path_detection: bool, 219 /// Try to fit macro constants into types smaller than u32/i32 220 #[arg(long)] 221 fit_macro_constant_types: bool, 222 /// Mark <TYPE> as opaque. 223 #[arg(long, value_name = "TYPE")] 224 opaque_type: Vec<String>, 225 /// Write Rust bindings to <OUTPUT>. 226 #[arg(long, short, value_name = "OUTPUT")] 227 output: Option<String>, 228 /// Add a raw line of Rust code at the beginning of output. 229 #[arg(long)] 230 raw_line: Vec<String>, 231 /// Add a raw line of Rust code to a given module. 232 #[arg(long, number_of_values = 2, value_names = ["MODULE-NAME", "RAW-LINE"])] 233 module_raw_line: Vec<String>, 234 #[arg(long, help = rust_target_help())] 235 rust_target: Option<RustTarget>, 236 /// Use types from Rust core instead of std. 237 #[arg(long)] 238 use_core: bool, 239 /// Conservatively generate inline namespaces to avoid name conflicts. 240 #[arg(long)] 241 conservative_inline_namespaces: bool, 242 /// MSVC C++ ABI mangling. DEPRECATED: Has no effect. 243 #[arg(long)] 244 use_msvc_mangling: bool, 245 /// Allowlist all the free-standing functions matching <REGEX>. Other non-allowlisted functions will not be generated. 246 #[arg(long, value_name = "REGEX")] 247 allowlist_function: Vec<String>, 248 /// Generate inline functions. 249 #[arg(long)] 250 generate_inline_functions: bool, 251 /// Only generate types matching <REGEX>. Other non-allowlisted types will not be generated. 252 #[arg(long, value_name = "REGEX")] 253 allowlist_type: Vec<String>, 254 /// Allowlist all the free-standing variables matching <REGEX>. Other non-allowlisted variables will not be generated. 255 #[arg(long, value_name = "REGEX")] 256 allowlist_var: Vec<String>, 257 /// Allowlist all contents of <PATH>. 258 #[arg(long, value_name = "PATH")] 259 allowlist_file: Vec<String>, 260 /// Print verbose error messages. 261 #[arg(long)] 262 verbose: bool, 263 /// Preprocess and dump the input header files to disk. Useful when debugging bindgen, using C-Reduce, or when filing issues. The resulting file will be named something like `__bindgen.i` or `__bindgen.ii`. 264 #[arg(long)] 265 dump_preprocessed_input: bool, 266 /// Do not record matching items in the regex sets. This disables reporting of unused items. 267 #[arg(long)] 268 no_record_matches: bool, 269 /// Ignored - this is enabled by default. 270 #[arg(long = "size_t-is-usize")] 271 size_t_is_usize: bool, 272 /// Do not bind size_t as usize (useful on platforms where those types are incompatible). 273 #[arg(long = "no-size_t-is-usize")] 274 no_size_t_is_usize: bool, 275 /// Do not format the generated bindings with rustfmt. 276 #[arg(long)] 277 no_rustfmt_bindings: bool, 278 /// Format the generated bindings with rustfmt. DEPRECATED: --rustfmt-bindings is now enabled by default. Disable with --no-rustfmt-bindings. 279 #[arg(long)] 280 rustfmt_bindings: bool, 281 /// The absolute path to the rustfmt configuration file. The configuration file will be used for formatting the bindings. This parameter is incompatible with --no-rustfmt-bindings. 282 #[arg(long, value_name = "PATH")] 283 rustfmt_configuration_file: Option<String>, 284 /// Avoid deriving PartialEq for types matching <REGEX>. 285 #[arg(long, value_name = "REGEX")] 286 no_partialeq: Vec<String>, 287 /// Avoid deriving Copy for types matching <REGEX>. 288 #[arg(long, value_name = "REGEX")] 289 no_copy: Vec<String>, 290 /// Avoid deriving Debug for types matching <REGEX>. 291 #[arg(long, value_name = "REGEX")] 292 no_debug: Vec<String>, 293 /// Avoid deriving/implementing Default for types matching <REGEX>. 294 #[arg(long, value_name = "REGEX")] 295 no_default: Vec<String>, 296 /// Avoid deriving Hash for types matching <REGEX>. 297 #[arg(long, value_name = "REGEX")] 298 no_hash: Vec<String>, 299 /// Add #[must_use] annotation to types matching <REGEX>. 300 #[arg(long, value_name = "REGEX")] 301 must_use_type: Vec<String>, 302 /// Enables detecting unexposed attributes in functions (slow). Used to generate #[must_use] annotations. 303 #[arg(long)] 304 enable_function_attribute_detection: bool, 305 /// Use `*const [T; size]` instead of `*const T` for C arrays 306 #[arg(long)] 307 use_array_pointers_in_arguments: bool, 308 /// The name to be used in a #[link(wasm_import_module = ...)] statement 309 #[arg(long, value_name = "NAME")] 310 wasm_import_module_name: Option<String>, 311 /// Use dynamic loading mode with the given library name. 312 #[arg(long, value_name = "NAME")] 313 dynamic_loading: Option<String>, 314 /// Require successful linkage to all functions in the library. 315 #[arg(long)] 316 dynamic_link_require_all: bool, 317 /// Makes generated bindings `pub` only for items if the items are publically accessible in C++. 318 #[arg(long)] 319 respect_cxx_access_specs: bool, 320 /// Always translate enum integer types to native Rust integer types. 321 #[arg(long)] 322 translate_enum_integer_types: bool, 323 /// Generate types with C style naming. 324 #[arg(long)] 325 c_naming: bool, 326 /// Always output explicit padding fields. 327 #[arg(long)] 328 explicit_padding: bool, 329 /// Enables generation of vtable functions. 330 #[arg(long)] 331 vtable_generation: bool, 332 /// Enables sorting of code generation in a predefined manner. 333 #[arg(long)] 334 sort_semantically: bool, 335 /// Deduplicates extern blocks. 336 #[arg(long)] 337 merge_extern_blocks: bool, 338 /// Overrides the ABI of functions matching <regex>. The <OVERRIDE> value must be of the shape <REGEX>=<ABI> where <ABI> can be one of C, stdcall, fastcall, thiscall, aapcs, win64 or C-unwind. 339 #[arg(long, value_name = "OVERRIDE")] 340 override_abi: Vec<String>, 341 /// Wrap unsafe operations in unsafe blocks. 342 #[arg(long)] 343 wrap_unsafe_ops: bool, 344 /// Derive custom traits on any kind of type. The <CUSTOM> value must be of the shape <REGEX>=<DERIVE> where <DERIVE> is a coma-separated list of derive macros. 345 #[arg(long, value_name = "CUSTOM")] 346 with_derive_custom: Vec<String>, 347 /// Derive custom traits on a `struct`. The <CUSTOM> value must be of the shape <REGEX>=<DERIVE> where <DERIVE> is a coma-separated list of derive macros. 348 #[arg(long, value_name = "CUSTOM")] 349 with_derive_custom_struct: Vec<String>, 350 /// Derive custom traits on an `enum. The <CUSTOM> value must be of the shape <REGEX>=<DERIVE> where <DERIVE> is a coma-separated list of derive macros. 351 #[arg(long, value_name = "CUSTOM")] 352 with_derive_custom_enum: Vec<String>, 353 /// Derive custom traits on a `union`. The <CUSTOM> value must be of the shape <REGEX>=<DERIVE> where <DERIVE> is a coma-separated list of derive macros. 354 #[arg(long, value_name = "CUSTOM")] 355 with_derive_custom_union: Vec<String>, 356 /// Generate wrappers for `static` and `static inline` functions. 357 #[arg(long, requires = "experimental")] 358 wrap_static_fns: bool, 359 /// Sets the path for the source file that must be created due to the presence of `static` and 360 /// `static inline` functions. 361 #[arg(long, requires = "experimental", value_name = "PATH")] 362 wrap_static_fns_path: Option<PathBuf>, 363 /// Sets the suffix added to the extern wrapper functions generated for `static` and `static 364 /// inline` functions. 365 #[arg(long, requires = "experimental", value_name = "SUFFIX")] 366 wrap_static_fns_suffix: Option<String>, 367 /// Enables experimental features. 368 #[arg(long)] 369 experimental: bool, 370 /// Prints the version, and exits 371 #[arg(short = 'V', long)] 372 version: bool, 373 /// Arguments to be passed straight through to clang. 374 clang_args: Vec<String>, 375} 376 377/// Construct a new [`Builder`](./struct.Builder.html) from command line flags. 378pub fn builder_from_flags<I>( 379 args: I, 380) -> Result<(Builder, Box<dyn io::Write>, bool), io::Error> 381where 382 I: Iterator<Item = String>, 383{ 384 let command = BindgenCommand::parse_from(args); 385 386 let BindgenCommand { 387 header, 388 depfile, 389 default_enum_style, 390 bitfield_enum, 391 newtype_enum, 392 newtype_global_enum, 393 rustified_enum, 394 constified_enum, 395 constified_enum_module, 396 default_macro_constant_type, 397 default_alias_style, 398 normal_alias, 399 new_type_alias, 400 new_type_alias_deref, 401 default_non_copy_union_style, 402 bindgen_wrapper_union, 403 manually_drop_union, 404 blocklist_type, 405 blocklist_function, 406 blocklist_item, 407 blocklist_file, 408 no_layout_tests, 409 no_derive_copy, 410 no_derive_debug, 411 no_derive_default, 412 impl_debug, 413 impl_partialeq, 414 with_derive_default, 415 with_derive_hash, 416 with_derive_partialeq, 417 with_derive_partialord, 418 with_derive_eq, 419 with_derive_ord, 420 no_doc_comments, 421 no_recursive_allowlist, 422 objc_extern_crate, 423 generate_block, 424 block_extern_crate, 425 distrust_clang_mangling, 426 builtins, 427 ctypes_prefix, 428 anon_fields_prefix, 429 time_phases, 430 emit_clang_ast, 431 emit_ir, 432 emit_ir_graphviz, 433 enable_cxx_namespaces, 434 disable_name_namespacing, 435 disable_nested_struct_naming, 436 disable_untagged_union, 437 disable_header_comment, 438 ignore_functions, 439 generate, 440 ignore_methods, 441 no_convert_floats, 442 no_prepend_enum_name, 443 no_include_path_detection, 444 fit_macro_constant_types, 445 opaque_type, 446 output, 447 raw_line, 448 module_raw_line, 449 rust_target, 450 use_core, 451 conservative_inline_namespaces, 452 use_msvc_mangling: _, 453 allowlist_function, 454 generate_inline_functions, 455 allowlist_type, 456 allowlist_var, 457 allowlist_file, 458 verbose, 459 dump_preprocessed_input, 460 no_record_matches, 461 size_t_is_usize: _, 462 no_size_t_is_usize, 463 no_rustfmt_bindings, 464 rustfmt_bindings: _, 465 rustfmt_configuration_file, 466 no_partialeq, 467 no_copy, 468 no_debug, 469 no_default, 470 no_hash, 471 must_use_type, 472 enable_function_attribute_detection, 473 use_array_pointers_in_arguments, 474 wasm_import_module_name, 475 dynamic_loading, 476 dynamic_link_require_all, 477 respect_cxx_access_specs, 478 translate_enum_integer_types, 479 c_naming, 480 explicit_padding, 481 vtable_generation, 482 sort_semantically, 483 merge_extern_blocks, 484 override_abi, 485 wrap_unsafe_ops, 486 with_derive_custom, 487 with_derive_custom_struct, 488 with_derive_custom_enum, 489 with_derive_custom_union, 490 wrap_static_fns, 491 wrap_static_fns_path, 492 wrap_static_fns_suffix, 493 experimental: _, 494 version, 495 clang_args, 496 } = command; 497 498 if version { 499 println!( 500 "bindgen {}", 501 option_env!("CARGO_PKG_VERSION").unwrap_or("unknown") 502 ); 503 if verbose { 504 println!("Clang: {}", bindgen::clang_version().full); 505 } 506 std::process::exit(0); 507 } 508 509 let mut builder = builder(); 510 511 if let Some(header) = header { 512 builder = builder.header(header); 513 } else { 514 return Err(Error::new(ErrorKind::Other, "Header not found")); 515 } 516 517 if let Some(rust_target) = rust_target { 518 builder = builder.rust_target(rust_target); 519 } 520 521 if let Some(variant) = default_enum_style { 522 builder = builder.default_enum_style(variant); 523 } 524 525 for regex in bitfield_enum { 526 builder = builder.bitfield_enum(regex); 527 } 528 529 for regex in newtype_enum { 530 builder = builder.newtype_enum(regex); 531 } 532 533 for regex in newtype_global_enum { 534 builder = builder.newtype_global_enum(regex); 535 } 536 537 for regex in rustified_enum { 538 builder = builder.rustified_enum(regex); 539 } 540 541 for regex in constified_enum { 542 builder = builder.constified_enum(regex); 543 } 544 545 for regex in constified_enum_module { 546 builder = builder.constified_enum_module(regex); 547 } 548 549 if let Some(default_macro_constant_type) = default_macro_constant_type { 550 builder = 551 builder.default_macro_constant_type(default_macro_constant_type) 552 } 553 554 if let Some(variant) = default_alias_style { 555 builder = builder.default_alias_style(variant); 556 } 557 558 for regex in normal_alias { 559 builder = builder.type_alias(regex); 560 } 561 562 for regex in new_type_alias { 563 builder = builder.new_type_alias(regex); 564 } 565 566 for regex in new_type_alias_deref { 567 builder = builder.new_type_alias_deref(regex); 568 } 569 570 if let Some(variant) = default_non_copy_union_style { 571 builder = builder.default_non_copy_union_style(variant); 572 } 573 574 for regex in bindgen_wrapper_union { 575 builder = builder.bindgen_wrapper_union(regex); 576 } 577 578 for regex in manually_drop_union { 579 builder = builder.manually_drop_union(regex); 580 } 581 582 for ty in blocklist_type { 583 builder = builder.blocklist_type(ty); 584 } 585 586 for fun in blocklist_function { 587 builder = builder.blocklist_function(fun); 588 } 589 590 for id in blocklist_item { 591 builder = builder.blocklist_item(id); 592 } 593 594 for file in blocklist_file { 595 builder = builder.blocklist_file(file); 596 } 597 598 if builtins { 599 builder = builder.emit_builtins(); 600 } 601 602 if no_layout_tests { 603 builder = builder.layout_tests(false); 604 } 605 606 if no_derive_copy { 607 builder = builder.derive_copy(false); 608 } 609 610 if no_derive_debug { 611 builder = builder.derive_debug(false); 612 } 613 614 if impl_debug { 615 builder = builder.impl_debug(true); 616 } 617 618 if impl_partialeq { 619 builder = builder.impl_partialeq(true); 620 } 621 622 if with_derive_default { 623 builder = builder.derive_default(true); 624 } 625 626 if with_derive_hash { 627 builder = builder.derive_hash(true); 628 } 629 630 if with_derive_partialeq { 631 builder = builder.derive_partialeq(true); 632 } 633 634 if with_derive_partialord { 635 builder = builder.derive_partialord(true); 636 } 637 638 if with_derive_eq { 639 builder = builder.derive_eq(true); 640 } 641 642 if with_derive_ord { 643 builder = builder.derive_ord(true); 644 } 645 646 if no_derive_default { 647 builder = builder.derive_default(false); 648 } 649 650 if no_prepend_enum_name { 651 builder = builder.prepend_enum_name(false); 652 } 653 654 if no_include_path_detection { 655 builder = builder.detect_include_paths(false); 656 } 657 658 if fit_macro_constant_types { 659 builder = builder.fit_macro_constants(true); 660 } 661 662 if time_phases { 663 builder = builder.time_phases(true); 664 } 665 666 if use_array_pointers_in_arguments { 667 builder = builder.array_pointers_in_arguments(true); 668 } 669 670 if let Some(wasm_import_name) = wasm_import_module_name { 671 builder = builder.wasm_import_module_name(wasm_import_name); 672 } 673 674 if let Some(prefix) = ctypes_prefix { 675 builder = builder.ctypes_prefix(prefix); 676 } 677 678 builder = builder.anon_fields_prefix(anon_fields_prefix); 679 680 if let Some(config) = generate { 681 builder = builder.with_codegen_config(config); 682 } 683 684 if emit_clang_ast { 685 builder = builder.emit_clang_ast(); 686 } 687 688 if emit_ir { 689 builder = builder.emit_ir(); 690 } 691 692 if let Some(path) = emit_ir_graphviz { 693 builder = builder.emit_ir_graphviz(path); 694 } 695 696 if enable_cxx_namespaces { 697 builder = builder.enable_cxx_namespaces(); 698 } 699 700 if enable_function_attribute_detection { 701 builder = builder.enable_function_attribute_detection(); 702 } 703 704 if disable_name_namespacing { 705 builder = builder.disable_name_namespacing(); 706 } 707 708 if disable_nested_struct_naming { 709 builder = builder.disable_nested_struct_naming(); 710 } 711 712 if disable_untagged_union { 713 builder = builder.disable_untagged_union(); 714 } 715 716 if disable_header_comment { 717 builder = builder.disable_header_comment(); 718 } 719 720 if ignore_functions { 721 builder = builder.ignore_functions(); 722 } 723 724 if ignore_methods { 725 builder = builder.ignore_methods(); 726 } 727 728 if no_convert_floats { 729 builder = builder.no_convert_floats(); 730 } 731 732 if no_doc_comments { 733 builder = builder.generate_comments(false); 734 } 735 736 if no_recursive_allowlist { 737 builder = builder.allowlist_recursively(false); 738 } 739 740 if objc_extern_crate { 741 builder = builder.objc_extern_crate(true); 742 } 743 744 if generate_block { 745 builder = builder.generate_block(true); 746 } 747 748 if block_extern_crate { 749 builder = builder.block_extern_crate(true); 750 } 751 752 for ty in opaque_type { 753 builder = builder.opaque_type(ty); 754 } 755 756 for line in raw_line { 757 builder = builder.raw_line(line); 758 } 759 760 let mut values = module_raw_line.into_iter(); 761 while let Some(module) = values.next() { 762 let line = values.next().unwrap(); 763 builder = builder.module_raw_line(module, line); 764 } 765 766 if use_core { 767 builder = builder.use_core(); 768 } 769 770 if distrust_clang_mangling { 771 builder = builder.trust_clang_mangling(false); 772 } 773 774 if conservative_inline_namespaces { 775 builder = builder.conservative_inline_namespaces(); 776 } 777 778 if generate_inline_functions { 779 builder = builder.generate_inline_functions(true); 780 } 781 782 for regex in allowlist_function { 783 builder = builder.allowlist_function(regex); 784 } 785 786 for regex in allowlist_type { 787 builder = builder.allowlist_type(regex); 788 } 789 790 for regex in allowlist_var { 791 builder = builder.allowlist_var(regex); 792 } 793 794 for file in allowlist_file { 795 builder = builder.allowlist_file(file); 796 } 797 798 for arg in clang_args { 799 builder = builder.clang_arg(arg); 800 } 801 802 let output = if let Some(path) = &output { 803 let file = File::create(path)?; 804 if let Some(depfile) = depfile { 805 builder = builder.depfile(path, depfile); 806 } 807 Box::new(io::BufWriter::new(file)) as Box<dyn io::Write> 808 } else { 809 if let Some(depfile) = depfile { 810 builder = builder.depfile("-", depfile); 811 } 812 Box::new(io::BufWriter::new(io::stdout())) as Box<dyn io::Write> 813 }; 814 815 if dump_preprocessed_input { 816 builder.dump_preprocessed_input()?; 817 } 818 819 if no_record_matches { 820 builder = builder.record_matches(false); 821 } 822 823 if no_size_t_is_usize { 824 builder = builder.size_t_is_usize(false); 825 } 826 827 if no_rustfmt_bindings { 828 builder = builder.rustfmt_bindings(false); 829 } 830 831 if let Some(path_str) = rustfmt_configuration_file { 832 let path = PathBuf::from(path_str); 833 834 if no_rustfmt_bindings { 835 return Err(Error::new( 836 ErrorKind::Other, 837 "Cannot supply both --rustfmt-configuration-file and --no-rustfmt-bindings", 838 )); 839 } 840 841 if !path.is_absolute() { 842 return Err(Error::new( 843 ErrorKind::Other, 844 "--rustfmt-configuration--file needs to be an absolute path!", 845 )); 846 } 847 848 if path.to_str().is_none() { 849 return Err(Error::new( 850 ErrorKind::Other, 851 "--rustfmt-configuration-file contains non-valid UTF8 characters.", 852 )); 853 } 854 855 builder = builder.rustfmt_configuration_file(Some(path)); 856 } 857 858 for regex in no_partialeq { 859 builder = builder.no_partialeq(regex); 860 } 861 862 for regex in no_copy { 863 builder = builder.no_copy(regex); 864 } 865 866 for regex in no_debug { 867 builder = builder.no_debug(regex); 868 } 869 870 for regex in no_default { 871 builder = builder.no_default(regex); 872 } 873 874 for regex in no_hash { 875 builder = builder.no_hash(regex); 876 } 877 878 for regex in must_use_type { 879 builder = builder.must_use_type(regex); 880 } 881 882 if let Some(dynamic_library_name) = dynamic_loading { 883 builder = builder.dynamic_library_name(dynamic_library_name); 884 } 885 886 if dynamic_link_require_all { 887 builder = builder.dynamic_link_require_all(true); 888 } 889 890 if respect_cxx_access_specs { 891 builder = builder.respect_cxx_access_specs(true); 892 } 893 894 if translate_enum_integer_types { 895 builder = builder.translate_enum_integer_types(true); 896 } 897 898 if c_naming { 899 builder = builder.c_naming(true); 900 } 901 902 if explicit_padding { 903 builder = builder.explicit_padding(true); 904 } 905 906 if vtable_generation { 907 builder = builder.vtable_generation(true); 908 } 909 910 if sort_semantically { 911 builder = builder.sort_semantically(true); 912 } 913 914 if merge_extern_blocks { 915 builder = builder.merge_extern_blocks(true); 916 } 917 918 for abi_override in override_abi { 919 let (regex, abi_str) = abi_override 920 .rsplit_once('=') 921 .expect("Invalid ABI override: Missing `=`"); 922 let abi = abi_str 923 .parse() 924 .unwrap_or_else(|err| panic!("Invalid ABI override: {}", err)); 925 builder = builder.override_abi(abi, regex); 926 } 927 928 if wrap_unsafe_ops { 929 builder = builder.wrap_unsafe_ops(true); 930 } 931 932 #[derive(Debug)] 933 struct CustomDeriveCallback { 934 derives: Vec<String>, 935 kind: Option<TypeKind>, 936 regex_set: bindgen::RegexSet, 937 } 938 939 impl bindgen::callbacks::ParseCallbacks for CustomDeriveCallback { 940 fn cli_args(&self) -> Vec<String> { 941 let mut args = vec![]; 942 943 let flag = match &self.kind { 944 None => "--with-derive-custom", 945 Some(TypeKind::Struct) => "--with-derive-custom-struct", 946 Some(TypeKind::Enum) => "--with-derive-custom-enum", 947 Some(TypeKind::Union) => "--with-derive-custom-union", 948 }; 949 950 let derives = self.derives.join(","); 951 952 for item in self.regex_set.get_items() { 953 args.extend_from_slice(&[ 954 flag.to_owned(), 955 format!("{}={}", item, derives), 956 ]); 957 } 958 959 args 960 } 961 962 fn add_derives( 963 &self, 964 info: &bindgen::callbacks::DeriveInfo<'_>, 965 ) -> Vec<String> { 966 if self.kind.map(|kind| kind == info.kind).unwrap_or(true) && 967 self.regex_set.matches(info.name) 968 { 969 return self.derives.clone(); 970 } 971 vec![] 972 } 973 } 974 975 for (custom_derives, kind) in [ 976 (with_derive_custom, None), 977 (with_derive_custom_struct, Some(TypeKind::Struct)), 978 (with_derive_custom_enum, Some(TypeKind::Enum)), 979 (with_derive_custom_union, Some(TypeKind::Union)), 980 ] { 981 for custom_derive in custom_derives { 982 let (regex, derives) = custom_derive 983 .rsplit_once('=') 984 .expect("Invalid custom derive argument: Missing `=`"); 985 let derives = derives.split(',').map(|s| s.to_owned()).collect(); 986 987 let mut regex_set = RegexSet::new(); 988 regex_set.insert(regex); 989 regex_set.build(false); 990 991 builder = builder.parse_callbacks(Box::new(CustomDeriveCallback { 992 derives, 993 kind, 994 regex_set, 995 })); 996 } 997 } 998 999 if wrap_static_fns { 1000 builder = builder.wrap_static_fns(true); 1001 } 1002 1003 if let Some(path) = wrap_static_fns_path { 1004 builder = builder.wrap_static_fns_path(path); 1005 } 1006 1007 if let Some(suffix) = wrap_static_fns_suffix { 1008 builder = builder.wrap_static_fns_suffix(suffix); 1009 } 1010 1011 Ok((builder, output, verbose)) 1012} 1013