1 use bindgen::callbacks::TypeKind;
2 use bindgen::{
3 builder, AliasVariation, Builder, CodegenConfig, EnumVariation,
4 MacroTypeVariation, NonCopyUnionStyle, RegexSet, RustTarget,
5 DEFAULT_ANON_FIELDS_PREFIX, RUST_TARGET_STRINGS,
6 };
7 use clap::Parser;
8 use std::fs::File;
9 use std::io::{self, Error, ErrorKind};
10 use std::path::PathBuf;
11
rust_target_help() -> String12 fn 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
parse_codegen_config(what_to_generate: &str) -> io::Result<CodegenConfig>20 fn 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 )]
48 struct 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.
builder_from_flags<I>( args: I, ) -> Result<(Builder, Box<dyn io::Write>, bool), io::Error> where I: Iterator<Item = String>,378 pub fn builder_from_flags<I>(
379 args: I,
380 ) -> Result<(Builder, Box<dyn io::Write>, bool), io::Error>
381 where
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