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