aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Galenson <jgalenson@google.com>2021-08-09 10:25:17 -0700
committerJoel Galenson <jgalenson@google.com>2021-08-09 10:25:17 -0700
commit4c81ebb91aaef7c1a3ccfc8776dec3f957724f4a (patch)
treed2a83d4133ed2768b4266925a20b1d5ab38d5056
parent2ed72dfeb742b69cd09e24fb399ac405c202d40f (diff)
downloadbindgen-4c81ebb91aaef7c1a3ccfc8776dec3f957724f4a.tar.gz
Upgrade rust/crates/bindgen to 0.59.1
Test: make Change-Id: I283fdfff59971959dc5ee949379329db19e56b17
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp19
-rw-r--r--Cargo.lock144
-rw-r--r--Cargo.toml7
-rw-r--r--Cargo.toml.orig7
-rw-r--r--METADATA8
-rw-r--r--README.md6
-rw-r--r--build.rs8
-rw-r--r--src/callbacks.rs8
-rw-r--r--src/clang.rs23
-rw-r--r--src/codegen/impl_debug.rs4
-rw-r--r--src/codegen/impl_partialeq.rs4
-rw-r--r--src/codegen/mod.rs74
-rw-r--r--src/codegen/struct_layout.rs42
-rw-r--r--src/deps.rs20
-rw-r--r--src/features.rs8
-rw-r--r--src/ir/analysis/derive.rs21
-rw-r--r--src/ir/comp.rs89
-rw-r--r--src/ir/context.rs39
-rw-r--r--src/ir/function.rs15
-rw-r--r--src/ir/item.rs41
-rw-r--r--src/ir/ty.rs1
-rw-r--r--src/lib.rs89
-rw-r--r--src/options.rs26
24 files changed, 605 insertions, 100 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 2263767..7298dd9 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
{
"git": {
- "sha1": "696455d1c15e682b2b89f81f409315ea4964aef3"
+ "sha1": "9a9438f3d6a3523c69d7bc890e8608b63dbe38a5"
}
}
diff --git a/Android.bp b/Android.bp
index 305d025..b505ad7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -110,28 +110,33 @@ rust_library_host {
// ansi_term-0.11.0
// atty-0.2.14
// bitflags-1.2.1 "default"
-// cexpr-0.4.0
+// bitvec-0.19.5 "alloc,std"
+// cexpr-0.5.0
// cfg-if-1.0.0
// clang-sys-1.2.0 "clang_3_5,clang_3_6,clang_3_7,clang_3_8,clang_3_9,clang_4_0,clang_5_0,clang_6_0,libloading,runtime"
// clap-2.33.3 "ansi_term,atty,color,default,strsim,suggestions,vec_map"
+// funty-1.1.0
// glob-0.3.0
// lazy_static-1.4.0
// lazycell-1.3.0
-// libc-0.2.93 "default,std"
+// libc-0.2.98 "default,std"
// libloading-0.7.0
// memchr-2.3.4 "std,use_std"
-// nom-5.1.2 "alloc,std"
+// nom-6.2.1 "alloc,bitvec,funty,std"
// peeking_take_while-0.1.2
-// proc-macro2-1.0.26
+// proc-macro2-1.0.28
// quote-1.0.9
-// regex-1.4.5 "std,unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment"
-// regex-syntax-0.6.23 "unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment"
+// radium-0.5.3
+// regex-1.4.6 "std,unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment"
+// regex-syntax-0.6.25 "unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment"
// rustc-hash-1.1.0 "default,std"
// shlex-1.0.0
// strsim-0.8.0
+// tap-1.0.1
// textwrap-0.11.0
// unicode-width-0.1.8 "default"
-// unicode-xid-0.2.1 "default"
+// unicode-xid-0.2.2 "default"
// vec_map-0.8.2
// version_check-0.9.3
// which-3.1.1
+// wyz-0.2.0 "alloc"
diff --git a/Cargo.lock b/Cargo.lock
index 7fc4535..0e93f41 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -33,7 +33,7 @@ dependencies = [
[[package]]
name = "bindgen"
-version = "0.58.1"
+version = "0.59.1"
dependencies = [
"bitflags",
"cexpr",
@@ -50,6 +50,7 @@ dependencies = [
"regex",
"rustc-hash",
"shlex",
+ "tempfile",
"which",
]
@@ -60,10 +61,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
+name = "bitvec"
+version = "0.19.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321"
+dependencies = [
+ "funty",
+ "radium",
+ "tap",
+ "wyz",
+]
+
+[[package]]
name = "cexpr"
-version = "0.4.0"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
+checksum = "db507a7679252d2276ed0dd8113c6875ec56d3089f9225b2b42c30cc1f8e5c89"
dependencies = [
"nom",
]
@@ -126,6 +139,23 @@ dependencies = [
]
[[package]]
+name = "funty"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
+
+[[package]]
+name = "getrandom"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "wasi",
+]
+
+[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -191,10 +221,12 @@ checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]]
name = "nom"
-version = "5.1.2"
+version = "6.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
+checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6"
dependencies = [
+ "bitvec",
+ "funty",
"memchr",
"version_check",
]
@@ -206,6 +238,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
+name = "ppv-lite86"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+
+[[package]]
name = "proc-macro2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -224,6 +262,61 @@ dependencies = [
]
[[package]]
+name = "radium"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
+
+[[package]]
+name = "rand"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
name = "regex"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -242,6 +335,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -260,6 +362,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
+name = "tap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+
+[[package]]
+name = "tempfile"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "rand",
+ "redox_syscall",
+ "remove_dir_all",
+ "winapi",
+]
+
+[[package]]
name = "termcolor"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -311,6 +433,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+
+[[package]]
name = "which"
version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -349,3 +477,9 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "wyz"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
diff --git a/Cargo.toml b/Cargo.toml
index 7cf9236..08e2383 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "bindgen"
-version = "0.58.1"
+version = "0.59.1"
authors = ["Jyun-Yan You <jyyou.tw@gmail.com>", "Emilio Cobos Álvarez <emilio@crisal.io>", "Nick Fitzgerald <fitzgen@gmail.com>", "The Servo project developers"]
build = "build.rs"
include = ["LICENSE", "README.md", "Cargo.toml", "build.rs", "src/*.rs", "src/**/*.rs"]
@@ -38,7 +38,7 @@ required-features = ["clap"]
version = "1.0.3"
[dependencies.cexpr]
-version = "0.4"
+version = "0.5"
[dependencies.clang-sys]
version = "1"
@@ -97,6 +97,9 @@ version = "0.1"
[dev-dependencies.shlex]
version = "1"
+[dev-dependencies.tempfile]
+version = "3"
+
[features]
default = ["logging", "clap", "runtime", "which-rustfmt"]
logging = ["env_logger", "log"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index dd30f09..7cf5953 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -14,7 +14,7 @@ readme = "README.md"
repository = "https://github.com/rust-lang/rust-bindgen"
documentation = "https://docs.rs/bindgen"
homepage = "https://rust-lang.github.io/rust-bindgen/"
-version = "0.58.1"
+version = "0.59.1"
edition = "2018"
build = "build.rs"
@@ -43,10 +43,11 @@ required-features = ["clap"]
diff = "0.1"
clap = "2"
shlex = "1"
+tempfile = "3"
[dependencies]
bitflags = "1.0.3"
-cexpr = "0.4"
+cexpr = "0.5"
# This kinda sucks: https://github.com/rust-lang/cargo/issues/1982
clap = { version = "2", optional = true }
clang-sys = { version = "1", features = ["clang_6_0"] }
@@ -58,8 +59,6 @@ regex = { version = "1.0", default-features = false , features = [ "std", "unico
which = { version = "3.0", optional = true, default-features = false }
shlex = "1"
rustc-hash = "1.0.1"
-# New validation in 0.3.6 breaks bindgen-integration:
-# https://github.com/alexcrichton/proc-macro2/commit/489c642.
proc-macro2 = { version = "1", default-features = false }
[dependencies.env_logger]
diff --git a/METADATA b/METADATA
index bed57d2..87aa75a 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/bindgen/bindgen-0.58.1.crate"
+ value: "https://static.crates.io/crates/bindgen/bindgen-0.59.1.crate"
}
- version: "0.58.1"
+ version: "0.59.1"
license_type: NOTICE
last_upgrade_date {
year: 2021
- month: 4
- day: 16
+ month: 8
+ day: 9
}
}
diff --git a/README.md b/README.md
index e1ad557..00f66eb 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ extern "C" {
## MSRV
-The minimum supported Rust version is **1.40**.
+The minimum supported Rust version is **1.44**.
No MSRV bump policy has been established yet, so MSRV may increase in any release.
@@ -60,6 +60,10 @@ End-users should set these environment variables to modify `bindgen`'s behavior
- Examples:
- Specify alternate sysroot: `--sysroot=/path/to/sysroot`
- Add include search path with spaces: `-I"/path/with spaces"`
+- `BINDGEN_EXTRA_CLANG_ARGS_<TARGET>`: similar to `BINDGEN_EXTRA_CLANG_ARGS`,
+ but used to set per-target arguments to pass to clang. Useful to set system include
+ directories in a target-specific way in cross-compilation environments with multiple targets.
+ Has precedence over `BINDGEN_EXTRA_CLANG_ARGS`.
Additionally, `bindgen` uses `libclang` to parse C and C++ header files.
To modify how `bindgen` searches for `libclang`, see the [`clang-sys` documentation][clang-sys-env].
diff --git a/build.rs b/build.rs
index cb40cb0..fcc0bb2 100644
--- a/build.rs
+++ b/build.rs
@@ -79,4 +79,12 @@ fn main() {
println!("cargo:rerun-if-env-changed=LIBCLANG_PATH");
println!("cargo:rerun-if-env-changed=LIBCLANG_STATIC_PATH");
println!("cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS");
+ println!(
+ "cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_{}",
+ std::env::var("TARGET").unwrap()
+ );
+ println!(
+ "cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_{}",
+ std::env::var("TARGET").unwrap().replace("-", "_")
+ );
}
diff --git a/src/callbacks.rs b/src/callbacks.rs
index e288af4..9b34544 100644
--- a/src/callbacks.rs
+++ b/src/callbacks.rs
@@ -95,4 +95,12 @@ pub trait ParseCallbacks: fmt::Debug + UnwindSafe {
) -> Option<ImplementsTrait> {
None
}
+
+ /// Provide a list of custom derive attributes.
+ ///
+ /// If no additional attributes are wanted, this function should return an
+ /// empty `Vec`.
+ fn add_derives(&self, _name: &str) -> Vec<String> {
+ vec![]
+ }
}
diff --git a/src/clang.rs b/src/clang.rs
index 6612508..db6467e 100644
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -241,7 +241,7 @@ impl Cursor {
self.x.kind
}
- /// Returns true is the cursor is a definition
+ /// Returns true if the cursor is a definition
pub fn is_definition(&self) -> bool {
unsafe { clang_isCursorDefinition(self.x) != 0 }
}
@@ -469,6 +469,27 @@ impl Cursor {
unsafe { clang_Cursor_isFunctionInlined(self.x) != 0 }
}
+ /// Is the referent a defaulted function?
+ pub fn is_defaulted_function(&self) -> bool {
+ unsafe { clang_CXXMethod_isDefaulted(self.x) != 0 }
+ }
+
+ /// Is the referent a deleted function?
+ pub fn is_deleted_function(&self) -> bool {
+ // Unfortunately, libclang doesn't yet have an API for checking if a
+ // member function is deleted, but the following should be a good
+ // enough approximation.
+ // Deleted functions are implicitly inline according to paragraph 4 of
+ // [dcl.fct.def.delete] in the C++ standard. Normal inline functions
+ // have a definition in the same translation unit, so if this is an
+ // inline function without a definition, and it's not a defaulted
+ // function, we can reasonably safely conclude that it's a deleted
+ // function.
+ self.is_inlined_function() &&
+ self.definition().is_none() &&
+ !self.is_defaulted_function()
+ }
+
/// Get the width of this cursor's referent bit field, or `None` if the
/// referent is not a bit field.
pub fn bit_width(&self) -> Option<u32> {
diff --git a/src/codegen/impl_debug.rs b/src/codegen/impl_debug.rs
index b8fdd0d..661711e 100644
--- a/src/codegen/impl_debug.rs
+++ b/src/codegen/impl_debug.rs
@@ -181,7 +181,9 @@ impl<'a> ImplDebug<'a> for Item {
format!("{}: Array with length {}", name, len),
vec![],
))
- } else if len < RUST_DERIVE_IN_ARRAY_LIMIT {
+ } else if len < RUST_DERIVE_IN_ARRAY_LIMIT ||
+ ctx.options().rust_features().larger_arrays
+ {
// The simple case
debug_print(name, quote! { #name_ident })
} else {
diff --git a/src/codegen/impl_partialeq.rs b/src/codegen/impl_partialeq.rs
index 5f2600e..5a1ba3f 100644
--- a/src/codegen/impl_partialeq.rs
+++ b/src/codegen/impl_partialeq.rs
@@ -114,7 +114,9 @@ fn gen_field(
}
TypeKind::Array(_, len) => {
- if len <= RUST_DERIVE_IN_ARRAY_LIMIT {
+ if len <= RUST_DERIVE_IN_ARRAY_LIMIT ||
+ ctx.options().rust_features().larger_arrays
+ {
quote_equals(name_ident)
} else {
quote! {
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index e62b1a8..0f3337a 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -618,12 +618,18 @@ impl CodeGenerator for Var {
return;
}
+ let mut attrs = vec![];
+ if let Some(comment) = item.comment(ctx) {
+ attrs.push(attributes::doc(comment));
+ }
+
let ty = self.ty().to_rust_ty_or_opaque(ctx, &());
if let Some(val) = self.val() {
match *val {
VarType::Bool(val) => {
result.push(quote! {
+ #(#attrs)*
pub const #canonical_ident : #ty = #val ;
});
}
@@ -643,6 +649,7 @@ impl CodeGenerator for Var {
helpers::ast_ty::uint_expr(val as _)
};
result.push(quote! {
+ #(#attrs)*
pub const #canonical_ident : #ty = #val ;
});
}
@@ -660,12 +667,14 @@ impl CodeGenerator for Var {
Ok(string) => {
let cstr = helpers::ast_ty::cstr_expr(string);
result.push(quote! {
+ #(#attrs)*
pub const #canonical_ident : &'static #ty = #cstr ;
});
}
Err(..) => {
let bytes = helpers::ast_ty::byte_array_expr(bytes);
result.push(quote! {
+ #(#attrs)*
pub const #canonical_ident : #ty = #bytes ;
});
}
@@ -674,6 +683,7 @@ impl CodeGenerator for Var {
VarType::Float(f) => {
match helpers::ast_ty::float_expr(ctx, f) {
Ok(expr) => result.push(quote! {
+ #(#attrs)*
pub const #canonical_ident : #ty = #expr ;
}),
Err(..) => return,
@@ -681,13 +691,12 @@ impl CodeGenerator for Var {
}
VarType::Char(c) => {
result.push(quote! {
+ #(#attrs)*
pub const #canonical_ident : #ty = #c ;
});
}
}
} else {
- let mut attrs = vec![];
-
// If necessary, apply a `#[link_name]` attribute
let link_name = self.mangled_name().unwrap_or(self.name());
if !utils::names_will_be_identical_after_mangling(
@@ -1493,7 +1502,10 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
let mut ctor_impl = quote! {};
// We cannot generate any constructor if the underlying storage can't
- // implement AsRef<[u8]> / AsMut<[u8]> / etc.
+ // implement AsRef<[u8]> / AsMut<[u8]> / etc, or can't derive Default.
+ //
+ // We don't check `larger_arrays` here because Default does still have
+ // the 32 items limitation.
let mut generate_ctor = layout.size <= RUST_DERIVE_IN_ARRAY_LIMIT;
let mut access_spec = !fields_should_be_private;
@@ -1503,7 +1515,9 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
continue;
}
- if layout.size > RUST_DERIVE_IN_ARRAY_LIMIT {
+ if layout.size > RUST_DERIVE_IN_ARRAY_LIMIT &&
+ !ctx.options().rust_features().larger_arrays
+ {
continue;
}
@@ -1788,6 +1802,14 @@ impl CodeGenerator for CompInfo {
(),
);
}
+ // Check whether an explicit padding field is needed
+ // at the end.
+ if let Some(comp_layout) = layout {
+ fields.extend(
+ struct_layout
+ .add_tail_padding(&canonical_name, comp_layout),
+ );
+ }
}
if is_opaque {
@@ -1988,6 +2010,15 @@ impl CodeGenerator for CompInfo {
let mut derives: Vec<_> = derivable_traits.into();
derives.extend(item.annotations().derives().iter().map(String::as_str));
+ // The custom derives callback may return a list of derive attributes;
+ // add them to the end of the list.
+ let custom_derives;
+ if let Some(cb) = &ctx.options().parse_callbacks {
+ custom_derives = cb.add_derives(&canonical_name);
+ // In most cases this will be a no-op, since custom_derives will be empty.
+ derives.extend(custom_derives.iter().map(|s| s.as_str()));
+ };
+
if !derives.is_empty() {
attributes.push(attributes::derives(&derives))
}
@@ -2187,9 +2218,32 @@ impl CodeGenerator for CompInfo {
if needs_default_impl {
let prefix = ctx.trait_prefix();
+ let body = if ctx.options().rust_features().maybe_uninit {
+ quote! {
+ let mut s = ::#prefix::mem::MaybeUninit::<Self>::uninit();
+ unsafe {
+ ::#prefix::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+ s.assume_init()
+ }
+ }
+ } else {
+ quote! {
+ unsafe {
+ let mut s: Self = ::#prefix::mem::uninitialized();
+ ::#prefix::ptr::write_bytes(&mut s, 0, 1);
+ s
+ }
+ }
+ };
+ // Note we use `ptr::write_bytes()` instead of `mem::zeroed()` because the latter does
+ // not necessarily ensure padding bytes are zeroed. Some C libraries are sensitive to
+ // non-zero padding bytes, especially when forwards/backwards compatability is
+ // involved.
result.push(quote! {
impl #generics Default for #ty_for_impl {
- fn default() -> Self { unsafe { ::#prefix::mem::zeroed() } }
+ fn default() -> Self {
+ #body
+ }
}
});
}
@@ -4198,6 +4252,16 @@ pub(crate) fn codegen(
}
}
+ if let Some(spec) = context.options().depfile.as_ref() {
+ match spec.write(context.deps()) {
+ Ok(()) => info!(
+ "Your depfile was generated successfully into: {}",
+ spec.depfile_path.display()
+ ),
+ Err(e) => warn!("{}", e),
+ }
+ }
+
context.resolve_item(context.root_module()).codegen(
context,
&mut result,
diff --git a/src/codegen/struct_layout.rs b/src/codegen/struct_layout.rs
index 2e4b973..1c6b977 100644
--- a/src/codegen/struct_layout.rs
+++ b/src/codegen/struct_layout.rs
@@ -217,8 +217,11 @@ impl<'a> StructLayoutTracker<'a> {
let padding_layout = if self.is_packed || is_union {
None
} else {
+ let force_padding = self.ctx.options().force_explicit_padding;
+
// Otherwise the padding is useless.
- let need_padding = padding_bytes >= field_layout.align ||
+ let need_padding = force_padding ||
+ padding_bytes >= field_layout.align ||
field_layout.align > MAX_GUARANTEED_ALIGN;
debug!(
@@ -236,11 +239,14 @@ impl<'a> StructLayoutTracker<'a> {
field_layout
);
+ let padding_align = if force_padding {
+ 1
+ } else {
+ cmp::min(field_layout.align, MAX_GUARANTEED_ALIGN)
+ };
+
if need_padding && padding_bytes != 0 {
- Some(Layout::new(
- padding_bytes,
- cmp::min(field_layout.align, MAX_GUARANTEED_ALIGN),
- ))
+ Some(Layout::new(padding_bytes, padding_align))
} else {
None
}
@@ -262,6 +268,32 @@ impl<'a> StructLayoutTracker<'a> {
padding_layout.map(|layout| self.padding_field(layout))
}
+ pub fn add_tail_padding(
+ &mut self,
+ comp_name: &str,
+ comp_layout: Layout,
+ ) -> Option<proc_macro2::TokenStream> {
+ // Only emit an padding field at the end of a struct if the
+ // user configures explicit padding.
+ if !self.ctx.options().force_explicit_padding {
+ return None;
+ }
+
+ if self.latest_offset == comp_layout.size {
+ // This struct does not contain tail padding.
+ return None;
+ }
+
+ trace!(
+ "need a tail padding field for {}: offset {} -> size {}",
+ comp_name,
+ self.latest_offset,
+ comp_layout.size
+ );
+ let size = comp_layout.size - self.latest_offset;
+ Some(self.padding_field(Layout::new(size, 0)))
+ }
+
pub fn pad_struct(
&mut self,
layout: Layout,
diff --git a/src/deps.rs b/src/deps.rs
new file mode 100644
index 0000000..479c396
--- /dev/null
+++ b/src/deps.rs
@@ -0,0 +1,20 @@
+/// Generating build depfiles from parsed bindings.
+use std::{collections::BTreeSet, path::PathBuf};
+
+#[derive(Debug)]
+pub(crate) struct DepfileSpec {
+ pub output_module: String,
+ pub depfile_path: PathBuf,
+}
+
+impl DepfileSpec {
+ pub fn write(&self, deps: &BTreeSet<String>) -> std::io::Result<()> {
+ let mut buf = format!("{}:", self.output_module);
+
+ for file in deps {
+ buf = format!("{} {}", buf, file);
+ }
+
+ std::fs::write(&self.depfile_path, &buf)
+ }
+}
diff --git a/src/features.rs b/src/features.rs
index 4ec9dee..99b789e 100644
--- a/src/features.rs
+++ b/src/features.rs
@@ -123,6 +123,9 @@ macro_rules! rust_target_base {
/// Rust stable 1.40
/// * `non_exhaustive` enums/structs ([Tracking issue](https://github.com/rust-lang/rust/issues/44109))
=> Stable_1_40 => 1.40;
+ /// Rust stable 1.47
+ /// * `larger_arrays` ([Tracking issue](https://github.com/rust-lang/rust/pull/74060))
+ => Stable_1_47 => 1.47;
/// Nightly rust
/// * `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
=> Nightly => nightly;
@@ -134,7 +137,7 @@ rust_target_base!(rust_target_def);
rust_target_base!(rust_target_values_def);
/// Latest stable release of Rust
-pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_40;
+pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_47;
/// Create RustFeatures struct definition, new(), and a getter for each field
macro_rules! rust_feature_def {
@@ -222,6 +225,9 @@ rust_feature_def!(
Stable_1_40 {
=> non_exhaustive;
}
+ Stable_1_47 {
+ => larger_arrays;
+ }
Nightly {
=> thiscall_abi;
}
diff --git a/src/ir/analysis/derive.rs b/src/ir/analysis/derive.rs
index be62666..44e6702 100644
--- a/src/ir/analysis/derive.rs
+++ b/src/ir/analysis/derive.rs
@@ -255,7 +255,7 @@ impl<'ctx> CannotDerive<'ctx> {
return CanDerive::No;
}
- if self.derive_trait.can_derive_large_array() {
+ if self.derive_trait.can_derive_large_array(&self.ctx) {
trace!(" array can derive {}", self.derive_trait);
return CanDerive::Yes;
}
@@ -377,7 +377,7 @@ impl<'ctx> CannotDerive<'ctx> {
// Bitfield units are always represented as arrays of u8, but
// they're not traced as arrays, so we need to check here
// instead.
- if !self.derive_trait.can_derive_large_array() &&
+ if !self.derive_trait.can_derive_large_array(&self.ctx) &&
info.has_too_large_bitfield_unit() &&
!item.is_opaque(self.ctx, &())
{
@@ -496,10 +496,17 @@ impl DeriveTrait {
}
}
- fn can_derive_large_array(&self) -> bool {
- match self {
- DeriveTrait::Copy => true,
- _ => false,
+ fn can_derive_large_array(&self, ctx: &BindgenContext) -> bool {
+ if ctx.options().rust_features().larger_arrays {
+ match self {
+ DeriveTrait::Default => false,
+ _ => true,
+ }
+ } else {
+ match self {
+ DeriveTrait::Copy => true,
+ _ => false,
+ }
}
}
@@ -686,7 +693,7 @@ impl<'ctx> MonotoneFramework for CannotDerive<'ctx> {
Some(ty) => {
let mut can_derive = self.constrain_type(item, ty);
if let CanDerive::Yes = can_derive {
- if !self.derive_trait.can_derive_large_array() &&
+ if !self.derive_trait.can_derive_large_array(&self.ctx) &&
ty.layout(self.ctx).map_or(false, |l| {
l.align > RUST_DERIVE_IN_ARRAY_LIMIT
})
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index 52dcddd..e554f9a 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -1113,21 +1113,17 @@ impl CompInfo {
}
// empty union case
- if self.fields().is_empty() {
+ if !self.has_fields() {
return None;
}
let mut max_size = 0;
// Don't allow align(0)
let mut max_align = 1;
- for field in self.fields() {
- let field_layout = field.layout(ctx);
-
- if let Some(layout) = field_layout {
- max_size = cmp::max(max_size, layout.size);
- max_align = cmp::max(max_align, layout.align);
- }
- }
+ self.each_known_field_layout(ctx, |layout| {
+ max_size = cmp::max(max_size, layout.size);
+ max_align = cmp::max(max_align, layout.align);
+ });
Some(Layout::new(max_size, max_align))
}
@@ -1139,12 +1135,49 @@ impl CompInfo {
CompFields::AfterComputingBitfieldUnits { ref fields, .. } => {
fields
}
- CompFields::BeforeComputingBitfieldUnits(_) => {
+ CompFields::BeforeComputingBitfieldUnits(..) => {
panic!("Should always have computed bitfield units first");
}
}
}
+ fn has_fields(&self) -> bool {
+ match self.fields {
+ CompFields::ErrorComputingBitfieldUnits => false,
+ CompFields::AfterComputingBitfieldUnits { ref fields, .. } => {
+ !fields.is_empty()
+ }
+ CompFields::BeforeComputingBitfieldUnits(ref raw_fields) => {
+ !raw_fields.is_empty()
+ }
+ }
+ }
+
+ fn each_known_field_layout(
+ &self,
+ ctx: &BindgenContext,
+ mut callback: impl FnMut(Layout),
+ ) {
+ match self.fields {
+ CompFields::ErrorComputingBitfieldUnits => return,
+ CompFields::AfterComputingBitfieldUnits { ref fields, .. } => {
+ for field in fields.iter() {
+ if let Some(layout) = field.layout(ctx) {
+ callback(layout);
+ }
+ }
+ }
+ CompFields::BeforeComputingBitfieldUnits(ref raw_fields) => {
+ for field in raw_fields.iter() {
+ let field_ty = ctx.resolve_type(field.0.ty);
+ if let Some(layout) = field_ty.layout(ctx) {
+ callback(layout);
+ }
+ }
+ }
+ }
+ }
+
fn has_bitfields(&self) -> bool {
match self.fields {
CompFields::ErrorComputingBitfieldUnits => false,
@@ -1249,6 +1282,7 @@ impl CompInfo {
let mut ci = CompInfo::new(kind);
ci.is_forward_declaration =
location.map_or(true, |cur| match cur.kind() {
+ CXCursor_ParmDecl => true,
CXCursor_StructDecl | CXCursor_UnionDecl |
CXCursor_ClassDecl => !cur.is_definition(),
_ => false,
@@ -1597,23 +1631,17 @@ impl CompInfo {
// Even though `libclang` doesn't expose `#pragma packed(...)`, we can
// detect it through its effects.
if let Some(parent_layout) = layout {
- if self.fields().iter().any(|f| match *f {
- Field::Bitfields(ref unit) => {
- unit.layout().align > parent_layout.align
- }
- Field::DataMember(ref data) => {
- let field_ty = ctx.resolve_type(data.ty());
- field_ty.layout(ctx).map_or(false, |field_ty_layout| {
- field_ty_layout.align > parent_layout.align
- })
- }
- }) {
+ let mut packed = false;
+ self.each_known_field_layout(ctx, |layout| {
+ packed = packed || layout.align > parent_layout.align;
+ });
+ if packed {
info!("Found a struct that was defined within `#pragma packed(...)`");
return true;
- } else if self.has_own_virtual_method {
- if parent_layout.align == 1 {
- return true;
- }
+ }
+
+ if self.has_own_virtual_method && parent_layout.align == 1 {
+ return true;
}
}
@@ -1626,10 +1654,13 @@ impl CompInfo {
}
/// Compute this compound structure's bitfield allocation units.
- pub fn compute_bitfield_units(&mut self, ctx: &BindgenContext) {
- // TODO(emilio): If we could detect #pragma packed here we'd fix layout
- // tests in divide-by-zero-in-struct-layout.rs
- self.fields.compute_bitfield_units(ctx, self.packed_attr)
+ pub fn compute_bitfield_units(
+ &mut self,
+ ctx: &BindgenContext,
+ layout: Option<&Layout>,
+ ) {
+ let packed = self.is_packed(ctx, layout);
+ self.fields.compute_bitfield_units(ctx, packed)
}
/// Assign for each anonymous field a generated name.
diff --git a/src/ir/context.rs b/src/ir/context.rs
index ccb05e7..72ce06b 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -29,7 +29,7 @@ use clang_sys;
use proc_macro2::{Ident, Span};
use std::borrow::Cow;
use std::cell::{Cell, RefCell};
-use std::collections::HashMap as StdHashMap;
+use std::collections::{BTreeSet, HashMap as StdHashMap};
use std::iter::IntoIterator;
use std::mem;
@@ -354,6 +354,9 @@ pub struct BindgenContext {
/// This needs to be an std::HashMap because the cexpr API requires it.
parsed_macros: StdHashMap<Vec<u8>, cexpr::expr::EvalResult>,
+ /// A set of all the included filenames.
+ deps: BTreeSet<String>,
+
/// The active replacements collected from replaces="xxx" annotations.
replacements: HashMap<Vec<String>, ItemId>,
@@ -545,8 +548,16 @@ If you encounter an error missing from this list, please file an issue or a PR!"
let root_module = Self::build_root_module(ItemId(0));
let root_module_id = root_module.id().as_module_id_unchecked();
+ // depfiles need to include the explicitly listed headers too
+ let mut deps = BTreeSet::default();
+ if let Some(filename) = &options.input_header {
+ deps.insert(filename.clone());
+ }
+ deps.extend(options.extra_input_headers.iter().cloned());
+
BindgenContext {
items: vec![Some(root_module)],
+ deps,
types: Default::default(),
type_params: Default::default(),
modules: Default::default(),
@@ -632,6 +643,19 @@ If you encounter an error missing from this list, please file an issue or a PR!"
self.options().parse_callbacks.as_ref().map(|t| &**t)
}
+ /// Add another path to the set of included files.
+ pub fn include_file(&mut self, filename: String) {
+ if let Some(cbs) = self.parse_callbacks() {
+ cbs.include_file(&filename);
+ }
+ self.deps.insert(filename);
+ }
+
+ /// Get any included files.
+ pub fn deps(&self) -> &BTreeSet<String> {
+ &self.deps
+ }
+
/// Define a new item.
///
/// This inserts it into the internal items set, and its type into the
@@ -957,12 +981,11 @@ If you encounter an error missing from this list, please file an issue or a PR!"
mem::replace(&mut self.need_bitfield_allocation, vec![]);
for id in need_bitfield_allocation {
self.with_loaned_item(id, |ctx, item| {
- item.kind_mut()
- .as_type_mut()
- .unwrap()
- .as_comp_mut()
+ let ty = item.kind_mut().as_type_mut().unwrap();
+ let layout = ty.layout(ctx);
+ ty.as_comp_mut()
.unwrap()
- .compute_bitfield_units(ctx);
+ .compute_bitfield_units(ctx, layout.as_ref());
});
}
}
@@ -1808,8 +1831,8 @@ If you encounter an error missing from this list, please file an issue or a PR!"
) -> Option<TypeId> {
use clang_sys::{CXCursor_TypeAliasTemplateDecl, CXCursor_TypeRef};
debug!(
- "builtin_or_resolved_ty: {:?}, {:?}, {:?}",
- ty, location, parent_id
+ "builtin_or_resolved_ty: {:?}, {:?}, {:?}, {:?}",
+ ty, location, with_id, parent_id
);
if let Some(decl) = ty.canonical_declaration(location.as_ref()) {
diff --git a/src/ir/function.rs b/src/ir/function.rs
index a6f63a6..661ee59 100644
--- a/src/ir/function.rs
+++ b/src/ir/function.rs
@@ -28,7 +28,9 @@ pub enum FunctionKind {
}
impl FunctionKind {
- fn from_cursor(cursor: &clang::Cursor) -> Option<FunctionKind> {
+ /// Given a clang cursor, return the kind of function it represents, or
+ /// `None` otherwise.
+ pub fn from_cursor(cursor: &clang::Cursor) -> Option<FunctionKind> {
// FIXME(emilio): Deduplicate logic with `ir::comp`.
Some(match cursor.kind() {
clang_sys::CXCursor_FunctionDecl => FunctionKind::Function,
@@ -595,10 +597,13 @@ impl ClangSubItemParser for Function {
return Err(ParseError::Continue);
}
- if !context.options().generate_inline_functions &&
- cursor.is_inlined_function()
- {
- return Err(ParseError::Continue);
+ if cursor.is_inlined_function() {
+ if !context.options().generate_inline_functions {
+ return Err(ParseError::Continue);
+ }
+ if cursor.is_deleted_function() {
+ return Err(ParseError::Continue);
+ }
}
let linkage = cursor.linkage();
diff --git a/src/ir/item.rs b/src/ir/item.rs
index 4541504..4e0ba80 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -4,7 +4,7 @@ use super::super::codegen::{EnumVariation, CONSTIFIED_ENUM_MODULE_REPR_NAME};
use super::analysis::{HasVtable, HasVtableResult, Sizedness, SizednessResult};
use super::annotations::Annotations;
use super::comment;
-use super::comp::MethodKind;
+use super::comp::{CompKind, MethodKind};
use super::context::{BindgenContext, ItemId, PartialType, TypeId};
use super::derive::{
CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq,
@@ -904,6 +904,12 @@ impl Item {
names.push(base_name);
}
+ if ctx.options().c_naming {
+ if let Some(prefix) = self.c_naming_prefix() {
+ names.insert(0, prefix.to_string());
+ }
+ }
+
let name = names.join("_");
let name = if opt.user_mangled == UserMangled::Yes {
@@ -1054,6 +1060,23 @@ impl Item {
path.reverse();
path
}
+
+ /// Returns a prefix for the canonical name when C naming is enabled.
+ fn c_naming_prefix(&self) -> Option<&str> {
+ let ty = match self.kind {
+ ItemKind::Type(ref ty) => ty,
+ _ => return None,
+ };
+
+ Some(match ty.kind() {
+ TypeKind::Comp(ref ci) => match ci.kind() {
+ CompKind::Struct => "struct",
+ CompKind::Union => "union",
+ },
+ TypeKind::Enum(..) => "enum",
+ _ => return None,
+ })
+ }
}
impl<T> IsOpaque for T
@@ -1415,9 +1438,7 @@ impl ClangItemParser for Item {
);
}
Some(filename) => {
- if let Some(cb) = ctx.parse_callbacks() {
- cb.include_file(&filename)
- }
+ ctx.include_file(filename);
}
}
}
@@ -1560,6 +1581,18 @@ impl ClangItemParser for Item {
}
}
+ // Treat all types that are declared inside functions as opaque. The Rust binding
+ // won't be able to do anything with them anyway.
+ //
+ // (If we don't do this check here, we can have subtle logic bugs because we generally
+ // ignore function bodies. See issue #2036.)
+ if let Some(ref parent) = ty.declaration().fallible_semantic_parent() {
+ if FunctionKind::from_cursor(parent).is_some() {
+ debug!("Skipping type declared inside function: {:?}", ty);
+ return Ok(Item::new_opaque_type(id, ty, ctx));
+ }
+ }
+
let decl = {
let decl = ty.declaration();
decl.definition().unwrap_or(decl)
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index e6eecc3..e049ed6 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -39,7 +39,6 @@ pub struct Type {
/// traits, and so if we have a type containing an array with more than this
/// many items, we won't be able to derive common traits on that type.
///
-/// We need type-level integers yesterday :'(
pub const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32;
impl Type {
diff --git a/src/lib.rs b/src/lib.rs
index d0253db..01adba3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -51,6 +51,7 @@ macro_rules! doc_mod {
mod clang;
mod codegen;
+mod deps;
mod features;
mod ir;
mod parse;
@@ -557,6 +558,14 @@ impl Builder {
output_vector.push("--translate-enum-integer-types".into());
}
+ if self.options.c_naming {
+ output_vector.push("--c-naming".into());
+ }
+
+ if self.options.force_explicit_padding {
+ output_vector.push("--explicit-padding".into());
+ }
+
// Add clang arguments
output_vector.push("--".into());
@@ -604,6 +613,19 @@ impl Builder {
self
}
+ /// Add a depfile output which will be written alongside the generated bindings.
+ pub fn depfile<H: Into<String>, D: Into<PathBuf>>(
+ mut self,
+ output_module: H,
+ depfile: D,
+ ) -> Builder {
+ self.options.depfile = Some(deps::DepfileSpec {
+ output_module: output_module.into(),
+ depfile_path: depfile.into(),
+ });
+ self
+ }
+
/// Add `contents` as an input C/C++ header named `name`.
///
/// The file `name` will be added to the clang arguments.
@@ -1401,11 +1423,22 @@ impl Builder {
self
}
+ /// If true, always emit explicit padding fields.
+ ///
+ /// If a struct needs to be serialized in its native format (padding bytes
+ /// and all), for example writing it to a file or sending it on the network,
+ /// then this should be enabled, as anything reading the padding bytes of
+ /// a struct may lead to Undefined Behavior.
+ pub fn explicit_padding(mut self, doit: bool) -> Self {
+ self.options.force_explicit_padding = doit;
+ self
+ }
+
/// Generate the Rust bindings using the options built up thus far.
pub fn generate(mut self) -> Result<Bindings, ()> {
// Add any extra arguments from the environment to the clang command line.
if let Some(extra_clang_args) =
- env::var("BINDGEN_EXTRA_CLANG_ARGS").ok()
+ get_target_dependent_env_var("BINDGEN_EXTRA_CLANG_ARGS")
{
// Try to parse it with shell quoting. If we fail, make it one single big argument.
if let Some(strings) = shlex::split(&extra_clang_args) {
@@ -1417,11 +1450,13 @@ impl Builder {
// Transform input headers to arguments on the clang command line.
self.options.input_header = self.input_headers.pop();
- self.options
- .clang_args
- .extend(self.input_headers.drain(..).flat_map(|header| {
- iter::once("-include".into()).chain(iter::once(header))
- }));
+ self.options.extra_input_headers = self.input_headers;
+ self.options.clang_args.extend(
+ self.options.extra_input_headers.iter().flat_map(|header| {
+ iter::once("-include".into())
+ .chain(iter::once(header.to_string()))
+ }),
+ );
self.options.input_unsaved_files.extend(
self.input_header_contents
@@ -1600,6 +1635,15 @@ impl Builder {
self.options.translate_enum_integer_types = doit;
self
}
+
+ /// Generate types with C style naming.
+ ///
+ /// This will add prefixes to the generated type names. For example instead of a struct `A` we
+ /// will generate struct `struct_A`. Currently applies to structs, unions, and enums.
+ pub fn c_naming(mut self, doit: bool) -> Self {
+ self.options.c_naming = doit;
+ self
+ }
}
/// Configuration options for generated bindings.
@@ -1624,6 +1668,9 @@ struct BindgenOptions {
/// The explicit rustfmt path.
rustfmt_path: Option<PathBuf>,
+ /// The path to which we should write a Makefile-syntax depfile (if any).
+ depfile: Option<deps::DepfileSpec>,
+
/// The set of types that we should have bindings for in the generated
/// code.
///
@@ -1785,6 +1832,9 @@ struct BindgenOptions {
/// The input header file.
input_header: Option<String>,
+ /// Any additional input header files.
+ extra_input_headers: Vec<String>,
+
/// Unsaved files for input.
input_unsaved_files: Vec<clang::UnsavedFile>,
@@ -1899,6 +1949,12 @@ struct BindgenOptions {
/// Always translate enum integer types to native Rust integer types.
translate_enum_integer_types: bool,
+
+ /// Generate types with C style naming.
+ c_naming: bool,
+
+ /// Always output explicit padding fields
+ force_explicit_padding: bool,
}
/// TODO(emilio): This is sort of a lie (see the error message that results from
@@ -1963,6 +2019,7 @@ impl Default for BindgenOptions {
blocklisted_items: Default::default(),
opaque_types: Default::default(),
rustfmt_path: Default::default(),
+ depfile: Default::default(),
allowlisted_types: Default::default(),
allowlisted_functions: Default::default(),
allowlisted_vars: Default::default(),
@@ -2008,6 +2065,7 @@ impl Default for BindgenOptions {
module_lines: HashMap::default(),
clang_args: vec![],
input_header: None,
+ extra_input_headers: vec![],
input_unsaved_files: vec![],
parse_callbacks: None,
codegen_config: CodegenConfig::all(),
@@ -2038,6 +2096,8 @@ impl Default for BindgenOptions {
dynamic_link_require_all: false,
respect_cxx_access_specs: false,
translate_enum_integer_types: false,
+ c_naming: false,
+ force_explicit_padding: false,
}
}
}
@@ -2319,7 +2379,7 @@ impl Bindings {
/// Write these bindings as source text to the given `Write`able.
pub fn write<'a>(&self, mut writer: Box<dyn Write + 'a>) -> io::Result<()> {
if !self.options.disable_header_comment {
- let version = Some("0.58.1");
+ let version = Some("0.59.1");
let header = format!(
"/* automatically generated by rust-bindgen {} */\n\n",
version.unwrap_or("(unknown version)")
@@ -2557,6 +2617,21 @@ pub fn clang_version() -> ClangVersion {
}
}
+/// Looks for the env var `var_${TARGET}`, and falls back to just `var` when it is not found.
+fn get_target_dependent_env_var(var: &str) -> Option<String> {
+ if let Ok(target) = env::var("TARGET") {
+ if let Ok(v) = env::var(&format!("{}_{}", var, target)) {
+ return Some(v);
+ }
+ if let Ok(v) =
+ env::var(&format!("{}_{}", var, target.replace("-", "_")))
+ {
+ return Some(v);
+ }
+ }
+ env::var(var).ok()
+}
+
/// A ParseCallbacks implementation that will act on file includes by echoing a rerun-if-changed
/// line
///
diff --git a/src/options.rs b/src/options.rs
index 70b7990..c02f275 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -23,13 +23,17 @@ where
);
let matches = App::new("bindgen")
- .version(Some("0.58.1").unwrap_or("unknown"))
+ .version(Some("0.59.1").unwrap_or("unknown"))
.about("Generates Rust bindings from C/C++ headers.")
.usage("bindgen [FLAGS] [OPTIONS] <header> -- <clang-args>...")
.args(&[
Arg::with_name("header")
.help("C or C++ header file")
.required(true),
+ Arg::with_name("depfile")
+ .long("depfile")
+ .takes_value(true)
+ .help("Path to write depfile to"),
Arg::with_name("default-enum-style")
.long("default-enum-style")
.help("The default style of code used to generate enums.")
@@ -509,6 +513,12 @@ where
Arg::with_name("translate-enum-integer-types")
.long("translate-enum-integer-types")
.help("Always translate enum integer types to native Rust integer types."),
+ Arg::with_name("c-naming")
+ .long("c-naming")
+ .help("Generate types with C style naming."),
+ Arg::with_name("explicit-padding")
+ .long("explicit-padding")
+ .help("Always output explicit padding fields."),
]) // .args()
.get_matches_from(args);
@@ -848,8 +858,14 @@ where
let output = if let Some(path) = matches.value_of("output") {
let file = File::create(path)?;
+ if let Some(depfile) = matches.value_of("depfile") {
+ builder = builder.depfile(path, depfile);
+ }
Box::new(io::BufWriter::new(file)) as Box<dyn io::Write>
} else {
+ if let Some(depfile) = matches.value_of("depfile") {
+ builder = builder.depfile("-", depfile);
+ }
Box::new(io::BufWriter::new(io::stdout())) as Box<dyn io::Write>
};
@@ -943,6 +959,14 @@ where
builder = builder.translate_enum_integer_types(true);
}
+ if matches.is_present("c-naming") {
+ builder = builder.c_naming(true);
+ }
+
+ if matches.is_present("explicit-padding") {
+ builder = builder.explicit_padding(true);
+ }
+
let verbose = matches.is_present("verbose");
Ok((builder, output, verbose))