mirror of
https://gitee.com/openharmony/third_party_rust_bindgen
synced 2025-03-02 03:35:44 +00:00
Support emitting Makefile-syntax depfiles like gcc/clang/rustc.
Needed to auto-bindgen with a ninja build without the build graph going stale.
This commit is contained in:
parent
c39c47c2e5
commit
1bb548b7a7
96
Cargo.lock
generated
96
Cargo.lock
generated
@ -50,6 +50,7 @@ dependencies = [
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"tempfile",
|
||||
"which",
|
||||
]
|
||||
|
||||
@ -125,6 +126,17 @@ dependencies = [
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[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"
|
||||
@ -205,6 +217,12 @@ version = "0.1.2"
|
||||
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"
|
||||
@ -223,6 +241,55 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[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"
|
||||
@ -241,6 +308,15 @@ version = "0.6.21"
|
||||
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"
|
||||
@ -259,6 +335,20 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[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"
|
||||
@ -310,6 +400,12 @@ version = "0.9.2"
|
||||
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"
|
||||
|
@ -43,6 +43,7 @@ required-features = ["clap"]
|
||||
diff = "0.1"
|
||||
clap = "2"
|
||||
shlex = "1"
|
||||
tempfile = "3"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.0.3"
|
||||
|
@ -4207,6 +4207,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,
|
||||
|
20
src/deps.rs
Normal file
20
src/deps.rs
Normal file
@ -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)
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -1415,9 +1415,7 @@ impl ClangItemParser for Item {
|
||||
);
|
||||
}
|
||||
Some(filename) => {
|
||||
if let Some(cb) = ctx.parse_callbacks() {
|
||||
cb.include_file(&filename)
|
||||
}
|
||||
ctx.include_file(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
34
src/lib.rs
34
src/lib.rs
@ -51,6 +51,7 @@ macro_rules! doc_mod {
|
||||
|
||||
mod clang;
|
||||
mod codegen;
|
||||
mod deps;
|
||||
mod features;
|
||||
mod ir;
|
||||
mod parse;
|
||||
@ -604,6 +605,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.
|
||||
@ -1417,11 +1431,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
|
||||
@ -1624,6 +1640,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 +1804,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>,
|
||||
|
||||
@ -1963,6 +1985,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 +2031,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(),
|
||||
|
@ -30,6 +30,10 @@ where
|
||||
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.")
|
||||
@ -848,8 +852,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>
|
||||
};
|
||||
|
||||
|
1
tests/expectations/tests/enum-default-rust.d
Normal file
1
tests/expectations/tests/enum-default-rust.d
Normal file
@ -0,0 +1 @@
|
||||
tests/expectations/tests/enum-default-rust.rs: tests/headers/enum-default-rust.h tests/headers/enum.h
|
@ -578,6 +578,32 @@ fn no_system_header_includes() {
|
||||
.success());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emit_depfile() {
|
||||
let header = PathBuf::from("tests/headers/enum-default-rust.h");
|
||||
let expected_depfile = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("tests")
|
||||
.join("expectations")
|
||||
.join("tests")
|
||||
.join("enum-default-rust.d");
|
||||
let observed_depfile = tempfile::NamedTempFile::new().unwrap();
|
||||
let mut builder = create_bindgen_builder(&header).unwrap();
|
||||
builder.builder = builder.builder.depfile(
|
||||
"tests/expectations/tests/enum-default-rust.rs",
|
||||
observed_depfile.path(),
|
||||
);
|
||||
|
||||
let check_roundtrip =
|
||||
env::var_os("BINDGEN_DISABLE_ROUNDTRIP_TEST").is_none();
|
||||
let (builder, _roundtrip_builder) =
|
||||
builder.into_builder(check_roundtrip).unwrap();
|
||||
let _bindings = builder.generate().unwrap();
|
||||
|
||||
let observed = std::fs::read_to_string(observed_depfile).unwrap();
|
||||
let expected = std::fs::read_to_string(expected_depfile).unwrap();
|
||||
assert_eq!(observed.trim(), expected.trim());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dump_preprocessed_input() {
|
||||
let arg_keyword =
|
||||
|
Loading…
x
Reference in New Issue
Block a user