Skip to content

Commit

Permalink
Support emitting Makefile-syntax depfiles like gcc/clang/rustc.
Browse files Browse the repository at this point in the history
Needed to auto-bindgen with a ninja build without the build graph
going stale.
  • Loading branch information
anp committed Apr 23, 2021
1 parent c39c47c commit e2f6730
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 9 deletions.
96 changes: 96 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -43,6 +43,7 @@ required-features = ["clap"]
diff = "0.1"
clap = "2"
shlex = "1"
tempfile = "3"

[dependencies]
bitflags = "1.0.3"
Expand Down
10 changes: 10 additions & 0 deletions src/codegen/mod.rs
Expand Up @@ -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,
Expand Down
20 changes: 20 additions & 0 deletions 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)
}
}
26 changes: 25 additions & 1 deletion src/ir/context.rs
Expand Up @@ -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;

Expand Down Expand Up @@ -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>,

Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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
Expand Down
4 changes: 1 addition & 3 deletions src/ir/item.rs
Expand Up @@ -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);
}
}
}
Expand Down
34 changes: 29 additions & 5 deletions src/lib.rs
Expand Up @@ -51,6 +51,7 @@ macro_rules! doc_mod {

mod clang;
mod codegen;
mod deps;
mod features;
mod ir;
mod parse;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
///
Expand Down Expand Up @@ -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>,

Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down
10 changes: 10 additions & 0 deletions src/options.rs
Expand Up @@ -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.")
Expand Down Expand Up @@ -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>
};

Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/enum-default-rust.d
@@ -0,0 +1 @@
tests/expectations/tests/enum-default-rust.rs: tests/headers/enum-default-rust.h tests/headers/enum.h

0 comments on commit e2f6730

Please sign in to comment.