Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid generating and writing bindings when called recursively #747

Merged
merged 1 commit into from Mar 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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