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