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