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