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