Skip to content

Commit

Permalink
Avoid generating and writing bindings when called recursively
Browse files Browse the repository at this point in the history
from a build script.
  • Loading branch information
petrochenkov authored and emilio committed Mar 31, 2022
1 parent ca7a942 commit aeb8193
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 7 deletions.
17 changes: 17 additions & 0 deletions src/bindgen/bindings.rs
Expand Up @@ -27,6 +27,9 @@ pub struct Bindings {
constants: Vec<Constant>,
items: Vec<ItemContainer>,
functions: Vec<Function>,
/// Bindings are generated by a recursive call to cbindgen
/// and shouldn't do anything when written anywhere.
noop: bool,
}

#[derive(PartialEq)]
Expand All @@ -43,6 +46,7 @@ impl Bindings {
globals: Vec<Static>,
items: Vec<ItemContainer>,
functions: Vec<Function>,
noop: bool,
) -> Bindings {
Bindings {
config,
Expand All @@ -52,6 +56,7 @@ impl Bindings {
constants,
items,
functions,
noop,
}
}

Expand Down Expand Up @@ -93,6 +98,10 @@ impl Bindings {
}

pub fn write_to_file<P: AsRef<path::Path>>(&self, path: P) -> bool {
if self.noop {
return false;
}

// Don't compare files if we've never written this file before
if !path.as_ref().is_file() {
if let Some(parent) = path::Path::new(path.as_ref()).parent() {
Expand Down Expand Up @@ -121,6 +130,10 @@ impl Bindings {
}

pub fn write_headers<F: Write>(&self, out: &mut SourceWriter<F>) {
if self.noop {
return;
}

if let Some(ref f) = self.config.header {
out.new_line_if_not_start();
write!(out, "{}", f);
Expand Down Expand Up @@ -247,6 +260,10 @@ impl Bindings {
}

pub fn write<F: Write>(&self, file: F) {
if self.noop {
return;
}

let mut out = SourceWriter::new(file, self);

self.write_headers(&mut out);
Expand Down
18 changes: 18 additions & 0 deletions src/bindgen/library.rs
Expand Up @@ -54,6 +54,23 @@ impl Library {
}

pub fn generate(mut self) -> Result<Bindings, Error> {
// If macro expansion is enabled, then cbindgen will attempt to build the crate
// and will run its build script which may run cbindgen again. That second run may start
// infinite recursion, or overwrite previously written files with bindings.
// So if we are called recursively, we are skipping the whole generation
// and produce "noop" bindings that won't be able to overwrite anything.
if std::env::var("_CBINDGEN_IS_RUNNING").is_ok() {
return Ok(Bindings::new(
self.config,
Default::default(),
Default::default(),
Default::default(),
Default::default(),
Default::default(),
true,
));
}

self.transfer_annotations();
self.simplify_standard_types();

Expand Down Expand Up @@ -134,6 +151,7 @@ impl Library {
globals,
items,
functions,
false,
))
}

Expand Down
7 changes: 0 additions & 7 deletions src/bindgen/parser.rs
Expand Up @@ -187,13 +187,6 @@ impl<'a> Parser<'a> {
fn parse_expand_crate(&mut self, pkg: &PackageRef) -> Result<(), Error> {
assert!(self.lib.is_some());

// If you want to expand the crate you run cbindgen on you might end up in an endless
// recursion if the cbindgen generation is triggered from build.rs. Hence don't run the
// expansion if the build was already triggered by cbindgen.
if std::env::var("_CBINDGEN_IS_RUNNING").is_ok() {
return Ok(());
}

let mod_items = {
if !self.cache_expanded_crate.contains_key(&pkg.name) {
let s = self
Expand Down

0 comments on commit aeb8193

Please sign in to comment.