Message ID | 20240828-rust-pl011-v9-7-35579191f17c@linaro.org |
---|---|
State | New |
Headers | show |
Series | Add Rust build support, ARM PL011 device impl | expand |
Manos Pitsidianakis <manos.pitsidianakis@linaro.org> writes: > Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and > provides some declaration macros for symbols visible to the rest of > QEMU. As mentioned on IRC I'm hitting a compilation error that bisects to this commit: [148/1010] Generating bindings for Rust rustmod-bindgen-rust_wrapper.h FAILED: bindings.rs /home/alex/.cargo/bin/bindgen ../../rust/wrapper.h --output /home/alex/lsrc/qemu.git/builds/rust/bindings.rs --disable-header-comment --raw-line '// @generated' --ctypes-prefix core::ffi --formatter rustfmt --generate-block --generate-cstr --impl-debug --merge-extern-blocks --no-doc-comments --use-core --with-derive-default --allowlist-file '/home/alex/lsrc/qemu.git/include/.*' --allowlist-file '/home/alex/lsrc/qemu.git/.*' --allowlist-file '/home/alex/lsrc/qemu.git/builds/rust/.*' -- -I/home/alex/lsrc/qemu.git/. -I/home/alex/lsrc/qemu.git/builds/rust/. -I/home/alex/lsrc/qemu.git/include -I/home/alex/lsrc/qemu.git/builds/rust/include -I/usr/include/capstone -I/usr/include/p11-kit-1 -I/usr/include/pixman-1 -I/usr/include/libpng16 -I/usr/include/spice-server -I/usr/include/spice-1 -I/usr/include/spice-1 -DSTRUCT_IOVEC_DEFINED -I/usr/include/libusb-1.0 -I/usr/include/SDL2 -D_REENTRANT -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -pthread -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/gio-unix-2.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -pthread -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/slirp -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -DNCURSES_WIDECHAR=1 -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/x86_64-linux-gnu -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -pthread -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/x86_64-linux-gnu -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -pthread -I/usr/include/vte-2.91 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/gtk-3.0 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/x86_64-linux-gnu -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -pthread -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/spice-server -I/usr/include/spice-1 -I/usr/include/cacard -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/nss -I/usr/include/nspr -I/usr/include/PCSC -pthread -D_REENTRANT -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT -I/usr/include/p11-kit-1 -I/usr/include/fuse3 -I/usr/include/x86_64-linux-gnu -D_FILE_OFFSET_BITS=64 -D__USE_FILE_OFFSET64 -D__USE_LARGEFILE64 -DUSE_POSIX_ACLS=1 -I/usr/include/uuid -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/p11-kit-1 -I/usr/include/p11-kit-1 -I/usr/include/p11-kit-1 -I/usr/include/p11-kit-1 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -std=gnu11 -MD -MQ ../../rust/wrapper.h -MF wrapper.h.d /usr/include/liburing.h:296:3: error: use of undeclared identifier 'memory_order_release' /usr/include/liburing.h:1080:11: error: use of undeclared identifier 'memory_order_acquire' /usr/include/liburing.h:1116:9: error: use of undeclared identifier 'memory_order_acquire' /usr/include/liburing.h:1125:9: error: use of undeclared identifier 'memory_order_relaxed' /usr/include/liburing.h:1161:2: error: use of undeclared identifier 'memory_order_relaxed' /usr/include/liburing.h:1197:19: error: use of undeclared identifier 'memory_order_acquire' /usr/include/liburing.h:1267:10: error: use of undeclared identifier 'memory_order_relaxed' /usr/include/liburing.h:1269:10: error: use of undeclared identifier 'memory_order_acquire' /usr/include/liburing.h:1320:2: error: use of undeclared identifier 'memory_order_release' panicked at /home/alex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bindgen-cli-0.69.4/main.rs:52:36: Unable to generate bindings: ClangDiagnostic("/usr/include/liburing.h:296:3: error: use of undeclared identifier 'memory_order_release'\n/usr/include/liburing.h:1080:11: error: use of undeclared identifier 'memory_order_acquire'\n/usr/include/liburing.h:1116:9: error: use of undeclared identifier 'memory_order_acquire'\n/usr/include/liburing.h:1125:9: error: use of undeclared identifier 'memory_order_relaxed'\n/usr/include/liburing.h:1161:2: error: use of undeclared identifier 'memory_order_relaxed'\n/usr/include/liburing.h:1197:19: error: use of undeclared identifier 'memory_order_acquire'\n/usr/include/liburing.h:1267:10: error: use of undeclared identifier 'memory_order_relaxed'\n/usr/include/liburing.h:1269:10: error: use of undeclared identifier 'memory_order_acquire'\n/usr/include/liburing.h:1320:2: error: use of undeclared identifier 'memory_order_release'\n") And I wasn't able to force the newer clang with: env CLANG_PATH=/usr/bin/clang-15 ../../configure '--disable-docs' --target-list=aarch64-softmmu --enable-rust So if clang is required for bindgen we at least need: - to probe for clang (separately from --cc) - allow the user to override the default - pass the clang we want to use somehow to bindgen Briefly looking at the bindgen code I see: fn main() { let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); let mut dst = File::create(Path::new(&out_dir).join("host-target.txt")).unwrap(); dst.write_all(env::var("TARGET").unwrap().as_bytes()) .unwrap(); // On behalf of clang_sys, rebuild ourselves if important configuration // variables change, to ensure that bindings get rebuilt if the // underlying libclang changes. println!("cargo:rerun-if-env-changed=LLVM_CONFIG_PATH"); println!("cargo:rerun-if-env-changed=LIBCLANG_PATH"); println!("cargo:rerun-if-env-changed=LIBCLANG_STATIC_PATH"); println!("cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS"); println!( "cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_{}", std::env::var("TARGET").unwrap() ); println!( "cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_{}", std::env::var("TARGET").unwrap().replace('-', "_") ); } So I wonder if this depends on what libclang versions can be found when cargo builds it? Although if it does it must do so dynamically: $ ldd /home/alex/.cargo/bin/bindgen linux-vdso.so.1 (0x00007f7cb43d8000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f7cb438c000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7cb42ad000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7cb3a1f000) /lib64/ld-linux-x86-64.so.2 (0x00007f7cb43da000)
On 8/28/2024 9:08 PM, Alex Bennée wrote: > Manos Pitsidianakis <manos.pitsidianakis@linaro.org> writes: > >> Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and >> provides some declaration macros for symbols visible to the rest of >> QEMU. > > As mentioned on IRC I'm hitting a compilation error that bisects to this > commit: > > [148/1010] Generating bindings for Rust rustmod-bindgen-rust_wrapper.h > FAILED: bindings.rs > /home/alex/.cargo/bin/bindgen ../../rust/wrapper.h --output /home/alex/lsrc/qemu.git/builds/rust/bindings.rs --disable-header-comment --raw-line '// @generated' --ctypes-prefix core::ffi --formatter rustfmt --generate-block --generate-cstr --impl-debug --merge-extern-blocks --no-doc-comments --use-core --with-derive-default --allowlist-file '/home/alex/lsrc/qemu.git/include/.*' --allowlist-file '/home/alex/lsrc/qemu.git/.*' --allowlist-file '/home/alex/lsrc/qemu.git/builds/rust/.*' -- -I/home/alex/lsrc/qemu.git/. -I/home/alex/lsrc/qemu.git/builds/rust/. -I/home/alex/lsrc/qemu.git/include -I/home/alex/lsrc/qemu.git/builds/rust/include -I/usr/include/capstone -I/usr/include/p11-kit-1 -I/usr/include/pixman-1 -I/usr/include/libpng16 -I/usr/include/spice-server -I/usr/include/spice-1 -I/usr/include/spice-1 -DSTRUCT_IOVEC_DEFINED -I/usr/include/libusb-1.0 -I/usr/include/SDL2 -D_REENTRANT -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -pthread -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/gio-unix-2.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -pthread -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/slirp -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -DNCURSES_WIDECHAR=1 -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/x86_64-linux-gnu -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -pthread -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/x86_64-linux-gnu -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -pthread -I/usr/include/vte-2.91 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/gtk-3.0 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/x86_64-linux-gnu -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -pthread -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/spice-server -I/usr/include/spice-1 -I/usr/include/cacard -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/nss -I/usr/include/nspr -I/usr/include/PCSC -pthread -D_REENTRANT -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT -I/usr/include/p11-kit-1 -I/usr/include/fuse3 -I/usr/include/x86_64-linux-gnu -D_FILE_OFFSET_BITS=64 -D__USE_FILE_OFFSET64 -D__USE_LARGEFILE64 -DUSE_POSIX_ACLS=1 -I/usr/include/uuid -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/p11-kit-1 -I/usr/include/p11-kit-1 -I/usr/include/p11-kit-1 -I/usr/include/p11-kit-1 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -std=gnu11 -MD -MQ ../../rust/wrapper.h -MF wrapper.h.d > /usr/include/liburing.h:296:3: error: use of undeclared identifier 'memory_order_release' > /usr/include/liburing.h:1080:11: error: use of undeclared identifier 'memory_order_acquire' > /usr/include/liburing.h:1116:9: error: use of undeclared identifier 'memory_order_acquire' > /usr/include/liburing.h:1125:9: error: use of undeclared identifier 'memory_order_relaxed' > /usr/include/liburing.h:1161:2: error: use of undeclared identifier 'memory_order_relaxed' > /usr/include/liburing.h:1197:19: error: use of undeclared identifier 'memory_order_acquire' > /usr/include/liburing.h:1267:10: error: use of undeclared identifier 'memory_order_relaxed' > /usr/include/liburing.h:1269:10: error: use of undeclared identifier 'memory_order_acquire' > /usr/include/liburing.h:1320:2: error: use of undeclared identifier 'memory_order_release' > panicked at /home/alex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bindgen-cli-0.69.4/main.rs:52:36: > Unable to generate bindings: ClangDiagnostic("/usr/include/liburing.h:296:3: error: use of undeclared identifier 'memory_order_release'\n/usr/include/liburing.h:1080:11: error: use of undeclared identifier 'memory_order_acquire'\n/usr/include/liburing.h:1116:9: error: use of undeclared identifier 'memory_order_acquire'\n/usr/include/liburing.h:1125:9: error: use of undeclared identifier 'memory_order_relaxed'\n/usr/include/liburing.h:1161:2: error: use of undeclared identifier 'memory_order_relaxed'\n/usr/include/liburing.h:1197:19: error: use of undeclared identifier 'memory_order_acquire'\n/usr/include/liburing.h:1267:10: error: use of undeclared identifier 'memory_order_relaxed'\n/usr/include/liburing.h:1269:10: error: use of undeclared identifier 'memory_order_acquire'\n/usr/include/liburing.h:1320:2: error: use of undeclared identifier 'memory_order_release'\n") Those missing identifiers should have been defined in stdatomic.h which is part of C11. You can check if that header exists under the default header search paths (which is listed by clang -E -Wp,-v -) and whether that file declares those enum constants. If so, you can further check whether there is any stdatomic.h elsewhere that shadows the standard one. > > And I wasn't able to force the newer clang with: > > env CLANG_PATH=/usr/bin/clang-15 ../../configure '--disable-docs' --target-list=aarch64-softmmu --enable-rust > > So if clang is required for bindgen we at least need: > > - to probe for clang (separately from --cc) > - allow the user to override the default > - pass the clang we want to use somehow to bindgen > > Briefly looking at the bindgen code I see: > > fn main() { > let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); > > let mut dst = > File::create(Path::new(&out_dir).join("host-target.txt")).unwrap(); > dst.write_all(env::var("TARGET").unwrap().as_bytes()) > .unwrap(); > > // On behalf of clang_sys, rebuild ourselves if important configuration > // variables change, to ensure that bindings get rebuilt if the > // underlying libclang changes. > println!("cargo:rerun-if-env-changed=LLVM_CONFIG_PATH"); > println!("cargo:rerun-if-env-changed=LIBCLANG_PATH"); > println!("cargo:rerun-if-env-changed=LIBCLANG_STATIC_PATH"); > println!("cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS"); > println!( > "cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_{}", > std::env::var("TARGET").unwrap() > ); > println!( > "cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_{}", > std::env::var("TARGET").unwrap().replace('-', "_") > ); > } This is build.rs which is a build script invoked by cargo. The entry of the bindgen executable is in the bindgen-cli crate. --- Best Regards Junjie Mao > > So I wonder if this depends on what libclang versions can be found when > cargo builds it? Although if it does it must do so dynamically: > > $ ldd /home/alex/.cargo/bin/bindgen > linux-vdso.so.1 (0x00007f7cb43d8000) > libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f7cb438c000) > libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7cb42ad000) > libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7cb3a1f000) > /lib64/ld-linux-x86-64.so.2 (0x00007f7cb43da000) >
🎱 On Fri, 30 Aug 2024, 04:19 Junjie Mao, <junjie.mao@intel.com> wrote: > On 8/28/2024 9:08 PM, Alex Bennée wrote: > > Manos Pitsidianakis <manos.pitsidianakis@linaro.org> writes: > > > >> Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and > >> provides some declaration macros for symbols visible to the rest of > >> QEMU. > > > > As mentioned on IRC I'm hitting a compilation error that bisects to this > > commit: > > > > [148/1010] Generating bindings for Rust rustmod-bindgen-rust_wrapper.h > > FAILED: bindings.rs > > /home/alex/.cargo/bin/bindgen ../../rust/wrapper.h --output > /home/alex/lsrc/qemu.git/builds/rust/bindings.rs --disable-header-comment > --raw-line '// @generated' --ctypes-prefix core::ffi --formatter rustfmt > --generate-block --generate-cstr --impl-debug --merge-extern-blocks > --no-doc-comments --use-core --with-derive-default --allowlist-file > '/home/alex/lsrc/qemu.git/include/.*' --allowlist-file > '/home/alex/lsrc/qemu.git/.*' --allowlist-file > '/home/alex/lsrc/qemu.git/builds/rust/.*' -- -I/home/alex/lsrc/qemu.git/. > -I/home/alex/lsrc/qemu.git/builds/rust/. -I/home/alex/lsrc/qemu.git/include > -I/home/alex/lsrc/qemu.git/builds/rust/include -I/usr/include/capstone > -I/usr/include/p11-kit-1 -I/usr/include/pixman-1 -I/usr/include/libpng16 > -I/usr/include/spice-server -I/usr/include/spice-1 -I/usr/include/spice-1 > -DSTRUCT_IOVEC_DEFINED -I/usr/include/libusb-1.0 -I/usr/include/SDL2 > -D_REENTRANT -I/usr/include/glib-2.0 > -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -pthread > -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/gio-unix-2.0 > -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include > -pthread -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/slirp > -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include > -DNCURSES_WIDECHAR=1 -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 > -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include > -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 > -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/harfbuzz > -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/libmount > -I/usr/include/blkid -I/usr/include/fribidi -I/usr/include/cairo > -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2.0 > -I/usr/include/x86_64-linux-gnu -I/usr/include/gio-unix-2.0 > -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 > -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 > -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -pthread > -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 > -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/harfbuzz > -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/libmount > -I/usr/include/blkid -I/usr/include/fribidi -I/usr/include/cairo > -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2.0 > -I/usr/include/x86_64-linux-gnu -I/usr/include/gio-unix-2.0 > -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 > -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 > -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -pthread > -I/usr/include/vte-2.91 -I/usr/include/glib-2.0 > -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/libmount > -I/usr/include/blkid -I/usr/include/pango-1.0 -I/usr/include/harfbuzz > -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/fribidi > -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/gtk-3.0 > -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/x86_64-linux-gnu > -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 > -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 > -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include > -pthread -I/usr/include/glib-2.0 > -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/spice-server > -I/usr/include/spice-1 -I/usr/include/cacard -I/usr/include/glib-2.0 > -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/nss > -I/usr/include/nspr -I/usr/include/PCSC -pthread -D_REENTRANT > -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT > -I/usr/include/p11-kit-1 -I/usr/include/fuse3 > -I/usr/include/x86_64-linux-gnu -D_FILE_OFFSET_BITS=64 > -D__USE_FILE_OFFSET64 -D__USE_LARGEFILE64 -DUSE_POSIX_ACLS=1 > -I/usr/include/uuid -I/usr/include/glib-2.0 > -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/p11-kit-1 > -I/usr/include/p11-kit-1 -I/usr/include/p11-kit-1 -I/usr/include/p11-kit-1 > -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE > -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include > -std=gnu11 -MD -MQ ../../rust/wrapper.h -MF wrapper.h.d > > /usr/include/liburing.h:296:3: error: use of undeclared identifier > 'memory_order_release' > > /usr/include/liburing.h:1080:11: error: use of undeclared identifier > 'memory_order_acquire' > > /usr/include/liburing.h:1116:9: error: use of undeclared identifier > 'memory_order_acquire' > > /usr/include/liburing.h:1125:9: error: use of undeclared identifier > 'memory_order_relaxed' > > /usr/include/liburing.h:1161:2: error: use of undeclared identifier > 'memory_order_relaxed' > > /usr/include/liburing.h:1197:19: error: use of undeclared identifier > 'memory_order_acquire' > > /usr/include/liburing.h:1267:10: error: use of undeclared identifier > 'memory_order_relaxed' > > /usr/include/liburing.h:1269:10: error: use of undeclared identifier > 'memory_order_acquire' > > /usr/include/liburing.h:1320:2: error: use of undeclared identifier > 'memory_order_release' > > panicked at > /home/alex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bindgen-cli-0.69.4/main.rs:52 > :36: > > Unable to generate bindings: > ClangDiagnostic("/usr/include/liburing.h:296:3: error: use of undeclared > identifier 'memory_order_release'\n/usr/include/liburing.h:1080:11: error: > use of undeclared identifier > 'memory_order_acquire'\n/usr/include/liburing.h:1116:9: error: use of > undeclared identifier > 'memory_order_acquire'\n/usr/include/liburing.h:1125:9: error: use of > undeclared identifier > 'memory_order_relaxed'\n/usr/include/liburing.h:1161:2: error: use of > undeclared identifier > 'memory_order_relaxed'\n/usr/include/liburing.h:1197:19: error: use of > undeclared identifier > 'memory_order_acquire'\n/usr/include/liburing.h:1267:10: error: use of > undeclared identifier > 'memory_order_relaxed'\n/usr/include/liburing.h:1269:10: error: use of > undeclared identifier > 'memory_order_acquire'\n/usr/include/liburing.h:1320:2: error: use of > undeclared identifier 'memory_order_release'\n") > > Those missing identifiers should have been defined in stdatomic.h which is > part > of C11. You can check if that header exists under the default header > search > paths (which is listed by clang -E -Wp,-v -) and whether that file > declares > those enum constants. If so, you can further check whether there is any > stdatomic.h elsewhere that shadows the standard one. > Indeed. These are in the compiler's own header files. I had problems on Debian when using clang-14 and clang-15 but I got rid of them after I upgraded to newer versions. If anyone can confirm/reproduce this we can add a meson warning check? > > > And I wasn't able to force the newer clang with: > > > > env CLANG_PATH=/usr/bin/clang-15 ../../configure '--disable-docs' > --target-list=aarch64-softmmu --enable-rust > > > > So if clang is required for bindgen we at least need: > > > > - to probe for clang (separately from --cc) > > - allow the user to override the default > > - pass the clang we want to use somehow to bindgen > > > > Briefly looking at the bindgen code I see: > > > > fn main() { > > let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); > > > > let mut dst = > > > File::create(Path::new(&out_dir).join("host-target.txt")).unwrap(); > > dst.write_all(env::var("TARGET").unwrap().as_bytes()) > > .unwrap(); > > > > // On behalf of clang_sys, rebuild ourselves if important > configuration > > // variables change, to ensure that bindings get rebuilt if the > > // underlying libclang changes. > > println!("cargo:rerun-if-env-changed=LLVM_CONFIG_PATH"); > > println!("cargo:rerun-if-env-changed=LIBCLANG_PATH"); > > println!("cargo:rerun-if-env-changed=LIBCLANG_STATIC_PATH"); > > println!("cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS"); > > println!( > > "cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_{}", > > std::env::var("TARGET").unwrap() > > ); > > println!( > > "cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_{}", > > std::env::var("TARGET").unwrap().replace('-', "_") > > ); > > } > > This is build.rs which is a build script invoked by cargo. The entry of > the > bindgen executable is in the bindgen-cli crate. > > --- > Best Regards > Junjie Mao > > > > > So I wonder if this depends on what libclang versions can be found when > > cargo builds it? Although if it does it must do so dynamically: > > > > $ ldd /home/alex/.cargo/bin/bindgen > > linux-vdso.so.1 (0x00007f7cb43d8000) > > libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 > (0x00007f7cb438c000) > > libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 > (0x00007f7cb42ad000) > > libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 > (0x00007f7cb3a1f000) > > /lib64/ld-linux-x86-64.so.2 (0x00007f7cb43da000) > > >
On 8/30/2024 2:43 PM, Manos Pitsidianakis wrote: > 🎱 > > On Fri, 30 Aug 2024, 04:19 Junjie Mao, <junjie.mao@intel.com > <mailto:junjie.mao@intel.com>> wrote: > > On 8/28/2024 9:08 PM, Alex Bennée wrote: > > Manos Pitsidianakis <manos.pitsidianakis@linaro.org > <mailto:manos.pitsidianakis@linaro.org>> writes: > > > >> Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and > >> provides some declaration macros for symbols visible to the rest of > >> QEMU. > > > > As mentioned on IRC I'm hitting a compilation error that bisects to this > > commit: > > > > [148/1010] Generating bindings for Rust rustmod-bindgen-rust_wrapper.h > > FAILED: bindings.rs <http://bindings.rs> > > /home/alex/.cargo/bin/bindgen ../../rust/wrapper.h --output > /home/alex/lsrc/qemu.git/builds/rust/bindings.rs <http://bindings.rs> > --disable-header-comment --raw-line '// @generated' --ctypes-prefix > core::ffi --formatter rustfmt --generate-block --generate-cstr --impl-debug > --merge-extern-blocks --no-doc-comments --use-core --with-derive-default > --allowlist-file '/home/alex/lsrc/qemu.git/include/.*' --allowlist-file > '/home/alex/lsrc/qemu.git/.*' --allowlist-file > '/home/alex/lsrc/qemu.git/builds/rust/.*' -- -I/home/alex/lsrc/qemu.git/. > -I/home/alex/lsrc/qemu.git/builds/rust/. -I/home/alex/lsrc/qemu.git/include > -I/home/alex/lsrc/qemu.git/builds/rust/include -I/usr/include/capstone > -I/usr/include/p11-kit-1 -I/usr/include/pixman-1 -I/usr/include/libpng16 > -I/usr/include/spice-server -I/usr/include/spice-1 -I/usr/include/spice-1 > -DSTRUCT_IOVEC_DEFINED -I/usr/include/libusb-1.0 -I/usr/include/SDL2 > -D_REENTRANT -I/usr/include/glib-2.0 > -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -pthread > -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/gio-unix-2.0 > -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include > -pthread -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/slirp > -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include > -DNCURSES_WIDECHAR=1 -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 > -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include > -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 > -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/harfbuzz > -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/libmount > -I/usr/include/blkid -I/usr/include/fribidi -I/usr/include/cairo > -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2.0 > -I/usr/include/x86_64-linux-gnu -I/usr/include/gio-unix-2.0 > -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 > -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 > -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -pthread -I/usr/include/gtk-3.0 > -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 > -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/harfbuzz > -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/libmount > -I/usr/include/blkid -I/usr/include/fribidi -I/usr/include/cairo > -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2.0 > -I/usr/include/x86_64-linux-gnu -I/usr/include/gio-unix-2.0 > -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 > -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 > -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -pthread > -I/usr/include/vte-2.91 -I/usr/include/glib-2.0 > -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/libmount > -I/usr/include/blkid -I/usr/include/pango-1.0 -I/usr/include/harfbuzz > -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/fribidi > -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/gtk-3.0 > -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/x86_64-linux-gnu > -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 > -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 > -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include > -pthread -I/usr/include/glib-2.0 > -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/spice-server > -I/usr/include/spice-1 -I/usr/include/cacard -I/usr/include/glib-2.0 > -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/nss > -I/usr/include/nspr -I/usr/include/PCSC -pthread -D_REENTRANT > -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT > -I/usr/include/p11-kit-1 -I/usr/include/fuse3 > -I/usr/include/x86_64-linux-gnu -D_FILE_OFFSET_BITS=64 -D__USE_FILE_OFFSET64 > -D__USE_LARGEFILE64 -DUSE_POSIX_ACLS=1 -I/usr/include/uuid > -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include > -I/usr/include/p11-kit-1 -I/usr/include/p11-kit-1 -I/usr/include/p11-kit-1 > -I/usr/include/p11-kit-1 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 > -D_LARGEFILE_SOURCE -I/usr/include/glib-2.0 > -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -std=gnu11 -MD -MQ > ../../rust/wrapper.h -MF wrapper.h.d > > /usr/include/liburing.h:296:3: error: use of undeclared identifier > 'memory_order_release' > > /usr/include/liburing.h:1080:11: error: use of undeclared identifier > 'memory_order_acquire' > > /usr/include/liburing.h:1116:9: error: use of undeclared identifier > 'memory_order_acquire' > > /usr/include/liburing.h:1125:9: error: use of undeclared identifier > 'memory_order_relaxed' > > /usr/include/liburing.h:1161:2: error: use of undeclared identifier > 'memory_order_relaxed' > > /usr/include/liburing.h:1197:19: error: use of undeclared identifier > 'memory_order_acquire' > > /usr/include/liburing.h:1267:10: error: use of undeclared identifier > 'memory_order_relaxed' > > /usr/include/liburing.h:1269:10: error: use of undeclared identifier > 'memory_order_acquire' > > /usr/include/liburing.h:1320:2: error: use of undeclared identifier > 'memory_order_release' > > panicked at > /home/alex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bindgen-cli-0.69.4/main.rs:52:36: > > Unable to generate bindings: > ClangDiagnostic("/usr/include/liburing.h:296:3: error: use of undeclared > identifier 'memory_order_release'\n/usr/include/liburing.h:1080:11: error: > use of undeclared identifier > 'memory_order_acquire'\n/usr/include/liburing.h:1116:9: error: use of > undeclared identifier > 'memory_order_acquire'\n/usr/include/liburing.h:1125:9: error: use of > undeclared identifier > 'memory_order_relaxed'\n/usr/include/liburing.h:1161:2: error: use of > undeclared identifier > 'memory_order_relaxed'\n/usr/include/liburing.h:1197:19: error: use of > undeclared identifier > 'memory_order_acquire'\n/usr/include/liburing.h:1267:10: error: use of > undeclared identifier > 'memory_order_relaxed'\n/usr/include/liburing.h:1269:10: error: use of > undeclared identifier > 'memory_order_acquire'\n/usr/include/liburing.h:1320:2: error: use of > undeclared identifier 'memory_order_release'\n") > > Those missing identifiers should have been defined in stdatomic.h which is part > of C11. You can check if that header exists under the default header search > paths (which is listed by clang -E -Wp,-v -) and whether that file declares > those enum constants. If so, you can further check whether there is any > stdatomic.h elsewhere that shadows the standard one. > > > Indeed. These are in the compiler's own header files. I had problems on Debian > when using clang-14 and clang-15 but I got rid of them after I upgraded to newer > versions. If anyone can confirm/reproduce this we can add a meson warning check? > > I can reproduce the issue after rolling back clang-18 to clang-15, but the issue is not tied to any specific clang version. It happens when the version of newest libclang does not match with the "clang" executable in PATH. The effective header search paths of libclang invoked by bindgen have the following: 1. The default search paths used by the "clang" executable. The clang-sys crate determines which executable to use and collects its default search paths, and bindgen adds them (in the form of "-isystem") to clang args. 2. The default search paths that libclang has. Clang has a version-specific standard header directory (on my Ubuntu it looks like /usr/lib/llvm-15/lib/clang/15.0.7/include). When those versions mismatch, the effective search paths contain two standard header paths, causing stdatomic.h to be included twice without declaring any symbol because clang's stdatomic.h starts with: #ifndef __CLANG_STDATOMIC_H #define __CLANG_STDATOMIC_H #if __STDC_HOSTED__ && \ __has_include_next(<stdatomic.h>) && \ (!defined(_MSC_VER) || (defined(__cplusplus) && __cplusplus >= 202002L)) # include_next <stdatomic.h> #else (symbol declarations ...) Both the clang executable and libclang library are detected by clang-sys at runtime. In my experiments, that crate always find the latest libclang, but doesn't necessarily find the latest clang when there are multiple "clang-X" but not "clang" in the system. How about we try bindgen on a simple header like: #include <libatomic.h> memory_order order; If that fails with unknown type name 'memory_order', suggest the user to symbolic link the latest clang executable as "clang". --- Best Regards Junjie Mao
Junjie Mao <junjie.mao@intel.com> writes: > On 8/28/2024 9:08 PM, Alex Bennée wrote: >> Manos Pitsidianakis <manos.pitsidianakis@linaro.org> writes: >> >>> Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and >>> provides some declaration macros for symbols visible to the rest of >>> QEMU. >> As mentioned on IRC I'm hitting a compilation error that bisects to >> this >> commit: >> [148/1010] Generating bindings for Rust >> rustmod-bindgen-rust_wrapper.h >> FAILED: bindings.rs >> /home/alex/.cargo/bin/bindgen ../../rust/wrapper.h --output >> /home/alex/lsrc/qemu.git/builds/rust/bindings.rs >> --disable-header-comment --raw-line '// @generated' --ctypes-prefix >> core::ffi --formatter rustfmt --generate-block --generate-cstr >> --impl-debug --merge-extern-blocks --no-doc-comments --use-core >> --with-derive-default --allowlist-file >> '/home/alex/lsrc/qemu.git/include/.*' --allowlist-file >> '/home/alex/lsrc/qemu.git/.*' --allowlist-file >> '/home/alex/lsrc/qemu.git/builds/rust/.*' -- >> -I/home/alex/lsrc/qemu.git/. >> -I/home/alex/lsrc/qemu.git/builds/rust/. >> -I/home/alex/lsrc/qemu.git/include >> -I/home/alex/lsrc/qemu.git/builds/rust/include >> -I/usr/include/capstone -I/usr/include/p11-kit-1 >> -I/usr/include/pixman-1 -I/usr/include/libpng16 >> -I/usr/include/spice-server -I/usr/include/spice-1 >> -I/usr/include/spice-1 -DSTRUCT_IOVEC_DEFINED >> -I/usr/include/libusb-1.0 -I/usr/include/SDL2 -D_REENTRANT >> -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include >> -pthread -I/usr/include/libmount -I/usr/include/blkid >> -I/usr/include/gio-unix-2.0 -I/usr/include/glib-2.0 >> -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -pthread >> -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/slirp >> -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include >> -DNCURSES_WIDECHAR=1 -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 >> -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include >> -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 >> -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include >> -I/usr/include/harfbuzz -I/usr/include/freetype2 >> -I/usr/include/libpng16 -I/usr/include/libmount -I/usr/include/blkid >> -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 >> -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/x86_64-linux-gnu >> -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 >> -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 >> -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include >> -pthread -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 >> -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include >> -I/usr/include/harfbuzz -I/usr/include/freetype2 >> -I/usr/include/libpng16 -I/usr/include/libmount -I/usr/include/blkid >> -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 >> -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/x86_64-linux-gnu >> -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 >> -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 >> -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include >> -pthread -I/usr/include/vte-2.91 -I/usr/include/glib-2.0 >> -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/libmount >> -I/usr/include/blkid -I/usr/include/pango-1.0 >> -I/usr/include/harfbuzz -I/usr/include/freetype2 >> -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/cairo >> -I/usr/include/pixman-1 -I/usr/include/gtk-3.0 >> -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/x86_64-linux-gnu >> -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 >> -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 >> -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include >> -pthread -I/usr/include/glib-2.0 >> -I/usr/lib/x86_64-linux-gnu/glib-2.0/include >> -I/usr/include/spice-server -I/usr/include/spice-1 >> -I/usr/include/cacard -I/usr/include/glib-2.0 >> -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/nss >> -I/usr/include/nspr -I/usr/include/PCSC -pthread -D_REENTRANT >> -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT >> -I/usr/include/p11-kit-1 -I/usr/include/fuse3 >> -I/usr/include/x86_64-linux-gnu -D_FILE_OFFSET_BITS=64 >> -D__USE_FILE_OFFSET64 -D__USE_LARGEFILE64 -DUSE_POSIX_ACLS=1 >> -I/usr/include/uuid -I/usr/include/glib-2.0 >> -I/usr/lib/x86_64-linux-gnu/glib-2.0/include >> -I/usr/include/p11-kit-1 -I/usr/include/p11-kit-1 >> -I/usr/include/p11-kit-1 -I/usr/include/p11-kit-1 -D_GNU_SOURCE >> -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -I/usr/include/glib-2.0 >> -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -std=gnu11 -MD -MQ >> ../../rust/wrapper.h -MF wrapper.h.d >> /usr/include/liburing.h:296:3: error: use of undeclared identifier 'memory_order_release' >> /usr/include/liburing.h:1080:11: error: use of undeclared identifier 'memory_order_acquire' >> /usr/include/liburing.h:1116:9: error: use of undeclared identifier 'memory_order_acquire' >> /usr/include/liburing.h:1125:9: error: use of undeclared identifier 'memory_order_relaxed' >> /usr/include/liburing.h:1161:2: error: use of undeclared identifier 'memory_order_relaxed' >> /usr/include/liburing.h:1197:19: error: use of undeclared identifier 'memory_order_acquire' >> /usr/include/liburing.h:1267:10: error: use of undeclared identifier 'memory_order_relaxed' >> /usr/include/liburing.h:1269:10: error: use of undeclared identifier 'memory_order_acquire' >> /usr/include/liburing.h:1320:2: error: use of undeclared identifier 'memory_order_release' >> panicked at /home/alex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bindgen-cli-0.69.4/main.rs:52:36: >> Unable to generate bindings: >> ClangDiagnostic("/usr/include/liburing.h:296:3: error: use of >> undeclared identifier >> 'memory_order_release'\n/usr/include/liburing.h:1080:11: error: use >> of undeclared identifier >> 'memory_order_acquire'\n/usr/include/liburing.h:1116:9: error: use >> of undeclared identifier >> 'memory_order_acquire'\n/usr/include/liburing.h:1125:9: error: use >> of undeclared identifier >> 'memory_order_relaxed'\n/usr/include/liburing.h:1161:2: error: use >> of undeclared identifier >> 'memory_order_relaxed'\n/usr/include/liburing.h:1197:19: error: use >> of undeclared identifier >> 'memory_order_acquire'\n/usr/include/liburing.h:1267:10: error: use >> of undeclared identifier >> 'memory_order_relaxed'\n/usr/include/liburing.h:1269:10: error: use >> of undeclared identifier >> 'memory_order_acquire'\n/usr/include/liburing.h:1320:2: error: use >> of undeclared identifier 'memory_order_release'\n") > > Those missing identifiers should have been defined in stdatomic.h > which is part of C11. You can check if that header exists under the > default header search paths (which is listed by clang -E -Wp,-v -) and > whether that file declares those enum constants. If so, you can > further check whether there is any stdatomic.h elsewhere that shadows > the standard one. It is there: /usr/lib/llvm-14/lib/clang/14.0.6/include/stdatomic.h in the search path: clang -E -Wp,-v - clang -cc1 version 14.0.6 based upon LLVM 14.0.6 default target x86_64-pc-linux-gnu ignoring nonexistent directory "/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include" ignoring nonexistent directory "/include" #include "..." search starts here: #include <...> search starts here: /usr/lib/llvm-14/lib/clang/14.0.6/include /usr/local/include /usr/include/x86_64-linux-gnu /usr/include End of search list. but not in the list above. Have we told clang not to include system search paths in the bindgen invocation?
On Fri, 30 Aug 2024 14:03, Alex Bennée <alex.bennee@linaro.org> wrote: [.snip.] > >It is there: > > /usr/lib/llvm-14/lib/clang/14.0.6/include/stdatomic.h > >in the search path: > > clang -E -Wp,-v - > clang -cc1 version 14.0.6 based upon LLVM 14.0.6 default target x86_64-pc-linux-gnu > ignoring nonexistent directory "/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include" > ignoring nonexistent directory "/include" > #include "..." search starts here: > #include <...> search starts here: > /usr/lib/llvm-14/lib/clang/14.0.6/include > /usr/local/include > /usr/include/x86_64-linux-gnu > /usr/include > End of search list. > >but not in the list above. Have we told clang not to include system >search paths in the bindgen invocation? stdatomic.h was first included in c11, and compilers already shipped the header on their own (since they use builtin operations). The compiler header paths are considered special system header paths by compilers, and what's happening here is a bug in the manual searching logic in libclang like explained in the other replies. The bindgen invocation looks at system search paths otherwise, or it'd fail to find headers used in QEMU.
On 8/31/2024 4:25 PM, Manos Pitsidianakis wrote: > On Fri, 30 Aug 2024 14:03, Alex Bennée <alex.bennee@linaro.org> wrote: > [.snip.] >> >> It is there: >> >> /usr/lib/llvm-14/lib/clang/14.0.6/include/stdatomic.h >> >> in the search path: >> >> clang -E -Wp,-v - >> clang -cc1 version 14.0.6 based upon LLVM 14.0.6 default target >> x86_64-pc-linux-gnu >> ignoring nonexistent directory >> "/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include" >> ignoring nonexistent directory "/include" >> #include "..." search starts here: >> #include <...> search starts here: >> /usr/lib/llvm-14/lib/clang/14.0.6/include >> /usr/local/include >> /usr/include/x86_64-linux-gnu >> /usr/include >> End of search list. >> >> but not in the list above. Have we told clang not to include system >> search paths in the bindgen invocation? > > stdatomic.h was first included in c11, and compilers already shipped the header > on their own (since they use builtin operations). The compiler header paths are > considered special system header paths by compilers, and what's happening here > is a bug in the manual searching logic in libclang like explained in the other Do you mean the manual searching logic in the *clang-sys* crate? There is also a related issue [1] on GitHub. [1] https://github.com/rust-lang/rust-bindgen/issues/2682 > replies. The bindgen invocation looks at system search paths otherwise, or it'd > fail to find headers used in QEMU. Another approach to work around that issue is to define BOTH CLANG_PATH and LIBCLANG_PATH env vars, e.g., CLANG_PATH=/usr/bin/clang-13 LIBCLANG_PATH=/lib/x86_64-linux-gnu/libclang-13.so. That works in my environment. The following is a draft to do it in meson.build. It does NOT work yet as bindgen() does not allow customizing environment variables. I'm checking how to make it in meson. diff --git a/meson.build b/meson.build index 68d5b53684..1f6fc21f8d 100644 --- a/meson.build +++ b/meson.build @@ -3879,6 +3879,30 @@ if have_rust and have_system capture : true, check: true).stdout().strip().split() + host_clang = find_program( + 'clang', version: '>=5.0.0', + required: true, native: true) + host_libclang = run_command( + host_clang, + '-print-file-name=libclang.so', + capture: true, + check: true).stdout().strip() + # Clang prints an absolute path when the library is found + if not host_libclang.startswith('/') + host_clang_major = host_clang.version().split('.')[0] + host_libclang = run_command( + host_clang, + '-print-file-name=libclang-' + host_clang_major + '.so', + capture: true, + check: true).stdout().strip() + endif + if not host_libclang.startswith('/') + error('Cannot find libclang.so for ' + host_clang.full_path()) + endif + message('Found libclang: ' + host_libclang) + + # TODO: set CLANG_PATH to host_clang.full_path() and LIBCLANG_PATH to + # host_libclang when invoking bindgen bindings_rs = import('rust').bindgen( input: 'rust/wrapper.h', dependencies: common_ss.all_dependencies(),
On Wed, Aug 28, 2024 at 6:12 AM Manos Pitsidianakis <manos.pitsidianakis@linaro.org> wrote: > > Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and > provides some declaration macros for symbols visible to the rest of > QEMU. The only comment I have is that I would drop the allocator support completely. It adds complications and, at least initially, we can plan/hope that all cross-language allocations go through a constructor function like error_setg() or object_new(). In the case of QOM, if we wanted to allocate objects in a Box rather than malloc-ed memory, we could also put in the object a free function that calls mem::drop(Box::from_raw(p)) Fixing rust.bindgen() to use the right CLANG_PATH/LIBCLANG_PATH should probably be done in meson itself. The (not too hard) alternative is to just use a custom_target. Paolo
On 9/4/2024 7:01 PM, Paolo Bonzini wrote: > On Wed, Aug 28, 2024 at 6:12 AM Manos Pitsidianakis > <manos.pitsidianakis@linaro.org> wrote: >> >> Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and >> provides some declaration macros for symbols visible to the rest of >> QEMU. > > The only comment I have is that I would drop the allocator support > completely. It adds complications and, at least initially, we can > plan/hope that all cross-language allocations go through a constructor > function like error_setg() or object_new(). > > In the case of QOM, if we wanted to allocate objects in a Box rather > than malloc-ed memory, we could also put in the object a free function > that calls > > mem::drop(Box::from_raw(p)) > > Fixing rust.bindgen() to use the right CLANG_PATH/LIBCLANG_PATH should > probably be done in meson itself. The (not too hard) alternative is to > just use a custom_target. To unblock this series at the moment a custom_target() is the only way. Fixes to either meson or clang-sys crate will take some time before they are available in a public release. The ideal fix to me is that clang-sys always find clang and libclang of the same version. I can take a look at that crate and think about how that can be done. Meanwhile, I opened a PR [1] to discuss this with the meson community. The PR itself adds the env argument to rust.bindgen(), but as you suggested meson can do more, e.g., when given a native clang executable, meson can search for the corresponding libclang and sets CLANG_PATH/LIBCLANG_PATH accordingly. I'll keep collecting their feedback and refining the changes in that PR. [1] https://github.com/mesonbuild/meson/pull/13631 > > Paolo >
On Wed, 04 Sep 2024 14:01, Paolo Bonzini <pbonzini@redhat.com> wrote: >On Wed, Aug 28, 2024 at 6:12 AM Manos Pitsidianakis ><manos.pitsidianakis@linaro.org> wrote: >> >> Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and >> provides some declaration macros for symbols visible to the rest of >> QEMU. > >The only comment I have is that I would drop the allocator support >completely. It adds complications and, at least initially, we can >plan/hope that all cross-language allocations go through a constructor >function like error_setg() or object_new(). > >In the case of QOM, if we wanted to allocate objects in a Box rather >than malloc-ed memory, we could also put in the object a free function >that calls > > mem::drop(Box::from_raw(p)) > >Fixing rust.bindgen() to use the right CLANG_PATH/LIBCLANG_PATH should >probably be done in meson itself. The (not too hard) alternative is to >just use a custom_target. Can we get the include directories of common_ss.all_dependencies() for a custom_target? Meson does this: for de in kwargs['dependencies']: for i in de.get_include_dirs(): clang_args.extend([f'-I{x}' for x in i.to_string_list( state.environment.get_source_dir(), state.environment.get_build_dir())]) clang_args.extend(de.get_all_compile_args()) for s in de.get_sources(): if isinstance(s, File): depend_files.append(s) elif isinstance(s, CustomTarget): depends.append(s) But I think the functionality to extract this info from dep objects is not exposed to meson.build files.
On Mon, Sep 2, 2024 at 7:59 AM Junjie Mao <junjie.mao@intel.com> wrote:
> + '-print-file-name=libclang-' + host_clang_major + '.so',
Note that libclang-MAJOR.so is a Debian-ism. On Fedora for example I
have libclang.so.MAJOR.MINOR instead.
Overall, this is a pain and I'd rather leave it to Meson developers to
fix it. Until then, you'll have to make sure your clang/libclang
versions match, or pass CLANG_PATH/LIBCLANG_PATH.
Paolo
diff --git a/MAINTAINERS b/MAINTAINERS index 642c07a9ff2ed2422ac50d1419751f92f81690bd..d35e9f6b20bb23c7580de488ebaabc6c031343d2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3348,6 +3348,12 @@ F: hw/core/register.c F: include/hw/register.h F: include/hw/registerfields.h +Rust +M: Manos Pitsidianakis <manos.pitsidianakis@linaro.org> +S: Maintained +F: rust/qemu-api +F: rust/rustfmt.toml + SLIRP M: Samuel Thibault <samuel.thibault@ens-lyon.org> S: Maintained diff --git a/rust/meson.build b/rust/meson.build index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4a58d106b1dd1d7bee39dd129f57ddb5a95bd9b7 100644 --- a/rust/meson.build +++ b/rust/meson.build @@ -0,0 +1 @@ +subdir('qemu-api') diff --git a/rust/qemu-api/.gitignore b/rust/qemu-api/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b9e7e004c867bd1b5d44e69634d78fdafbfc1306 --- /dev/null +++ b/rust/qemu-api/.gitignore @@ -0,0 +1,2 @@ +# Ignore generated bindings file overrides. +src/bindings.rs diff --git a/rust/qemu-api/Cargo.lock b/rust/qemu-api/Cargo.lock new file mode 100644 index 0000000000000000000000000000000000000000..e9c51a243a85499cfa3ce2f9da225184ddf05d24 --- /dev/null +++ b/rust/qemu-api/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "qemu_api" +version = "0.1.0" diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..efc369e5ae926fd5c63e38a68e621ff3ad3b6e3b --- /dev/null +++ b/rust/qemu-api/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "qemu_api" +version = "0.1.0" +edition = "2021" +authors = ["Manos Pitsidianakis <manos.pitsidianakis@linaro.org>"] +license = "GPL-2.0-or-later" +readme = "README.md" +homepage = "https://www.qemu.org" +description = "Rust bindings for QEMU" +repository = "https://gitlab.com/qemu-project/qemu/" +resolver = "2" +publish = false +keywords = [] +categories = [] + +[dependencies] + +[features] +default = ["allocator"] +allocator = [] + +# Do not include in any global workspace +[workspace] + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(MESON)', 'cfg(HAVE_GLIB_WITH_ALIGNED_ALLOC)'] } diff --git a/rust/qemu-api/README.md b/rust/qemu-api/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7588fa29ef37e29d424fc7c333ea1c9c6139181b --- /dev/null +++ b/rust/qemu-api/README.md @@ -0,0 +1,17 @@ +# QEMU bindings and API wrappers + +This library exports helper Rust types, Rust macros and C FFI bindings for internal QEMU APIs. + +The C bindings can be generated with `bindgen`, using this build target: + +```console +$ ninja bindings.rs +``` + +## Generate Rust documentation + +To generate docs for this crate, including private items: + +```sh +cargo doc --no-deps --document-private-items +``` diff --git a/rust/qemu-api/build.rs b/rust/qemu-api/build.rs new file mode 100644 index 0000000000000000000000000000000000000000..419b154c2d267a4b067b66f17b882bed0e65493a --- /dev/null +++ b/rust/qemu-api/build.rs @@ -0,0 +1,14 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> +// SPDX-License-Identifier: GPL-2.0-or-later + +use std::path::Path; + +fn main() { + if !Path::new("src/bindings.rs").exists() { + panic!( + "No generated C bindings found! Either build them manually with bindgen or with meson \ + (`ninja bindings.rs`) and copy them to src/bindings.rs, or build through meson." + ); + } +} diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..cf2b465e9f7cc7fb10af0d3aac469b58211cd64e --- /dev/null +++ b/rust/qemu-api/meson.build @@ -0,0 +1,21 @@ +_qemu_api_rs = static_library( + 'qemu_api', + structured_sources( + [ + 'src/lib.rs', + 'src/definitions.rs', + 'src/device_class.rs', + ], + {'.' : bindings_rs}, + ), + override_options: ['rust_std=2021', 'build.rust_std=2021'], + rust_abi: 'rust', + rust_args: rustc_config_args + [ + '--cfg', 'MESON', + '--cfg', 'feature="allocator"', + ], +) + +qemu_api = declare_dependency( + link_with: _qemu_api_rs, +) diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/definitions.rs new file mode 100644 index 0000000000000000000000000000000000000000..4abd0253bd1ff4f3f2e11528329709ef54a43c24 --- /dev/null +++ b/rust/qemu-api/src/definitions.rs @@ -0,0 +1,109 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> +// SPDX-License-Identifier: GPL-2.0-or-later + +//! Definitions required by QEMU when registering a device. + +/// Trait a type must implement to be registered with QEMU. +pub trait ObjectImpl { + type Class; + const TYPE_INFO: crate::bindings::TypeInfo; + const TYPE_NAME: &'static ::core::ffi::CStr; + const PARENT_TYPE_NAME: Option<&'static ::core::ffi::CStr>; + const INSTANCE_INIT: ::core::option::Option< + unsafe extern "C" fn(obj: *mut crate::bindings::Object), + >; + const INSTANCE_POST_INIT: ::core::option::Option< + unsafe extern "C" fn(obj: *mut crate::bindings::Object), + >; + const INSTANCE_FINALIZE: ::core::option::Option< + unsafe extern "C" fn(obj: *mut crate::bindings::Object), + >; + const ABSTRACT: bool; +} + +pub trait Class { + const CLASS_INIT: ::core::option::Option< + unsafe extern "C" fn( + klass: *mut crate::bindings::ObjectClass, + data: *mut core::ffi::c_void, + ), + >; + const CLASS_BASE_INIT: ::core::option::Option< + unsafe extern "C" fn( + klass: *mut crate::bindings::ObjectClass, + data: *mut core::ffi::c_void, + ), + >; +} + +#[macro_export] +macro_rules! module_init { + ($func:expr, $type:expr) => { + #[used] + #[cfg_attr(target_os = "linux", link_section = ".ctors")] + #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")] + #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")] + pub static LOAD_MODULE: extern "C" fn() = { + assert!($type < $crate::bindings::module_init_type_MODULE_INIT_MAX); + + extern "C" fn __load() { + unsafe { + $crate::bindings::register_module_init(Some($func), $type); + } + } + + __load + }; + }; + (qom: $func:ident => $body:block) => { + // NOTE: To have custom identifiers for the ctor func we need to either supply + // them directly as a macro argument or create them with a proc macro. + #[used] + #[cfg_attr(target_os = "linux", link_section = ".ctors")] + #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")] + #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")] + pub static LOAD_MODULE: extern "C" fn() = { + extern "C" fn __load() { + #[no_mangle] + unsafe extern "C" fn $func() { + $body + } + + unsafe { + $crate::bindings::register_module_init( + Some($func), + $crate::bindings::module_init_type_MODULE_INIT_QOM, + ); + } + } + + __load + }; + }; +} + +#[macro_export] +macro_rules! type_info { + ($t:ty) => { + $crate::bindings::TypeInfo { + name: <$t as $crate::definitions::ObjectImpl>::TYPE_NAME.as_ptr(), + parent: if let Some(pname) = <$t as $crate::definitions::ObjectImpl>::PARENT_TYPE_NAME { + pname.as_ptr() + } else { + ::core::ptr::null_mut() + }, + instance_size: ::core::mem::size_of::<$t>(), + instance_align: ::core::mem::align_of::<$t>(), + instance_init: <$t as $crate::definitions::ObjectImpl>::INSTANCE_INIT, + instance_post_init: <$t as $crate::definitions::ObjectImpl>::INSTANCE_POST_INIT, + instance_finalize: <$t as $crate::definitions::ObjectImpl>::INSTANCE_FINALIZE, + abstract_: <$t as $crate::definitions::ObjectImpl>::ABSTRACT, + class_size: ::core::mem::size_of::<<$t as $crate::definitions::ObjectImpl>::Class>(), + class_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::Class>::CLASS_INIT, + class_base_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::Class>::CLASS_BASE_INIT, + class_data: ::core::ptr::null_mut(), + interfaces: ::core::ptr::null_mut(), + }; + } +} diff --git a/rust/qemu-api/src/device_class.rs b/rust/qemu-api/src/device_class.rs new file mode 100644 index 0000000000000000000000000000000000000000..69ee912c333c3dce8bc127a286acaadd57ca20b3 --- /dev/null +++ b/rust/qemu-api/src/device_class.rs @@ -0,0 +1,128 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> +// SPDX-License-Identifier: GPL-2.0-or-later + +use std::sync::OnceLock; + +use crate::bindings::Property; + +#[macro_export] +macro_rules! device_class_init { + ($func:ident, props => $props:ident, realize_fn => $realize_fn:expr, reset_fn => $reset_fn:expr, vmsd => $vmsd:ident$(,)*) => { + #[no_mangle] + pub unsafe extern "C" fn $func( + klass: *mut $crate::bindings::ObjectClass, + _: *mut ::core::ffi::c_void, + ) { + let mut dc = + ::core::ptr::NonNull::new(klass.cast::<$crate::bindings::DeviceClass>()).unwrap(); + dc.as_mut().realize = $realize_fn; + dc.as_mut().reset = $reset_fn; + dc.as_mut().vmsd = &$vmsd; + $crate::bindings::device_class_set_props(dc.as_mut(), $props.as_mut_ptr()); + } + }; +} + +#[macro_export] +macro_rules! define_property { + ($name:expr, $state:ty, $field:expr, $prop:expr, $type:expr, default = $defval:expr$(,)*) => { + $crate::bindings::Property { + name: { + #[used] + static _TEMP: &::core::ffi::CStr = $name; + _TEMP.as_ptr() + }, + info: $prop, + offset: ::core::mem::offset_of!($state, $field) + .try_into() + .expect("Could not fit offset value to type"), + bitnr: 0, + bitmask: 0, + set_default: true, + defval: $crate::bindings::Property__bindgen_ty_1 { u: $defval.into() }, + arrayoffset: 0, + arrayinfo: ::core::ptr::null(), + arrayfieldsize: 0, + link_type: ::core::ptr::null(), + } + }; + ($name:expr, $state:ty, $field:expr, $prop:expr, $type:expr$(,)*) => { + $crate::bindings::Property { + name: { + #[used] + static _TEMP: &::core::ffi::CStr = $name; + _TEMP.as_ptr() + }, + info: $prop, + offset: ::core::mem::offset_of!($state, $field) + .try_into() + .expect("Could not fit offset value to type"), + bitnr: 0, + bitmask: 0, + set_default: false, + defval: $crate::bindings::Property__bindgen_ty_1 { i: 0 }, + arrayoffset: 0, + arrayinfo: ::core::ptr::null(), + arrayfieldsize: 0, + link_type: ::core::ptr::null(), + } + }; +} + +#[repr(C)] +pub struct Properties<const N: usize>(pub OnceLock<[Property; N]>, pub fn() -> [Property; N]); + +impl<const N: usize> Properties<N> { + pub fn as_mut_ptr(&mut self) -> *mut Property { + _ = self.0.get_or_init(self.1); + self.0.get_mut().unwrap().as_mut_ptr() + } +} + +#[macro_export] +macro_rules! declare_properties { + ($ident:ident, $($prop:expr),*$(,)*) => { + + const fn _calc_prop_len() -> usize { + let mut len = 1; + $({ + _ = stringify!($prop); + len += 1; + })* + len + } + const PROP_LEN: usize = _calc_prop_len(); + + fn _make_properties() -> [$crate::bindings::Property; PROP_LEN] { + [ + $($prop),*, + unsafe { ::core::mem::MaybeUninit::<$crate::bindings::Property>::zeroed().assume_init() }, + ] + } + + #[no_mangle] + pub static mut $ident: $crate::device_class::Properties<PROP_LEN> = $crate::device_class::Properties(::std::sync::OnceLock::new(), _make_properties); + }; +} + +#[macro_export] +macro_rules! vm_state_description { + ($(#[$outer:meta])* + $name:ident, + $(name: $vname:expr,)* + $(unmigratable: $um_val:expr,)* + ) => { + #[used] + $(#[$outer])* + pub static $name: $crate::bindings::VMStateDescription = $crate::bindings::VMStateDescription { + $(name: { + #[used] + static VMSTATE_NAME: &::core::ffi::CStr = $vname; + $vname.as_ptr() + },)* + unmigratable: true, + ..unsafe { ::core::mem::MaybeUninit::<$crate::bindings::VMStateDescription>::zeroed().assume_init() } + }; + } +} diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..26637024907dc23d5ca81a8ce21cd9c307c022ea --- /dev/null +++ b/rust/qemu-api/src/lib.rs @@ -0,0 +1,154 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> +// SPDX-License-Identifier: GPL-2.0-or-later + +#![cfg_attr(not(MESON), doc = include_str!("../README.md"))] + +#[allow( + dead_code, + improper_ctypes_definitions, + improper_ctypes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + clippy::missing_const_for_fn, + clippy::too_many_arguments, + clippy::approx_constant, + clippy::use_self, + clippy::useless_transmute, + clippy::missing_safety_doc, +)] +#[rustfmt::skip] +pub mod bindings; + +unsafe impl Send for bindings::Property {} +unsafe impl Sync for bindings::Property {} +unsafe impl Sync for bindings::TypeInfo {} +unsafe impl Sync for bindings::VMStateDescription {} + +pub mod definitions; +pub mod device_class; + +#[cfg(test)] +mod tests; + +use std::alloc::{GlobalAlloc, Layout}; + +#[cfg(HAVE_GLIB_WITH_ALIGNED_ALLOC)] +extern "C" { + fn g_aligned_alloc0( + n_blocks: bindings::gsize, + n_block_bytes: bindings::gsize, + alignment: bindings::gsize, + ) -> bindings::gpointer; + fn g_aligned_free(mem: bindings::gpointer); +} + +#[cfg(not(HAVE_GLIB_WITH_ALIGNED_ALLOC))] +extern "C" { + fn qemu_memalign(alignment: usize, size: usize) -> *mut ::core::ffi::c_void; + fn qemu_vfree(ptr: *mut ::core::ffi::c_void); +} + +extern "C" { + fn g_malloc0(n_bytes: bindings::gsize) -> bindings::gpointer; + fn g_free(mem: bindings::gpointer); +} + +/// An allocator that uses the same allocator as QEMU in C. +/// +/// It is enabled by default with the `allocator` feature. +/// +/// To set it up manually as a global allocator in your crate: +/// +/// ```ignore +/// use qemu_api::QemuAllocator; +/// +/// #[global_allocator] +/// static GLOBAL: QemuAllocator = QemuAllocator::new(); +/// ``` +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct QemuAllocator { + _unused: [u8; 0], +} + +#[cfg_attr(all(feature = "allocator", not(test)), global_allocator)] +pub static GLOBAL: QemuAllocator = QemuAllocator::new(); + +impl QemuAllocator { + // From the glibc documentation, on GNU systems, malloc guarantees 16-byte + // alignment on 64-bit systems and 8-byte alignment on 32-bit systems. See + // https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html. + // This alignment guarantee also applies to Windows and Android. On Darwin + // and OpenBSD, the alignment is 16 bytes on both 64-bit and 32-bit systems. + #[cfg(all( + target_pointer_width = "32", + not(any(target_os = "macos", target_os = "openbsd")) + ))] + pub const DEFAULT_ALIGNMENT_BYTES: Option<usize> = Some(8); + #[cfg(all( + target_pointer_width = "64", + not(any(target_os = "macos", target_os = "openbsd")) + ))] + pub const DEFAULT_ALIGNMENT_BYTES: Option<usize> = Some(16); + #[cfg(all( + any(target_pointer_width = "32", target_pointer_width = "64"), + any(target_os = "macos", target_os = "openbsd") + ))] + pub const DEFAULT_ALIGNMENT_BYTES: Option<usize> = Some(16); + #[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))] + pub const DEFAULT_ALIGNMENT_BYTES: Option<usize> = None; + + pub const fn new() -> Self { + Self { _unused: [] } + } +} + +impl Default for QemuAllocator { + fn default() -> Self { + Self::new() + } +} + +// Sanity check. +const _: [(); 8] = [(); ::core::mem::size_of::<*mut ::core::ffi::c_void>()]; + +unsafe impl GlobalAlloc for QemuAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + if matches!(Self::DEFAULT_ALIGNMENT_BYTES, Some(default) if default.checked_rem(layout.align()) == Some(0)) + { + g_malloc0(layout.size().try_into().unwrap()).cast::<u8>() + } else { + #[cfg(HAVE_GLIB_WITH_ALIGNED_ALLOC)] + { + g_aligned_alloc0( + layout.size().try_into().unwrap(), + 1, + (8 * layout.align()).try_into().unwrap(), + ) + .cast::<u8>() + } + #[cfg(not(HAVE_GLIB_WITH_ALIGNED_ALLOC))] + { + qemu_memalign(8 * layout.align(), layout.size()).cast::<u8>() + } + } + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + if matches!(Self::DEFAULT_ALIGNMENT_BYTES, Some(default) if default.checked_rem(layout.align()) == Some(0)) + { + g_free(ptr.cast::<_>()) + } else { + #[cfg(HAVE_GLIB_WITH_ALIGNED_ALLOC)] + { + g_aligned_free(ptr.cast::<_>()) + } + #[cfg(not(HAVE_GLIB_WITH_ALIGNED_ALLOC))] + { + qemu_vfree(ptr.cast::<_>()) + } + } + } +} diff --git a/rust/qemu-api/src/tests.rs b/rust/qemu-api/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..df54edbd4e27e7d2aafc243355d1826d52497c21 --- /dev/null +++ b/rust/qemu-api/src/tests.rs @@ -0,0 +1,49 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> +// SPDX-License-Identifier: GPL-2.0-or-later + +use crate::{ + bindings::*, declare_properties, define_property, device_class_init, vm_state_description, +}; + +#[test] +fn test_device_decl_macros() { + // Test that macros can compile. + vm_state_description! { + VMSTATE, + name: c"name", + unmigratable: true, + } + + #[repr(C)] + pub struct DummyState { + pub char_backend: CharBackend, + pub migrate_clock: bool, + } + + declare_properties! { + DUMMY_PROPERTIES, + define_property!( + c"chardev", + DummyState, + char_backend, + unsafe { &qdev_prop_chr }, + CharBackend + ), + define_property!( + c"migrate-clk", + DummyState, + migrate_clock, + unsafe { &qdev_prop_bool }, + bool + ), + } + + device_class_init! { + dummy_class_init, + props => DUMMY_PROPERTIES, + realize_fn => None, + reset_fn => None, + vmsd => VMSTATE, + } +} diff --git a/rust/rustfmt.toml b/rust/rustfmt.toml new file mode 100644 index 0000000000000000000000000000000000000000..ebecb99fe09e010d66c06b324f43d77b8ee00ea9 --- /dev/null +++ b/rust/rustfmt.toml @@ -0,0 +1,7 @@ +edition = "2021" +format_generated_files = false +format_code_in_doc_comments = true +format_strings = true +imports_granularity = "Crate" +group_imports = "StdExternalCrate" +wrap_comments = true