• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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