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(unused_extern_crates)]
12 // To avoid rather annoying warnings when matching with CXCursor_xxx as a
13 // constant.
14 #![allow(non_upper_case_globals)]
15 // `quote!` nests quite deeply.
16 #![recursion_limit = "128"]
17
18 #[macro_use]
19 extern crate bitflags;
20 #[macro_use]
21 extern crate lazy_static;
22 #[macro_use]
23 extern crate quote;
24
25 #[cfg(feature = "logging")]
26 #[macro_use]
27 extern crate log;
28
29 #[cfg(not(feature = "logging"))]
30 #[macro_use]
31 mod log_stubs;
32
33 #[macro_use]
34 mod extra_assertions;
35
36 // A macro to declare an internal module for which we *must* provide
37 // documentation for. If we are building with the "testing_only_docs" feature,
38 // then the module is declared public, and our `#![deny(missing_docs)]` pragma
39 // applies to it. This feature is used in CI, so we won't let anything slip by
40 // undocumented. Normal builds, however, will leave the module private, so that
41 // we don't expose internals to library consumers.
42 macro_rules! doc_mod {
43 ($m:ident, $doc_mod_name:ident) => {
44 #[cfg(feature = "testing_only_docs")]
45 pub mod $doc_mod_name {
46 //! Autogenerated documentation module.
47 pub use super::$m::*;
48 }
49 };
50 }
51
52 macro_rules! fn_with_regex_arg {
53 ($(#[$attrs:meta])* pub fn $($tokens:tt)*) => {
54 $(#[$attrs])*
55 /// Check the [regular expression arguments] section and the [regex] crate
56 /// documentation for further information.
57 ///
58 /// [regular expression arguments]: ./struct.Builder.html#regular-expression-arguments
59 /// [regex]: <https://docs.rs/regex>
60 pub fn $($tokens)*
61 };
62 }
63
64 mod clang;
65 mod codegen;
66 mod deps;
67 mod features;
68 pub mod ir;
69 mod parse;
70 mod regex_set;
71 mod time;
72
73 pub mod callbacks;
74
75 doc_mod!(clang, clang_docs);
76 doc_mod!(features, features_docs);
77 doc_mod!(ir, ir_docs);
78 doc_mod!(parse, parse_docs);
79 doc_mod!(regex_set, regex_set_docs);
80
81 use codegen::CodegenError;
82 use ir::comment;
83
84 pub use crate::codegen::{
85 AliasVariation, EnumVariation, MacroTypeVariation, NonCopyUnionStyle,
86 };
87 use crate::features::RustFeatures;
88 pub use crate::features::{
89 RustTarget, LATEST_STABLE_RUST, RUST_TARGET_STRINGS,
90 };
91 use crate::ir::context::{BindgenContext, ItemId};
92 pub use crate::ir::function::Abi;
93 use crate::ir::item::Item;
94 use crate::parse::ParseError;
95 pub use crate::regex_set::RegexSet;
96
97 use std::borrow::Cow;
98 use std::env;
99 use std::fs::{File, OpenOptions};
100 use std::io::{self, Write};
101 use std::path::{Path, PathBuf};
102 use std::process::{Command, Stdio};
103 use std::rc::Rc;
104
105 // Some convenient typedefs for a fast hash map and hash set.
106 type HashMap<K, V> = ::rustc_hash::FxHashMap<K, V>;
107 type HashSet<K> = ::rustc_hash::FxHashSet<K>;
108 pub(crate) use std::collections::hash_map::Entry;
109
110 /// Default prefix for the anon fields.
111 pub const DEFAULT_ANON_FIELDS_PREFIX: &str = "__bindgen_anon_";
112 const DEFAULT_NON_EXTERN_FNS_SUFFIX: &str = "__extern";
113
file_is_cpp(name_file: &str) -> bool114 fn file_is_cpp(name_file: &str) -> bool {
115 name_file.ends_with(".hpp") ||
116 name_file.ends_with(".hxx") ||
117 name_file.ends_with(".hh") ||
118 name_file.ends_with(".h++")
119 }
120
args_are_cpp(clang_args: &[String]) -> bool121 fn args_are_cpp(clang_args: &[String]) -> bool {
122 for w in clang_args.windows(2) {
123 if w[0] == "-xc++" || w[1] == "-xc++" {
124 return true;
125 }
126 if w[0] == "-x" && w[1] == "c++" {
127 return true;
128 }
129 if w[0] == "-include" && file_is_cpp(&w[1]) {
130 return true;
131 }
132 }
133 false
134 }
135
136 bitflags! {
137 /// A type used to indicate which kind of items we have to generate.
138 pub struct CodegenConfig: u32 {
139 /// Whether to generate functions.
140 const FUNCTIONS = 1 << 0;
141 /// Whether to generate types.
142 const TYPES = 1 << 1;
143 /// Whether to generate constants.
144 const VARS = 1 << 2;
145 /// Whether to generate methods.
146 const METHODS = 1 << 3;
147 /// Whether to generate constructors
148 const CONSTRUCTORS = 1 << 4;
149 /// Whether to generate destructors.
150 const DESTRUCTORS = 1 << 5;
151 }
152 }
153
154 impl CodegenConfig {
155 /// Returns true if functions should be generated.
functions(self) -> bool156 pub fn functions(self) -> bool {
157 self.contains(CodegenConfig::FUNCTIONS)
158 }
159
160 /// Returns true if types should be generated.
types(self) -> bool161 pub fn types(self) -> bool {
162 self.contains(CodegenConfig::TYPES)
163 }
164
165 /// Returns true if constants should be generated.
vars(self) -> bool166 pub fn vars(self) -> bool {
167 self.contains(CodegenConfig::VARS)
168 }
169
170 /// Returns true if methds should be generated.
methods(self) -> bool171 pub fn methods(self) -> bool {
172 self.contains(CodegenConfig::METHODS)
173 }
174
175 /// Returns true if constructors should be generated.
constructors(self) -> bool176 pub fn constructors(self) -> bool {
177 self.contains(CodegenConfig::CONSTRUCTORS)
178 }
179
180 /// Returns true if destructors should be generated.
destructors(self) -> bool181 pub fn destructors(self) -> bool {
182 self.contains(CodegenConfig::DESTRUCTORS)
183 }
184 }
185
186 impl Default for CodegenConfig {
default() -> Self187 fn default() -> Self {
188 CodegenConfig::all()
189 }
190 }
191
192 /// Configure and generate Rust bindings for a C/C++ header.
193 ///
194 /// This is the main entry point to the library.
195 ///
196 /// ```ignore
197 /// use bindgen::builder;
198 ///
199 /// // Configure and generate bindings.
200 /// let bindings = builder().header("path/to/input/header")
201 /// .allowlist_type("SomeCoolClass")
202 /// .allowlist_function("do_some_cool_thing")
203 /// .generate()?;
204 ///
205 /// // Write the generated bindings to an output file.
206 /// bindings.write_to_file("path/to/output.rs")?;
207 /// ```
208 ///
209 /// # Enums
210 ///
211 /// Bindgen can map C/C++ enums into Rust in different ways. The way bindgen maps enums depends on
212 /// the pattern passed to several methods:
213 ///
214 /// 1. [`constified_enum_module()`](#method.constified_enum_module)
215 /// 2. [`bitfield_enum()`](#method.bitfield_enum)
216 /// 3. [`newtype_enum()`](#method.newtype_enum)
217 /// 4. [`rustified_enum()`](#method.rustified_enum)
218 ///
219 /// For each C enum, bindgen tries to match the pattern in the following order:
220 ///
221 /// 1. Constified enum module
222 /// 2. Bitfield enum
223 /// 3. Newtype enum
224 /// 4. Rustified enum
225 ///
226 /// If none of the above patterns match, then bindgen will generate a set of Rust constants.
227 ///
228 /// # Clang arguments
229 ///
230 /// Extra arguments can be passed to with clang:
231 /// 1. [`clang_arg()`](#method.clang_arg): takes a single argument
232 /// 2. [`clang_args()`](#method.clang_args): takes an iterator of arguments
233 /// 3. `BINDGEN_EXTRA_CLANG_ARGS` environment variable: whitespace separate
234 /// environment variable of arguments
235 ///
236 /// Clang arguments specific to your crate should be added via the
237 /// `clang_arg()`/`clang_args()` methods.
238 ///
239 /// End-users of the crate may need to set the `BINDGEN_EXTRA_CLANG_ARGS` environment variable to
240 /// add additional arguments. For example, to build against a different sysroot a user could set
241 /// `BINDGEN_EXTRA_CLANG_ARGS` to `--sysroot=/path/to/sysroot`.
242 ///
243 /// # Regular expression arguments
244 ///
245 /// Some [`Builder`] methods like the `allowlist_*` and `blocklist_*` family of methods allow
246 /// regular expressions as arguments. These regular expressions will be parenthesized and wrapped
247 /// in `^` and `$`. So if `<regex>` is passed as argument, the regular expression to be stored will
248 /// be `^(<regex>)$`.
249 ///
250 /// Releases of `bindgen` with a version lesser or equal to `0.62.0` used to accept the wildcard
251 /// pattern `*` as a valid regular expression. This behavior has been deprecated and the `.*`
252 /// pattern must be used instead.
253 #[derive(Debug, Default, Clone)]
254 pub struct Builder {
255 options: BindgenOptions,
256 }
257
258 /// Construct a new [`Builder`](./struct.Builder.html).
builder() -> Builder259 pub fn builder() -> Builder {
260 Default::default()
261 }
262
get_extra_clang_args() -> Vec<String>263 fn get_extra_clang_args() -> Vec<String> {
264 // Add any extra arguments from the environment to the clang command line.
265 let extra_clang_args =
266 match get_target_dependent_env_var("BINDGEN_EXTRA_CLANG_ARGS") {
267 None => return vec![],
268 Some(s) => s,
269 };
270 // Try to parse it with shell quoting. If we fail, make it one single big argument.
271 if let Some(strings) = shlex::split(&extra_clang_args) {
272 return strings;
273 }
274 vec![extra_clang_args]
275 }
276
277 impl Builder {
278 /// Generates the command line flags use for creating `Builder`.
command_line_flags(&self) -> Vec<String>279 pub fn command_line_flags(&self) -> Vec<String> {
280 let mut output_vector: Vec<String> = Vec::new();
281
282 if let Some(header) = self.options.input_headers.last().cloned() {
283 // Positional argument 'header'
284 output_vector.push(header);
285 }
286
287 output_vector.push("--rust-target".into());
288 output_vector.push(self.options.rust_target.into());
289
290 // FIXME(emilio): This is a bit hacky, maybe we should stop re-using the
291 // RustFeatures to store the "disable_untagged_union" call, and make it
292 // a different flag that we check elsewhere / in generate().
293 if !self.options.rust_features.untagged_union &&
294 RustFeatures::from(self.options.rust_target).untagged_union
295 {
296 output_vector.push("--disable-untagged-union".into());
297 }
298
299 if self.options.default_enum_style != Default::default() {
300 output_vector.push("--default-enum-style".into());
301 output_vector.push(
302 match self.options.default_enum_style {
303 codegen::EnumVariation::Rust {
304 non_exhaustive: false,
305 } => "rust",
306 codegen::EnumVariation::Rust {
307 non_exhaustive: true,
308 } => "rust_non_exhaustive",
309 codegen::EnumVariation::NewType {
310 is_bitfield: true,
311 ..
312 } => "bitfield",
313 codegen::EnumVariation::NewType {
314 is_bitfield: false,
315 is_global,
316 } => {
317 if is_global {
318 "newtype_global"
319 } else {
320 "newtype"
321 }
322 }
323 codegen::EnumVariation::Consts => "consts",
324 codegen::EnumVariation::ModuleConsts => "moduleconsts",
325 }
326 .into(),
327 )
328 }
329
330 if self.options.default_macro_constant_type != Default::default() {
331 output_vector.push("--default-macro-constant-type".into());
332 output_vector
333 .push(self.options.default_macro_constant_type.as_str().into());
334 }
335
336 if self.options.default_alias_style != Default::default() {
337 output_vector.push("--default-alias-style".into());
338 output_vector
339 .push(self.options.default_alias_style.as_str().into());
340 }
341
342 if self.options.default_non_copy_union_style != Default::default() {
343 output_vector.push("--default-non-copy-union-style".into());
344 output_vector.push(
345 self.options.default_non_copy_union_style.as_str().into(),
346 );
347 }
348
349 let regex_sets = &[
350 (&self.options.bitfield_enums, "--bitfield-enum"),
351 (&self.options.newtype_enums, "--newtype-enum"),
352 (&self.options.newtype_global_enums, "--newtype-global-enum"),
353 (&self.options.rustified_enums, "--rustified-enum"),
354 (
355 &self.options.rustified_non_exhaustive_enums,
356 "--rustified-enum-non-exhaustive",
357 ),
358 (
359 &self.options.constified_enum_modules,
360 "--constified-enum-module",
361 ),
362 (&self.options.constified_enums, "--constified-enum"),
363 (&self.options.type_alias, "--type-alias"),
364 (&self.options.new_type_alias, "--new-type-alias"),
365 (&self.options.new_type_alias_deref, "--new-type-alias-deref"),
366 (
367 &self.options.bindgen_wrapper_union,
368 "--bindgen-wrapper-union",
369 ),
370 (&self.options.manually_drop_union, "--manually-drop-union"),
371 (&self.options.blocklisted_types, "--blocklist-type"),
372 (&self.options.blocklisted_functions, "--blocklist-function"),
373 (&self.options.blocklisted_items, "--blocklist-item"),
374 (&self.options.blocklisted_files, "--blocklist-file"),
375 (&self.options.opaque_types, "--opaque-type"),
376 (&self.options.allowlisted_functions, "--allowlist-function"),
377 (&self.options.allowlisted_types, "--allowlist-type"),
378 (&self.options.allowlisted_vars, "--allowlist-var"),
379 (&self.options.allowlisted_files, "--allowlist-file"),
380 (&self.options.no_partialeq_types, "--no-partialeq"),
381 (&self.options.no_copy_types, "--no-copy"),
382 (&self.options.no_debug_types, "--no-debug"),
383 (&self.options.no_default_types, "--no-default"),
384 (&self.options.no_hash_types, "--no-hash"),
385 (&self.options.must_use_types, "--must-use-type"),
386 ];
387
388 for (set, flag) in regex_sets {
389 for item in set.get_items() {
390 output_vector.push((*flag).to_owned());
391 output_vector.push(item.to_owned());
392 }
393 }
394
395 for (abi, set) in &self.options.abi_overrides {
396 for item in set.get_items() {
397 output_vector.push("--override-abi".to_owned());
398 output_vector.push(format!("{}={}", item, abi));
399 }
400 }
401
402 if !self.options.layout_tests {
403 output_vector.push("--no-layout-tests".into());
404 }
405
406 if self.options.impl_debug {
407 output_vector.push("--impl-debug".into());
408 }
409
410 if self.options.impl_partialeq {
411 output_vector.push("--impl-partialeq".into());
412 }
413
414 if !self.options.derive_copy {
415 output_vector.push("--no-derive-copy".into());
416 }
417
418 if !self.options.derive_debug {
419 output_vector.push("--no-derive-debug".into());
420 }
421
422 if !self.options.derive_default {
423 output_vector.push("--no-derive-default".into());
424 } else {
425 output_vector.push("--with-derive-default".into());
426 }
427
428 if self.options.derive_hash {
429 output_vector.push("--with-derive-hash".into());
430 }
431
432 if self.options.derive_partialord {
433 output_vector.push("--with-derive-partialord".into());
434 }
435
436 if self.options.derive_ord {
437 output_vector.push("--with-derive-ord".into());
438 }
439
440 if self.options.derive_partialeq {
441 output_vector.push("--with-derive-partialeq".into());
442 }
443
444 if self.options.derive_eq {
445 output_vector.push("--with-derive-eq".into());
446 }
447
448 if self.options.time_phases {
449 output_vector.push("--time-phases".into());
450 }
451
452 if !self.options.generate_comments {
453 output_vector.push("--no-doc-comments".into());
454 }
455
456 if !self.options.allowlist_recursively {
457 output_vector.push("--no-recursive-allowlist".into());
458 }
459
460 if self.options.objc_extern_crate {
461 output_vector.push("--objc-extern-crate".into());
462 }
463
464 if self.options.generate_block {
465 output_vector.push("--generate-block".into());
466 }
467
468 if self.options.block_extern_crate {
469 output_vector.push("--block-extern-crate".into());
470 }
471
472 if self.options.builtins {
473 output_vector.push("--builtins".into());
474 }
475
476 if let Some(ref prefix) = self.options.ctypes_prefix {
477 output_vector.push("--ctypes-prefix".into());
478 output_vector.push(prefix.clone());
479 }
480
481 if self.options.anon_fields_prefix != DEFAULT_ANON_FIELDS_PREFIX {
482 output_vector.push("--anon-fields-prefix".into());
483 output_vector.push(self.options.anon_fields_prefix.clone());
484 }
485
486 if self.options.emit_ast {
487 output_vector.push("--emit-clang-ast".into());
488 }
489
490 if self.options.emit_ir {
491 output_vector.push("--emit-ir".into());
492 }
493 if let Some(ref graph) = self.options.emit_ir_graphviz {
494 output_vector.push("--emit-ir-graphviz".into());
495 output_vector.push(graph.clone())
496 }
497 if self.options.enable_cxx_namespaces {
498 output_vector.push("--enable-cxx-namespaces".into());
499 }
500 if self.options.enable_function_attribute_detection {
501 output_vector.push("--enable-function-attribute-detection".into());
502 }
503 if self.options.disable_name_namespacing {
504 output_vector.push("--disable-name-namespacing".into());
505 }
506 if self.options.disable_nested_struct_naming {
507 output_vector.push("--disable-nested-struct-naming".into());
508 }
509
510 if self.options.disable_header_comment {
511 output_vector.push("--disable-header-comment".into());
512 }
513
514 if !self.options.codegen_config.functions() {
515 output_vector.push("--ignore-functions".into());
516 }
517
518 output_vector.push("--generate".into());
519
520 //Temporary placeholder for below 4 options
521 let mut options: Vec<String> = Vec::new();
522 if self.options.codegen_config.functions() {
523 options.push("functions".into());
524 }
525 if self.options.codegen_config.types() {
526 options.push("types".into());
527 }
528 if self.options.codegen_config.vars() {
529 options.push("vars".into());
530 }
531 if self.options.codegen_config.methods() {
532 options.push("methods".into());
533 }
534 if self.options.codegen_config.constructors() {
535 options.push("constructors".into());
536 }
537 if self.options.codegen_config.destructors() {
538 options.push("destructors".into());
539 }
540
541 output_vector.push(options.join(","));
542
543 if !self.options.codegen_config.methods() {
544 output_vector.push("--ignore-methods".into());
545 }
546
547 if !self.options.convert_floats {
548 output_vector.push("--no-convert-floats".into());
549 }
550
551 if !self.options.prepend_enum_name {
552 output_vector.push("--no-prepend-enum-name".into());
553 }
554
555 if self.options.fit_macro_constants {
556 output_vector.push("--fit-macro-constant-types".into());
557 }
558
559 if self.options.array_pointers_in_arguments {
560 output_vector.push("--use-array-pointers-in-arguments".into());
561 }
562
563 if let Some(ref wasm_import_module_name) =
564 self.options.wasm_import_module_name
565 {
566 output_vector.push("--wasm-import-module-name".into());
567 output_vector.push(wasm_import_module_name.clone());
568 }
569
570 for line in &self.options.raw_lines {
571 output_vector.push("--raw-line".into());
572 output_vector.push(line.clone());
573 }
574
575 for (module, lines) in &self.options.module_lines {
576 for line in lines.iter() {
577 output_vector.push("--module-raw-line".into());
578 output_vector.push(module.clone());
579 output_vector.push(line.clone());
580 }
581 }
582
583 if self.options.use_core {
584 output_vector.push("--use-core".into());
585 }
586
587 if self.options.conservative_inline_namespaces {
588 output_vector.push("--conservative-inline-namespaces".into());
589 }
590
591 if self.options.generate_inline_functions {
592 output_vector.push("--generate-inline-functions".into());
593 }
594
595 if !self.options.record_matches {
596 output_vector.push("--no-record-matches".into());
597 }
598
599 if !self.options.size_t_is_usize {
600 output_vector.push("--no-size_t-is-usize".into());
601 }
602
603 if !self.options.rustfmt_bindings {
604 output_vector.push("--no-rustfmt-bindings".into());
605 }
606
607 if let Some(path) = self
608 .options
609 .rustfmt_configuration_file
610 .as_ref()
611 .and_then(|f| f.to_str())
612 {
613 output_vector.push("--rustfmt-configuration-file".into());
614 output_vector.push(path.into());
615 }
616
617 if let Some(ref name) = self.options.dynamic_library_name {
618 output_vector.push("--dynamic-loading".into());
619 output_vector.push(name.clone());
620 }
621
622 if self.options.dynamic_link_require_all {
623 output_vector.push("--dynamic-link-require-all".into());
624 }
625
626 if self.options.respect_cxx_access_specs {
627 output_vector.push("--respect-cxx-access-specs".into());
628 }
629
630 if self.options.translate_enum_integer_types {
631 output_vector.push("--translate-enum-integer-types".into());
632 }
633
634 if self.options.c_naming {
635 output_vector.push("--c-naming".into());
636 }
637
638 if self.options.force_explicit_padding {
639 output_vector.push("--explicit-padding".into());
640 }
641
642 if self.options.vtable_generation {
643 output_vector.push("--vtable-generation".into());
644 }
645
646 if self.options.sort_semantically {
647 output_vector.push("--sort-semantically".into());
648 }
649
650 if self.options.merge_extern_blocks {
651 output_vector.push("--merge-extern-blocks".into());
652 }
653
654 if self.options.wrap_unsafe_ops {
655 output_vector.push("--wrap-unsafe-ops".into());
656 }
657
658 #[cfg(feature = "cli")]
659 for callbacks in &self.options.parse_callbacks {
660 output_vector.extend(callbacks.cli_args());
661 }
662 if self.options.wrap_static_fns {
663 output_vector.push("--wrap-static-fns".into())
664 }
665
666 if let Some(ref path) = self.options.wrap_static_fns_path {
667 output_vector.push("--wrap-static-fns-path".into());
668 output_vector.push(path.display().to_string());
669 }
670
671 if let Some(ref suffix) = self.options.wrap_static_fns_suffix {
672 output_vector.push("--wrap-static-fns-suffix".into());
673 output_vector.push(suffix.clone());
674 }
675
676 if cfg!(feature = "experimental") {
677 output_vector.push("--experimental".into());
678 }
679
680 // Add clang arguments
681
682 output_vector.push("--".into());
683
684 if !self.options.clang_args.is_empty() {
685 output_vector.extend(self.options.clang_args.iter().cloned());
686 }
687
688 // To pass more than one header, we need to pass all but the last
689 // header via the `-include` clang arg
690 for header in &self.options.input_headers
691 [..self.options.input_headers.len().saturating_sub(1)]
692 {
693 output_vector.push("-include".to_string());
694 output_vector.push(header.clone());
695 }
696
697 output_vector
698 }
699
700 /// Add an input C/C++ header to generate bindings for.
701 ///
702 /// This can be used to generate bindings to a single header:
703 ///
704 /// ```ignore
705 /// let bindings = bindgen::Builder::default()
706 /// .header("input.h")
707 /// .generate()
708 /// .unwrap();
709 /// ```
710 ///
711 /// Or you can invoke it multiple times to generate bindings to multiple
712 /// headers:
713 ///
714 /// ```ignore
715 /// let bindings = bindgen::Builder::default()
716 /// .header("first.h")
717 /// .header("second.h")
718 /// .header("third.h")
719 /// .generate()
720 /// .unwrap();
721 /// ```
header<T: Into<String>>(mut self, header: T) -> Builder722 pub fn header<T: Into<String>>(mut self, header: T) -> Builder {
723 self.options.input_headers.push(header.into());
724 self
725 }
726
727 /// Add a depfile output which will be written alongside the generated bindings.
depfile<H: Into<String>, D: Into<PathBuf>>( mut self, output_module: H, depfile: D, ) -> Builder728 pub fn depfile<H: Into<String>, D: Into<PathBuf>>(
729 mut self,
730 output_module: H,
731 depfile: D,
732 ) -> Builder {
733 self.options.depfile = Some(deps::DepfileSpec {
734 output_module: output_module.into(),
735 depfile_path: depfile.into(),
736 });
737 self
738 }
739
740 /// Add `contents` as an input C/C++ header named `name`.
741 ///
742 /// The file `name` will be added to the clang arguments.
header_contents(mut self, name: &str, contents: &str) -> Builder743 pub fn header_contents(mut self, name: &str, contents: &str) -> Builder {
744 // Apparently clang relies on having virtual FS correspondent to
745 // the real one, so we need absolute paths here
746 let absolute_path = env::current_dir()
747 .expect("Cannot retrieve current directory")
748 .join(name)
749 .to_str()
750 .expect("Cannot convert current directory name to string")
751 .to_owned();
752 self.options
753 .input_header_contents
754 .push((absolute_path, contents.into()));
755 self
756 }
757
758 /// Specify the rust target
759 ///
760 /// The default is the latest stable Rust version
rust_target(mut self, rust_target: RustTarget) -> Self761 pub fn rust_target(mut self, rust_target: RustTarget) -> Self {
762 #[allow(deprecated)]
763 if rust_target <= RustTarget::Stable_1_30 {
764 warn!(
765 "The {} rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues",
766 String::from(rust_target)
767 );
768 }
769 self.options.set_rust_target(rust_target);
770 self
771 }
772
773 /// Disable support for native Rust unions, if supported.
disable_untagged_union(mut self) -> Self774 pub fn disable_untagged_union(mut self) -> Self {
775 self.options.rust_features.untagged_union = false;
776 self
777 }
778
779 /// Disable insertion of bindgen's version identifier into generated
780 /// bindings.
disable_header_comment(mut self) -> Self781 pub fn disable_header_comment(mut self) -> Self {
782 self.options.disable_header_comment = true;
783 self
784 }
785
786 /// Set the output graphviz file.
emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder787 pub fn emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder {
788 let path = path.into();
789 self.options.emit_ir_graphviz = Some(path);
790 self
791 }
792
793 /// Whether the generated bindings should contain documentation comments
794 /// (docstrings) or not. This is set to true by default.
795 ///
796 /// Note that clang by default excludes comments from system headers, pass
797 /// `-fretain-comments-from-system-headers` as
798 /// [`clang_arg`][Builder::clang_arg] to include them. It can also be told
799 /// to process all comments (not just documentation ones) using the
800 /// `-fparse-all-comments` flag. See [slides on clang comment parsing](
801 /// https://llvm.org/devmtg/2012-11/Gribenko_CommentParsing.pdf) for
802 /// background and examples.
generate_comments(mut self, doit: bool) -> Self803 pub fn generate_comments(mut self, doit: bool) -> Self {
804 self.options.generate_comments = doit;
805 self
806 }
807
808 /// Whether to allowlist recursively or not. Defaults to true.
809 ///
810 /// Given that we have explicitly allowlisted the "initiate_dance_party"
811 /// function in this C header:
812 ///
813 /// ```c
814 /// typedef struct MoonBoots {
815 /// int bouncy_level;
816 /// } MoonBoots;
817 ///
818 /// void initiate_dance_party(MoonBoots* boots);
819 /// ```
820 ///
821 /// We would normally generate bindings to both the `initiate_dance_party`
822 /// function and the `MoonBoots` struct that it transitively references. By
823 /// configuring with `allowlist_recursively(false)`, `bindgen` will not emit
824 /// bindings for anything except the explicitly allowlisted items, and there
825 /// would be no emitted struct definition for `MoonBoots`. However, the
826 /// `initiate_dance_party` function would still reference `MoonBoots`!
827 ///
828 /// **Disabling this feature will almost certainly cause `bindgen` to emit
829 /// bindings that will not compile!** If you disable this feature, then it
830 /// is *your* responsibility to provide definitions for every type that is
831 /// referenced from an explicitly allowlisted item. One way to provide the
832 /// definitions is by using the [`Builder::raw_line`](#method.raw_line)
833 /// method, another would be to define them in Rust and then `include!(...)`
834 /// the bindings immediately afterwards.
allowlist_recursively(mut self, doit: bool) -> Self835 pub fn allowlist_recursively(mut self, doit: bool) -> Self {
836 self.options.allowlist_recursively = doit;
837 self
838 }
839
840 /// Generate `#[macro_use] extern crate objc;` instead of `use objc;`
841 /// in the prologue of the files generated from objective-c files
objc_extern_crate(mut self, doit: bool) -> Self842 pub fn objc_extern_crate(mut self, doit: bool) -> Self {
843 self.options.objc_extern_crate = doit;
844 self
845 }
846
847 /// Generate proper block signatures instead of void pointers.
generate_block(mut self, doit: bool) -> Self848 pub fn generate_block(mut self, doit: bool) -> Self {
849 self.options.generate_block = doit;
850 self
851 }
852
853 /// Generate `#[macro_use] extern crate block;` instead of `use block;`
854 /// in the prologue of the files generated from apple block files
block_extern_crate(mut self, doit: bool) -> Self855 pub fn block_extern_crate(mut self, doit: bool) -> Self {
856 self.options.block_extern_crate = doit;
857 self
858 }
859
860 /// Whether to use the clang-provided name mangling. This is true by default
861 /// and probably needed for C++ features.
862 ///
863 /// However, some old libclang versions seem to return incorrect results in
864 /// some cases for non-mangled functions, see [1], so we allow disabling it.
865 ///
866 /// [1]: https://github.com/rust-lang/rust-bindgen/issues/528
trust_clang_mangling(mut self, doit: bool) -> Self867 pub fn trust_clang_mangling(mut self, doit: bool) -> Self {
868 self.options.enable_mangling = doit;
869 self
870 }
871
872 fn_with_regex_arg! {
873 /// Hide the given type from the generated bindings. Regular expressions are
874 /// supported.
875 ///
876 /// To blocklist types prefixed with "mylib" use `"mylib_.*"`.
877 pub fn blocklist_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
878 self.options.blocklisted_types.insert(arg);
879 self
880 }
881 }
882
883 fn_with_regex_arg! {
884 /// Hide the given function from the generated bindings. Regular expressions
885 /// are supported.
886 ///
887 /// Methods can be blocklisted by prefixing the name of the type implementing
888 /// them followed by an underscore. So if `Foo` has a method `bar`, it can
889 /// be blocklisted as `Foo_bar`.
890 ///
891 /// To blocklist functions prefixed with "mylib" use `"mylib_.*"`.
892 pub fn blocklist_function<T: AsRef<str>>(mut self, arg: T) -> Builder {
893 self.options.blocklisted_functions.insert(arg);
894 self
895 }
896 }
897
898 fn_with_regex_arg! {
899 /// Hide the given item from the generated bindings, regardless of
900 /// whether it's a type, function, module, etc. Regular
901 /// expressions are supported.
902 ///
903 /// To blocklist items prefixed with "mylib" use `"mylib_.*"`.
904 pub fn blocklist_item<T: AsRef<str>>(mut self, arg: T) -> Builder {
905 self.options.blocklisted_items.insert(arg);
906 self
907 }
908 }
909
910 fn_with_regex_arg! {
911 /// Hide any contents of the given file from the generated bindings,
912 /// regardless of whether it's a type, function, module etc.
913 pub fn blocklist_file<T: AsRef<str>>(mut self, arg: T) -> Builder {
914 self.options.blocklisted_files.insert(arg);
915 self
916 }
917 }
918
919 fn_with_regex_arg! {
920 /// Treat the given type as opaque in the generated bindings. Regular
921 /// expressions are supported.
922 ///
923 /// To change types prefixed with "mylib" into opaque, use `"mylib_.*"`.
924 pub fn opaque_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
925 self.options.opaque_types.insert(arg);
926 self
927 }
928 }
929
930 fn_with_regex_arg! {
931 /// Allowlist the given type so that it (and all types that it transitively
932 /// refers to) appears in the generated bindings. Regular expressions are
933 /// supported.
934 ///
935 /// To allowlist types prefixed with "mylib" use `"mylib_.*"`.
936 pub fn allowlist_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
937 self.options.allowlisted_types.insert(arg);
938 self
939 }
940 }
941
942 fn_with_regex_arg! {
943 /// Allowlist the given function so that it (and all types that it
944 /// transitively refers to) appears in the generated bindings. Regular
945 /// expressions are supported.
946 ///
947 /// Methods can be allowlisted by prefixing the name of the type
948 /// implementing them followed by an underscore. So if `Foo` has a method
949 /// `bar`, it can be allowlisted as `Foo_bar`.
950 ///
951 /// To allowlist functions prefixed with "mylib" use `"mylib_.*"`.
952 pub fn allowlist_function<T: AsRef<str>>(mut self, arg: T) -> Builder {
953 self.options.allowlisted_functions.insert(arg);
954 self
955 }
956 }
957
958 fn_with_regex_arg! {
959 /// Allowlist the given variable so that it (and all types that it
960 /// transitively refers to) appears in the generated bindings. Regular
961 /// expressions are supported.
962 ///
963 /// To allowlist variables prefixed with "mylib" use `"mylib_.*"`.
964 pub fn allowlist_var<T: AsRef<str>>(mut self, arg: T) -> Builder {
965 self.options.allowlisted_vars.insert(arg);
966 self
967 }
968 }
969
970 fn_with_regex_arg! {
971 /// Allowlist the given file so that its contents appear in the generated bindings.
972 pub fn allowlist_file<T: AsRef<str>>(mut self, arg: T) -> Builder {
973 self.options.allowlisted_files.insert(arg);
974 self
975 }
976 }
977
978 /// Set the default style of code to generate for enums
default_enum_style( mut self, arg: codegen::EnumVariation, ) -> Builder979 pub fn default_enum_style(
980 mut self,
981 arg: codegen::EnumVariation,
982 ) -> Builder {
983 self.options.default_enum_style = arg;
984 self
985 }
986
987 fn_with_regex_arg! {
988 /// Mark the given enum (or set of enums, if using a pattern) as being
989 /// bitfield-like. Regular expressions are supported.
990 ///
991 /// This makes bindgen generate a type that isn't a rust `enum`. Regular
992 /// expressions are supported.
993 ///
994 /// This is similar to the newtype enum style, but with the bitwise
995 /// operators implemented.
996 pub fn bitfield_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
997 self.options.bitfield_enums.insert(arg);
998 self
999 }
1000 }
1001
1002 fn_with_regex_arg! {
1003 /// Mark the given enum (or set of enums, if using a pattern) as a newtype.
1004 /// Regular expressions are supported.
1005 ///
1006 /// This makes bindgen generate a type that isn't a Rust `enum`. Regular
1007 /// expressions are supported.
1008 pub fn newtype_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
1009 self.options.newtype_enums.insert(arg);
1010 self
1011 }
1012 }
1013
1014 fn_with_regex_arg! {
1015 /// Mark the given enum (or set of enums, if using a pattern) as a newtype
1016 /// whose variants are exposed as global constants.
1017 ///
1018 /// Regular expressions are supported.
1019 ///
1020 /// This makes bindgen generate a type that isn't a Rust `enum`. Regular
1021 /// expressions are supported.
1022 pub fn newtype_global_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
1023 self.options.newtype_global_enums.insert(arg);
1024 self
1025 }
1026 }
1027
1028 fn_with_regex_arg! {
1029 /// Mark the given enum (or set of enums, if using a pattern) as a Rust
1030 /// enum.
1031 ///
1032 /// This makes bindgen generate enums instead of constants. Regular
1033 /// expressions are supported.
1034 ///
1035 /// **Use this with caution**, creating this in unsafe code
1036 /// (including FFI) with an invalid value will invoke undefined behaviour.
1037 /// You may want to use the newtype enum style instead.
1038 pub fn rustified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
1039 self.options.rustified_enums.insert(arg);
1040 self
1041 }
1042 }
1043
1044 fn_with_regex_arg! {
1045 /// Mark the given enum (or set of enums, if using a pattern) as a Rust
1046 /// enum with the `#[non_exhaustive]` attribute.
1047 ///
1048 /// This makes bindgen generate enums instead of constants. Regular
1049 /// expressions are supported.
1050 ///
1051 /// **Use this with caution**, creating this in unsafe code
1052 /// (including FFI) with an invalid value will invoke undefined behaviour.
1053 /// You may want to use the newtype enum style instead.
1054 pub fn rustified_non_exhaustive_enum<T: AsRef<str>>(
1055 mut self,
1056 arg: T,
1057 ) -> Builder {
1058 self.options.rustified_non_exhaustive_enums.insert(arg);
1059 self
1060 }
1061 }
1062
1063 fn_with_regex_arg! {
1064 /// Mark the given enum (or set of enums, if using a pattern) as a set of
1065 /// constants that are not to be put into a module.
1066 pub fn constified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
1067 self.options.constified_enums.insert(arg);
1068 self
1069 }
1070 }
1071
1072 fn_with_regex_arg! {
1073 /// Mark the given enum (or set of enums, if using a pattern) as a set of
1074 /// constants that should be put into a module.
1075 ///
1076 /// This makes bindgen generate modules containing constants instead of
1077 /// just constants. Regular expressions are supported.
1078 pub fn constified_enum_module<T: AsRef<str>>(mut self, arg: T) -> Builder {
1079 self.options.constified_enum_modules.insert(arg);
1080 self
1081 }
1082 }
1083
1084 /// Set the default type for macro constants
default_macro_constant_type( mut self, arg: codegen::MacroTypeVariation, ) -> Builder1085 pub fn default_macro_constant_type(
1086 mut self,
1087 arg: codegen::MacroTypeVariation,
1088 ) -> Builder {
1089 self.options.default_macro_constant_type = arg;
1090 self
1091 }
1092
1093 /// Set the default style of code to generate for typedefs
default_alias_style( mut self, arg: codegen::AliasVariation, ) -> Builder1094 pub fn default_alias_style(
1095 mut self,
1096 arg: codegen::AliasVariation,
1097 ) -> Builder {
1098 self.options.default_alias_style = arg;
1099 self
1100 }
1101
1102 fn_with_regex_arg! {
1103 /// Mark the given typedef alias (or set of aliases, if using a pattern) to
1104 /// use regular Rust type aliasing.
1105 ///
1106 /// This is the default behavior and should be used if `default_alias_style`
1107 /// was set to NewType or NewTypeDeref and you want to override it for a
1108 /// set of typedefs.
1109 pub fn type_alias<T: AsRef<str>>(mut self, arg: T) -> Builder {
1110 self.options.type_alias.insert(arg);
1111 self
1112 }
1113 }
1114
1115 fn_with_regex_arg! {
1116 /// Mark the given typedef alias (or set of aliases, if using a pattern) to
1117 /// be generated as a new type by having the aliased type be wrapped in a
1118 /// #[repr(transparent)] struct.
1119 ///
1120 /// Used to enforce stricter type checking.
1121 pub fn new_type_alias<T: AsRef<str>>(mut self, arg: T) -> Builder {
1122 self.options.new_type_alias.insert(arg);
1123 self
1124 }
1125 }
1126
1127 fn_with_regex_arg! {
1128 /// Mark the given typedef alias (or set of aliases, if using a pattern) to
1129 /// be generated as a new type by having the aliased type be wrapped in a
1130 /// #[repr(transparent)] struct and also have an automatically generated
1131 /// impl's of `Deref` and `DerefMut` to their aliased type.
1132 pub fn new_type_alias_deref<T: AsRef<str>>(mut self, arg: T) -> Builder {
1133 self.options.new_type_alias_deref.insert(arg);
1134 self
1135 }
1136 }
1137
1138 /// Set the default style of code to generate for unions with a non-Copy member.
default_non_copy_union_style( mut self, arg: codegen::NonCopyUnionStyle, ) -> Self1139 pub fn default_non_copy_union_style(
1140 mut self,
1141 arg: codegen::NonCopyUnionStyle,
1142 ) -> Self {
1143 self.options.default_non_copy_union_style = arg;
1144 self
1145 }
1146
1147 fn_with_regex_arg! {
1148 /// Mark the given union (or set of union, if using a pattern) to use
1149 /// a bindgen-generated wrapper for its members if at least one is non-Copy.
1150 pub fn bindgen_wrapper_union<T: AsRef<str>>(mut self, arg: T) -> Self {
1151 self.options.bindgen_wrapper_union.insert(arg);
1152 self
1153 }
1154 }
1155
1156 fn_with_regex_arg! {
1157 /// Mark the given union (or set of union, if using a pattern) to use
1158 /// [`::core::mem::ManuallyDrop`] for its members if at least one is non-Copy.
1159 ///
1160 /// Note: `ManuallyDrop` was stabilized in Rust 1.20.0, do not use it if your
1161 /// MSRV is lower.
1162 pub fn manually_drop_union<T: AsRef<str>>(mut self, arg: T) -> Self {
1163 self.options.manually_drop_union.insert(arg);
1164 self
1165 }
1166 }
1167
1168 fn_with_regex_arg! {
1169 /// Add a string to prepend to the generated bindings. The string is passed
1170 /// through without any modification.
1171 pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Self {
1172 self.options.raw_lines.push(arg.into());
1173 self
1174 }
1175 }
1176
1177 /// 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>,1178 pub fn module_raw_line<T, U>(mut self, mod_: T, line: U) -> Self
1179 where
1180 T: Into<String>,
1181 U: Into<String>,
1182 {
1183 self.options
1184 .module_lines
1185 .entry(mod_.into())
1186 .or_insert_with(Vec::new)
1187 .push(line.into());
1188 self
1189 }
1190
1191 /// 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>,1192 pub fn module_raw_lines<T, I>(mut self, mod_: T, lines: I) -> Self
1193 where
1194 T: Into<String>,
1195 I: IntoIterator,
1196 I::Item: Into<String>,
1197 {
1198 self.options
1199 .module_lines
1200 .entry(mod_.into())
1201 .or_insert_with(Vec::new)
1202 .extend(lines.into_iter().map(Into::into));
1203 self
1204 }
1205
1206 /// Add an argument to be passed straight through to clang.
clang_arg<T: Into<String>>(mut self, arg: T) -> Builder1207 pub fn clang_arg<T: Into<String>>(mut self, arg: T) -> Builder {
1208 self.options.clang_args.push(arg.into());
1209 self
1210 }
1211
1212 /// Add arguments to be passed straight through to clang.
clang_args<I>(mut self, iter: I) -> Builder where I: IntoIterator, I::Item: AsRef<str>,1213 pub fn clang_args<I>(mut self, iter: I) -> Builder
1214 where
1215 I: IntoIterator,
1216 I::Item: AsRef<str>,
1217 {
1218 for arg in iter {
1219 self = self.clang_arg(arg.as_ref())
1220 }
1221 self
1222 }
1223
1224 /// Emit bindings for builtin definitions (for example `__builtin_va_list`)
1225 /// in the generated Rust.
emit_builtins(mut self) -> Builder1226 pub fn emit_builtins(mut self) -> Builder {
1227 self.options.builtins = true;
1228 self
1229 }
1230
1231 /// Avoid converting floats to `f32`/`f64` by default.
no_convert_floats(mut self) -> Self1232 pub fn no_convert_floats(mut self) -> Self {
1233 self.options.convert_floats = false;
1234 self
1235 }
1236
1237 /// Set whether layout tests should be generated.
layout_tests(mut self, doit: bool) -> Self1238 pub fn layout_tests(mut self, doit: bool) -> Self {
1239 self.options.layout_tests = doit;
1240 self
1241 }
1242
1243 /// Set whether `Debug` should be implemented, if it can not be derived automatically.
impl_debug(mut self, doit: bool) -> Self1244 pub fn impl_debug(mut self, doit: bool) -> Self {
1245 self.options.impl_debug = doit;
1246 self
1247 }
1248
1249 /// Set whether `PartialEq` should be implemented, if it can not be derived automatically.
impl_partialeq(mut self, doit: bool) -> Self1250 pub fn impl_partialeq(mut self, doit: bool) -> Self {
1251 self.options.impl_partialeq = doit;
1252 self
1253 }
1254
1255 /// Set whether `Copy` should be derived by default.
derive_copy(mut self, doit: bool) -> Self1256 pub fn derive_copy(mut self, doit: bool) -> Self {
1257 self.options.derive_copy = doit;
1258 self
1259 }
1260
1261 /// Set whether `Debug` should be derived by default.
derive_debug(mut self, doit: bool) -> Self1262 pub fn derive_debug(mut self, doit: bool) -> Self {
1263 self.options.derive_debug = doit;
1264 self
1265 }
1266
1267 /// Set whether `Default` should be derived by default.
derive_default(mut self, doit: bool) -> Self1268 pub fn derive_default(mut self, doit: bool) -> Self {
1269 self.options.derive_default = doit;
1270 self
1271 }
1272
1273 /// Set whether `Hash` should be derived by default.
derive_hash(mut self, doit: bool) -> Self1274 pub fn derive_hash(mut self, doit: bool) -> Self {
1275 self.options.derive_hash = doit;
1276 self
1277 }
1278
1279 /// Set whether `PartialOrd` should be derived by default.
1280 /// If we don't compute partialord, we also cannot compute
1281 /// ord. Set the derive_ord to `false` when doit is `false`.
derive_partialord(mut self, doit: bool) -> Self1282 pub fn derive_partialord(mut self, doit: bool) -> Self {
1283 self.options.derive_partialord = doit;
1284 if !doit {
1285 self.options.derive_ord = false;
1286 }
1287 self
1288 }
1289
1290 /// Set whether `Ord` should be derived by default.
1291 /// We can't compute `Ord` without computing `PartialOrd`,
1292 /// so we set the same option to derive_partialord.
derive_ord(mut self, doit: bool) -> Self1293 pub fn derive_ord(mut self, doit: bool) -> Self {
1294 self.options.derive_ord = doit;
1295 self.options.derive_partialord = doit;
1296 self
1297 }
1298
1299 /// Set whether `PartialEq` should be derived by default.
1300 ///
1301 /// If we don't derive `PartialEq`, we also cannot derive `Eq`, so deriving
1302 /// `Eq` is also disabled when `doit` is `false`.
derive_partialeq(mut self, doit: bool) -> Self1303 pub fn derive_partialeq(mut self, doit: bool) -> Self {
1304 self.options.derive_partialeq = doit;
1305 if !doit {
1306 self.options.derive_eq = false;
1307 }
1308 self
1309 }
1310
1311 /// Set whether `Eq` should be derived by default.
1312 ///
1313 /// We can't derive `Eq` without also deriving `PartialEq`, so we also
1314 /// enable deriving `PartialEq` when `doit` is `true`.
derive_eq(mut self, doit: bool) -> Self1315 pub fn derive_eq(mut self, doit: bool) -> Self {
1316 self.options.derive_eq = doit;
1317 if doit {
1318 self.options.derive_partialeq = doit;
1319 }
1320 self
1321 }
1322
1323 /// Set whether or not to time bindgen phases, and print information to
1324 /// stderr.
time_phases(mut self, doit: bool) -> Self1325 pub fn time_phases(mut self, doit: bool) -> Self {
1326 self.options.time_phases = doit;
1327 self
1328 }
1329
1330 /// Emit Clang AST.
emit_clang_ast(mut self) -> Builder1331 pub fn emit_clang_ast(mut self) -> Builder {
1332 self.options.emit_ast = true;
1333 self
1334 }
1335
1336 /// Emit IR.
emit_ir(mut self) -> Builder1337 pub fn emit_ir(mut self) -> Builder {
1338 self.options.emit_ir = true;
1339 self
1340 }
1341
1342 /// Enable C++ namespaces.
enable_cxx_namespaces(mut self) -> Builder1343 pub fn enable_cxx_namespaces(mut self) -> Builder {
1344 self.options.enable_cxx_namespaces = true;
1345 self
1346 }
1347
1348 /// Enable detecting must_use attributes on C functions.
1349 ///
1350 /// This is quite slow in some cases (see #1465), so it's disabled by
1351 /// default.
1352 ///
1353 /// Note that for this to do something meaningful for now at least, the rust
1354 /// target version has to have support for `#[must_use]`.
enable_function_attribute_detection(mut self) -> Self1355 pub fn enable_function_attribute_detection(mut self) -> Self {
1356 self.options.enable_function_attribute_detection = true;
1357 self
1358 }
1359
1360 /// Disable name auto-namespacing.
1361 ///
1362 /// By default, bindgen mangles names like `foo::bar::Baz` to look like
1363 /// `foo_bar_Baz` instead of just `Baz`.
1364 ///
1365 /// This method disables that behavior.
1366 ///
1367 /// Note that this intentionally does not change the names used for
1368 /// allowlisting and blocklisting, which should still be mangled with the
1369 /// namespaces.
1370 ///
1371 /// Note, also, that this option may cause bindgen to generate duplicate
1372 /// names.
disable_name_namespacing(mut self) -> Builder1373 pub fn disable_name_namespacing(mut self) -> Builder {
1374 self.options.disable_name_namespacing = true;
1375 self
1376 }
1377
1378 /// Disable nested struct naming.
1379 ///
1380 /// The following structs have different names for C and C++. In case of C
1381 /// they are visible as `foo` and `bar`. In case of C++ they are visible as
1382 /// `foo` and `foo::bar`.
1383 ///
1384 /// ```c
1385 /// struct foo {
1386 /// struct bar {
1387 /// } b;
1388 /// };
1389 /// ```
1390 ///
1391 /// Bindgen wants to avoid duplicate names by default so it follows C++ naming
1392 /// and it generates `foo`/`foo_bar` instead of just `foo`/`bar`.
1393 ///
1394 /// This method disables this behavior and it is indented to be used only
1395 /// for headers that were written for C.
disable_nested_struct_naming(mut self) -> Builder1396 pub fn disable_nested_struct_naming(mut self) -> Builder {
1397 self.options.disable_nested_struct_naming = true;
1398 self
1399 }
1400
1401 /// Treat inline namespaces conservatively.
1402 ///
1403 /// This is tricky, because in C++ is technically legal to override an item
1404 /// defined in an inline namespace:
1405 ///
1406 /// ```cpp
1407 /// inline namespace foo {
1408 /// using Bar = int;
1409 /// }
1410 /// using Bar = long;
1411 /// ```
1412 ///
1413 /// Even though referencing `Bar` is a compiler error.
1414 ///
1415 /// We want to support this (arguably esoteric) use case, but we don't want
1416 /// to make the rest of bindgen users pay an usability penalty for that.
1417 ///
1418 /// To support this, we need to keep all the inline namespaces around, but
1419 /// then bindgen usage is a bit more difficult, because you cannot
1420 /// reference, e.g., `std::string` (you'd need to use the proper inline
1421 /// namespace).
1422 ///
1423 /// We could complicate a lot of the logic to detect name collisions, and if
1424 /// not detected generate a `pub use inline_ns::*` or something like that.
1425 ///
1426 /// That's probably something we can do if we see this option is needed in a
1427 /// lot of cases, to improve it's usability, but my guess is that this is
1428 /// not going to be too useful.
conservative_inline_namespaces(mut self) -> Builder1429 pub fn conservative_inline_namespaces(mut self) -> Builder {
1430 self.options.conservative_inline_namespaces = true;
1431 self
1432 }
1433
1434 /// Whether inline functions should be generated or not.
1435 ///
1436 /// Note that they will usually not work. However you can use
1437 /// `-fkeep-inline-functions` or `-fno-inline-functions` if you are
1438 /// responsible of compiling the library to make them callable.
generate_inline_functions(mut self, doit: bool) -> Self1439 pub fn generate_inline_functions(mut self, doit: bool) -> Self {
1440 self.options.generate_inline_functions = doit;
1441 self
1442 }
1443
1444 /// Ignore functions.
ignore_functions(mut self) -> Builder1445 pub fn ignore_functions(mut self) -> Builder {
1446 self.options.codegen_config.remove(CodegenConfig::FUNCTIONS);
1447 self
1448 }
1449
1450 /// Ignore methods.
ignore_methods(mut self) -> Builder1451 pub fn ignore_methods(mut self) -> Builder {
1452 self.options.codegen_config.remove(CodegenConfig::METHODS);
1453 self
1454 }
1455
1456 /// Use core instead of libstd in the generated bindings.
use_core(mut self) -> Builder1457 pub fn use_core(mut self) -> Builder {
1458 self.options.use_core = true;
1459 self
1460 }
1461
1462 /// Use the given prefix for the raw types instead of `::std::os::raw`.
ctypes_prefix<T: Into<String>>(mut self, prefix: T) -> Builder1463 pub fn ctypes_prefix<T: Into<String>>(mut self, prefix: T) -> Builder {
1464 self.options.ctypes_prefix = Some(prefix.into());
1465 self
1466 }
1467
1468 /// Use the given prefix for the anon fields.
anon_fields_prefix<T: Into<String>>(mut self, prefix: T) -> Builder1469 pub fn anon_fields_prefix<T: Into<String>>(mut self, prefix: T) -> Builder {
1470 self.options.anon_fields_prefix = prefix.into();
1471 self
1472 }
1473
1474 /// Allows configuring types in different situations, see the
1475 /// [`ParseCallbacks`](./callbacks/trait.ParseCallbacks.html) documentation.
parse_callbacks( mut self, cb: Box<dyn callbacks::ParseCallbacks>, ) -> Self1476 pub fn parse_callbacks(
1477 mut self,
1478 cb: Box<dyn callbacks::ParseCallbacks>,
1479 ) -> Self {
1480 self.options.parse_callbacks.push(Rc::from(cb));
1481 self
1482 }
1483
1484 /// Choose what to generate using a
1485 /// [`CodegenConfig`](./struct.CodegenConfig.html).
with_codegen_config(mut self, config: CodegenConfig) -> Self1486 pub fn with_codegen_config(mut self, config: CodegenConfig) -> Self {
1487 self.options.codegen_config = config;
1488 self
1489 }
1490
1491 /// Whether to detect include paths using clang_sys.
detect_include_paths(mut self, doit: bool) -> Self1492 pub fn detect_include_paths(mut self, doit: bool) -> Self {
1493 self.options.detect_include_paths = doit;
1494 self
1495 }
1496
1497 /// Whether to try to fit macro constants to types smaller than u32/i32
fit_macro_constants(mut self, doit: bool) -> Self1498 pub fn fit_macro_constants(mut self, doit: bool) -> Self {
1499 self.options.fit_macro_constants = doit;
1500 self
1501 }
1502
1503 /// Prepend the enum name to constant or newtype variants.
prepend_enum_name(mut self, doit: bool) -> Self1504 pub fn prepend_enum_name(mut self, doit: bool) -> Self {
1505 self.options.prepend_enum_name = doit;
1506 self
1507 }
1508
1509 /// Set whether `size_t` should be translated to `usize` automatically.
size_t_is_usize(mut self, is: bool) -> Self1510 pub fn size_t_is_usize(mut self, is: bool) -> Self {
1511 self.options.size_t_is_usize = is;
1512 self
1513 }
1514
1515 /// Set whether rustfmt should format the generated bindings.
rustfmt_bindings(mut self, doit: bool) -> Self1516 pub fn rustfmt_bindings(mut self, doit: bool) -> Self {
1517 self.options.rustfmt_bindings = doit;
1518 self
1519 }
1520
1521 /// Set whether we should record matched items in our regex sets.
record_matches(mut self, doit: bool) -> Self1522 pub fn record_matches(mut self, doit: bool) -> Self {
1523 self.options.record_matches = doit;
1524 self
1525 }
1526
1527 /// Set the absolute path to the rustfmt configuration file, if None, the standard rustfmt
1528 /// options are used.
rustfmt_configuration_file(mut self, path: Option<PathBuf>) -> Self1529 pub fn rustfmt_configuration_file(mut self, path: Option<PathBuf>) -> Self {
1530 self = self.rustfmt_bindings(true);
1531 self.options.rustfmt_configuration_file = path;
1532 self
1533 }
1534
1535 /// Sets an explicit path to rustfmt, to be used when rustfmt is enabled.
with_rustfmt<P: Into<PathBuf>>(mut self, path: P) -> Self1536 pub fn with_rustfmt<P: Into<PathBuf>>(mut self, path: P) -> Self {
1537 self.options.rustfmt_path = Some(path.into());
1538 self
1539 }
1540
1541 /// If true, always emit explicit padding fields.
1542 ///
1543 /// If a struct needs to be serialized in its native format (padding bytes
1544 /// and all), for example writing it to a file or sending it on the network,
1545 /// then this should be enabled, as anything reading the padding bytes of
1546 /// a struct may lead to Undefined Behavior.
explicit_padding(mut self, doit: bool) -> Self1547 pub fn explicit_padding(mut self, doit: bool) -> Self {
1548 self.options.force_explicit_padding = doit;
1549 self
1550 }
1551
1552 /// If true, enables experimental support to generate vtable functions.
1553 ///
1554 /// Should mostly work, though some edge cases are likely to be broken.
vtable_generation(mut self, doit: bool) -> Self1555 pub fn vtable_generation(mut self, doit: bool) -> Self {
1556 self.options.vtable_generation = doit;
1557 self
1558 }
1559
1560 /// If true, enables the sorting of the output in a predefined manner.
1561 ///
1562 /// TODO: Perhaps move the sorting order out into a config
sort_semantically(mut self, doit: bool) -> Self1563 pub fn sort_semantically(mut self, doit: bool) -> Self {
1564 self.options.sort_semantically = doit;
1565 self
1566 }
1567
1568 /// If true, merges extern blocks.
merge_extern_blocks(mut self, doit: bool) -> Self1569 pub fn merge_extern_blocks(mut self, doit: bool) -> Self {
1570 self.options.merge_extern_blocks = doit;
1571 self
1572 }
1573
1574 /// Generate the Rust bindings using the options built up thus far.
generate(mut self) -> Result<Bindings, BindgenError>1575 pub fn generate(mut self) -> Result<Bindings, BindgenError> {
1576 // Add any extra arguments from the environment to the clang command line.
1577 self.options.clang_args.extend(get_extra_clang_args());
1578
1579 // Transform input headers to arguments on the clang command line.
1580 self.options.clang_args.extend(
1581 self.options.input_headers
1582 [..self.options.input_headers.len().saturating_sub(1)]
1583 .iter()
1584 .flat_map(|header| ["-include".into(), header.to_string()]),
1585 );
1586
1587 let input_unsaved_files =
1588 std::mem::take(&mut self.options.input_header_contents)
1589 .into_iter()
1590 .map(|(name, contents)| clang::UnsavedFile::new(name, contents))
1591 .collect::<Vec<_>>();
1592
1593 Bindings::generate(self.options, input_unsaved_files)
1594 }
1595
1596 /// Preprocess and dump the input header files to disk.
1597 ///
1598 /// This is useful when debugging bindgen, using C-Reduce, or when filing
1599 /// issues. The resulting file will be named something like `__bindgen.i` or
1600 /// `__bindgen.ii`
dump_preprocessed_input(&self) -> io::Result<()>1601 pub fn dump_preprocessed_input(&self) -> io::Result<()> {
1602 let clang =
1603 clang_sys::support::Clang::find(None, &[]).ok_or_else(|| {
1604 io::Error::new(
1605 io::ErrorKind::Other,
1606 "Cannot find clang executable",
1607 )
1608 })?;
1609
1610 // The contents of a wrapper file that includes all the input header
1611 // files.
1612 let mut wrapper_contents = String::new();
1613
1614 // Whether we are working with C or C++ inputs.
1615 let mut is_cpp = args_are_cpp(&self.options.clang_args);
1616
1617 // For each input header, add `#include "$header"`.
1618 for header in &self.options.input_headers {
1619 is_cpp |= file_is_cpp(header);
1620
1621 wrapper_contents.push_str("#include \"");
1622 wrapper_contents.push_str(header);
1623 wrapper_contents.push_str("\"\n");
1624 }
1625
1626 // For each input header content, add a prefix line of `#line 0 "$name"`
1627 // followed by the contents.
1628 for (name, contents) in &self.options.input_header_contents {
1629 is_cpp |= file_is_cpp(name);
1630
1631 wrapper_contents.push_str("#line 0 \"");
1632 wrapper_contents.push_str(name);
1633 wrapper_contents.push_str("\"\n");
1634 wrapper_contents.push_str(contents);
1635 }
1636
1637 let wrapper_path = PathBuf::from(if is_cpp {
1638 "__bindgen.cpp"
1639 } else {
1640 "__bindgen.c"
1641 });
1642
1643 {
1644 let mut wrapper_file = File::create(&wrapper_path)?;
1645 wrapper_file.write_all(wrapper_contents.as_bytes())?;
1646 }
1647
1648 let mut cmd = Command::new(clang.path);
1649 cmd.arg("-save-temps")
1650 .arg("-E")
1651 .arg("-C")
1652 .arg("-c")
1653 .arg(&wrapper_path)
1654 .stdout(Stdio::piped());
1655
1656 for a in &self.options.clang_args {
1657 cmd.arg(a);
1658 }
1659
1660 for a in get_extra_clang_args() {
1661 cmd.arg(a);
1662 }
1663
1664 let mut child = cmd.spawn()?;
1665
1666 let mut preprocessed = child.stdout.take().unwrap();
1667 let mut file = File::create(if is_cpp {
1668 "__bindgen.ii"
1669 } else {
1670 "__bindgen.i"
1671 })?;
1672 io::copy(&mut preprocessed, &mut file)?;
1673
1674 if child.wait()?.success() {
1675 Ok(())
1676 } else {
1677 Err(io::Error::new(
1678 io::ErrorKind::Other,
1679 "clang exited with non-zero status",
1680 ))
1681 }
1682 }
1683
1684 fn_with_regex_arg! {
1685 /// Don't derive `PartialEq` for a given type. Regular
1686 /// expressions are supported.
1687 pub fn no_partialeq<T: Into<String>>(mut self, arg: T) -> Builder {
1688 self.options.no_partialeq_types.insert(arg.into());
1689 self
1690 }
1691 }
1692
1693 fn_with_regex_arg! {
1694 /// Don't derive `Copy` for a given type. Regular
1695 /// expressions are supported.
1696 pub fn no_copy<T: Into<String>>(mut self, arg: T) -> Self {
1697 self.options.no_copy_types.insert(arg.into());
1698 self
1699 }
1700 }
1701
1702 fn_with_regex_arg! {
1703 /// Don't derive `Debug` for a given type. Regular
1704 /// expressions are supported.
1705 pub fn no_debug<T: Into<String>>(mut self, arg: T) -> Self {
1706 self.options.no_debug_types.insert(arg.into());
1707 self
1708 }
1709 }
1710
1711 fn_with_regex_arg! {
1712 /// Don't derive/impl `Default` for a given type. Regular
1713 /// expressions are supported.
1714 pub fn no_default<T: Into<String>>(mut self, arg: T) -> Self {
1715 self.options.no_default_types.insert(arg.into());
1716 self
1717 }
1718 }
1719
1720 fn_with_regex_arg! {
1721 /// Don't derive `Hash` for a given type. Regular
1722 /// expressions are supported.
1723 pub fn no_hash<T: Into<String>>(mut self, arg: T) -> Builder {
1724 self.options.no_hash_types.insert(arg.into());
1725 self
1726 }
1727 }
1728
1729 fn_with_regex_arg! {
1730 /// Add `#[must_use]` for the given type. Regular
1731 /// expressions are supported.
1732 pub fn must_use_type<T: Into<String>>(mut self, arg: T) -> Builder {
1733 self.options.must_use_types.insert(arg.into());
1734 self
1735 }
1736 }
1737
1738 /// 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) -> Self1739 pub fn array_pointers_in_arguments(mut self, doit: bool) -> Self {
1740 self.options.array_pointers_in_arguments = doit;
1741 self
1742 }
1743
1744 /// Set the wasm import module name
wasm_import_module_name<T: Into<String>>( mut self, import_name: T, ) -> Self1745 pub fn wasm_import_module_name<T: Into<String>>(
1746 mut self,
1747 import_name: T,
1748 ) -> Self {
1749 self.options.wasm_import_module_name = Some(import_name.into());
1750 self
1751 }
1752
1753 /// Specify the dynamic library name if we are generating bindings for a shared library.
dynamic_library_name<T: Into<String>>( mut self, dynamic_library_name: T, ) -> Self1754 pub fn dynamic_library_name<T: Into<String>>(
1755 mut self,
1756 dynamic_library_name: T,
1757 ) -> Self {
1758 self.options.dynamic_library_name = Some(dynamic_library_name.into());
1759 self
1760 }
1761
1762 /// Require successful linkage for all routines in a shared library.
1763 /// This allows us to optimize function calls by being able to safely assume function pointers
1764 /// are valid.
dynamic_link_require_all(mut self, req: bool) -> Self1765 pub fn dynamic_link_require_all(mut self, req: bool) -> Self {
1766 self.options.dynamic_link_require_all = req;
1767 self
1768 }
1769
1770 /// Generate bindings as `pub` only if the bound item is publically accessible by C++.
respect_cxx_access_specs(mut self, doit: bool) -> Self1771 pub fn respect_cxx_access_specs(mut self, doit: bool) -> Self {
1772 self.options.respect_cxx_access_specs = doit;
1773 self
1774 }
1775
1776 /// Always translate enum integer types to native Rust integer types.
1777 ///
1778 /// This will result in enums having types such as `u32` and `i16` instead
1779 /// of `c_uint` and `c_short`. Types for Rustified enums are always
1780 /// translated.
translate_enum_integer_types(mut self, doit: bool) -> Self1781 pub fn translate_enum_integer_types(mut self, doit: bool) -> Self {
1782 self.options.translate_enum_integer_types = doit;
1783 self
1784 }
1785
1786 /// Generate types with C style naming.
1787 ///
1788 /// This will add prefixes to the generated type names. For example instead of a struct `A` we
1789 /// will generate struct `struct_A`. Currently applies to structs, unions, and enums.
c_naming(mut self, doit: bool) -> Self1790 pub fn c_naming(mut self, doit: bool) -> Self {
1791 self.options.c_naming = doit;
1792 self
1793 }
1794
1795 /// Override the ABI of a given function. Regular expressions are supported.
override_abi<T: Into<String>>(mut self, abi: Abi, arg: T) -> Self1796 pub fn override_abi<T: Into<String>>(mut self, abi: Abi, arg: T) -> Self {
1797 self.options
1798 .abi_overrides
1799 .entry(abi)
1800 .or_default()
1801 .insert(arg.into());
1802 self
1803 }
1804
1805 /// If true, wraps unsafe operations in unsafe blocks.
wrap_unsafe_ops(mut self, doit: bool) -> Self1806 pub fn wrap_unsafe_ops(mut self, doit: bool) -> Self {
1807 self.options.wrap_unsafe_ops = doit;
1808 self
1809 }
1810
1811 #[cfg(feature = "experimental")]
1812 /// Whether to generate extern wrappers for `static` and `static inline` functions. Defaults to
1813 /// false.
wrap_static_fns(mut self, doit: bool) -> Self1814 pub fn wrap_static_fns(mut self, doit: bool) -> Self {
1815 self.options.wrap_static_fns = doit;
1816 self
1817 }
1818
1819 #[cfg(feature = "experimental")]
1820 /// Set the path for the source code file that would be created if any wrapper functions must
1821 /// be generated due to the presence of static functions.
1822 ///
1823 /// Bindgen will automatically add the right extension to the header and source code files.
wrap_static_fns_path<T: AsRef<Path>>(mut self, path: T) -> Self1824 pub fn wrap_static_fns_path<T: AsRef<Path>>(mut self, path: T) -> Self {
1825 self.options.wrap_static_fns_path = Some(path.as_ref().to_owned());
1826 self
1827 }
1828
1829 #[cfg(feature = "experimental")]
1830 /// Set the suffix added to the extern wrapper functions generated for `static` and `static
1831 /// inline` functions.
wrap_static_fns_suffix<T: AsRef<str>>(mut self, suffix: T) -> Self1832 pub fn wrap_static_fns_suffix<T: AsRef<str>>(mut self, suffix: T) -> Self {
1833 self.options.wrap_static_fns_suffix = Some(suffix.as_ref().to_owned());
1834 self
1835 }
1836 }
1837
1838 /// Configuration options for generated bindings.
1839 #[derive(Clone, Debug)]
1840 struct BindgenOptions {
1841 /// The set of types that have been blocklisted and should not appear
1842 /// anywhere in the generated code.
1843 blocklisted_types: RegexSet,
1844
1845 /// The set of functions that have been blocklisted and should not appear
1846 /// in the generated code.
1847 blocklisted_functions: RegexSet,
1848
1849 /// The set of items, regardless of item-type, that have been
1850 /// blocklisted and should not appear in the generated code.
1851 blocklisted_items: RegexSet,
1852
1853 /// The set of files whose contents should be blocklisted and should not
1854 /// appear in the generated code.
1855 blocklisted_files: RegexSet,
1856
1857 /// The set of types that should be treated as opaque structures in the
1858 /// generated code.
1859 opaque_types: RegexSet,
1860
1861 /// The explicit rustfmt path.
1862 rustfmt_path: Option<PathBuf>,
1863
1864 /// The path to which we should write a Makefile-syntax depfile (if any).
1865 depfile: Option<deps::DepfileSpec>,
1866
1867 /// The set of types that we should have bindings for in the generated
1868 /// code.
1869 ///
1870 /// This includes all types transitively reachable from any type in this
1871 /// set. One might think of allowlisted types/vars/functions as GC roots,
1872 /// and the generated Rust code as including everything that gets marked.
1873 allowlisted_types: RegexSet,
1874
1875 /// Allowlisted functions. See docs for `allowlisted_types` for more.
1876 allowlisted_functions: RegexSet,
1877
1878 /// Allowlisted variables. See docs for `allowlisted_types` for more.
1879 allowlisted_vars: RegexSet,
1880
1881 /// The set of files whose contents should be allowlisted.
1882 allowlisted_files: RegexSet,
1883
1884 /// The default style of code to generate for enums
1885 default_enum_style: codegen::EnumVariation,
1886
1887 /// The enum patterns to mark an enum as a bitfield
1888 /// (newtype with bitwise operations).
1889 bitfield_enums: RegexSet,
1890
1891 /// The enum patterns to mark an enum as a newtype.
1892 newtype_enums: RegexSet,
1893
1894 /// The enum patterns to mark an enum as a global newtype.
1895 newtype_global_enums: RegexSet,
1896
1897 /// The enum patterns to mark an enum as a Rust enum.
1898 rustified_enums: RegexSet,
1899
1900 /// The enum patterns to mark an enum as a non-exhaustive Rust enum.
1901 rustified_non_exhaustive_enums: RegexSet,
1902
1903 /// The enum patterns to mark an enum as a module of constants.
1904 constified_enum_modules: RegexSet,
1905
1906 /// The enum patterns to mark an enum as a set of constants.
1907 constified_enums: RegexSet,
1908
1909 /// The default type for C macro constants.
1910 default_macro_constant_type: codegen::MacroTypeVariation,
1911
1912 /// The default style of code to generate for typedefs.
1913 default_alias_style: codegen::AliasVariation,
1914
1915 /// Typedef patterns that will use regular type aliasing.
1916 type_alias: RegexSet,
1917
1918 /// Typedef patterns that will be aliased by creating a new struct.
1919 new_type_alias: RegexSet,
1920
1921 /// Typedef patterns that will be wrapped in a new struct and have
1922 /// Deref and Deref to their aliased type.
1923 new_type_alias_deref: RegexSet,
1924
1925 /// The default style of code to generate for union containing non-Copy
1926 /// members.
1927 default_non_copy_union_style: codegen::NonCopyUnionStyle,
1928
1929 /// The union patterns to mark an non-Copy union as using the bindgen
1930 /// generated wrapper.
1931 bindgen_wrapper_union: RegexSet,
1932
1933 /// The union patterns to mark an non-Copy union as using the
1934 /// `::core::mem::ManuallyDrop` wrapper.
1935 manually_drop_union: RegexSet,
1936
1937 /// Whether we should generate builtins or not.
1938 builtins: bool,
1939
1940 /// True if we should dump the Clang AST for debugging purposes.
1941 emit_ast: bool,
1942
1943 /// True if we should dump our internal IR for debugging purposes.
1944 emit_ir: bool,
1945
1946 /// Output graphviz dot file.
1947 emit_ir_graphviz: Option<String>,
1948
1949 /// True if we should emulate C++ namespaces with Rust modules in the
1950 /// generated bindings.
1951 enable_cxx_namespaces: bool,
1952
1953 /// True if we should try to find unexposed attributes in functions, in
1954 /// order to be able to generate #[must_use] attributes in Rust.
1955 enable_function_attribute_detection: bool,
1956
1957 /// True if we should avoid mangling names with namespaces.
1958 disable_name_namespacing: bool,
1959
1960 /// True if we should avoid generating nested struct names.
1961 disable_nested_struct_naming: bool,
1962
1963 /// True if we should avoid embedding version identifiers into source code.
1964 disable_header_comment: bool,
1965
1966 /// True if we should generate layout tests for generated structures.
1967 layout_tests: bool,
1968
1969 /// True if we should implement the Debug trait for C/C++ structures and types
1970 /// that do not support automatically deriving Debug.
1971 impl_debug: bool,
1972
1973 /// True if we should implement the PartialEq trait for C/C++ structures and types
1974 /// that do not support automatically deriving PartialEq.
1975 impl_partialeq: bool,
1976
1977 /// True if we should derive Copy trait implementations for C/C++ structures
1978 /// and types.
1979 derive_copy: bool,
1980
1981 /// True if we should derive Debug trait implementations for C/C++ structures
1982 /// and types.
1983 derive_debug: bool,
1984
1985 /// True if we should derive Default trait implementations for C/C++ structures
1986 /// and types.
1987 derive_default: bool,
1988
1989 /// True if we should derive Hash trait implementations for C/C++ structures
1990 /// and types.
1991 derive_hash: bool,
1992
1993 /// True if we should derive PartialOrd trait implementations for C/C++ structures
1994 /// and types.
1995 derive_partialord: bool,
1996
1997 /// True if we should derive Ord trait implementations for C/C++ structures
1998 /// and types.
1999 derive_ord: bool,
2000
2001 /// True if we should derive PartialEq trait implementations for C/C++ structures
2002 /// and types.
2003 derive_partialeq: bool,
2004
2005 /// True if we should derive Eq trait implementations for C/C++ structures
2006 /// and types.
2007 derive_eq: bool,
2008
2009 /// True if we should avoid using libstd to use libcore instead.
2010 use_core: bool,
2011
2012 /// An optional prefix for the "raw" types, like `c_int`, `c_void`...
2013 ctypes_prefix: Option<String>,
2014
2015 /// The prefix for the anon fields.
2016 anon_fields_prefix: String,
2017
2018 /// Whether to time the bindgen phases.
2019 time_phases: bool,
2020
2021 /// Whether we should convert float types to f32/f64 types.
2022 convert_floats: bool,
2023
2024 /// The set of raw lines to prepend to the top-level module of generated
2025 /// Rust code.
2026 raw_lines: Vec<String>,
2027
2028 /// The set of raw lines to prepend to each of the modules.
2029 ///
2030 /// This only makes sense if the `enable_cxx_namespaces` option is set.
2031 module_lines: HashMap<String, Vec<String>>,
2032
2033 /// The set of arguments to pass straight through to Clang.
2034 clang_args: Vec<String>,
2035
2036 /// The input header files.
2037 input_headers: Vec<String>,
2038
2039 /// Tuples of unsaved file contents of the form (name, contents).
2040 input_header_contents: Vec<(String, String)>,
2041
2042 /// A user-provided visitor to allow customizing different kinds of
2043 /// situations.
2044 parse_callbacks: Vec<Rc<dyn callbacks::ParseCallbacks>>,
2045
2046 /// Which kind of items should we generate? By default, we'll generate all
2047 /// of them.
2048 codegen_config: CodegenConfig,
2049
2050 /// Whether to treat inline namespaces conservatively.
2051 ///
2052 /// See the builder method description for more details.
2053 conservative_inline_namespaces: bool,
2054
2055 /// Whether to keep documentation comments in the generated output. See the
2056 /// documentation for more details. Defaults to true.
2057 generate_comments: bool,
2058
2059 /// Whether to generate inline functions. Defaults to false.
2060 generate_inline_functions: bool,
2061
2062 /// Whether to allowlist types recursively. Defaults to true.
2063 allowlist_recursively: bool,
2064
2065 /// Instead of emitting 'use objc;' to files generated from objective c files,
2066 /// generate '#[macro_use] extern crate objc;'
2067 objc_extern_crate: bool,
2068
2069 /// Instead of emitting 'use block;' to files generated from objective c files,
2070 /// generate '#[macro_use] extern crate block;'
2071 generate_block: bool,
2072
2073 /// Instead of emitting 'use block;' to files generated from objective c files,
2074 /// generate '#[macro_use] extern crate block;'
2075 block_extern_crate: bool,
2076
2077 /// Whether to use the clang-provided name mangling. This is true and
2078 /// probably needed for C++ features.
2079 ///
2080 /// However, some old libclang versions seem to return incorrect results in
2081 /// some cases for non-mangled functions, see [1], so we allow disabling it.
2082 ///
2083 /// [1]: https://github.com/rust-lang/rust-bindgen/issues/528
2084 enable_mangling: bool,
2085
2086 /// Whether to detect include paths using clang_sys.
2087 detect_include_paths: bool,
2088
2089 /// Whether to try to fit macro constants into types smaller than u32/i32
2090 fit_macro_constants: bool,
2091
2092 /// Whether to prepend the enum name to constant or newtype variants.
2093 prepend_enum_name: bool,
2094
2095 /// Version of the Rust compiler to target
2096 rust_target: RustTarget,
2097
2098 /// Features to enable, derived from `rust_target`
2099 rust_features: RustFeatures,
2100
2101 /// Whether we should record which items in the regex sets ever matched.
2102 ///
2103 /// This may be a bit slower, but will enable reporting of unused allowlist
2104 /// items via the `error!` log.
2105 record_matches: bool,
2106
2107 /// Whether `size_t` should be translated to `usize` automatically.
2108 size_t_is_usize: bool,
2109
2110 /// Whether rustfmt should format the generated bindings.
2111 rustfmt_bindings: bool,
2112
2113 /// The absolute path to the rustfmt configuration file, if None, the standard rustfmt
2114 /// options are used.
2115 rustfmt_configuration_file: Option<PathBuf>,
2116
2117 /// The set of types that we should not derive `PartialEq` for.
2118 no_partialeq_types: RegexSet,
2119
2120 /// The set of types that we should not derive `Copy` for.
2121 no_copy_types: RegexSet,
2122
2123 /// The set of types that we should not derive `Debug` for.
2124 no_debug_types: RegexSet,
2125
2126 /// The set of types that we should not derive/impl `Default` for.
2127 no_default_types: RegexSet,
2128
2129 /// The set of types that we should not derive `Hash` for.
2130 no_hash_types: RegexSet,
2131
2132 /// The set of types that we should be annotated with `#[must_use]`.
2133 must_use_types: RegexSet,
2134
2135 /// Decide if C arrays should be regular pointers in rust or array pointers
2136 array_pointers_in_arguments: bool,
2137
2138 /// Wasm import module name.
2139 wasm_import_module_name: Option<String>,
2140
2141 /// The name of the dynamic library (if we are generating bindings for a shared library). If
2142 /// this is None, no dynamic bindings are created.
2143 dynamic_library_name: Option<String>,
2144
2145 /// Require successful linkage for all routines in a shared library.
2146 /// This allows us to optimize function calls by being able to safely assume function pointers
2147 /// are valid. No effect if `dynamic_library_name` is None.
2148 dynamic_link_require_all: bool,
2149
2150 /// Only make generated bindings `pub` if the items would be publically accessible
2151 /// by C++.
2152 respect_cxx_access_specs: bool,
2153
2154 /// Always translate enum integer types to native Rust integer types.
2155 translate_enum_integer_types: bool,
2156
2157 /// Generate types with C style naming.
2158 c_naming: bool,
2159
2160 /// Always output explicit padding fields
2161 force_explicit_padding: bool,
2162
2163 /// Emit vtable functions.
2164 vtable_generation: bool,
2165
2166 /// Sort the code generation.
2167 sort_semantically: bool,
2168
2169 /// Deduplicate `extern` blocks.
2170 merge_extern_blocks: bool,
2171
2172 abi_overrides: HashMap<Abi, RegexSet>,
2173
2174 /// Whether to wrap unsafe operations in unsafe blocks or not.
2175 wrap_unsafe_ops: bool,
2176
2177 wrap_static_fns: bool,
2178
2179 wrap_static_fns_suffix: Option<String>,
2180
2181 wrap_static_fns_path: Option<PathBuf>,
2182 }
2183
2184 impl BindgenOptions {
build(&mut self)2185 fn build(&mut self) {
2186 let regex_sets = [
2187 &mut self.allowlisted_vars,
2188 &mut self.allowlisted_types,
2189 &mut self.allowlisted_functions,
2190 &mut self.allowlisted_files,
2191 &mut self.blocklisted_types,
2192 &mut self.blocklisted_functions,
2193 &mut self.blocklisted_items,
2194 &mut self.blocklisted_files,
2195 &mut self.opaque_types,
2196 &mut self.bitfield_enums,
2197 &mut self.constified_enums,
2198 &mut self.constified_enum_modules,
2199 &mut self.newtype_enums,
2200 &mut self.newtype_global_enums,
2201 &mut self.rustified_enums,
2202 &mut self.rustified_non_exhaustive_enums,
2203 &mut self.type_alias,
2204 &mut self.new_type_alias,
2205 &mut self.new_type_alias_deref,
2206 &mut self.bindgen_wrapper_union,
2207 &mut self.manually_drop_union,
2208 &mut self.no_partialeq_types,
2209 &mut self.no_copy_types,
2210 &mut self.no_debug_types,
2211 &mut self.no_default_types,
2212 &mut self.no_hash_types,
2213 &mut self.must_use_types,
2214 ];
2215 let record_matches = self.record_matches;
2216 for regex_set in self.abi_overrides.values_mut().chain(regex_sets) {
2217 regex_set.build(record_matches);
2218 }
2219 }
2220
2221 /// Update rust target version
set_rust_target(&mut self, rust_target: RustTarget)2222 pub fn set_rust_target(&mut self, rust_target: RustTarget) {
2223 self.rust_target = rust_target;
2224
2225 // Keep rust_features synced with rust_target
2226 self.rust_features = rust_target.into();
2227 }
2228
2229 /// Get features supported by target Rust version
rust_features(&self) -> RustFeatures2230 pub fn rust_features(&self) -> RustFeatures {
2231 self.rust_features
2232 }
2233
last_callback<T>( &self, f: impl Fn(&dyn callbacks::ParseCallbacks) -> Option<T>, ) -> Option<T>2234 fn last_callback<T>(
2235 &self,
2236 f: impl Fn(&dyn callbacks::ParseCallbacks) -> Option<T>,
2237 ) -> Option<T> {
2238 self.parse_callbacks
2239 .iter()
2240 .filter_map(|cb| f(cb.as_ref()))
2241 .last()
2242 }
2243
all_callbacks<T>( &self, f: impl Fn(&dyn callbacks::ParseCallbacks) -> Vec<T>, ) -> Vec<T>2244 fn all_callbacks<T>(
2245 &self,
2246 f: impl Fn(&dyn callbacks::ParseCallbacks) -> Vec<T>,
2247 ) -> Vec<T> {
2248 self.parse_callbacks
2249 .iter()
2250 .flat_map(|cb| f(cb.as_ref()))
2251 .collect()
2252 }
2253
process_comment(&self, comment: &str) -> String2254 fn process_comment(&self, comment: &str) -> String {
2255 let comment = comment::preprocess(comment);
2256 self.parse_callbacks
2257 .last()
2258 .and_then(|cb| cb.process_comment(&comment))
2259 .unwrap_or(comment)
2260 }
2261 }
2262
2263 impl Default for BindgenOptions {
default() -> BindgenOptions2264 fn default() -> BindgenOptions {
2265 macro_rules! options {
2266 ($($field:ident $(: $value:expr)?,)* --default-fields-- $($default_field:ident,)*) => {
2267 BindgenOptions {
2268 $($field $(: $value)*,)*
2269 $($default_field: Default::default(),)*
2270 }
2271 };
2272 }
2273
2274 let rust_target = RustTarget::default();
2275
2276 options! {
2277 rust_target,
2278 rust_features: rust_target.into(),
2279 layout_tests: true,
2280 derive_copy: true,
2281 derive_debug: true,
2282 anon_fields_prefix: DEFAULT_ANON_FIELDS_PREFIX.into(),
2283 convert_floats: true,
2284 codegen_config: CodegenConfig::all(),
2285 generate_comments: true,
2286 allowlist_recursively: true,
2287 enable_mangling: true,
2288 detect_include_paths: true,
2289 prepend_enum_name: true,
2290 record_matches: true,
2291 rustfmt_bindings: true,
2292 size_t_is_usize: true,
2293
2294 --default-fields--
2295 blocklisted_types,
2296 blocklisted_functions,
2297 blocklisted_items,
2298 blocklisted_files,
2299 opaque_types,
2300 rustfmt_path,
2301 depfile,
2302 allowlisted_types,
2303 allowlisted_functions,
2304 allowlisted_vars,
2305 allowlisted_files,
2306 default_enum_style,
2307 bitfield_enums,
2308 newtype_enums,
2309 newtype_global_enums,
2310 rustified_enums,
2311 rustified_non_exhaustive_enums,
2312 constified_enums,
2313 constified_enum_modules,
2314 default_macro_constant_type,
2315 default_alias_style,
2316 type_alias,
2317 new_type_alias,
2318 new_type_alias_deref,
2319 default_non_copy_union_style,
2320 bindgen_wrapper_union,
2321 manually_drop_union,
2322 builtins,
2323 emit_ast,
2324 emit_ir,
2325 emit_ir_graphviz,
2326 impl_debug,
2327 impl_partialeq,
2328 derive_default,
2329 derive_hash,
2330 derive_partialord,
2331 derive_ord,
2332 derive_partialeq,
2333 derive_eq,
2334 enable_cxx_namespaces,
2335 enable_function_attribute_detection,
2336 disable_name_namespacing,
2337 disable_nested_struct_naming,
2338 disable_header_comment,
2339 use_core,
2340 ctypes_prefix,
2341 raw_lines,
2342 module_lines,
2343 clang_args,
2344 input_headers,
2345 input_header_contents,
2346 parse_callbacks,
2347 conservative_inline_namespaces,
2348 generate_inline_functions,
2349 generate_block,
2350 objc_extern_crate,
2351 block_extern_crate,
2352 fit_macro_constants,
2353 time_phases,
2354 rustfmt_configuration_file,
2355 no_partialeq_types,
2356 no_copy_types,
2357 no_debug_types,
2358 no_default_types,
2359 no_hash_types,
2360 must_use_types,
2361 array_pointers_in_arguments,
2362 wasm_import_module_name,
2363 dynamic_library_name,
2364 dynamic_link_require_all,
2365 respect_cxx_access_specs,
2366 translate_enum_integer_types,
2367 c_naming,
2368 force_explicit_padding,
2369 vtable_generation,
2370 sort_semantically,
2371 merge_extern_blocks,
2372 abi_overrides,
2373 wrap_unsafe_ops,
2374 wrap_static_fns,
2375 wrap_static_fns_suffix,
2376 wrap_static_fns_path,
2377 }
2378 }
2379 }
2380
2381 #[cfg(feature = "runtime")]
ensure_libclang_is_loaded()2382 fn ensure_libclang_is_loaded() {
2383 if clang_sys::is_loaded() {
2384 return;
2385 }
2386
2387 // XXX (issue #350): Ensure that our dynamically loaded `libclang`
2388 // doesn't get dropped prematurely, nor is loaded multiple times
2389 // across different threads.
2390
2391 lazy_static! {
2392 static ref LIBCLANG: std::sync::Arc<clang_sys::SharedLibrary> = {
2393 clang_sys::load().expect("Unable to find libclang");
2394 clang_sys::get_library().expect(
2395 "We just loaded libclang and it had better still be \
2396 here!",
2397 )
2398 };
2399 }
2400
2401 clang_sys::set_library(Some(LIBCLANG.clone()));
2402 }
2403
2404 #[cfg(not(feature = "runtime"))]
ensure_libclang_is_loaded()2405 fn ensure_libclang_is_loaded() {}
2406
2407 /// Error type for rust-bindgen.
2408 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2409 #[non_exhaustive]
2410 pub enum BindgenError {
2411 /// The header was a folder.
2412 FolderAsHeader(PathBuf),
2413 /// Permissions to read the header is insufficient.
2414 InsufficientPermissions(PathBuf),
2415 /// The header does not exist.
2416 NotExist(PathBuf),
2417 /// Clang diagnosed an error.
2418 ClangDiagnostic(String),
2419 /// Code generation reported an error.
2420 Codegen(CodegenError),
2421 }
2422
2423 impl std::fmt::Display for BindgenError {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result2424 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2425 match self {
2426 BindgenError::FolderAsHeader(h) => {
2427 write!(f, "'{}' is a folder", h.display())
2428 }
2429 BindgenError::InsufficientPermissions(h) => {
2430 write!(f, "insufficient permissions to read '{}'", h.display())
2431 }
2432 BindgenError::NotExist(h) => {
2433 write!(f, "header '{}' does not exist.", h.display())
2434 }
2435 BindgenError::ClangDiagnostic(message) => {
2436 write!(f, "clang diagnosed error: {}", message)
2437 }
2438 BindgenError::Codegen(err) => {
2439 write!(f, "codegen error: {}", err)
2440 }
2441 }
2442 }
2443 }
2444
2445 impl std::error::Error for BindgenError {}
2446
2447 /// Generated Rust bindings.
2448 #[derive(Debug)]
2449 pub struct Bindings {
2450 options: BindgenOptions,
2451 warnings: Vec<String>,
2452 module: proc_macro2::TokenStream,
2453 }
2454
2455 pub(crate) const HOST_TARGET: &str =
2456 include_str!(concat!(env!("OUT_DIR"), "/host-target.txt"));
2457
2458 // Some architecture triplets are different between rust and libclang, see #1211
2459 // and duplicates.
rust_to_clang_target(rust_target: &str) -> String2460 fn rust_to_clang_target(rust_target: &str) -> String {
2461 if rust_target.starts_with("aarch64-apple-") {
2462 let mut clang_target = "arm64-apple-".to_owned();
2463 clang_target
2464 .push_str(rust_target.strip_prefix("aarch64-apple-").unwrap());
2465 return clang_target;
2466 } else if rust_target.starts_with("riscv64gc-") {
2467 let mut clang_target = "riscv64-".to_owned();
2468 clang_target.push_str(rust_target.strip_prefix("riscv64gc-").unwrap());
2469 return clang_target;
2470 } else if rust_target.ends_with("-espidf") {
2471 let mut clang_target =
2472 rust_target.strip_suffix("-espidf").unwrap().to_owned();
2473 clang_target.push_str("-elf");
2474 if clang_target.starts_with("riscv32imc-") {
2475 clang_target = "riscv32-".to_owned() +
2476 clang_target.strip_prefix("riscv32imc-").unwrap();
2477 }
2478 return clang_target;
2479 }
2480 rust_target.to_owned()
2481 }
2482
2483 /// Returns the effective target, and whether it was explicitly specified on the
2484 /// clang flags.
find_effective_target(clang_args: &[String]) -> (String, bool)2485 fn find_effective_target(clang_args: &[String]) -> (String, bool) {
2486 let mut args = clang_args.iter();
2487 while let Some(opt) = args.next() {
2488 if opt.starts_with("--target=") {
2489 let mut split = opt.split('=');
2490 split.next();
2491 return (split.next().unwrap().to_owned(), true);
2492 }
2493
2494 if opt == "-target" {
2495 if let Some(target) = args.next() {
2496 return (target.clone(), true);
2497 }
2498 }
2499 }
2500
2501 // If we're running from a build script, try to find the cargo target.
2502 if let Ok(t) = env::var("TARGET") {
2503 return (rust_to_clang_target(&t), false);
2504 }
2505
2506 (rust_to_clang_target(HOST_TARGET), false)
2507 }
2508
2509 impl Bindings {
2510 /// Generate bindings for the given options.
generate( mut options: BindgenOptions, input_unsaved_files: Vec<clang::UnsavedFile>, ) -> Result<Bindings, BindgenError>2511 pub(crate) fn generate(
2512 mut options: BindgenOptions,
2513 input_unsaved_files: Vec<clang::UnsavedFile>,
2514 ) -> Result<Bindings, BindgenError> {
2515 ensure_libclang_is_loaded();
2516
2517 #[cfg(feature = "runtime")]
2518 debug!(
2519 "Generating bindings, libclang at {}",
2520 clang_sys::get_library().unwrap().path().display()
2521 );
2522 #[cfg(not(feature = "runtime"))]
2523 debug!("Generating bindings, libclang linked");
2524
2525 options.build();
2526
2527 let (effective_target, explicit_target) =
2528 find_effective_target(&options.clang_args);
2529
2530 let is_host_build =
2531 rust_to_clang_target(HOST_TARGET) == effective_target;
2532
2533 // NOTE: The is_host_build check wouldn't be sound normally in some
2534 // cases if we were to call a binary (if you have a 32-bit clang and are
2535 // building on a 64-bit system for example). But since we rely on
2536 // opening libclang.so, it has to be the same architecture and thus the
2537 // check is fine.
2538 if !explicit_target && !is_host_build {
2539 options
2540 .clang_args
2541 .insert(0, format!("--target={}", effective_target));
2542 };
2543
2544 fn detect_include_paths(options: &mut BindgenOptions) {
2545 if !options.detect_include_paths {
2546 return;
2547 }
2548
2549 // Filter out include paths and similar stuff, so we don't incorrectly
2550 // promote them to `-isystem`.
2551 let clang_args_for_clang_sys = {
2552 let mut last_was_include_prefix = false;
2553 options
2554 .clang_args
2555 .iter()
2556 .filter(|arg| {
2557 if last_was_include_prefix {
2558 last_was_include_prefix = false;
2559 return false;
2560 }
2561
2562 let arg = &**arg;
2563
2564 // https://clang.llvm.org/docs/ClangCommandLineReference.html
2565 // -isystem and -isystem-after are harmless.
2566 if arg == "-I" || arg == "--include-directory" {
2567 last_was_include_prefix = true;
2568 return false;
2569 }
2570
2571 if arg.starts_with("-I") ||
2572 arg.starts_with("--include-directory=")
2573 {
2574 return false;
2575 }
2576
2577 true
2578 })
2579 .cloned()
2580 .collect::<Vec<_>>()
2581 };
2582
2583 debug!(
2584 "Trying to find clang with flags: {:?}",
2585 clang_args_for_clang_sys
2586 );
2587
2588 let clang = match clang_sys::support::Clang::find(
2589 None,
2590 &clang_args_for_clang_sys,
2591 ) {
2592 None => return,
2593 Some(clang) => clang,
2594 };
2595
2596 debug!("Found clang: {:?}", clang);
2597
2598 // Whether we are working with C or C++ inputs.
2599 let is_cpp = args_are_cpp(&options.clang_args) ||
2600 options.input_headers.iter().any(|h| file_is_cpp(h));
2601
2602 let search_paths = if is_cpp {
2603 clang.cpp_search_paths
2604 } else {
2605 clang.c_search_paths
2606 };
2607
2608 if let Some(search_paths) = search_paths {
2609 for path in search_paths.into_iter() {
2610 if let Ok(path) = path.into_os_string().into_string() {
2611 options.clang_args.push("-isystem".to_owned());
2612 options.clang_args.push(path);
2613 }
2614 }
2615 }
2616 }
2617
2618 detect_include_paths(&mut options);
2619
2620 #[cfg(unix)]
2621 fn can_read(perms: &std::fs::Permissions) -> bool {
2622 use std::os::unix::fs::PermissionsExt;
2623 perms.mode() & 0o444 > 0
2624 }
2625
2626 #[cfg(not(unix))]
2627 fn can_read(_: &std::fs::Permissions) -> bool {
2628 true
2629 }
2630
2631 if let Some(h) = options.input_headers.last() {
2632 let path = Path::new(h);
2633 if let Ok(md) = std::fs::metadata(path) {
2634 if md.is_dir() {
2635 return Err(BindgenError::FolderAsHeader(path.into()));
2636 }
2637 if !can_read(&md.permissions()) {
2638 return Err(BindgenError::InsufficientPermissions(
2639 path.into(),
2640 ));
2641 }
2642 let h = h.clone();
2643 options.clang_args.push(h);
2644 } else {
2645 return Err(BindgenError::NotExist(path.into()));
2646 }
2647 }
2648
2649 for (idx, f) in input_unsaved_files.iter().enumerate() {
2650 if idx != 0 || !options.input_headers.is_empty() {
2651 options.clang_args.push("-include".to_owned());
2652 }
2653 options.clang_args.push(f.name.to_str().unwrap().to_owned())
2654 }
2655
2656 debug!("Fixed-up options: {:?}", options);
2657
2658 let time_phases = options.time_phases;
2659 let mut context = BindgenContext::new(options, &input_unsaved_files);
2660
2661 if is_host_build {
2662 debug_assert_eq!(
2663 context.target_pointer_size(),
2664 std::mem::size_of::<*mut ()>(),
2665 "{:?} {:?}",
2666 effective_target,
2667 HOST_TARGET
2668 );
2669 }
2670
2671 {
2672 let _t = time::Timer::new("parse").with_output(time_phases);
2673 parse(&mut context)?;
2674 }
2675
2676 let (module, options, warnings) =
2677 codegen::codegen(context).map_err(BindgenError::Codegen)?;
2678
2679 Ok(Bindings {
2680 options,
2681 warnings,
2682 module,
2683 })
2684 }
2685
2686 /// Write these bindings as source text to a file.
write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()>2687 pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
2688 let file = OpenOptions::new()
2689 .write(true)
2690 .truncate(true)
2691 .create(true)
2692 .open(path.as_ref())?;
2693 self.write(Box::new(file))?;
2694 Ok(())
2695 }
2696
2697 /// Write these bindings as source text to the given `Write`able.
write<'a>(&self, mut writer: Box<dyn Write + 'a>) -> io::Result<()>2698 pub fn write<'a>(&self, mut writer: Box<dyn Write + 'a>) -> io::Result<()> {
2699 if !self.options.disable_header_comment {
2700 let version = option_env!("CARGO_PKG_VERSION");
2701 let header = format!(
2702 "/* automatically generated by rust-bindgen {} */\n\n",
2703 version.unwrap_or("(unknown version)")
2704 );
2705 writer.write_all(header.as_bytes())?;
2706 }
2707
2708 for line in self.options.raw_lines.iter() {
2709 writer.write_all(line.as_bytes())?;
2710 writer.write_all("\n".as_bytes())?;
2711 }
2712
2713 if !self.options.raw_lines.is_empty() {
2714 writer.write_all("\n".as_bytes())?;
2715 }
2716
2717 let bindings = self.module.to_string();
2718
2719 match self.rustfmt_generated_string(&bindings) {
2720 Ok(rustfmt_bindings) => {
2721 writer.write_all(rustfmt_bindings.as_bytes())?;
2722 }
2723 Err(err) => {
2724 eprintln!(
2725 "Failed to run rustfmt: {} (non-fatal, continuing)",
2726 err
2727 );
2728 writer.write_all(bindings.as_bytes())?;
2729 }
2730 }
2731 Ok(())
2732 }
2733
2734 /// Gets the rustfmt path to rustfmt the generated bindings.
rustfmt_path(&self) -> io::Result<Cow<PathBuf>>2735 fn rustfmt_path(&self) -> io::Result<Cow<PathBuf>> {
2736 debug_assert!(self.options.rustfmt_bindings);
2737 if let Some(ref p) = self.options.rustfmt_path {
2738 return Ok(Cow::Borrowed(p));
2739 }
2740 if let Ok(rustfmt) = env::var("RUSTFMT") {
2741 return Ok(Cow::Owned(rustfmt.into()));
2742 }
2743 #[cfg(feature = "which-rustfmt")]
2744 match which::which("rustfmt") {
2745 Ok(p) => Ok(Cow::Owned(p)),
2746 Err(e) => {
2747 Err(io::Error::new(io::ErrorKind::Other, format!("{}", e)))
2748 }
2749 }
2750 #[cfg(not(feature = "which-rustfmt"))]
2751 // No rustfmt binary was specified, so assume that the binary is called
2752 // "rustfmt" and that it is in the user's PATH.
2753 Ok(Cow::Owned("rustfmt".into()))
2754 }
2755
2756 /// 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>>2757 fn rustfmt_generated_string<'a>(
2758 &self,
2759 source: &'a str,
2760 ) -> io::Result<Cow<'a, str>> {
2761 let _t = time::Timer::new("rustfmt_generated_string")
2762 .with_output(self.options.time_phases);
2763
2764 if !self.options.rustfmt_bindings {
2765 return Ok(Cow::Borrowed(source));
2766 }
2767
2768 let rustfmt = self.rustfmt_path()?;
2769 let mut cmd = Command::new(&*rustfmt);
2770
2771 cmd.stdin(Stdio::piped()).stdout(Stdio::piped());
2772
2773 if let Some(path) = self
2774 .options
2775 .rustfmt_configuration_file
2776 .as_ref()
2777 .and_then(|f| f.to_str())
2778 {
2779 cmd.args(["--config-path", path]);
2780 }
2781
2782 let mut child = cmd.spawn()?;
2783 let mut child_stdin = child.stdin.take().unwrap();
2784 let mut child_stdout = child.stdout.take().unwrap();
2785
2786 let source = source.to_owned();
2787
2788 // Write to stdin in a new thread, so that we can read from stdout on this
2789 // thread. This keeps the child from blocking on writing to its stdout which
2790 // might block us from writing to its stdin.
2791 let stdin_handle = ::std::thread::spawn(move || {
2792 let _ = child_stdin.write_all(source.as_bytes());
2793 source
2794 });
2795
2796 let mut output = vec![];
2797 io::copy(&mut child_stdout, &mut output)?;
2798
2799 let status = child.wait()?;
2800 let source = stdin_handle.join().expect(
2801 "The thread writing to rustfmt's stdin doesn't do \
2802 anything that could panic",
2803 );
2804
2805 match String::from_utf8(output) {
2806 Ok(bindings) => match status.code() {
2807 Some(0) => Ok(Cow::Owned(bindings)),
2808 Some(2) => Err(io::Error::new(
2809 io::ErrorKind::Other,
2810 "Rustfmt parsing errors.".to_string(),
2811 )),
2812 Some(3) => {
2813 warn!("Rustfmt could not format some lines.");
2814 Ok(Cow::Owned(bindings))
2815 }
2816 _ => Err(io::Error::new(
2817 io::ErrorKind::Other,
2818 "Internal rustfmt error".to_string(),
2819 )),
2820 },
2821 _ => Ok(Cow::Owned(source)),
2822 }
2823 }
2824
2825 /// Emit all the warning messages raised while generating the bindings in a build script.
2826 ///
2827 /// If you are using `bindgen` outside of a build script you should use [`Bindings::warnings`]
2828 /// and handle the messages accordingly instead.
2829 #[inline]
emit_warnings(&self)2830 pub fn emit_warnings(&self) {
2831 for message in &self.warnings {
2832 println!("cargo:warning={}", message);
2833 }
2834 }
2835
2836 /// Return all the warning messages raised while generating the bindings.
2837 #[inline]
warnings(&self) -> &[String]2838 pub fn warnings(&self) -> &[String] {
2839 &self.warnings
2840 }
2841 }
2842
2843 impl std::fmt::Display for Bindings {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result2844 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2845 let mut bytes = vec![];
2846 self.write(Box::new(&mut bytes) as Box<dyn Write>)
2847 .expect("writing to a vec cannot fail");
2848 f.write_str(
2849 std::str::from_utf8(&bytes)
2850 .expect("we should only write bindings that are valid utf-8"),
2851 )
2852 }
2853 }
2854
2855 /// Determines whether the given cursor is in any of the files matched by the
2856 /// options.
filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool2857 fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool {
2858 ctx.options().builtins || !cursor.is_builtin()
2859 }
2860
2861 /// Parse one `Item` from the Clang cursor.
parse_one( ctx: &mut BindgenContext, cursor: clang::Cursor, parent: Option<ItemId>, ) -> clang_sys::CXChildVisitResult2862 fn parse_one(
2863 ctx: &mut BindgenContext,
2864 cursor: clang::Cursor,
2865 parent: Option<ItemId>,
2866 ) -> clang_sys::CXChildVisitResult {
2867 if !filter_builtins(ctx, &cursor) {
2868 return CXChildVisit_Continue;
2869 }
2870
2871 use clang_sys::CXChildVisit_Continue;
2872 match Item::parse(cursor, parent, ctx) {
2873 Ok(..) => {}
2874 Err(ParseError::Continue) => {}
2875 Err(ParseError::Recurse) => {
2876 cursor.visit(|child| parse_one(ctx, child, parent));
2877 }
2878 }
2879 CXChildVisit_Continue
2880 }
2881
2882 /// Parse the Clang AST into our `Item` internal representation.
parse(context: &mut BindgenContext) -> Result<(), BindgenError>2883 fn parse(context: &mut BindgenContext) -> Result<(), BindgenError> {
2884 use clang_sys::*;
2885
2886 let mut error = None;
2887 for d in context.translation_unit().diags().iter() {
2888 let msg = d.format();
2889 let is_err = d.severity() >= CXDiagnostic_Error;
2890 if is_err {
2891 let error = error.get_or_insert_with(String::new);
2892 error.push_str(&msg);
2893 error.push('\n');
2894 } else {
2895 eprintln!("clang diag: {}", msg);
2896 }
2897 }
2898
2899 if let Some(message) = error {
2900 return Err(BindgenError::ClangDiagnostic(message));
2901 }
2902
2903 let cursor = context.translation_unit().cursor();
2904
2905 if context.options().emit_ast {
2906 fn dump_if_not_builtin(cur: &clang::Cursor) -> CXChildVisitResult {
2907 if !cur.is_builtin() {
2908 clang::ast_dump(cur, 0)
2909 } else {
2910 CXChildVisit_Continue
2911 }
2912 }
2913 cursor.visit(|cur| dump_if_not_builtin(&cur));
2914 }
2915
2916 let root = context.root_module();
2917 context.with_module(root, |context| {
2918 cursor.visit(|cursor| parse_one(context, cursor, None))
2919 });
2920
2921 assert!(
2922 context.current_module() == context.root_module(),
2923 "How did this happen?"
2924 );
2925 Ok(())
2926 }
2927
2928 /// Extracted Clang version data
2929 #[derive(Debug)]
2930 pub struct ClangVersion {
2931 /// Major and minor semver, if parsing was successful
2932 pub parsed: Option<(u32, u32)>,
2933 /// full version string
2934 pub full: String,
2935 }
2936
2937 /// Get the major and the minor semver numbers of Clang's version
clang_version() -> ClangVersion2938 pub fn clang_version() -> ClangVersion {
2939 ensure_libclang_is_loaded();
2940
2941 //Debian clang version 11.0.1-2
2942 let raw_v: String = clang::extract_clang_version();
2943 let split_v: Option<Vec<&str>> = raw_v
2944 .split_whitespace()
2945 .find(|t| t.chars().next().map_or(false, |v| v.is_ascii_digit()))
2946 .map(|v| v.split('.').collect());
2947 if let Some(v) = split_v {
2948 if v.len() >= 2 {
2949 let maybe_major = v[0].parse::<u32>();
2950 let maybe_minor = v[1].parse::<u32>();
2951 if let (Ok(major), Ok(minor)) = (maybe_major, maybe_minor) {
2952 return ClangVersion {
2953 parsed: Some((major, minor)),
2954 full: raw_v.clone(),
2955 };
2956 }
2957 }
2958 };
2959 ClangVersion {
2960 parsed: None,
2961 full: raw_v.clone(),
2962 }
2963 }
2964
2965 /// Looks for the env var `var_${TARGET}`, and falls back to just `var` when it is not found.
get_target_dependent_env_var(var: &str) -> Option<String>2966 fn get_target_dependent_env_var(var: &str) -> Option<String> {
2967 if let Ok(target) = env::var("TARGET") {
2968 if let Ok(v) = env::var(format!("{}_{}", var, target)) {
2969 return Some(v);
2970 }
2971 if let Ok(v) = env::var(format!("{}_{}", var, target.replace('-', "_")))
2972 {
2973 return Some(v);
2974 }
2975 }
2976 env::var(var).ok()
2977 }
2978
2979 /// A ParseCallbacks implementation that will act on file includes by echoing a rerun-if-changed
2980 /// line
2981 ///
2982 /// When running inside a `build.rs` script, this can be used to make cargo invalidate the
2983 /// generated bindings whenever any of the files included from the header change:
2984 /// ```
2985 /// use bindgen::builder;
2986 /// let bindings = builder()
2987 /// .header("path/to/input/header")
2988 /// .parse_callbacks(Box::new(bindgen::CargoCallbacks))
2989 /// .generate();
2990 /// ```
2991 #[derive(Debug)]
2992 pub struct CargoCallbacks;
2993
2994 impl callbacks::ParseCallbacks for CargoCallbacks {
include_file(&self, filename: &str)2995 fn include_file(&self, filename: &str) {
2996 println!("cargo:rerun-if-changed={}", filename);
2997 }
2998 }
2999
3000 /// Test command_line_flag function.
3001 #[test]
commandline_flag_unit_test_function()3002 fn commandline_flag_unit_test_function() {
3003 //Test 1
3004 let bindings = crate::builder();
3005 let command_line_flags = bindings.command_line_flags();
3006
3007 let test_cases = vec![
3008 "--rust-target",
3009 "--no-derive-default",
3010 "--generate",
3011 "functions,types,vars,methods,constructors,destructors",
3012 ]
3013 .iter()
3014 .map(|&x| x.into())
3015 .collect::<Vec<String>>();
3016
3017 assert!(test_cases.iter().all(|x| command_line_flags.contains(x)));
3018
3019 //Test 2
3020 let bindings = crate::builder()
3021 .header("input_header")
3022 .allowlist_type("Distinct_Type")
3023 .allowlist_function("safe_function");
3024
3025 let command_line_flags = bindings.command_line_flags();
3026 let test_cases = vec![
3027 "--rust-target",
3028 "input_header",
3029 "--no-derive-default",
3030 "--generate",
3031 "functions,types,vars,methods,constructors,destructors",
3032 "--allowlist-type",
3033 "Distinct_Type",
3034 "--allowlist-function",
3035 "safe_function",
3036 ]
3037 .iter()
3038 .map(|&x| x.into())
3039 .collect::<Vec<String>>();
3040 println!("{:?}", command_line_flags);
3041
3042 assert!(test_cases.iter().all(|x| command_line_flags.contains(x)));
3043 }
3044
3045 #[test]
test_rust_to_clang_target()3046 fn test_rust_to_clang_target() {
3047 assert_eq!(rust_to_clang_target("aarch64-apple-ios"), "arm64-apple-ios");
3048 }
3049
3050 #[test]
test_rust_to_clang_target_riscv()3051 fn test_rust_to_clang_target_riscv() {
3052 assert_eq!(
3053 rust_to_clang_target("riscv64gc-unknown-linux-gnu"),
3054 "riscv64-unknown-linux-gnu"
3055 )
3056 }
3057
3058 #[test]
test_rust_to_clang_target_espidf()3059 fn test_rust_to_clang_target_espidf() {
3060 assert_eq!(
3061 rust_to_clang_target("riscv32imc-esp-espidf"),
3062 "riscv32-esp-elf"
3063 );
3064 assert_eq!(
3065 rust_to_clang_target("xtensa-esp32-espidf"),
3066 "xtensa-esp32-elf"
3067 );
3068 }
3069