summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen/mod.rs10
-rw-r--r--src/deps.rs20
-rw-r--r--src/ir/context.rs26
-rw-r--r--src/ir/item.rs4
-rw-r--r--src/lib.rs34
-rw-r--r--src/options.rs10
6 files changed, 95 insertions, 9 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index e498d2b2..1a702b00 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -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,
diff --git a/src/deps.rs b/src/deps.rs
new file mode 100644
index 00000000..479c396c
--- /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/ir/context.rs b/src/ir/context.rs
index ccb05e75..2b8acc36 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
diff --git a/src/ir/item.rs b/src/ir/item.rs
index 45415045..d7c92ab4 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -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);
}
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 418811e3..58c99c8d 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;
@@ -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(),
diff --git a/src/options.rs b/src/options.rs
index 36267321..ff2d4282 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -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>
};