From 87ca4011e597e5aac8f085acb81f06f93ced801b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 31 Mar 2022 19:46:41 +0300 Subject: [PATCH] Avoid generating and writing bindings when called recursively from a build script. --- src/bindgen/bindings.rs | 17 +++++++++++++++++ src/bindgen/library.rs | 18 ++++++++++++++++++ src/bindgen/parser.rs | 7 ------- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/bindgen/bindings.rs b/src/bindgen/bindings.rs index b501f8960..2b0f86a9a 100644 --- a/src/bindgen/bindings.rs +++ b/src/bindgen/bindings.rs @@ -27,6 +27,9 @@ pub struct Bindings { constants: Vec, items: Vec, functions: Vec, + /// Bindings are generated by a recursive call to cbindgen + /// and shouldn't do anything when written anywhere. + noop: bool, } #[derive(PartialEq)] @@ -43,6 +46,7 @@ impl Bindings { globals: Vec, items: Vec, functions: Vec, + noop: bool, ) -> Bindings { Bindings { config, @@ -52,6 +56,7 @@ impl Bindings { constants, items, functions, + noop, } } @@ -93,6 +98,10 @@ impl Bindings { } pub fn write_to_file>(&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() { @@ -121,6 +130,10 @@ impl Bindings { } pub fn write_headers(&self, out: &mut SourceWriter) { + if self.noop { + return; + } + if let Some(ref f) = self.config.header { out.new_line_if_not_start(); write!(out, "{}", f); @@ -247,6 +260,10 @@ impl Bindings { } pub fn write(&self, file: F) { + if self.noop { + return; + } + let mut out = SourceWriter::new(file, self); self.write_headers(&mut out); diff --git a/src/bindgen/library.rs b/src/bindgen/library.rs index b1f9eb457..1f9fb4c92 100644 --- a/src/bindgen/library.rs +++ b/src/bindgen/library.rs @@ -54,6 +54,23 @@ impl Library { } pub fn generate(mut self) -> Result { + // 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(); @@ -134,6 +151,7 @@ impl Library { globals, items, functions, + false, )) } diff --git a/src/bindgen/parser.rs b/src/bindgen/parser.rs index 0a610774f..804ead033 100644 --- a/src/bindgen/parser.rs +++ b/src/bindgen/parser.rs @@ -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