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