From: Marc-AndrĂ© Lureau <[email protected]>

bindgen < 0.72.1 linked against libclang >= 22 generates opaque structs
for C types declared with "typedef struct X X;" forward declarations,
common in QEMU. The struct fields are missing from the generated Rust
bindings. For example, with bindgen 0.71.x and LLVM 22, a struct like:

  typedef struct VMStateField VMStateField;
  struct VMStateField {
      const char *name;
      int version_id;
  };

produces:

  pub struct VMStateField {
      pub _address: u8,
  }

instead of:

  pub struct VMStateField {
      pub name: *const c_char,
      pub version_id: c_int,
  }

The build then fails with:
  error[E0609]: no field `version_id` on type `VMStateField`
  error[E0609]: no field `flags` on type `VMStateField`
  error[E0560]: struct `util_sys::Error` has no field named `msg`

Check the bindgen version against llvm-config at configure time. With
-Drust=enabled, error out; with -Drust=auto, disable Rust and suggest
the upgrade.

Signed-off-by: Marc-Andre Lureau <[email protected]>
---
 meson.build | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/meson.build b/meson.build
index 164328ded83..c965cef352e 100644
--- a/meson.build
+++ b/meson.build
@@ -125,6 +125,25 @@ if have_rust
       have_rust = false
     endif
   endif
+
+  # bindgen < 0.72.1 generates opaque structs for "typedef struct X X;"
+  # patterns when linked against libclang >= 22.
+  if have_rust and bindgen.version().version_compare('<0.72.1')
+    llvm_config = find_program('llvm-config', required: false)
+    if llvm_config.found()
+      llvm_version = run_command(llvm_config, '--version',
+                                 check: true).stdout().strip()
+      if llvm_version.version_compare('>=22.0.0')
+        if get_option('rust').enabled()
+          error('bindgen ' + bindgen.version() + ' is incompatible with LLVM ' 
+ llvm_version + '. ' +
+                'Please upgrade with "cargo install --locked 
[email protected]"')
+        else
+          warning('bindgen ' + bindgen.version() + ' is incompatible with LLVM 
' + llvm_version + ', disabling Rust.')
+          have_rust = false
+        endif
+      endif
+    endif
+  endif
 endif
 
 if have_rust
-- 
2.55.0


Reply via email to