1 //! Generate Rust bindings for C and C++ libraries.
2 //!
3 //! Provide a C/C++ header file, receive Rust FFI code to call into C/C++
4 //! functions and use types defined in the header.
5 //!
6 //! See the [`Builder`](./struct.Builder.html) struct for usage.
7 //!
8 //! See the [Users Guide](https://rust-lang.github.io/rust-bindgen/) for
9 //! additional documentation.
10 #![deny(missing_docs)]
11 #![deny(warnings)]
12 #![deny(unused_extern_crates)]
13 // To avoid rather annoying warnings when matching with CXCursor_xxx as a
14 // constant.
15 #![allow(non_upper_case_globals)]
16 // `quote!` nests quite deeply.
17 #![recursion_limit = "128"]
18
19 #[macro_use]
20 extern crate bitflags;
21 extern crate cexpr;
22 #[macro_use]
23 #[allow(unused_extern_crates)]
24 extern crate cfg_if;
25 extern crate clang_sys;
26 extern crate rustc_hash;
27 #[macro_use]
28 extern crate lazy_static;
29 extern crate peeking_take_while;
30 #[macro_use]
31 extern crate quote;
32 extern crate proc_macro2;
33 extern crate regex;
34 extern crate shlex;
35 #[cfg(feature = "which-rustfmt")]
36 extern crate which;
37
38 #[cfg(feature = "logging")]
39 #[macro_use]
40 extern crate log;
41
42 #[cfg(not(feature = "logging"))]
43 #[macro_use]
44 mod log_stubs;
45
46 #[macro_use]
47 mod extra_assertions;
48
49 // A macro to declare an internal module for which we *must* provide
50 // documentation for. If we are building with the "testing_only_docs" feature,
51 // then the module is declared public, and our `#![deny(missing_docs)]` pragma
52 // applies to it. This feature is used in CI, so we won't let anything slip by
53 // undocumented. Normal builds, however, will leave the module private, so that
54 // we don't expose internals to library consumers.
55 macro_rules! doc_mod {
56 ($m:ident, $doc_mod_name:ident) => {
57 cfg_if! {
58 if #[cfg(feature = "testing_only_docs")] {
59 pub mod $doc_mod_name {
60 //! Autogenerated documentation module.
61 pub use super::$m::*;
62 }
63 } else {
64 }
65 }
66 };
67 }
68
69 mod clang;
70 mod codegen;
71 mod features;
72 mod ir;
73 mod parse;
74 mod regex_set;
75 mod time;
76
77 pub mod callbacks;
78
79 doc_mod!(clang, clang_docs);
80 doc_mod!(features, features_docs);
81 doc_mod!(ir, ir_docs);
82 doc_mod!(parse, parse_docs);
83 doc_mod!(regex_set, regex_set_docs);
84
85 pub use codegen::EnumVariation;
86 use features::RustFeatures;
87 pub use features::{RustTarget, LATEST_STABLE_RUST, RUST_TARGET_STRINGS};
88 use ir::context::{BindgenContext, ItemId};
89 use ir::item::Item;
90 use parse::{ClangItemParser, ParseError};
91 use regex_set::RegexSet;
92
93 use std::borrow::Cow;
94 use std::fs::{File, OpenOptions};
95 use std::io::{self, Write};
96 use std::path::{Path, PathBuf};
97 use std::process::{Command, Stdio};
98 use std::sync::Arc;
99 use std::{env, iter};
100
101 // Some convenient typedefs for a fast hash map and hash set.
102 type HashMap<K, V> = ::rustc_hash::FxHashMap<K, V>;
103 type HashSet<K> = ::rustc_hash::FxHashSet<K>;
104 pub(crate) use std::collections::hash_map::Entry;
105
args_are_cpp(clang_args: &[String]) -> bool106 fn args_are_cpp(clang_args: &[String]) -> bool {
107 return clang_args
108 .windows(2)
109 .any(|w| w[0] == "-xc++" || w[1] == "-xc++" || w == &["-x", "c++"]);
110 }
111
112 bitflags! {
113 /// A type used to indicate which kind of items we have to generate.
114 pub struct CodegenConfig: u32 {
115 /// Whether to generate functions.
116 const FUNCTIONS = 1 << 0;
117 /// Whether to generate types.
118 const TYPES = 1 << 1;
119 /// Whether to generate constants.
120 const VARS = 1 << 2;
121 /// Whether to generate methods.
122 const METHODS = 1 << 3;
123 /// Whether to generate constructors
124 const CONSTRUCTORS = 1 << 4;
125 /// Whether to generate destructors.
126 const DESTRUCTORS = 1 << 5;
127 }
128 }
129
130 impl CodegenConfig {
131 /// Returns true if functions should be generated.
functions(self) -> bool132 pub fn functions(self) -> bool {
133 self.contains(CodegenConfig::FUNCTIONS)
134 }
135
136 /// Returns true if types should be generated.
types(self) -> bool137 pub fn types(self) -> bool {
138 self.contains(CodegenConfig::TYPES)
139 }
140
141 /// Returns true if constants should be generated.
vars(self) -> bool142 pub fn vars(self) -> bool {
143 self.contains(CodegenConfig::VARS)
144 }
145
146 /// Returns true if methds should be generated.
methods(self) -> bool147 pub fn methods(self) -> bool {
148 self.contains(CodegenConfig::METHODS)
149 }
150
151 /// Returns true if constructors should be generated.
constructors(self) -> bool152 pub fn constructors(self) -> bool {
153 self.contains(CodegenConfig::CONSTRUCTORS)
154 }
155
156 /// Returns true if destructors should be generated.
destructors(self) -> bool157 pub fn destructors(self) -> bool {
158 self.contains(CodegenConfig::DESTRUCTORS)
159 }
160 }
161
162 impl Default for CodegenConfig {
default() -> Self163 fn default() -> Self {
164 CodegenConfig::all()
165 }
166 }
167
168 /// Configure and generate Rust bindings for a C/C++ header.
169 ///
170 /// This is the main entry point to the library.
171 ///
172 /// ```ignore
173 /// use bindgen::builder;
174 ///
175 /// // Configure and generate bindings.
176 /// let bindings = builder().header("path/to/input/header")
177 /// .whitelisted_type("SomeCoolClass")
178 /// .whitelisted_function("do_some_cool_thing")
179 /// .generate()?;
180 ///
181 /// // Write the generated bindings to an output file.
182 /// bindings.write_to_file("path/to/output.rs")?;
183 /// ```
184 ///
185 /// # Enums
186 ///
187 /// Bindgen can map C/C++ enums into Rust in different ways. The way bindgen maps enums depends on
188 /// the pattern passed to several methods:
189 ///
190 /// 1. [`constified_enum_module()`](#method.constified_enum_module)
191 /// 2. [`bitfield_enum()`](#method.bitfield_enum)
192 /// 3. [`rustified_enum()`](#method.rustified_enum)
193 ///
194 /// For each C enum, bindgen tries to match the pattern in the following order:
195 ///
196 /// 1. Constified enum module
197 /// 2. Bitfield enum
198 /// 3. Rustified enum
199 ///
200 /// If none of the above patterns match, then bindgen will generate a set of Rust constants.
201 #[derive(Debug, Default)]
202 pub struct Builder {
203 options: BindgenOptions,
204 input_headers: Vec<String>,
205 // Tuples of unsaved file contents of the form (name, contents).
206 input_header_contents: Vec<(String, String)>,
207 }
208
209 /// Construct a new [`Builder`](./struct.Builder.html).
builder() -> Builder210 pub fn builder() -> Builder {
211 Default::default()
212 }
213
214 impl Builder {
215 /// Generates the command line flags use for creating `Builder`.
command_line_flags(&self) -> Vec<String>216 pub fn command_line_flags(&self) -> Vec<String> {
217 let mut output_vector: Vec<String> = Vec::new();
218
219 if let Some(header) = self.input_headers.last().cloned() {
220 // Positional argument 'header'
221 output_vector.push(header);
222 }
223
224 output_vector.push("--rust-target".into());
225 output_vector.push(self.options.rust_target.into());
226
227 if self.options.default_enum_style != Default::default() {
228 output_vector.push("--default-enum-style=".into());
229 output_vector.push(
230 match self.options.default_enum_style {
231 codegen::EnumVariation::Rust {
232 non_exhaustive: false,
233 } => "rust",
234 codegen::EnumVariation::Rust {
235 non_exhaustive: true,
236 } => "rust_non_exhaustive",
237 codegen::EnumVariation::Bitfield => "bitfield",
238 codegen::EnumVariation::Consts => "consts",
239 codegen::EnumVariation::ModuleConsts => "moduleconsts",
240 }
241 .into(),
242 )
243 }
244
245 self.options
246 .bitfield_enums
247 .get_items()
248 .iter()
249 .map(|item| {
250 output_vector.push("--bitfield-enum".into());
251 output_vector.push(item.to_owned());
252 })
253 .count();
254
255 self.options
256 .rustified_enums
257 .get_items()
258 .iter()
259 .map(|item| {
260 output_vector.push("--rustified-enum".into());
261 output_vector.push(item.to_owned());
262 })
263 .count();
264
265 self.options
266 .rustified_non_exhaustive_enums
267 .get_items()
268 .iter()
269 .map(|item| {
270 output_vector.push("--rustified-enum-non-exhaustive".into());
271 output_vector.push(item.to_owned());
272 })
273 .count();
274
275 self.options
276 .constified_enum_modules
277 .get_items()
278 .iter()
279 .map(|item| {
280 output_vector.push("--constified-enum-module".into());
281 output_vector.push(item.to_owned());
282 })
283 .count();
284
285 self.options
286 .constified_enums
287 .get_items()
288 .iter()
289 .map(|item| {
290 output_vector.push("--constified-enum".into());
291 output_vector.push(item.to_owned());
292 })
293 .count();
294
295 self.options
296 .blacklisted_types
297 .get_items()
298 .iter()
299 .map(|item| {
300 output_vector.push("--blacklist-type".into());
301 output_vector.push(item.to_owned());
302 })
303 .count();
304
305 self.options
306 .blacklisted_functions
307 .get_items()
308 .iter()
309 .map(|item| {
310 output_vector.push("--blacklist-function".into());
311 output_vector.push(item.to_owned());
312 })
313 .count();
314
315 self.options
316 .blacklisted_items
317 .get_items()
318 .iter()
319 .map(|item| {
320 output_vector.push("--blacklist-item".into());
321 output_vector.push(item.to_owned());
322 })
323 .count();
324
325 if !self.options.layout_tests {
326 output_vector.push("--no-layout-tests".into());
327 }
328
329 if self.options.impl_debug {
330 output_vector.push("--impl-debug".into());
331 }
332
333 if self.options.impl_partialeq {
334 output_vector.push("--impl-partialeq".into());
335 }
336
337 if !self.options.derive_copy {
338 output_vector.push("--no-derive-copy".into());
339 }
340
341 if !self.options.derive_debug {
342 output_vector.push("--no-derive-debug".into());
343 }
344
345 if !self.options.derive_default {
346 output_vector.push("--no-derive-default".into());
347 } else {
348 output_vector.push("--with-derive-default".into());
349 }
350
351 if self.options.derive_hash {
352 output_vector.push("--with-derive-hash".into());
353 }
354
355 if self.options.derive_partialord {
356 output_vector.push("--with-derive-partialord".into());
357 }
358
359 if self.options.derive_ord {
360 output_vector.push("--with-derive-ord".into());
361 }
362
363 if self.options.derive_partialeq {
364 output_vector.push("--with-derive-partialeq".into());
365 }
366
367 if self.options.derive_eq {
368 output_vector.push("--with-derive-eq".into());
369 }
370
371 if self.options.time_phases {
372 output_vector.push("--time-phases".into());
373 }
374
375 if !self.options.generate_comments {
376 output_vector.push("--no-doc-comments".into());
377 }
378
379 if !self.options.whitelist_recursively {
380 output_vector.push("--no-recursive-whitelist".into());
381 }
382
383 if self.options.objc_extern_crate {
384 output_vector.push("--objc-extern-crate".into());
385 }
386
387 if self.options.generate_block {
388 output_vector.push("--generate-block".into());
389 }
390
391 if self.options.block_extern_crate {
392 output_vector.push("--block-extern-crate".into());
393 }
394
395 if self.options.builtins {
396 output_vector.push("--builtins".into());
397 }
398
399 if let Some(ref prefix) = self.options.ctypes_prefix {
400 output_vector.push("--ctypes-prefix".into());
401 output_vector.push(prefix.clone());
402 }
403
404 if self.options.emit_ast {
405 output_vector.push("--emit-clang-ast".into());
406 }
407
408 if self.options.emit_ir {
409 output_vector.push("--emit-ir".into());
410 }
411 if let Some(ref graph) = self.options.emit_ir_graphviz {
412 output_vector.push("--emit-ir-graphviz".into());
413 output_vector.push(graph.clone())
414 }
415 if self.options.enable_cxx_namespaces {
416 output_vector.push("--enable-cxx-namespaces".into());
417 }
418 if self.options.enable_function_attribute_detection {
419 output_vector.push("--enable-function-attribute-detection".into());
420 }
421 if self.options.disable_name_namespacing {
422 output_vector.push("--disable-name-namespacing".into());
423 }
424
425 if !self.options.codegen_config.functions() {
426 output_vector.push("--ignore-functions".into());
427 }
428
429 output_vector.push("--generate".into());
430
431 //Temporary placeholder for below 4 options
432 let mut options: Vec<String> = Vec::new();
433 if self.options.codegen_config.functions() {
434 options.push("functions".into());
435 }
436 if self.options.codegen_config.types() {
437 options.push("types".into());
438 }
439 if self.options.codegen_config.vars() {
440 options.push("vars".into());
441 }
442 if self.options.codegen_config.methods() {
443 options.push("methods".into());
444 }
445 if self.options.codegen_config.constructors() {
446 options.push("constructors".into());
447 }
448 if self.options.codegen_config.destructors() {
449 options.push("destructors".into());
450 }
451
452 output_vector.push(options.join(","));
453
454 if !self.options.codegen_config.methods() {
455 output_vector.push("--ignore-methods".into());
456 }
457
458 if !self.options.convert_floats {
459 output_vector.push("--no-convert-floats".into());
460 }
461
462 if !self.options.prepend_enum_name {
463 output_vector.push("--no-prepend-enum-name".into());
464 }
465
466 if self.options.array_pointers_in_arguments {
467 output_vector.push("--use-array-pointers-in-arguments".into());
468 }
469
470 self.options
471 .opaque_types
472 .get_items()
473 .iter()
474 .map(|item| {
475 output_vector.push("--opaque-type".into());
476 output_vector.push(item.to_owned());
477 })
478 .count();
479
480 self.options
481 .raw_lines
482 .iter()
483 .map(|item| {
484 output_vector.push("--raw-line".into());
485 output_vector.push(item.to_owned());
486 })
487 .count();
488
489 if self.options.use_core {
490 output_vector.push("--use-core".into());
491 }
492
493 if self.options.conservative_inline_namespaces {
494 output_vector.push("--conservative-inline-namespaces".into());
495 }
496
497 self.options
498 .whitelisted_functions
499 .get_items()
500 .iter()
501 .map(|item| {
502 output_vector.push("--whitelist-function".into());
503 output_vector.push(item.to_owned());
504 })
505 .count();
506
507 self.options
508 .whitelisted_types
509 .get_items()
510 .iter()
511 .map(|item| {
512 output_vector.push("--whitelist-type".into());
513 output_vector.push(item.to_owned());
514 })
515 .count();
516
517 self.options
518 .whitelisted_vars
519 .get_items()
520 .iter()
521 .map(|item| {
522 output_vector.push("--whitelist-var".into());
523 output_vector.push(item.to_owned());
524 })
525 .count();
526
527 output_vector.push("--".into());
528
529 if !self.options.clang_args.is_empty() {
530 output_vector.extend(self.options.clang_args.iter().cloned());
531 }
532
533 if self.input_headers.len() > 1 {
534 output_vector.extend(
535 self.input_headers[..self.input_headers.len() - 1]
536 .iter()
537 .cloned(),
538 );
539 }
540
541 if !self.options.record_matches {
542 output_vector.push("--no-record-matches".into());
543 }
544
545 if !self.options.rustfmt_bindings {
546 output_vector.push("--no-rustfmt-bindings".into());
547 }
548
549 if let Some(path) = self
550 .options
551 .rustfmt_configuration_file
552 .as_ref()
553 .and_then(|f| f.to_str())
554 {
555 output_vector.push("--rustfmt-configuration-file".into());
556 output_vector.push(path.into());
557 }
558
559 self.options
560 .no_partialeq_types
561 .get_items()
562 .iter()
563 .map(|item| {
564 output_vector.push("--no-partialeq".into());
565 output_vector.push(item.to_owned());
566 })
567 .count();
568
569 self.options
570 .no_copy_types
571 .get_items()
572 .iter()
573 .map(|item| {
574 output_vector.push("--no-copy".into());
575 output_vector.push(item.to_owned());
576 })
577 .count();
578
579 self.options
580 .no_hash_types
581 .get_items()
582 .iter()
583 .map(|item| {
584 output_vector.push("--no-hash".into());
585 output_vector.push(item.to_owned());
586 })
587 .count();
588
589 output_vector
590 }
591
592 /// Add an input C/C++ header to generate bindings for.
593 ///
594 /// This can be used to generate bindings to a single header:
595 ///
596 /// ```ignore
597 /// let bindings = bindgen::Builder::default()
598 /// .header("input.h")
599 /// .generate()
600 /// .unwrap();
601 /// ```
602 ///
603 /// Or you can invoke it multiple times to generate bindings to multiple
604 /// headers:
605 ///
606 /// ```ignore
607 /// let bindings = bindgen::Builder::default()
608 /// .header("first.h")
609 /// .header("second.h")
610 /// .header("third.h")
611 /// .generate()
612 /// .unwrap();
613 /// ```
header<T: Into<String>>(mut self, header: T) -> Builder614 pub fn header<T: Into<String>>(mut self, header: T) -> Builder {
615 self.input_headers.push(header.into());
616 self
617 }
618
619 /// Add `contents` as an input C/C++ header named `name`.
620 ///
621 /// The file `name` will be added to the clang arguments.
header_contents(mut self, name: &str, contents: &str) -> Builder622 pub fn header_contents(mut self, name: &str, contents: &str) -> Builder {
623 self.input_header_contents
624 .push((name.into(), contents.into()));
625 self
626 }
627
628 /// Specify the rust target
629 ///
630 /// The default is the latest stable Rust version
rust_target(mut self, rust_target: RustTarget) -> Self631 pub fn rust_target(mut self, rust_target: RustTarget) -> Self {
632 self.options.set_rust_target(rust_target);
633 self
634 }
635
636 /// Disable support for native Rust unions, if supported.
disable_untagged_union(mut self) -> Self637 pub fn disable_untagged_union(mut self) -> Self {
638 self.options.rust_features.untagged_union = false;
639 self
640 }
641
642 /// Set the output graphviz file.
emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder643 pub fn emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder {
644 let path = path.into();
645 self.options.emit_ir_graphviz = Some(path);
646 self
647 }
648
649 /// Whether the generated bindings should contain documentation comments or
650 /// not.
651 ///
652 /// This ideally will always be true, but it may need to be false until we
653 /// implement some processing on comments to work around issues as described
654 /// in:
655 ///
656 /// https://github.com/rust-lang/rust-bindgen/issues/426
generate_comments(mut self, doit: bool) -> Self657 pub fn generate_comments(mut self, doit: bool) -> Self {
658 self.options.generate_comments = doit;
659 self
660 }
661
662 /// Whether to whitelist recursively or not. Defaults to true.
663 ///
664 /// Given that we have explicitly whitelisted the "initiate_dance_party"
665 /// function in this C header:
666 ///
667 /// ```c
668 /// typedef struct MoonBoots {
669 /// int bouncy_level;
670 /// } MoonBoots;
671 ///
672 /// void initiate_dance_party(MoonBoots* boots);
673 /// ```
674 ///
675 /// We would normally generate bindings to both the `initiate_dance_party`
676 /// function and the `MoonBoots` struct that it transitively references. By
677 /// configuring with `whitelist_recursively(false)`, `bindgen` will not emit
678 /// bindings for anything except the explicitly whitelisted items, and there
679 /// would be no emitted struct definition for `MoonBoots`. However, the
680 /// `initiate_dance_party` function would still reference `MoonBoots`!
681 ///
682 /// **Disabling this feature will almost certainly cause `bindgen` to emit
683 /// bindings that will not compile!** If you disable this feature, then it
684 /// is *your* responsibility to provide definitions for every type that is
685 /// referenced from an explicitly whitelisted item. One way to provide the
686 /// definitions is by using the [`Builder::raw_line`](#method.raw_line)
687 /// method, another would be to define them in Rust and then `include!(...)`
688 /// the bindings immediately afterwards.
whitelist_recursively(mut self, doit: bool) -> Self689 pub fn whitelist_recursively(mut self, doit: bool) -> Self {
690 self.options.whitelist_recursively = doit;
691 self
692 }
693
694 /// Generate `#[macro_use] extern crate objc;` instead of `use objc;`
695 /// in the prologue of the files generated from objective-c files
objc_extern_crate(mut self, doit: bool) -> Self696 pub fn objc_extern_crate(mut self, doit: bool) -> Self {
697 self.options.objc_extern_crate = doit;
698 self
699 }
700
701 /// Generate proper block signatures instead of void pointers.
generate_block(mut self, doit: bool) -> Self702 pub fn generate_block(mut self, doit: bool) -> Self {
703 self.options.generate_block = doit;
704 self
705 }
706
707 /// Generate `#[macro_use] extern crate block;` instead of `use block;`
708 /// in the prologue of the files generated from apple block files
block_extern_crate(mut self, doit: bool) -> Self709 pub fn block_extern_crate(mut self, doit: bool) -> Self {
710 self.options.block_extern_crate = doit;
711 self
712 }
713
714 /// Whether to use the clang-provided name mangling. This is true by default
715 /// and probably needed for C++ features.
716 ///
717 /// However, some old libclang versions seem to return incorrect results in
718 /// some cases for non-mangled functions, see [1], so we allow disabling it.
719 ///
720 /// [1]: https://github.com/rust-lang/rust-bindgen/issues/528
trust_clang_mangling(mut self, doit: bool) -> Self721 pub fn trust_clang_mangling(mut self, doit: bool) -> Self {
722 self.options.enable_mangling = doit;
723 self
724 }
725
726 /// Hide the given type from the generated bindings. Regular expressions are
727 /// supported.
728 #[deprecated(note = "Use blacklist_type instead")]
hide_type<T: AsRef<str>>(self, arg: T) -> Builder729 pub fn hide_type<T: AsRef<str>>(self, arg: T) -> Builder {
730 self.blacklist_type(arg)
731 }
732
733 /// Hide the given type from the generated bindings. Regular expressions are
734 /// supported.
blacklist_type<T: AsRef<str>>(mut self, arg: T) -> Builder735 pub fn blacklist_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
736 self.options.blacklisted_types.insert(arg);
737 self
738 }
739
740 /// Hide the given function from the generated bindings. Regular expressions
741 /// are supported.
blacklist_function<T: AsRef<str>>(mut self, arg: T) -> Builder742 pub fn blacklist_function<T: AsRef<str>>(mut self, arg: T) -> Builder {
743 self.options.blacklisted_functions.insert(arg);
744 self
745 }
746
747 /// Hide the given item from the generated bindings, regardless of
748 /// whether it's a type, function, module, etc. Regular
749 /// expressions are supported.
blacklist_item<T: AsRef<str>>(mut self, arg: T) -> Builder750 pub fn blacklist_item<T: AsRef<str>>(mut self, arg: T) -> Builder {
751 self.options.blacklisted_items.insert(arg);
752 self
753 }
754
755 /// Treat the given type as opaque in the generated bindings. Regular
756 /// expressions are supported.
opaque_type<T: AsRef<str>>(mut self, arg: T) -> Builder757 pub fn opaque_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
758 self.options.opaque_types.insert(arg);
759 self
760 }
761
762 /// Whitelist the given type so that it (and all types that it transitively
763 /// refers to) appears in the generated bindings. Regular expressions are
764 /// supported.
765 #[deprecated(note = "use whitelist_type instead")]
whitelisted_type<T: AsRef<str>>(self, arg: T) -> Builder766 pub fn whitelisted_type<T: AsRef<str>>(self, arg: T) -> Builder {
767 self.whitelist_type(arg)
768 }
769
770 /// Whitelist the given type so that it (and all types that it transitively
771 /// refers to) appears in the generated bindings. Regular expressions are
772 /// supported.
whitelist_type<T: AsRef<str>>(mut self, arg: T) -> Builder773 pub fn whitelist_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
774 self.options.whitelisted_types.insert(arg);
775 self
776 }
777
778 /// Whitelist the given function so that it (and all types that it
779 /// transitively refers to) appears in the generated bindings. Regular
780 /// expressions are supported.
whitelist_function<T: AsRef<str>>(mut self, arg: T) -> Builder781 pub fn whitelist_function<T: AsRef<str>>(mut self, arg: T) -> Builder {
782 self.options.whitelisted_functions.insert(arg);
783 self
784 }
785
786 /// Whitelist the given function.
787 ///
788 /// Deprecated: use whitelist_function instead.
789 #[deprecated(note = "use whitelist_function instead")]
whitelisted_function<T: AsRef<str>>(self, arg: T) -> Builder790 pub fn whitelisted_function<T: AsRef<str>>(self, arg: T) -> Builder {
791 self.whitelist_function(arg)
792 }
793
794 /// Whitelist the given variable so that it (and all types that it
795 /// transitively refers to) appears in the generated bindings. Regular
796 /// expressions are supported.
whitelist_var<T: AsRef<str>>(mut self, arg: T) -> Builder797 pub fn whitelist_var<T: AsRef<str>>(mut self, arg: T) -> Builder {
798 self.options.whitelisted_vars.insert(arg);
799 self
800 }
801
802 /// Whitelist the given variable.
803 ///
804 /// Deprecated: use whitelist_var instead.
805 #[deprecated(note = "use whitelist_var instead")]
whitelisted_var<T: AsRef<str>>(self, arg: T) -> Builder806 pub fn whitelisted_var<T: AsRef<str>>(self, arg: T) -> Builder {
807 self.whitelist_var(arg)
808 }
809
810 /// Set the default style of code to generate for enums
default_enum_style( mut self, arg: codegen::EnumVariation, ) -> Builder811 pub fn default_enum_style(
812 mut self,
813 arg: codegen::EnumVariation,
814 ) -> Builder {
815 self.options.default_enum_style = arg;
816 self
817 }
818
819 /// Mark the given enum (or set of enums, if using a pattern) as being
820 /// bitfield-like. Regular expressions are supported.
821 ///
822 /// This makes bindgen generate a type that isn't a rust `enum`. Regular
823 /// expressions are supported.
bitfield_enum<T: AsRef<str>>(mut self, arg: T) -> Builder824 pub fn bitfield_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
825 self.options.bitfield_enums.insert(arg);
826 self
827 }
828
829 /// Mark the given enum (or set of enums, if using a pattern) as a Rust
830 /// enum.
831 ///
832 /// This makes bindgen generate enums instead of constants. Regular
833 /// expressions are supported.
834 ///
835 /// **Use this with caution,** you probably want to use the non_exhaustive
836 /// flavor of rust enums instead of this one. Take a look at
837 /// https://github.com/rust-lang/rust/issues/36927 for more information.
rustified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder838 pub fn rustified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
839 self.options.rustified_enums.insert(arg);
840 self
841 }
842
843 /// Mark the given enum (or set of enums, if using a pattern) as a Rust
844 /// enum with the #[non_exhaustive] attribute.
845 ///
846 /// This makes bindgen generate enums instead of constants. Regular
847 /// expressions are supported.
rustified_non_exhaustive_enum<T: AsRef<str>>( mut self, arg: T, ) -> Builder848 pub fn rustified_non_exhaustive_enum<T: AsRef<str>>(
849 mut self,
850 arg: T,
851 ) -> Builder {
852 self.options.rustified_non_exhaustive_enums.insert(arg);
853 self
854 }
855
856 /// Mark the given enum (or set of enums, if using a pattern) as a set of
857 /// constants that are not to be put into a module.
constified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder858 pub fn constified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
859 self.options.constified_enums.insert(arg);
860 self
861 }
862
863 /// Mark the given enum (or set of enums, if using a pattern) as a set of
864 /// constants that should be put into a module.
865 ///
866 /// This makes bindgen generate modules containing constants instead of
867 /// just constants. Regular expressions are supported.
constified_enum_module<T: AsRef<str>>(mut self, arg: T) -> Builder868 pub fn constified_enum_module<T: AsRef<str>>(mut self, arg: T) -> Builder {
869 self.options.constified_enum_modules.insert(arg);
870 self
871 }
872
873 /// Add a string to prepend to the generated bindings. The string is passed
874 /// through without any modification.
raw_line<T: Into<String>>(mut self, arg: T) -> Self875 pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Self {
876 self.options.raw_lines.push(arg.into());
877 self
878 }
879
880 /// Add a given line to the beginning of module `mod`.
module_raw_line<T, U>(mut self, mod_: T, line: U) -> Self where T: Into<String>, U: Into<String>,881 pub fn module_raw_line<T, U>(mut self, mod_: T, line: U) -> Self
882 where
883 T: Into<String>,
884 U: Into<String>,
885 {
886 self.options
887 .module_lines
888 .entry(mod_.into())
889 .or_insert_with(Vec::new)
890 .push(line.into());
891 self
892 }
893
894 /// Add a given set of lines to the beginning of module `mod`.
module_raw_lines<T, I>(mut self, mod_: T, lines: I) -> Self where T: Into<String>, I: IntoIterator, I::Item: Into<String>,895 pub fn module_raw_lines<T, I>(mut self, mod_: T, lines: I) -> Self
896 where
897 T: Into<String>,
898 I: IntoIterator,
899 I::Item: Into<String>,
900 {
901 self.options
902 .module_lines
903 .entry(mod_.into())
904 .or_insert_with(Vec::new)
905 .extend(lines.into_iter().map(Into::into));
906 self
907 }
908
909 /// Add an argument to be passed straight through to clang.
clang_arg<T: Into<String>>(mut self, arg: T) -> Builder910 pub fn clang_arg<T: Into<String>>(mut self, arg: T) -> Builder {
911 self.options.clang_args.push(arg.into());
912 self
913 }
914
915 /// Add arguments to be passed straight through to clang.
clang_args<I>(mut self, iter: I) -> Builder where I: IntoIterator, I::Item: AsRef<str>,916 pub fn clang_args<I>(mut self, iter: I) -> Builder
917 where
918 I: IntoIterator,
919 I::Item: AsRef<str>,
920 {
921 for arg in iter {
922 self = self.clang_arg(arg.as_ref())
923 }
924 self
925 }
926
927 /// Emit bindings for builtin definitions (for example `__builtin_va_list`)
928 /// in the generated Rust.
emit_builtins(mut self) -> Builder929 pub fn emit_builtins(mut self) -> Builder {
930 self.options.builtins = true;
931 self
932 }
933
934 /// Avoid converting floats to `f32`/`f64` by default.
no_convert_floats(mut self) -> Self935 pub fn no_convert_floats(mut self) -> Self {
936 self.options.convert_floats = false;
937 self
938 }
939
940 /// Set whether layout tests should be generated.
layout_tests(mut self, doit: bool) -> Self941 pub fn layout_tests(mut self, doit: bool) -> Self {
942 self.options.layout_tests = doit;
943 self
944 }
945
946 /// Set whether `Debug` should be implemented, if it can not be derived automatically.
impl_debug(mut self, doit: bool) -> Self947 pub fn impl_debug(mut self, doit: bool) -> Self {
948 self.options.impl_debug = doit;
949 self
950 }
951
952 /// Set whether `PartialEq` should be implemented, if it can not be derived automatically.
impl_partialeq(mut self, doit: bool) -> Self953 pub fn impl_partialeq(mut self, doit: bool) -> Self {
954 self.options.impl_partialeq = doit;
955 self
956 }
957
958 /// Set whether `Copy` should be derived by default.
derive_copy(mut self, doit: bool) -> Self959 pub fn derive_copy(mut self, doit: bool) -> Self {
960 self.options.derive_copy = doit;
961 self
962 }
963
964 /// Set whether `Debug` should be derived by default.
derive_debug(mut self, doit: bool) -> Self965 pub fn derive_debug(mut self, doit: bool) -> Self {
966 self.options.derive_debug = doit;
967 self
968 }
969
970 /// Set whether `Default` should be derived by default.
derive_default(mut self, doit: bool) -> Self971 pub fn derive_default(mut self, doit: bool) -> Self {
972 self.options.derive_default = doit;
973 self
974 }
975
976 /// Set whether `Hash` should be derived by default.
derive_hash(mut self, doit: bool) -> Self977 pub fn derive_hash(mut self, doit: bool) -> Self {
978 self.options.derive_hash = doit;
979 self
980 }
981
982 /// Set whether `PartialOrd` should be derived by default.
983 /// If we don't compute partialord, we also cannot compute
984 /// ord. Set the derive_ord to `false` when doit is `false`.
derive_partialord(mut self, doit: bool) -> Self985 pub fn derive_partialord(mut self, doit: bool) -> Self {
986 self.options.derive_partialord = doit;
987 if !doit {
988 self.options.derive_ord = false;
989 }
990 self
991 }
992
993 /// Set whether `Ord` should be derived by default.
994 /// We can't compute `Ord` without computing `PartialOrd`,
995 /// so we set the same option to derive_partialord.
derive_ord(mut self, doit: bool) -> Self996 pub fn derive_ord(mut self, doit: bool) -> Self {
997 self.options.derive_ord = doit;
998 self.options.derive_partialord = doit;
999 self
1000 }
1001
1002 /// Set whether `PartialEq` should be derived by default.
1003 ///
1004 /// If we don't derive `PartialEq`, we also cannot derive `Eq`, so deriving
1005 /// `Eq` is also disabled when `doit` is `false`.
derive_partialeq(mut self, doit: bool) -> Self1006 pub fn derive_partialeq(mut self, doit: bool) -> Self {
1007 self.options.derive_partialeq = doit;
1008 if !doit {
1009 self.options.derive_eq = false;
1010 }
1011 self
1012 }
1013
1014 /// Set whether `Eq` should be derived by default.
1015 ///
1016 /// We can't derive `Eq` without also deriving `PartialEq`, so we also
1017 /// enable deriving `PartialEq` when `doit` is `true`.
derive_eq(mut self, doit: bool) -> Self1018 pub fn derive_eq(mut self, doit: bool) -> Self {
1019 self.options.derive_eq = doit;
1020 if doit {
1021 self.options.derive_partialeq = doit;
1022 }
1023 self
1024 }
1025
1026 /// Set whether or not to time bindgen phases, and print information to
1027 /// stderr.
time_phases(mut self, doit: bool) -> Self1028 pub fn time_phases(mut self, doit: bool) -> Self {
1029 self.options.time_phases = doit;
1030 self
1031 }
1032
1033 /// Emit Clang AST.
emit_clang_ast(mut self) -> Builder1034 pub fn emit_clang_ast(mut self) -> Builder {
1035 self.options.emit_ast = true;
1036 self
1037 }
1038
1039 /// Emit IR.
emit_ir(mut self) -> Builder1040 pub fn emit_ir(mut self) -> Builder {
1041 self.options.emit_ir = true;
1042 self
1043 }
1044
1045 /// Enable C++ namespaces.
enable_cxx_namespaces(mut self) -> Builder1046 pub fn enable_cxx_namespaces(mut self) -> Builder {
1047 self.options.enable_cxx_namespaces = true;
1048 self
1049 }
1050
1051 /// Enable detecting must_use attributes on C functions.
1052 ///
1053 /// This is quite slow in some cases (see #1465), so it's disabled by
1054 /// default.
1055 ///
1056 /// Note that for this to do something meaningful for now at least, the rust
1057 /// target version has to have support for `#[must_use]`.
enable_function_attribute_detection(mut self) -> Self1058 pub fn enable_function_attribute_detection(mut self) -> Self {
1059 self.options.enable_function_attribute_detection = true;
1060 self
1061 }
1062
1063 /// Disable name auto-namespacing.
1064 ///
1065 /// By default, bindgen mangles names like `foo::bar::Baz` to look like
1066 /// `foo_bar_Baz` instead of just `Baz`.
1067 ///
1068 /// This method disables that behavior.
1069 ///
1070 /// Note that this intentionally does not change the names used for
1071 /// whitelisting and blacklisting, which should still be mangled with the
1072 /// namespaces.
1073 ///
1074 /// Note, also, that this option may cause bindgen to generate duplicate
1075 /// names.
disable_name_namespacing(mut self) -> Builder1076 pub fn disable_name_namespacing(mut self) -> Builder {
1077 self.options.disable_name_namespacing = true;
1078 self
1079 }
1080
1081 /// Treat inline namespaces conservatively.
1082 ///
1083 /// This is tricky, because in C++ is technically legal to override an item
1084 /// defined in an inline namespace:
1085 ///
1086 /// ```cpp
1087 /// inline namespace foo {
1088 /// using Bar = int;
1089 /// }
1090 /// using Bar = long;
1091 /// ```
1092 ///
1093 /// Even though referencing `Bar` is a compiler error.
1094 ///
1095 /// We want to support this (arguably esoteric) use case, but we don't want
1096 /// to make the rest of bindgen users pay an usability penalty for that.
1097 ///
1098 /// To support this, we need to keep all the inline namespaces around, but
1099 /// then bindgen usage is a bit more difficult, because you cannot
1100 /// reference, e.g., `std::string` (you'd need to use the proper inline
1101 /// namespace).
1102 ///
1103 /// We could complicate a lot of the logic to detect name collisions, and if
1104 /// not detected generate a `pub use inline_ns::*` or something like that.
1105 ///
1106 /// That's probably something we can do if we see this option is needed in a
1107 /// lot of cases, to improve it's usability, but my guess is that this is
1108 /// not going to be too useful.
conservative_inline_namespaces(mut self) -> Builder1109 pub fn conservative_inline_namespaces(mut self) -> Builder {
1110 self.options.conservative_inline_namespaces = true;
1111 self
1112 }
1113
1114 /// Whether inline functions should be generated or not.
1115 ///
1116 /// Note that they will usually not work. However you can use
1117 /// `-fkeep-inline-functions` or `-fno-inline-functions` if you are
1118 /// responsible of compiling the library to make them callable.
generate_inline_functions(mut self, doit: bool) -> Self1119 pub fn generate_inline_functions(mut self, doit: bool) -> Self {
1120 self.options.generate_inline_functions = doit;
1121 self
1122 }
1123
1124 /// Ignore functions.
ignore_functions(mut self) -> Builder1125 pub fn ignore_functions(mut self) -> Builder {
1126 self.options.codegen_config.remove(CodegenConfig::FUNCTIONS);
1127 self
1128 }
1129
1130 /// Ignore methods.
ignore_methods(mut self) -> Builder1131 pub fn ignore_methods(mut self) -> Builder {
1132 self.options.codegen_config.remove(CodegenConfig::METHODS);
1133 self
1134 }
1135
1136 /// Avoid generating any unstable Rust, such as Rust unions, in the generated bindings.
1137 #[deprecated(note = "please use `rust_target` instead")]
unstable_rust(self, doit: bool) -> Self1138 pub fn unstable_rust(self, doit: bool) -> Self {
1139 let rust_target = if doit {
1140 RustTarget::Nightly
1141 } else {
1142 LATEST_STABLE_RUST
1143 };
1144 self.rust_target(rust_target)
1145 }
1146
1147 /// Use core instead of libstd in the generated bindings.
use_core(mut self) -> Builder1148 pub fn use_core(mut self) -> Builder {
1149 self.options.use_core = true;
1150 self
1151 }
1152
1153 /// Use the given prefix for the raw types instead of `::std::os::raw`.
ctypes_prefix<T: Into<String>>(mut self, prefix: T) -> Builder1154 pub fn ctypes_prefix<T: Into<String>>(mut self, prefix: T) -> Builder {
1155 self.options.ctypes_prefix = Some(prefix.into());
1156 self
1157 }
1158
1159 /// Allows configuring types in different situations, see the
1160 /// [`ParseCallbacks`](./callbacks/trait.ParseCallbacks.html) documentation.
parse_callbacks( mut self, cb: Box<dyn callbacks::ParseCallbacks>, ) -> Self1161 pub fn parse_callbacks(
1162 mut self,
1163 cb: Box<dyn callbacks::ParseCallbacks>,
1164 ) -> Self {
1165 self.options.parse_callbacks = Some(cb);
1166 self
1167 }
1168
1169 /// Choose what to generate using a
1170 /// [`CodegenConfig`](./struct.CodegenConfig.html).
with_codegen_config(mut self, config: CodegenConfig) -> Self1171 pub fn with_codegen_config(mut self, config: CodegenConfig) -> Self {
1172 self.options.codegen_config = config;
1173 self
1174 }
1175
1176 /// Whether to detect include paths using clang_sys.
detect_include_paths(mut self, doit: bool) -> Self1177 pub fn detect_include_paths(mut self, doit: bool) -> Self {
1178 self.options.detect_include_paths = doit;
1179 self
1180 }
1181
1182 /// Prepend the enum name to constant or bitfield variants.
prepend_enum_name(mut self, doit: bool) -> Self1183 pub fn prepend_enum_name(mut self, doit: bool) -> Self {
1184 self.options.prepend_enum_name = doit;
1185 self
1186 }
1187
1188 /// Set whether rustfmt should format the generated bindings.
rustfmt_bindings(mut self, doit: bool) -> Self1189 pub fn rustfmt_bindings(mut self, doit: bool) -> Self {
1190 self.options.rustfmt_bindings = doit;
1191 self
1192 }
1193
1194 /// Set whether we should record matched items in our regex sets.
record_matches(mut self, doit: bool) -> Self1195 pub fn record_matches(mut self, doit: bool) -> Self {
1196 self.options.record_matches = doit;
1197 self
1198 }
1199
1200 /// Set the absolute path to the rustfmt configuration file, if None, the standard rustfmt
1201 /// options are used.
rustfmt_configuration_file(mut self, path: Option<PathBuf>) -> Self1202 pub fn rustfmt_configuration_file(mut self, path: Option<PathBuf>) -> Self {
1203 self = self.rustfmt_bindings(true);
1204 self.options.rustfmt_configuration_file = path;
1205 self
1206 }
1207
1208 /// Sets an explicit path to rustfmt, to be used when rustfmt is enabled.
with_rustfmt<P: Into<PathBuf>>(mut self, path: P) -> Self1209 pub fn with_rustfmt<P: Into<PathBuf>>(mut self, path: P) -> Self {
1210 self.options.rustfmt_path = Some(path.into());
1211 self
1212 }
1213
1214 /// Generate the Rust bindings using the options built up thus far.
generate(mut self) -> Result<Bindings, ()>1215 pub fn generate(mut self) -> Result<Bindings, ()> {
1216 // Add any extra arguments from the environment to the clang command line.
1217 if let Some(extra_clang_args) =
1218 env::var("BINDGEN_EXTRA_CLANG_ARGS").ok()
1219 {
1220 // Try to parse it with shell quoting. If we fail, make it one single big argument.
1221 if let Some(strings) = shlex::split(&extra_clang_args) {
1222 self.options.clang_args.extend(strings);
1223 } else {
1224 self.options.clang_args.push(extra_clang_args);
1225 };
1226 }
1227
1228 // Transform input headers to arguments on the clang command line.
1229 self.options.input_header = self.input_headers.pop();
1230 self.options
1231 .clang_args
1232 .extend(self.input_headers.drain(..).flat_map(|header| {
1233 iter::once("-include".into()).chain(iter::once(header))
1234 }));
1235
1236 self.options.input_unsaved_files.extend(
1237 self.input_header_contents
1238 .drain(..)
1239 .map(|(name, contents)| {
1240 clang::UnsavedFile::new(&name, &contents)
1241 }),
1242 );
1243
1244 Bindings::generate(self.options)
1245 }
1246
1247 /// Preprocess and dump the input header files to disk.
1248 ///
1249 /// This is useful when debugging bindgen, using C-Reduce, or when filing
1250 /// issues. The resulting file will be named something like `__bindgen.i` or
1251 /// `__bindgen.ii`
dump_preprocessed_input(&self) -> io::Result<()>1252 pub fn dump_preprocessed_input(&self) -> io::Result<()> {
1253 fn check_is_cpp(name_file: &str) -> bool {
1254 name_file.ends_with(".hpp") ||
1255 name_file.ends_with(".hxx") ||
1256 name_file.ends_with(".hh") ||
1257 name_file.ends_with(".h++")
1258 }
1259
1260 let clang =
1261 clang_sys::support::Clang::find(None, &[]).ok_or_else(|| {
1262 io::Error::new(
1263 io::ErrorKind::Other,
1264 "Cannot find clang executable",
1265 )
1266 })?;
1267
1268 // The contents of a wrapper file that includes all the input header
1269 // files.
1270 let mut wrapper_contents = String::new();
1271
1272 // Whether we are working with C or C++ inputs.
1273 let mut is_cpp = args_are_cpp(&self.options.clang_args);
1274
1275 // For each input header, add `#include "$header"`.
1276 for header in &self.input_headers {
1277 is_cpp |= check_is_cpp(header);
1278
1279 wrapper_contents.push_str("#include \"");
1280 wrapper_contents.push_str(header);
1281 wrapper_contents.push_str("\"\n");
1282 }
1283
1284 // For each input header content, add a prefix line of `#line 0 "$name"`
1285 // followed by the contents.
1286 for &(ref name, ref contents) in &self.input_header_contents {
1287 is_cpp |= check_is_cpp(name);
1288
1289 wrapper_contents.push_str("#line 0 \"");
1290 wrapper_contents.push_str(name);
1291 wrapper_contents.push_str("\"\n");
1292 wrapper_contents.push_str(contents);
1293 }
1294
1295 let wrapper_path = PathBuf::from(if is_cpp {
1296 "__bindgen.cpp"
1297 } else {
1298 "__bindgen.c"
1299 });
1300
1301 {
1302 let mut wrapper_file = File::create(&wrapper_path)?;
1303 wrapper_file.write(wrapper_contents.as_bytes())?;
1304 }
1305
1306 let mut cmd = Command::new(&clang.path);
1307 cmd.arg("-save-temps")
1308 .arg("-E")
1309 .arg("-C")
1310 .arg("-c")
1311 .arg(&wrapper_path)
1312 .stdout(Stdio::piped());
1313
1314 for a in &self.options.clang_args {
1315 cmd.arg(a);
1316 }
1317
1318 let mut child = cmd.spawn()?;
1319
1320 let mut preprocessed = child.stdout.take().unwrap();
1321 let mut file = File::create(if is_cpp {
1322 "__bindgen.ii"
1323 } else {
1324 "__bindgen.i"
1325 })?;
1326 io::copy(&mut preprocessed, &mut file)?;
1327
1328 if child.wait()?.success() {
1329 Ok(())
1330 } else {
1331 Err(io::Error::new(
1332 io::ErrorKind::Other,
1333 "clang exited with non-zero status",
1334 ))
1335 }
1336 }
1337
1338 /// Don't derive `PartialEq` for a given type. Regular
1339 /// expressions are supported.
no_partialeq<T: Into<String>>(mut self, arg: T) -> Builder1340 pub fn no_partialeq<T: Into<String>>(mut self, arg: T) -> Builder {
1341 self.options.no_partialeq_types.insert(arg.into());
1342 self
1343 }
1344
1345 /// Don't derive `Copy` for a given type. Regular
1346 /// expressions are supported.
no_copy<T: Into<String>>(mut self, arg: T) -> Self1347 pub fn no_copy<T: Into<String>>(mut self, arg: T) -> Self {
1348 self.options.no_copy_types.insert(arg.into());
1349 self
1350 }
1351
1352 /// Don't derive `Hash` for a given type. Regular
1353 /// expressions are supported.
no_hash<T: Into<String>>(mut self, arg: T) -> Builder1354 pub fn no_hash<T: Into<String>>(mut self, arg: T) -> Builder {
1355 self.options.no_hash_types.insert(arg.into());
1356 self
1357 }
1358
1359 /// Set whether `arr[size]` should be treated as `*mut T` or `*mut [T; size]` (same for mut)
array_pointers_in_arguments(mut self, doit: bool) -> Self1360 pub fn array_pointers_in_arguments(mut self, doit: bool) -> Self {
1361 self.options.array_pointers_in_arguments = doit;
1362 self
1363 }
1364 }
1365
1366 /// Configuration options for generated bindings.
1367 #[derive(Debug)]
1368 struct BindgenOptions {
1369 /// The set of types that have been blacklisted and should not appear
1370 /// anywhere in the generated code.
1371 blacklisted_types: RegexSet,
1372
1373 /// The set of functions that have been blacklisted and should not appear
1374 /// in the generated code.
1375 blacklisted_functions: RegexSet,
1376
1377 /// The set of items, regardless of item-type, that have been
1378 /// blacklisted and should not appear in the generated code.
1379 blacklisted_items: RegexSet,
1380
1381 /// The set of types that should be treated as opaque structures in the
1382 /// generated code.
1383 opaque_types: RegexSet,
1384
1385 /// The explicit rustfmt path.
1386 rustfmt_path: Option<PathBuf>,
1387
1388 /// The set of types that we should have bindings for in the generated
1389 /// code.
1390 ///
1391 /// This includes all types transitively reachable from any type in this
1392 /// set. One might think of whitelisted types/vars/functions as GC roots,
1393 /// and the generated Rust code as including everything that gets marked.
1394 whitelisted_types: RegexSet,
1395
1396 /// Whitelisted functions. See docs for `whitelisted_types` for more.
1397 whitelisted_functions: RegexSet,
1398
1399 /// Whitelisted variables. See docs for `whitelisted_types` for more.
1400 whitelisted_vars: RegexSet,
1401
1402 /// The default style of code to generate for enums
1403 default_enum_style: codegen::EnumVariation,
1404
1405 /// The enum patterns to mark an enum as bitfield.
1406 bitfield_enums: RegexSet,
1407
1408 /// The enum patterns to mark an enum as a Rust enum.
1409 rustified_enums: RegexSet,
1410
1411 rustified_non_exhaustive_enums: RegexSet,
1412
1413 /// The enum patterns to mark an enum as a module of constants.
1414 constified_enum_modules: RegexSet,
1415
1416 /// The enum patterns to mark an enum as a set of constants.
1417 constified_enums: RegexSet,
1418
1419 /// Whether we should generate builtins or not.
1420 builtins: bool,
1421
1422 /// True if we should dump the Clang AST for debugging purposes.
1423 emit_ast: bool,
1424
1425 /// True if we should dump our internal IR for debugging purposes.
1426 emit_ir: bool,
1427
1428 /// Output graphviz dot file.
1429 emit_ir_graphviz: Option<String>,
1430
1431 /// True if we should emulate C++ namespaces with Rust modules in the
1432 /// generated bindings.
1433 enable_cxx_namespaces: bool,
1434
1435 /// True if we should try to find unexposed attributes in functions, in
1436 /// order to be able to generate #[must_use] attributes in Rust.
1437 enable_function_attribute_detection: bool,
1438
1439 /// True if we should avoid mangling names with namespaces.
1440 disable_name_namespacing: bool,
1441
1442 /// True if we should generate layout tests for generated structures.
1443 layout_tests: bool,
1444
1445 /// True if we should implement the Debug trait for C/C++ structures and types
1446 /// that do not support automatically deriving Debug.
1447 impl_debug: bool,
1448
1449 /// True if we should implement the PartialEq trait for C/C++ structures and types
1450 /// that do not support automatically deriving PartialEq.
1451 impl_partialeq: bool,
1452
1453 /// True if we should derive Copy trait implementations for C/C++ structures
1454 /// and types.
1455 derive_copy: bool,
1456
1457 /// True if we should derive Debug trait implementations for C/C++ structures
1458 /// and types.
1459 derive_debug: bool,
1460
1461 /// True if we should derive Default trait implementations for C/C++ structures
1462 /// and types.
1463 derive_default: bool,
1464
1465 /// True if we should derive Hash trait implementations for C/C++ structures
1466 /// and types.
1467 derive_hash: bool,
1468
1469 /// True if we should derive PartialOrd trait implementations for C/C++ structures
1470 /// and types.
1471 derive_partialord: bool,
1472
1473 /// True if we should derive Ord trait implementations for C/C++ structures
1474 /// and types.
1475 derive_ord: bool,
1476
1477 /// True if we should derive PartialEq trait implementations for C/C++ structures
1478 /// and types.
1479 derive_partialeq: bool,
1480
1481 /// True if we should derive Eq trait implementations for C/C++ structures
1482 /// and types.
1483 derive_eq: bool,
1484
1485 /// True if we should avoid using libstd to use libcore instead.
1486 use_core: bool,
1487
1488 /// An optional prefix for the "raw" types, like `c_int`, `c_void`...
1489 ctypes_prefix: Option<String>,
1490
1491 /// Whether to time the bindgen phases.
1492 time_phases: bool,
1493
1494 /// True if we should generate constant names that are **directly** under
1495 /// namespaces.
1496 namespaced_constants: bool,
1497
1498 /// True if we should use MSVC name mangling rules.
1499 msvc_mangling: bool,
1500
1501 /// Whether we should convert float types to f32/f64 types.
1502 convert_floats: bool,
1503
1504 /// The set of raw lines to prepend to the top-level module of generated
1505 /// Rust code.
1506 raw_lines: Vec<String>,
1507
1508 /// The set of raw lines to prepend to each of the modules.
1509 ///
1510 /// This only makes sense if the `enable_cxx_namespaces` option is set.
1511 module_lines: HashMap<String, Vec<String>>,
1512
1513 /// The set of arguments to pass straight through to Clang.
1514 clang_args: Vec<String>,
1515
1516 /// The input header file.
1517 input_header: Option<String>,
1518
1519 /// Unsaved files for input.
1520 input_unsaved_files: Vec<clang::UnsavedFile>,
1521
1522 /// A user-provided visitor to allow customizing different kinds of
1523 /// situations.
1524 parse_callbacks: Option<Box<dyn callbacks::ParseCallbacks>>,
1525
1526 /// Which kind of items should we generate? By default, we'll generate all
1527 /// of them.
1528 codegen_config: CodegenConfig,
1529
1530 /// Whether to treat inline namespaces conservatively.
1531 ///
1532 /// See the builder method description for more details.
1533 conservative_inline_namespaces: bool,
1534
1535 /// Whether to keep documentation comments in the generated output. See the
1536 /// documentation for more details.
1537 generate_comments: bool,
1538
1539 /// Whether to generate inline functions. Defaults to false.
1540 generate_inline_functions: bool,
1541
1542 /// Whether to whitelist types recursively. Defaults to true.
1543 whitelist_recursively: bool,
1544
1545 /// Instead of emitting 'use objc;' to files generated from objective c files,
1546 /// generate '#[macro_use] extern crate objc;'
1547 objc_extern_crate: bool,
1548
1549 /// Instead of emitting 'use block;' to files generated from objective c files,
1550 /// generate '#[macro_use] extern crate block;'
1551 generate_block: bool,
1552
1553 /// Instead of emitting 'use block;' to files generated from objective c files,
1554 /// generate '#[macro_use] extern crate block;'
1555 block_extern_crate: bool,
1556
1557 /// Whether to use the clang-provided name mangling. This is true and
1558 /// probably needed for C++ features.
1559 ///
1560 /// However, some old libclang versions seem to return incorrect results in
1561 /// some cases for non-mangled functions, see [1], so we allow disabling it.
1562 ///
1563 /// [1]: https://github.com/rust-lang/rust-bindgen/issues/528
1564 enable_mangling: bool,
1565
1566 /// Whether to detect include paths using clang_sys.
1567 detect_include_paths: bool,
1568
1569 /// Whether to prepend the enum name to bitfield or constant variants.
1570 prepend_enum_name: bool,
1571
1572 /// Version of the Rust compiler to target
1573 rust_target: RustTarget,
1574
1575 /// Features to enable, derived from `rust_target`
1576 rust_features: RustFeatures,
1577
1578 /// Whether we should record which items in the regex sets ever matched.
1579 ///
1580 /// This may be a bit slower, but will enable reporting of unused whitelist
1581 /// items via the `error!` log.
1582 record_matches: bool,
1583
1584 /// Whether rustfmt should format the generated bindings.
1585 rustfmt_bindings: bool,
1586
1587 /// The absolute path to the rustfmt configuration file, if None, the standard rustfmt
1588 /// options are used.
1589 rustfmt_configuration_file: Option<PathBuf>,
1590
1591 /// The set of types that we should not derive `PartialEq` for.
1592 no_partialeq_types: RegexSet,
1593
1594 /// The set of types that we should not derive `Copy` for.
1595 no_copy_types: RegexSet,
1596
1597 /// The set of types that we should not derive `Hash` for.
1598 no_hash_types: RegexSet,
1599
1600 /// Decide if C arrays should be regular pointers in rust or array pointers
1601 array_pointers_in_arguments: bool,
1602 }
1603
1604 /// TODO(emilio): This is sort of a lie (see the error message that results from
1605 /// removing this), but since we don't share references across panic boundaries
1606 /// it's ok.
1607 impl ::std::panic::UnwindSafe for BindgenOptions {}
1608
1609 impl BindgenOptions {
build(&mut self)1610 fn build(&mut self) {
1611 let mut regex_sets = [
1612 &mut self.whitelisted_vars,
1613 &mut self.whitelisted_types,
1614 &mut self.whitelisted_functions,
1615 &mut self.blacklisted_types,
1616 &mut self.blacklisted_functions,
1617 &mut self.blacklisted_items,
1618 &mut self.opaque_types,
1619 &mut self.bitfield_enums,
1620 &mut self.constified_enums,
1621 &mut self.constified_enum_modules,
1622 &mut self.rustified_enums,
1623 &mut self.no_partialeq_types,
1624 &mut self.no_copy_types,
1625 &mut self.no_hash_types,
1626 ];
1627 let record_matches = self.record_matches;
1628 for regex_set in &mut regex_sets {
1629 regex_set.build(record_matches);
1630 }
1631 }
1632
1633 /// Update rust target version
set_rust_target(&mut self, rust_target: RustTarget)1634 pub fn set_rust_target(&mut self, rust_target: RustTarget) {
1635 self.rust_target = rust_target;
1636
1637 // Keep rust_features synced with rust_target
1638 self.rust_features = rust_target.into();
1639 }
1640
1641 /// Get features supported by target Rust version
rust_features(&self) -> RustFeatures1642 pub fn rust_features(&self) -> RustFeatures {
1643 self.rust_features
1644 }
1645 }
1646
1647 impl Default for BindgenOptions {
default() -> BindgenOptions1648 fn default() -> BindgenOptions {
1649 let rust_target = RustTarget::default();
1650
1651 BindgenOptions {
1652 rust_target,
1653 rust_features: rust_target.into(),
1654 blacklisted_types: Default::default(),
1655 blacklisted_functions: Default::default(),
1656 blacklisted_items: Default::default(),
1657 opaque_types: Default::default(),
1658 rustfmt_path: Default::default(),
1659 whitelisted_types: Default::default(),
1660 whitelisted_functions: Default::default(),
1661 whitelisted_vars: Default::default(),
1662 default_enum_style: Default::default(),
1663 bitfield_enums: Default::default(),
1664 rustified_enums: Default::default(),
1665 rustified_non_exhaustive_enums: Default::default(),
1666 constified_enums: Default::default(),
1667 constified_enum_modules: Default::default(),
1668 builtins: false,
1669 emit_ast: false,
1670 emit_ir: false,
1671 emit_ir_graphviz: None,
1672 layout_tests: true,
1673 impl_debug: false,
1674 impl_partialeq: false,
1675 derive_copy: true,
1676 derive_debug: true,
1677 derive_default: false,
1678 derive_hash: false,
1679 derive_partialord: false,
1680 derive_ord: false,
1681 derive_partialeq: false,
1682 derive_eq: false,
1683 enable_cxx_namespaces: false,
1684 enable_function_attribute_detection: false,
1685 disable_name_namespacing: false,
1686 use_core: false,
1687 ctypes_prefix: None,
1688 namespaced_constants: true,
1689 msvc_mangling: false,
1690 convert_floats: true,
1691 raw_lines: vec![],
1692 module_lines: HashMap::default(),
1693 clang_args: vec![],
1694 input_header: None,
1695 input_unsaved_files: vec![],
1696 parse_callbacks: None,
1697 codegen_config: CodegenConfig::all(),
1698 conservative_inline_namespaces: false,
1699 generate_comments: true,
1700 generate_inline_functions: false,
1701 whitelist_recursively: true,
1702 generate_block: false,
1703 objc_extern_crate: false,
1704 block_extern_crate: false,
1705 enable_mangling: true,
1706 detect_include_paths: true,
1707 prepend_enum_name: true,
1708 time_phases: false,
1709 record_matches: true,
1710 rustfmt_bindings: true,
1711 rustfmt_configuration_file: None,
1712 no_partialeq_types: Default::default(),
1713 no_copy_types: Default::default(),
1714 no_hash_types: Default::default(),
1715 array_pointers_in_arguments: false,
1716 }
1717 }
1718 }
1719
ensure_libclang_is_loaded()1720 fn ensure_libclang_is_loaded() {
1721 if clang_sys::is_loaded() {
1722 return;
1723 }
1724
1725 // XXX (issue #350): Ensure that our dynamically loaded `libclang`
1726 // doesn't get dropped prematurely, nor is loaded multiple times
1727 // across different threads.
1728
1729 lazy_static! {
1730 static ref LIBCLANG: Arc<clang_sys::SharedLibrary> = {
1731 clang_sys::load().expect("Unable to find libclang");
1732 clang_sys::get_library().expect(
1733 "We just loaded libclang and it had better still be \
1734 here!",
1735 )
1736 };
1737 }
1738
1739 clang_sys::set_library(Some(LIBCLANG.clone()));
1740 }
1741
1742 /// Generated Rust bindings.
1743 #[derive(Debug)]
1744 pub struct Bindings {
1745 options: BindgenOptions,
1746 module: proc_macro2::TokenStream,
1747 }
1748
1749 impl Bindings {
1750 /// Generate bindings for the given options.
generate( mut options: BindgenOptions, ) -> Result<Bindings, ()>1751 pub(crate) fn generate(
1752 mut options: BindgenOptions,
1753 ) -> Result<Bindings, ()> {
1754 ensure_libclang_is_loaded();
1755
1756 debug!(
1757 "Generating bindings, libclang at {}",
1758 clang_sys::get_library().unwrap().path().display()
1759 );
1760
1761 options.build();
1762
1763 fn detect_include_paths(options: &mut BindgenOptions) {
1764 if !options.detect_include_paths {
1765 return;
1766 }
1767
1768 // Filter out include paths and similar stuff, so we don't incorrectly
1769 // promote them to `-isystem`.
1770 let clang_args_for_clang_sys = {
1771 let mut last_was_include_prefix = false;
1772 options
1773 .clang_args
1774 .iter()
1775 .filter(|arg| {
1776 if last_was_include_prefix {
1777 last_was_include_prefix = false;
1778 return false;
1779 }
1780
1781 let arg = &**arg;
1782
1783 // https://clang.llvm.org/docs/ClangCommandLineReference.html
1784 // -isystem and -isystem-after are harmless.
1785 if arg == "-I" || arg == "--include-directory" {
1786 last_was_include_prefix = true;
1787 return false;
1788 }
1789
1790 if arg.starts_with("-I") ||
1791 arg.starts_with("--include-directory=")
1792 {
1793 return false;
1794 }
1795
1796 true
1797 })
1798 .cloned()
1799 .collect::<Vec<_>>()
1800 };
1801
1802 debug!(
1803 "Trying to find clang with flags: {:?}",
1804 clang_args_for_clang_sys
1805 );
1806
1807 let clang = match clang_sys::support::Clang::find(
1808 None,
1809 &clang_args_for_clang_sys,
1810 ) {
1811 None => return,
1812 Some(clang) => clang,
1813 };
1814
1815 debug!("Found clang: {:?}", clang);
1816
1817 // Whether we are working with C or C++ inputs.
1818 let is_cpp = args_are_cpp(&options.clang_args);
1819 let search_paths = if is_cpp {
1820 clang.cpp_search_paths
1821 } else {
1822 clang.c_search_paths
1823 };
1824
1825 if let Some(search_paths) = search_paths {
1826 for path in search_paths.into_iter() {
1827 if let Ok(path) = path.into_os_string().into_string() {
1828 options.clang_args.push("-isystem".to_owned());
1829 options.clang_args.push(path);
1830 }
1831 }
1832 }
1833 }
1834
1835 detect_include_paths(&mut options);
1836
1837 #[cfg(unix)]
1838 fn can_read(perms: &std::fs::Permissions) -> bool {
1839 use std::os::unix::fs::PermissionsExt;
1840 perms.mode() & 0o444 > 0
1841 }
1842
1843 #[cfg(not(unix))]
1844 fn can_read(_: &std::fs::Permissions) -> bool {
1845 true
1846 }
1847
1848 if let Some(h) = options.input_header.as_ref() {
1849 if let Ok(md) = std::fs::metadata(h) {
1850 if md.is_dir() {
1851 eprintln!("error: '{}' is a folder", h);
1852 return Err(());
1853 }
1854 if !can_read(&md.permissions()) {
1855 eprintln!(
1856 "error: insufficient permissions to read '{}'",
1857 h
1858 );
1859 return Err(());
1860 }
1861 options.clang_args.push(h.clone())
1862 } else {
1863 eprintln!("error: header '{}' does not exist.", h);
1864 return Err(());
1865 }
1866 }
1867
1868 for f in options.input_unsaved_files.iter() {
1869 options.clang_args.push(f.name.to_str().unwrap().to_owned())
1870 }
1871
1872 debug!("Fixed-up options: {:?}", options);
1873
1874 let time_phases = options.time_phases;
1875 let mut context = BindgenContext::new(options);
1876
1877 {
1878 let _t = time::Timer::new("parse").with_output(time_phases);
1879 parse(&mut context)?;
1880 }
1881
1882 let (items, options) = codegen::codegen(context);
1883
1884 Ok(Bindings {
1885 options: options,
1886 module: quote! {
1887 #( #items )*
1888 },
1889 })
1890 }
1891
1892 /// Convert these bindings into source text (with raw lines prepended).
to_string(&self) -> String1893 pub fn to_string(&self) -> String {
1894 let mut bytes = vec![];
1895 self.write(Box::new(&mut bytes) as Box<dyn Write>)
1896 .expect("writing to a vec cannot fail");
1897 String::from_utf8(bytes)
1898 .expect("we should only write bindings that are valid utf-8")
1899 }
1900
1901 /// Write these bindings as source text to a file.
write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()>1902 pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
1903 let file = OpenOptions::new()
1904 .write(true)
1905 .truncate(true)
1906 .create(true)
1907 .open(path.as_ref())?;
1908 self.write(Box::new(file))?;
1909 Ok(())
1910 }
1911
1912 /// Write these bindings as source text to the given `Write`able.
write<'a>(&self, mut writer: Box<dyn Write + 'a>) -> io::Result<()>1913 pub fn write<'a>(&self, mut writer: Box<dyn Write + 'a>) -> io::Result<()> {
1914 writer.write(
1915 "/* automatically generated by rust-bindgen */\n\n".as_bytes(),
1916 )?;
1917
1918 for line in self.options.raw_lines.iter() {
1919 writer.write(line.as_bytes())?;
1920 writer.write("\n".as_bytes())?;
1921 }
1922
1923 if !self.options.raw_lines.is_empty() {
1924 writer.write("\n".as_bytes())?;
1925 }
1926
1927 let bindings = self.module.to_string();
1928
1929 match self.rustfmt_generated_string(&bindings) {
1930 Ok(rustfmt_bindings) => {
1931 writer.write(rustfmt_bindings.as_bytes())?;
1932 }
1933 Err(err) => {
1934 eprintln!(
1935 "Failed to run rustfmt: {} (non-fatal, continuing)",
1936 err
1937 );
1938 writer.write(bindings.as_bytes())?;
1939 }
1940 }
1941 Ok(())
1942 }
1943
1944 /// Gets the rustfmt path to rustfmt the generated bindings.
rustfmt_path<'a>(&'a self) -> io::Result<Cow<'a, PathBuf>>1945 fn rustfmt_path<'a>(&'a self) -> io::Result<Cow<'a, PathBuf>> {
1946 debug_assert!(self.options.rustfmt_bindings);
1947 if let Some(ref p) = self.options.rustfmt_path {
1948 return Ok(Cow::Borrowed(p));
1949 }
1950 if let Ok(rustfmt) = env::var("RUSTFMT") {
1951 return Ok(Cow::Owned(rustfmt.into()));
1952 }
1953 #[cfg(feature = "which-rustfmt")]
1954 match which::which("rustfmt") {
1955 Ok(p) => Ok(Cow::Owned(p)),
1956 Err(e) => {
1957 Err(io::Error::new(io::ErrorKind::Other, format!("{}", e)))
1958 }
1959 }
1960 #[cfg(not(feature = "which-rustfmt"))]
1961 Err(io::Error::new(
1962 io::ErrorKind::Other,
1963 "which wasn't enabled, and no rustfmt binary specified",
1964 ))
1965 }
1966
1967 /// Checks if rustfmt_bindings is set and runs rustfmt on the string
rustfmt_generated_string<'a>( &self, source: &'a str, ) -> io::Result<Cow<'a, str>>1968 fn rustfmt_generated_string<'a>(
1969 &self,
1970 source: &'a str,
1971 ) -> io::Result<Cow<'a, str>> {
1972 let _t = time::Timer::new("rustfmt_generated_string")
1973 .with_output(self.options.time_phases);
1974
1975 if !self.options.rustfmt_bindings {
1976 return Ok(Cow::Borrowed(source));
1977 }
1978
1979 let rustfmt = self.rustfmt_path()?;
1980 let mut cmd = Command::new(&*rustfmt);
1981
1982 cmd.stdin(Stdio::piped()).stdout(Stdio::piped());
1983
1984 if let Some(path) = self
1985 .options
1986 .rustfmt_configuration_file
1987 .as_ref()
1988 .and_then(|f| f.to_str())
1989 {
1990 cmd.args(&["--config-path", path]);
1991 }
1992
1993 let mut child = cmd.spawn()?;
1994 let mut child_stdin = child.stdin.take().unwrap();
1995 let mut child_stdout = child.stdout.take().unwrap();
1996
1997 let source = source.to_owned();
1998
1999 // Write to stdin in a new thread, so that we can read from stdout on this
2000 // thread. This keeps the child from blocking on writing to its stdout which
2001 // might block us from writing to its stdin.
2002 let stdin_handle = ::std::thread::spawn(move || {
2003 let _ = child_stdin.write_all(source.as_bytes());
2004 source
2005 });
2006
2007 let mut output = vec![];
2008 io::copy(&mut child_stdout, &mut output)?;
2009
2010 let status = child.wait()?;
2011 let source = stdin_handle.join().expect(
2012 "The thread writing to rustfmt's stdin doesn't do \
2013 anything that could panic",
2014 );
2015
2016 match String::from_utf8(output) {
2017 Ok(bindings) => match status.code() {
2018 Some(0) => Ok(Cow::Owned(bindings)),
2019 Some(2) => Err(io::Error::new(
2020 io::ErrorKind::Other,
2021 "Rustfmt parsing errors.".to_string(),
2022 )),
2023 Some(3) => {
2024 warn!("Rustfmt could not format some lines.");
2025 Ok(Cow::Owned(bindings))
2026 }
2027 _ => Err(io::Error::new(
2028 io::ErrorKind::Other,
2029 "Internal rustfmt error".to_string(),
2030 )),
2031 },
2032 _ => Ok(Cow::Owned(source)),
2033 }
2034 }
2035 }
2036
2037 /// Determines whether the given cursor is in any of the files matched by the
2038 /// options.
filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool2039 fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool {
2040 ctx.options().builtins || !cursor.is_builtin()
2041 }
2042
2043 /// Parse one `Item` from the Clang cursor.
parse_one( ctx: &mut BindgenContext, cursor: clang::Cursor, parent: Option<ItemId>, ) -> clang_sys::CXChildVisitResult2044 fn parse_one(
2045 ctx: &mut BindgenContext,
2046 cursor: clang::Cursor,
2047 parent: Option<ItemId>,
2048 ) -> clang_sys::CXChildVisitResult {
2049 if !filter_builtins(ctx, &cursor) {
2050 return CXChildVisit_Continue;
2051 }
2052
2053 use clang_sys::CXChildVisit_Continue;
2054 match Item::parse(cursor, parent, ctx) {
2055 Ok(..) => {}
2056 Err(ParseError::Continue) => {}
2057 Err(ParseError::Recurse) => {
2058 cursor.visit(|child| parse_one(ctx, child, parent));
2059 }
2060 }
2061 CXChildVisit_Continue
2062 }
2063
2064 /// Parse the Clang AST into our `Item` internal representation.
parse(context: &mut BindgenContext) -> Result<(), ()>2065 fn parse(context: &mut BindgenContext) -> Result<(), ()> {
2066 use clang_sys::*;
2067
2068 let mut any_error = false;
2069 for d in context.translation_unit().diags().iter() {
2070 let msg = d.format();
2071 let is_err = d.severity() >= CXDiagnostic_Error;
2072 eprintln!("{}, err: {}", msg, is_err);
2073 any_error |= is_err;
2074 }
2075
2076 if any_error {
2077 return Err(());
2078 }
2079
2080 let cursor = context.translation_unit().cursor();
2081
2082 if context.options().emit_ast {
2083 fn dump_if_not_builtin(cur: &clang::Cursor) -> CXChildVisitResult {
2084 if !cur.is_builtin() {
2085 clang::ast_dump(&cur, 0)
2086 } else {
2087 CXChildVisit_Continue
2088 }
2089 }
2090 cursor.visit(|cur| dump_if_not_builtin(&cur));
2091 }
2092
2093 let root = context.root_module();
2094 context.with_module(root, |context| {
2095 cursor.visit(|cursor| parse_one(context, cursor, None))
2096 });
2097
2098 assert!(
2099 context.current_module() == context.root_module(),
2100 "How did this happen?"
2101 );
2102 Ok(())
2103 }
2104
2105 /// Extracted Clang version data
2106 #[derive(Debug)]
2107 pub struct ClangVersion {
2108 /// Major and minor semver, if parsing was successful
2109 pub parsed: Option<(u32, u32)>,
2110 /// full version string
2111 pub full: String,
2112 }
2113
2114 /// Get the major and the minor semver numbers of Clang's version
clang_version() -> ClangVersion2115 pub fn clang_version() -> ClangVersion {
2116 if !clang_sys::is_loaded() {
2117 // TODO(emilio): Return meaningful error (breaking).
2118 clang_sys::load().expect("Unable to find libclang");
2119 }
2120
2121 let raw_v: String = clang::extract_clang_version();
2122 let split_v: Option<Vec<&str>> = raw_v
2123 .split_whitespace()
2124 .nth(2)
2125 .map(|v| v.split('.').collect());
2126 match split_v {
2127 Some(v) => {
2128 if v.len() >= 2 {
2129 let maybe_major = v[0].parse::<u32>();
2130 let maybe_minor = v[1].parse::<u32>();
2131 match (maybe_major, maybe_minor) {
2132 (Ok(major), Ok(minor)) => {
2133 return ClangVersion {
2134 parsed: Some((major, minor)),
2135 full: raw_v.clone(),
2136 }
2137 }
2138 _ => {}
2139 }
2140 }
2141 }
2142 None => {}
2143 };
2144 ClangVersion {
2145 parsed: None,
2146 full: raw_v.clone(),
2147 }
2148 }
2149
2150 /// Test command_line_flag function.
2151 #[test]
commandline_flag_unit_test_function()2152 fn commandline_flag_unit_test_function() {
2153 //Test 1
2154 let bindings = ::builder();
2155 let command_line_flags = bindings.command_line_flags();
2156
2157 let test_cases = vec![
2158 "--rust-target",
2159 "--no-derive-default",
2160 "--generate",
2161 "functions,types,vars,methods,constructors,destructors",
2162 ]
2163 .iter()
2164 .map(|&x| x.into())
2165 .collect::<Vec<String>>();
2166
2167 assert!(test_cases
2168 .iter()
2169 .all(|ref x| command_line_flags.contains(x),));
2170
2171 //Test 2
2172 let bindings = ::builder()
2173 .header("input_header")
2174 .whitelist_type("Distinct_Type")
2175 .whitelist_function("safe_function");
2176
2177 let command_line_flags = bindings.command_line_flags();
2178 let test_cases = vec![
2179 "--rust-target",
2180 "input_header",
2181 "--no-derive-default",
2182 "--generate",
2183 "functions,types,vars,methods,constructors,destructors",
2184 "--whitelist-type",
2185 "Distinct_Type",
2186 "--whitelist-function",
2187 "safe_function",
2188 ]
2189 .iter()
2190 .map(|&x| x.into())
2191 .collect::<Vec<String>>();
2192 println!("{:?}", command_line_flags);
2193
2194 assert!(test_cases
2195 .iter()
2196 .all(|ref x| command_line_flags.contains(x),));
2197 }
2198