Repository: mozilla/cbindgen (language: rust)

Issue:
Having problems expanding macros with build.rs
I encountered a problem with the expansion of macros using build.rs. Here is a minimal example to point out the problems I'm having. I have the following `lib.rs`.  

```rust 
// lib.rs file

macro_rules! number {
    ($name:ident, $number:expr) => {
        #[no_mangle]
        pub extern "C" fn $name () -> u64 {
            $number
        }
    }
}

number!(two, 2);
```

with the following `cbindgen.toml`

```rust
language = "C"

[parse.expand]
crates = ["testing"]
```

If I run `rustup run nightly cbindgen ./ --config cbindgen.toml --crate testing --output bindings.h`, the macros are expanded, and I get the expected file `bindings.h`. 

However, if I try to expand macros and build the binding using a `build.rs` file, the compilation takes a lot and returns an error at the end of it. The build files I've tried are the following: 

```rust 
// With the builder struct

extern crate cbindgen;
use std::env;

fn main() {
    cbindgen::Builder::new()
        .with_crate(env::var("CARGO_MANIFEST_DIR").unwrap())
        .with_parse_expand(&["testing"])
        .generate()
        .expect("Unable to generate bindings")
        .write_to_file("bindings.h");
}
```

and 

```rust 
// With the generate function using the same cbindgen.toml as above
extern crate cbindgen;

fn main() {
    cbindgen::generate(std::env::var("CARGO_MANIFEST_DIR").unwrap())
        .expect("Unable to generate bindings")
        .write_to_file("bindings.h");
}
```

When running `RUST_BACKTRACE=1 cargo build` I get a ton of lines like this (not copying all because would be huge): 

```shell
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/ops/function.rs:227:5\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
```

and the final lines of the error are 
```shell
  stack backtrace:
     0: rust_begin_unwind
               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/std/src/panicking.rs:498:5
     1: core::panicking::panic_fmt
               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/panicking.rs:116:14
     2: core::result::unwrap_failed
               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/result.rs:1690:5
     3: core::result::Result<T,E>::expect
               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/result.rs:975:23
     4: build_script_build::main
               at ./build.rs:4:5
     5: core::ops::function::FnOnce::call_once
               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/ops/function.rs:227:5
  note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

```

Is this a known issue? Or am I maybe doing something wrong? 

Thank you! 


Discussion / hints:
Which version of cbindgen are you running as a dependency? I think https://github.com/eqrion/cbindgen/pull/747 should've fixed this.
Seems that this error is different: 

```
> cbindgen --version
cbindgen 0.23.0
```

and in the cargo file 

```
[build-dependencies]
cbindgen = "0.23.0"
```

Also

```
> cargo --version
cargo 1.60.0 (d1fd9fe2c 2022-03-01)
> rustc --version
rustc 1.60.0 (7737e0b5c 2022-04-04)
```
If you can put together a test-case I can look into it.
Test case as in a little repo to reproduce the error? I've put the minimal failing example in this repo https://github.com/iquerejeta/cbindgen-test

Thanks for looking into it! 
I'm running into the same thing recently. While I have not had an error yet, it does take a long time when using `Builder::with_parse_expand`. Have not tried with cbindgen and a configuration just yet and will be trying that sometime today. 

EDIT: Forgot to update that it works fine with cbindgen cli but just stalls when using it as a build dependency. Havent had time to dive into it to debug it (since i have a workaround by just calling cbindgen directly but is an annoying process) but curious as to why its an issue now unless its something that was introduced into 0.23. 
Anyone have updates on this? I'm running into the same issue on `cbindgen = "0.24.3"`.
> Anyone have updates on this? I'm running into the same issue on `cbindgen = "0.24.3"`.

Its still an issue the last I checked. I think the solution is to either build with nightly (believe i have tested this but cannot confirm right now) or just run cbindgen directly or in your build.rs 
I've resorted to running cbindgen in the build.rs as so:

```
Command::new("rustup")
        .arg("run")
        .arg("nightly")
        .arg("cbindgen")
        .arg("./")
        .arg("--config")
        .arg("cbindgen.toml")
        .arg("--crate")
        .arg("testing")
        .arg("--output")
        .arg(bindings)
        .output()
        .expect("failed to execute cbindgen cli");
```

but even so, the build times are very long (almost 10 minutes) because of this invocation of cbindgen.

Fix patch:
diff --git a/src/bindgen/builder.rs b/src/bindgen/builder.rs
index 6ee06e9cd..17d4ad1df 100644
--- a/src/bindgen/builder.rs
+++ b/src/bindgen/builder.rs
@@ -345,6 +345,24 @@ impl Builder {
     }
 
     pub fn generate(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(),
+                Default::default(),
+                true,
+            ));
+        }
+
         let mut result = Parse::new();
 
         if self.std_types {
diff --git a/src/bindgen/library.rs b/src/bindgen/library.rs
index 23ec38dc6..c00a6ebc6 100644
--- a/src/bindgen/library.rs
+++ b/src/bindgen/library.rs
@@ -54,24 +54,6 @@ 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(),
-                Default::default(),
-                true,
-            ));
-        }
-
         self.transfer_annotations();
         self.simplify_standard_types();
 


Test patch: