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