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