1 use bindgen::{
2     builder, AliasVariation, Builder, CodegenConfig, EnumVariation,
3     MacroTypeVariation, RustTarget, DEFAULT_ANON_FIELDS_PREFIX,
4     RUST_TARGET_STRINGS,
5 };
6 use clap::{App, Arg};
7 use std::fs::File;
8 use std::io::{self, stderr, Error, ErrorKind, Write};
9 use std::path::PathBuf;
10 use std::str::FromStr;
11 
12 /// 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>,13 pub fn builder_from_flags<I>(
14     args: I,
15 ) -> Result<(Builder, Box<dyn io::Write>, bool), io::Error>
16 where
17     I: Iterator<Item = String>,
18 {
19     let rust_target_help = format!(
20         "Version of the Rust compiler to target. Valid options are: {:?}. Defaults to {:?}.",
21         RUST_TARGET_STRINGS,
22         String::from(RustTarget::default())
23     );
24 
25     let matches = App::new("bindgen")
26         .version(Some("0.58.1").unwrap_or("unknown"))
27         .about("Generates Rust bindings from C/C++ headers.")
28         .usage("bindgen [FLAGS] [OPTIONS] <header> -- <clang-args>...")
29         .args(&[
30             Arg::with_name("header")
31                 .help("C or C++ header file")
32                 .required(true),
33             Arg::with_name("default-enum-style")
34                 .long("default-enum-style")
35                 .help("The default style of code used to generate enums.")
36                 .value_name("variant")
37                 .default_value("consts")
38                 .possible_values(&[
39                     "consts",
40                     "moduleconsts",
41                     "bitfield",
42                     "newtype",
43                     "rust",
44                     "rust_non_exhaustive",
45                 ])
46                 .multiple(false),
47             Arg::with_name("bitfield-enum")
48                 .long("bitfield-enum")
49                 .help(
50                     "Mark any enum whose name matches <regex> as a set of \
51                      bitfield flags.",
52                 )
53                 .value_name("regex")
54                 .takes_value(true)
55                 .multiple(true)
56                 .number_of_values(1),
57             Arg::with_name("newtype-enum")
58                 .long("newtype-enum")
59                 .help("Mark any enum whose name matches <regex> as a newtype.")
60                 .value_name("regex")
61                 .takes_value(true)
62                 .multiple(true)
63                 .number_of_values(1),
64             Arg::with_name("rustified-enum")
65                 .long("rustified-enum")
66                 .help("Mark any enum whose name matches <regex> as a Rust enum.")
67                 .value_name("regex")
68                 .takes_value(true)
69                 .multiple(true)
70                 .number_of_values(1),
71             Arg::with_name("constified-enum")
72                 .long("constified-enum")
73                 .help(
74                     "Mark any enum whose name matches <regex> as a series of \
75                      constants.",
76                 )
77                 .value_name("regex")
78                 .takes_value(true)
79                 .multiple(true)
80                 .number_of_values(1),
81             Arg::with_name("constified-enum-module")
82                 .long("constified-enum-module")
83                 .help(
84                     "Mark any enum whose name matches <regex> as a module of \
85                      constants.",
86                 )
87                 .value_name("regex")
88                 .takes_value(true)
89                 .multiple(true)
90                 .number_of_values(1),
91             Arg::with_name("default-macro-constant-type")
92                 .long("default-macro-constant-type")
93                 .help("The default signed/unsigned type for C macro constants.")
94                 .value_name("variant")
95                 .default_value("unsigned")
96                 .possible_values(&["signed", "unsigned"])
97                 .multiple(false),
98             Arg::with_name("default-alias-style")
99                 .long("default-alias-style")
100                 .help("The default style of code used to generate typedefs.")
101                 .value_name("variant")
102                 .default_value("type_alias")
103                 .possible_values(&[
104                     "type_alias",
105                     "new_type",
106                     "new_type_deref",
107                 ])
108                 .multiple(false),
109             Arg::with_name("normal-alias")
110                 .long("normal-alias")
111                 .help(
112                     "Mark any typedef alias whose name matches <regex> to use \
113                      normal type aliasing.",
114                 )
115                 .value_name("regex")
116                 .takes_value(true)
117                 .multiple(true)
118                 .number_of_values(1),
119              Arg::with_name("new-type-alias")
120                 .long("new-type-alias")
121                 .help(
122                     "Mark any typedef alias whose name matches <regex> to have \
123                      a new type generated for it.",
124                 )
125                 .value_name("regex")
126                 .takes_value(true)
127                 .multiple(true)
128                 .number_of_values(1),
129              Arg::with_name("new-type-alias-deref")
130                 .long("new-type-alias-deref")
131                 .help(
132                     "Mark any typedef alias whose name matches <regex> to have \
133                      a new type with Deref and DerefMut to the inner type.",
134                 )
135                 .value_name("regex")
136                 .takes_value(true)
137                 .multiple(true)
138                 .number_of_values(1),
139             Arg::with_name("blocklist-type")
140                 .alias("blacklist-type")
141                 .long("blocklist-type")
142                 .help("Mark <type> as hidden.")
143                 .value_name("type")
144                 .takes_value(true)
145                 .multiple(true)
146                 .number_of_values(1),
147             Arg::with_name("blocklist-function")
148                 .alias("blacklist-function")
149                 .long("blocklist-function")
150                 .help("Mark <function> as hidden.")
151                 .value_name("function")
152                 .takes_value(true)
153                 .multiple(true)
154                 .number_of_values(1),
155             Arg::with_name("blocklist-item")
156                 .alias("blacklist-item")
157                 .long("blocklist-item")
158                 .help("Mark <item> as hidden.")
159                 .value_name("item")
160                 .takes_value(true)
161                 .multiple(true)
162                 .number_of_values(1),
163             Arg::with_name("no-layout-tests")
164                 .long("no-layout-tests")
165                 .help("Avoid generating layout tests for any type."),
166             Arg::with_name("no-derive-copy")
167                 .long("no-derive-copy")
168                 .help("Avoid deriving Copy on any type."),
169             Arg::with_name("no-derive-debug")
170                 .long("no-derive-debug")
171                 .help("Avoid deriving Debug on any type."),
172             Arg::with_name("no-derive-default")
173                 .long("no-derive-default")
174                 .hidden(true)
175                 .help("Avoid deriving Default on any type."),
176             Arg::with_name("impl-debug").long("impl-debug").help(
177                 "Create Debug implementation, if it can not be derived \
178                  automatically.",
179             ),
180             Arg::with_name("impl-partialeq")
181                 .long("impl-partialeq")
182                 .help(
183                     "Create PartialEq implementation, if it can not be derived \
184                      automatically.",
185                 ),
186             Arg::with_name("with-derive-default")
187                 .long("with-derive-default")
188                 .help("Derive Default on any type."),
189             Arg::with_name("with-derive-hash")
190                 .long("with-derive-hash")
191                 .help("Derive hash on any type."),
192             Arg::with_name("with-derive-partialeq")
193                 .long("with-derive-partialeq")
194                 .help("Derive partialeq on any type."),
195             Arg::with_name("with-derive-partialord")
196                 .long("with-derive-partialord")
197                 .help("Derive partialord on any type."),
198             Arg::with_name("with-derive-eq")
199                 .long("with-derive-eq")
200                 .help(
201                     "Derive eq on any type. Enable this option also \
202                      enables --with-derive-partialeq",
203                 ),
204             Arg::with_name("with-derive-ord")
205                 .long("with-derive-ord")
206                 .help(
207                     "Derive ord on any type. Enable this option also \
208                      enables --with-derive-partialord",
209                 ),
210             Arg::with_name("no-doc-comments")
211                 .long("no-doc-comments")
212                 .help(
213                     "Avoid including doc comments in the output, see: \
214                      https://github.com/rust-lang/rust-bindgen/issues/426",
215                 ),
216             Arg::with_name("no-recursive-allowlist")
217                 .long("no-recursive-allowlist")
218                 .alias("no-recursive-whitelist")
219                 .help(
220                     "Disable allowlisting types recursively. This will cause \
221                      bindgen to emit Rust code that won't compile! See the \
222                      `bindgen::Builder::allowlist_recursively` method's \
223                      documentation for details.",
224                 ),
225             Arg::with_name("objc-extern-crate")
226                 .long("objc-extern-crate")
227                 .help("Use extern crate instead of use for objc."),
228             Arg::with_name("generate-block")
229                 .long("generate-block")
230                 .help("Generate block signatures instead of void pointers."),
231             Arg::with_name("block-extern-crate")
232                 .long("block-extern-crate")
233                 .help("Use extern crate instead of use for block."),
234             Arg::with_name("distrust-clang-mangling")
235                 .long("distrust-clang-mangling")
236                 .help("Do not trust the libclang-provided mangling"),
237             Arg::with_name("builtins").long("builtins").help(
238                 "Output bindings for builtin definitions, e.g. \
239                  __builtin_va_list.",
240             ),
241             Arg::with_name("ctypes-prefix")
242                 .long("ctypes-prefix")
243                 .help(
244                     "Use the given prefix before raw types instead of \
245                      ::std::os::raw.",
246                 )
247                 .value_name("prefix")
248                 .takes_value(true),
249             Arg::with_name("anon-fields-prefix")
250                 .long("anon-fields-prefix")
251                 .help("Use the given prefix for the anon fields.")
252                 .value_name("prefix")
253                 .default_value(DEFAULT_ANON_FIELDS_PREFIX)
254                 .takes_value(true),
255             Arg::with_name("time-phases")
256                 .long("time-phases")
257                 .help("Time the different bindgen phases and print to stderr"),
258             // All positional arguments after the end of options marker, `--`
259             Arg::with_name("clang-args").last(true).multiple(true),
260             Arg::with_name("emit-clang-ast")
261                 .long("emit-clang-ast")
262                 .help("Output the Clang AST for debugging purposes."),
263             Arg::with_name("emit-ir")
264                 .long("emit-ir")
265                 .help("Output our internal IR for debugging purposes."),
266             Arg::with_name("emit-ir-graphviz")
267                 .long("emit-ir-graphviz")
268                 .help("Dump graphviz dot file.")
269                 .value_name("path")
270                 .takes_value(true),
271             Arg::with_name("enable-cxx-namespaces")
272                 .long("enable-cxx-namespaces")
273                 .help("Enable support for C++ namespaces."),
274             Arg::with_name("disable-name-namespacing")
275                 .long("disable-name-namespacing")
276                 .help(
277                     "Disable namespacing via mangling, causing bindgen to \
278                      generate names like \"Baz\" instead of \"foo_bar_Baz\" \
279                      for an input name \"foo::bar::Baz\".",
280                 ),
281             Arg::with_name("disable-nested-struct-naming")
282                 .long("disable-nested-struct-naming")
283                 .help(
284                     "Disable nested struct naming, causing bindgen to generate \
285                      names like \"bar\" instead of \"foo_bar\" for a nested \
286                      definition \"struct foo { struct bar { } b; };\"."
287                 ),
288             Arg::with_name("disable-untagged-union")
289                 .long("disable-untagged-union")
290                 .help(
291                     "Disable support for native Rust unions.",
292                 ),
293             Arg::with_name("disable-header-comment")
294                 .long("disable-header-comment")
295                 .help("Suppress insertion of bindgen's version identifier into generated bindings.")
296                 .multiple(true),
297             Arg::with_name("ignore-functions")
298                 .long("ignore-functions")
299                 .help(
300                     "Do not generate bindings for functions or methods. This \
301                      is useful when you only care about struct layouts.",
302                 ),
303             Arg::with_name("generate")
304                 .long("generate")
305                 .help(
306                     "Generate only given items, split by commas. \
307                      Valid values are \"functions\",\"types\", \"vars\", \
308                      \"methods\", \"constructors\" and \"destructors\".",
309                 )
310                 .takes_value(true),
311             Arg::with_name("ignore-methods")
312                 .long("ignore-methods")
313                 .help("Do not generate bindings for methods."),
314             Arg::with_name("no-convert-floats")
315                 .long("no-convert-floats")
316                 .help("Do not automatically convert floats to f32/f64."),
317             Arg::with_name("no-prepend-enum-name")
318                 .long("no-prepend-enum-name")
319                 .help("Do not prepend the enum name to constant or newtype variants."),
320             Arg::with_name("no-include-path-detection")
321                 .long("no-include-path-detection")
322                 .help("Do not try to detect default include paths"),
323             Arg::with_name("fit-macro-constant-types")
324                 .long("fit-macro-constant-types")
325                 .help("Try to fit macro constants into types smaller than u32/i32"),
326             Arg::with_name("unstable-rust")
327                 .long("unstable-rust")
328                 .help("Generate unstable Rust code (deprecated; use --rust-target instead).")
329                 .multiple(true), // FIXME: Pass legacy test suite
330             Arg::with_name("opaque-type")
331                 .long("opaque-type")
332                 .help("Mark <type> as opaque.")
333                 .value_name("type")
334                 .takes_value(true)
335                 .multiple(true)
336                 .number_of_values(1),
337             Arg::with_name("output")
338                 .short("o")
339                 .long("output")
340                 .help("Write Rust bindings to <output>.")
341                 .takes_value(true),
342             Arg::with_name("raw-line")
343                 .long("raw-line")
344                 .help("Add a raw line of Rust code at the beginning of output.")
345                 .takes_value(true)
346                 .multiple(true)
347                 .number_of_values(1),
348             Arg::with_name("module-raw-line")
349                 .long("module-raw-line")
350                 .help("Add a raw line of Rust code to a given module.")
351                 .takes_value(true)
352                 .multiple(true)
353                 .number_of_values(2)
354                 .value_names(&["module-name", "raw-line"]),
355             Arg::with_name("rust-target")
356                 .long("rust-target")
357                 .help(&rust_target_help)
358                 .takes_value(true),
359             Arg::with_name("use-core")
360                 .long("use-core")
361                 .help("Use types from Rust core instead of std."),
362             Arg::with_name("conservative-inline-namespaces")
363                 .long("conservative-inline-namespaces")
364                 .help(
365                     "Conservatively generate inline namespaces to avoid name \
366                      conflicts.",
367                 ),
368             Arg::with_name("use-msvc-mangling")
369                 .long("use-msvc-mangling")
370                 .help("MSVC C++ ABI mangling. DEPRECATED: Has no effect."),
371             Arg::with_name("allowlist-function")
372                 .long("allowlist-function")
373                 .alias("whitelist-function")
374                 .help(
375                     "Allowlist all the free-standing functions matching \
376                      <regex>. Other non-allowlisted functions will not be \
377                      generated.",
378                 )
379                 .value_name("regex")
380                 .takes_value(true)
381                 .multiple(true)
382                 .number_of_values(1),
383             Arg::with_name("generate-inline-functions")
384                 .long("generate-inline-functions")
385                 .help("Generate inline functions."),
386             Arg::with_name("allowlist-type")
387                 .long("allowlist-type")
388                 .alias("whitelist-type")
389                 .help(
390                     "Only generate types matching <regex>. Other non-allowlisted types will \
391                      not be generated.",
392                 )
393                 .value_name("regex")
394                 .takes_value(true)
395                 .multiple(true)
396                 .number_of_values(1),
397             Arg::with_name("allowlist-var")
398                 .long("allowlist-var")
399                 .alias("whitelist-var")
400                 .help(
401                     "Allowlist all the free-standing variables matching \
402                      <regex>. Other non-allowlisted variables will not be \
403                      generated.",
404                 )
405                 .value_name("regex")
406                 .takes_value(true)
407                 .multiple(true)
408                 .number_of_values(1),
409             Arg::with_name("verbose")
410                 .long("verbose")
411                 .help("Print verbose error messages."),
412             Arg::with_name("dump-preprocessed-input")
413                 .long("dump-preprocessed-input")
414                 .help(
415                     "Preprocess and dump the input header files to disk. \
416                      Useful when debugging bindgen, using C-Reduce, or when \
417                      filing issues. The resulting file will be named \
418                      something like `__bindgen.i` or `__bindgen.ii`.",
419                 ),
420             Arg::with_name("no-record-matches")
421                 .long("no-record-matches")
422                 .help(
423                     "Do not record matching items in the regex sets. \
424                      This disables reporting of unused items.",
425                 ),
426             Arg::with_name("size_t-is-usize")
427                 .long("size_t-is-usize")
428                 .help("Translate size_t to usize."),
429             Arg::with_name("no-rustfmt-bindings")
430                 .long("no-rustfmt-bindings")
431                 .help("Do not format the generated bindings with rustfmt."),
432             Arg::with_name("rustfmt-bindings")
433                 .long("rustfmt-bindings")
434                 .help(
435                     "Format the generated bindings with rustfmt. DEPRECATED: \
436                      --rustfmt-bindings is now enabled by default. Disable \
437                      with --no-rustfmt-bindings.",
438                 ),
439             Arg::with_name("rustfmt-configuration-file")
440                 .long("rustfmt-configuration-file")
441                 .help(
442                     "The absolute path to the rustfmt configuration file. \
443                      The configuration file will be used for formatting the bindings. \
444                      This parameter is incompatible with --no-rustfmt-bindings.",
445                 )
446                 .value_name("path")
447                 .takes_value(true)
448                 .multiple(false)
449                 .number_of_values(1),
450             Arg::with_name("no-partialeq")
451                 .long("no-partialeq")
452                 .help("Avoid deriving PartialEq for types matching <regex>.")
453                 .value_name("regex")
454                 .takes_value(true)
455                 .multiple(true)
456                 .number_of_values(1),
457             Arg::with_name("no-copy")
458                 .long("no-copy")
459                 .help("Avoid deriving Copy for types matching <regex>.")
460                 .value_name("regex")
461                 .takes_value(true)
462                 .multiple(true)
463                 .number_of_values(1),
464             Arg::with_name("no-debug")
465                 .long("no-debug")
466                 .help("Avoid deriving Debug for types matching <regex>.")
467                 .value_name("regex")
468                 .takes_value(true)
469                 .multiple(true)
470                 .number_of_values(1),
471             Arg::with_name("no-default")
472                 .long("no-default")
473                 .help("Avoid deriving/implement Default for types matching <regex>.")
474                 .value_name("regex")
475                 .takes_value(true)
476                 .multiple(true)
477                 .number_of_values(1),
478             Arg::with_name("no-hash")
479                 .long("no-hash")
480                 .help("Avoid deriving Hash for types matching <regex>.")
481                 .value_name("regex")
482                 .takes_value(true)
483                 .multiple(true)
484                 .number_of_values(1),
485             Arg::with_name("enable-function-attribute-detection")
486                 .long("enable-function-attribute-detection")
487                 .help(
488                     "Enables detecting unexposed attributes in functions (slow).
489                        Used to generate #[must_use] annotations.",
490                 ),
491             Arg::with_name("use-array-pointers-in-arguments")
492                 .long("use-array-pointers-in-arguments")
493                 .help("Use `*const [T; size]` instead of `*const T` for C arrays"),
494             Arg::with_name("wasm-import-module-name")
495                 .long("wasm-import-module-name")
496                 .value_name("name")
497                 .takes_value(true)
498                 .help("The name to be used in a #[link(wasm_import_module = ...)] statement"),
499             Arg::with_name("dynamic-loading")
500                 .long("dynamic-loading")
501                 .takes_value(true)
502                 .help("Use dynamic loading mode with the given library name."),
503             Arg::with_name("dynamic-link-require-all")
504                 .long("dynamic-link-require-all")
505                 .help("Require successful linkage to all functions in the library."),
506             Arg::with_name("respect-cxx-access-specs")
507                 .long("respect-cxx-access-specs")
508                 .help("Makes generated bindings `pub` only for items if the items are publically accessible in C++."),
509             Arg::with_name("translate-enum-integer-types")
510                 .long("translate-enum-integer-types")
511                 .help("Always translate enum integer types to native Rust integer types."),
512         ]) // .args()
513         .get_matches_from(args);
514 
515     let mut builder = builder();
516 
517     if let Some(header) = matches.value_of("header") {
518         builder = builder.header(header);
519     } else {
520         return Err(Error::new(ErrorKind::Other, "Header not found"));
521     }
522 
523     if matches.is_present("unstable-rust") {
524         builder = builder.rust_target(RustTarget::Nightly);
525         writeln!(
526             &mut stderr(),
527             "warning: the `--unstable-rust` option is deprecated"
528         )
529         .expect("Unable to write error message");
530     }
531 
532     if let Some(rust_target) = matches.value_of("rust-target") {
533         builder = builder.rust_target(RustTarget::from_str(rust_target)?);
534     }
535 
536     if let Some(variant) = matches.value_of("default-enum-style") {
537         builder = builder.default_enum_style(EnumVariation::from_str(variant)?)
538     }
539 
540     if let Some(bitfields) = matches.values_of("bitfield-enum") {
541         for regex in bitfields {
542             builder = builder.bitfield_enum(regex);
543         }
544     }
545 
546     if let Some(newtypes) = matches.values_of("newtype-enum") {
547         for regex in newtypes {
548             builder = builder.newtype_enum(regex);
549         }
550     }
551 
552     if let Some(rustifieds) = matches.values_of("rustified-enum") {
553         for regex in rustifieds {
554             builder = builder.rustified_enum(regex);
555         }
556     }
557 
558     if let Some(const_enums) = matches.values_of("constified-enum") {
559         for regex in const_enums {
560             builder = builder.constified_enum(regex);
561         }
562     }
563 
564     if let Some(constified_mods) = matches.values_of("constified-enum-module") {
565         for regex in constified_mods {
566             builder = builder.constified_enum_module(regex);
567         }
568     }
569 
570     if let Some(variant) = matches.value_of("default-macro-constant-type") {
571         builder = builder
572             .default_macro_constant_type(MacroTypeVariation::from_str(variant)?)
573     }
574 
575     if let Some(variant) = matches.value_of("default-alias-style") {
576         builder =
577             builder.default_alias_style(AliasVariation::from_str(variant)?);
578     }
579 
580     if let Some(type_alias) = matches.values_of("normal-alias") {
581         for regex in type_alias {
582             builder = builder.type_alias(regex);
583         }
584     }
585 
586     if let Some(new_type) = matches.values_of("new-type-alias") {
587         for regex in new_type {
588             builder = builder.new_type_alias(regex);
589         }
590     }
591 
592     if let Some(new_type_deref) = matches.values_of("new-type-alias-deref") {
593         for regex in new_type_deref {
594             builder = builder.new_type_alias_deref(regex);
595         }
596     }
597 
598     if let Some(hidden_types) = matches.values_of("blocklist-type") {
599         for ty in hidden_types {
600             builder = builder.blocklist_type(ty);
601         }
602     }
603 
604     if let Some(hidden_functions) = matches.values_of("blocklist-function") {
605         for fun in hidden_functions {
606             builder = builder.blocklist_function(fun);
607         }
608     }
609 
610     if let Some(hidden_identifiers) = matches.values_of("blocklist-item") {
611         for id in hidden_identifiers {
612             builder = builder.blocklist_item(id);
613         }
614     }
615 
616     if matches.is_present("builtins") {
617         builder = builder.emit_builtins();
618     }
619 
620     if matches.is_present("no-layout-tests") {
621         builder = builder.layout_tests(false);
622     }
623 
624     if matches.is_present("no-derive-copy") {
625         builder = builder.derive_copy(false);
626     }
627 
628     if matches.is_present("no-derive-debug") {
629         builder = builder.derive_debug(false);
630     }
631 
632     if matches.is_present("impl-debug") {
633         builder = builder.impl_debug(true);
634     }
635 
636     if matches.is_present("impl-partialeq") {
637         builder = builder.impl_partialeq(true);
638     }
639 
640     if matches.is_present("with-derive-default") {
641         builder = builder.derive_default(true);
642     }
643 
644     if matches.is_present("with-derive-hash") {
645         builder = builder.derive_hash(true);
646     }
647 
648     if matches.is_present("with-derive-partialeq") {
649         builder = builder.derive_partialeq(true);
650     }
651 
652     if matches.is_present("with-derive-partialord") {
653         builder = builder.derive_partialord(true);
654     }
655 
656     if matches.is_present("with-derive-eq") {
657         builder = builder.derive_eq(true);
658     }
659 
660     if matches.is_present("with-derive-ord") {
661         builder = builder.derive_ord(true);
662     }
663 
664     if matches.is_present("no-derive-default") {
665         builder = builder.derive_default(false);
666     }
667 
668     if matches.is_present("no-prepend-enum-name") {
669         builder = builder.prepend_enum_name(false);
670     }
671 
672     if matches.is_present("no-include-path-detection") {
673         builder = builder.detect_include_paths(false);
674     }
675 
676     if matches.is_present("fit-macro-constant-types") {
677         builder = builder.fit_macro_constants(true);
678     }
679 
680     if matches.is_present("time-phases") {
681         builder = builder.time_phases(true);
682     }
683 
684     if matches.is_present("use-array-pointers-in-arguments") {
685         builder = builder.array_pointers_in_arguments(true);
686     }
687 
688     if let Some(wasm_import_name) = matches.value_of("wasm-import-module-name")
689     {
690         builder = builder.wasm_import_module_name(wasm_import_name);
691     }
692 
693     if let Some(prefix) = matches.value_of("ctypes-prefix") {
694         builder = builder.ctypes_prefix(prefix);
695     }
696 
697     if let Some(prefix) = matches.value_of("anon-fields-prefix") {
698         builder = builder.anon_fields_prefix(prefix);
699     }
700 
701     if let Some(what_to_generate) = matches.value_of("generate") {
702         let mut config = CodegenConfig::empty();
703         for what in what_to_generate.split(",") {
704             match what {
705                 "functions" => config.insert(CodegenConfig::FUNCTIONS),
706                 "types" => config.insert(CodegenConfig::TYPES),
707                 "vars" => config.insert(CodegenConfig::VARS),
708                 "methods" => config.insert(CodegenConfig::METHODS),
709                 "constructors" => config.insert(CodegenConfig::CONSTRUCTORS),
710                 "destructors" => config.insert(CodegenConfig::DESTRUCTORS),
711                 otherwise => {
712                     return Err(Error::new(
713                         ErrorKind::Other,
714                         format!("Unknown generate item: {}", otherwise),
715                     ));
716                 }
717             }
718         }
719         builder = builder.with_codegen_config(config);
720     }
721 
722     if matches.is_present("emit-clang-ast") {
723         builder = builder.emit_clang_ast();
724     }
725 
726     if matches.is_present("emit-ir") {
727         builder = builder.emit_ir();
728     }
729 
730     if let Some(path) = matches.value_of("emit-ir-graphviz") {
731         builder = builder.emit_ir_graphviz(path);
732     }
733 
734     if matches.is_present("enable-cxx-namespaces") {
735         builder = builder.enable_cxx_namespaces();
736     }
737 
738     if matches.is_present("enable-function-attribute-detection") {
739         builder = builder.enable_function_attribute_detection();
740     }
741 
742     if matches.is_present("disable-name-namespacing") {
743         builder = builder.disable_name_namespacing();
744     }
745 
746     if matches.is_present("disable-nested-struct-naming") {
747         builder = builder.disable_nested_struct_naming();
748     }
749 
750     if matches.is_present("disable-untagged-union") {
751         builder = builder.disable_untagged_union();
752     }
753 
754     if matches.is_present("disable-header-comment") {
755         builder = builder.disable_header_comment();
756     }
757 
758     if matches.is_present("ignore-functions") {
759         builder = builder.ignore_functions();
760     }
761 
762     if matches.is_present("ignore-methods") {
763         builder = builder.ignore_methods();
764     }
765 
766     if matches.is_present("no-convert-floats") {
767         builder = builder.no_convert_floats();
768     }
769 
770     if matches.is_present("no-doc-comments") {
771         builder = builder.generate_comments(false);
772     }
773 
774     if matches.is_present("no-recursive-allowlist") {
775         builder = builder.allowlist_recursively(false);
776     }
777 
778     if matches.is_present("objc-extern-crate") {
779         builder = builder.objc_extern_crate(true);
780     }
781 
782     if matches.is_present("generate-block") {
783         builder = builder.generate_block(true);
784     }
785 
786     if matches.is_present("block-extern-crate") {
787         builder = builder.block_extern_crate(true);
788     }
789 
790     if let Some(opaque_types) = matches.values_of("opaque-type") {
791         for ty in opaque_types {
792             builder = builder.opaque_type(ty);
793         }
794     }
795 
796     if let Some(lines) = matches.values_of("raw-line") {
797         for line in lines {
798             builder = builder.raw_line(line);
799         }
800     }
801 
802     if let Some(mut values) = matches.values_of("module-raw-line") {
803         while let Some(module) = values.next() {
804             let line = values.next().unwrap();
805             builder = builder.module_raw_line(module, line);
806         }
807     }
808 
809     if matches.is_present("use-core") {
810         builder = builder.use_core();
811     }
812 
813     if matches.is_present("distrust-clang-mangling") {
814         builder = builder.trust_clang_mangling(false);
815     }
816 
817     if matches.is_present("conservative-inline-namespaces") {
818         builder = builder.conservative_inline_namespaces();
819     }
820 
821     if matches.is_present("generate-inline-functions") {
822         builder = builder.generate_inline_functions(true);
823     }
824 
825     if let Some(allowlist) = matches.values_of("allowlist-function") {
826         for regex in allowlist {
827             builder = builder.allowlist_function(regex);
828         }
829     }
830 
831     if let Some(allowlist) = matches.values_of("allowlist-type") {
832         for regex in allowlist {
833             builder = builder.allowlist_type(regex);
834         }
835     }
836 
837     if let Some(allowlist) = matches.values_of("allowlist-var") {
838         for regex in allowlist {
839             builder = builder.allowlist_var(regex);
840         }
841     }
842 
843     if let Some(args) = matches.values_of("clang-args") {
844         for arg in args {
845             builder = builder.clang_arg(arg);
846         }
847     }
848 
849     let output = if let Some(path) = matches.value_of("output") {
850         let file = File::create(path)?;
851         Box::new(io::BufWriter::new(file)) as Box<dyn io::Write>
852     } else {
853         Box::new(io::BufWriter::new(io::stdout())) as Box<dyn io::Write>
854     };
855 
856     if matches.is_present("dump-preprocessed-input") {
857         builder.dump_preprocessed_input()?;
858     }
859 
860     if matches.is_present("no-record-matches") {
861         builder = builder.record_matches(false);
862     }
863 
864     if matches.is_present("size_t-is-usize") {
865         builder = builder.size_t_is_usize(true);
866     }
867 
868     let no_rustfmt_bindings = matches.is_present("no-rustfmt-bindings");
869     if no_rustfmt_bindings {
870         builder = builder.rustfmt_bindings(false);
871     }
872 
873     if let Some(path_str) = matches.value_of("rustfmt-configuration-file") {
874         let path = PathBuf::from(path_str);
875 
876         if no_rustfmt_bindings {
877             return Err(Error::new(
878                 ErrorKind::Other,
879                 "Cannot supply both --rustfmt-configuration-file and --no-rustfmt-bindings",
880             ));
881         }
882 
883         if !path.is_absolute() {
884             return Err(Error::new(
885                 ErrorKind::Other,
886                 "--rustfmt-configuration--file needs to be an absolute path!",
887             ));
888         }
889 
890         if path.to_str().is_none() {
891             return Err(Error::new(
892                 ErrorKind::Other,
893                 "--rustfmt-configuration-file contains non-valid UTF8 characters.",
894             ));
895         }
896 
897         builder = builder.rustfmt_configuration_file(Some(path));
898     }
899 
900     if let Some(no_partialeq) = matches.values_of("no-partialeq") {
901         for regex in no_partialeq {
902             builder = builder.no_partialeq(regex);
903         }
904     }
905 
906     if let Some(no_copy) = matches.values_of("no-copy") {
907         for regex in no_copy {
908             builder = builder.no_copy(regex);
909         }
910     }
911 
912     if let Some(no_debug) = matches.values_of("no-debug") {
913         for regex in no_debug {
914             builder = builder.no_debug(regex);
915         }
916     }
917 
918     if let Some(no_default) = matches.values_of("no-default") {
919         for regex in no_default {
920             builder = builder.no_default(regex);
921         }
922     }
923 
924     if let Some(no_hash) = matches.values_of("no-hash") {
925         for regex in no_hash {
926             builder = builder.no_hash(regex);
927         }
928     }
929 
930     if let Some(dynamic_library_name) = matches.value_of("dynamic-loading") {
931         builder = builder.dynamic_library_name(dynamic_library_name);
932     }
933 
934     if matches.is_present("dynamic-link-require-all") {
935         builder = builder.dynamic_link_require_all(true);
936     }
937 
938     if matches.is_present("respect-cxx-access-specs") {
939         builder = builder.respect_cxx_access_specs(true);
940     }
941 
942     if matches.is_present("translate-enum-integer-types") {
943         builder = builder.translate_enum_integer_types(true);
944     }
945 
946     let verbose = matches.is_present("verbose");
947 
948     Ok((builder, output, verbose))
949 }
950