* [PATCH for-10.2 0/2] meson: let Meson handle mixed-language linking of Rust and C objects
@ 2025-08-11 16:17 Paolo Bonzini
2025-08-11 16:17 ` [PATCH 1/2] rust: do not link C libraries into Rust rlibs Paolo Bonzini
2025-08-11 16:17 ` [PATCH 2/2] meson: let Meson handle mixed-language linking of Rust and C objects Paolo Bonzini
0 siblings, 2 replies; 3+ messages in thread
From: Paolo Bonzini @ 2025-08-11 16:17 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, manos.pitsidianakis
One of the pending issues with Rust's build system integration is
the bloated executables caused by the use of staticlibs.
For an example of what this means, see the following test:
hello.c:
extern void hello(void);
int main(void)
{
hello();
}
hello.rs:
#![no_main]
#[no_mangle]
extern "C" fn hello() {
println!("hello world");
}
staticlib + gcc:
$ rustc -Copt-level=2 --crate-type=staticlib hello.rs --emit link=libhello.a
$ gcc hello.c -lhello -O2
$ size ./a.out
text data bss dec hex filename
917435 39593 352 957380 e9bc4 ./a.out
rustc + static libstd:
$ gcc -c -o hello.o hello.c -O2
$ rustc hello.rs -Clink-arg=hello.o
$ size ./hello
text data bss dec hex filename
322684 14464 590 337738 5274a ./hello
rustc + dynamic libstd:
$ gcc -c -o hello.o hello.c -O2
$ rustc hello.rs -Clink-arg=-Wl,-R$(rustc --print target-libdir) -Clink-arg=hello.o -Cprefer-dynamic
$ size ./hello
text data bss dec hex filename
1809 600 993 3402 d4a ./hello
The second and third methods will be supported by Meson 1.9.0
(https://mesonbuild.com/Release-notes-for-1-9-0.html). Modify the final
link pass to use a Rust source file directly, instead of going through
a staticlib, when the target includes Rust crates; Meson will then do
the right thing automatically.
Paolo
Paolo Bonzini (2):
rust: do not link C libraries into Rust rlibs
meson: let Meson handle mixed-language linking of Rust and C objects
meson.build | 19 ++++++++-----------
rust/hw/char/pl011/meson.build | 2 +-
rust/hw/timer/hpet/meson.build | 2 +-
rust/meson.build | 2 --
rust/qemu-api/meson.build | 15 +++++++++------
scripts/rust/rust_root_crate.sh | 1 +
6 files changed, 20 insertions(+), 21 deletions(-)
--
2.50.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/2] rust: do not link C libraries into Rust rlibs
2025-08-11 16:17 [PATCH for-10.2 0/2] meson: let Meson handle mixed-language linking of Rust and C objects Paolo Bonzini
@ 2025-08-11 16:17 ` Paolo Bonzini
2025-08-11 16:17 ` [PATCH 2/2] meson: let Meson handle mixed-language linking of Rust and C objects Paolo Bonzini
1 sibling, 0 replies; 3+ messages in thread
From: Paolo Bonzini @ 2025-08-11 16:17 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, manos.pitsidianakis
When a C library is linked into a Rust rlib, rustc remembers the dependency
into the metadata and adds the library to the linker command line.
Unfortunately, static libraries are sensitive to their position on the
command line and rustc does not always get it right.
Meson could work around it itself by never adding these static libraries
to the rlibs (after all, Meson tracks the transitive dependencies already
and knows how to add them to dependents of those rlibs); at least for now,
do it in QEMU: never link C libraries into Rust rlibs, and add them to the
final build products only.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
rust/hw/char/pl011/meson.build | 2 +-
rust/hw/timer/hpet/meson.build | 2 +-
rust/meson.build | 2 --
rust/qemu-api/meson.build | 15 +++++++++------
4 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/rust/hw/char/pl011/meson.build b/rust/hw/char/pl011/meson.build
index 2a1be329abc..16acf12f7cc 100644
--- a/rust/hw/char/pl011/meson.build
+++ b/rust/hw/char/pl011/meson.build
@@ -7,7 +7,7 @@ _libpl011_rs = static_library(
bilge_rs,
bilge_impl_rs,
bits_rs,
- qemu_api,
+ qemu_api_rs,
qemu_api_macros,
],
)
diff --git a/rust/hw/timer/hpet/meson.build b/rust/hw/timer/hpet/meson.build
index c2d7c0532ca..64195410a3e 100644
--- a/rust/hw/timer/hpet/meson.build
+++ b/rust/hw/timer/hpet/meson.build
@@ -4,7 +4,7 @@ _libhpet_rs = static_library(
override_options: ['rust_std=2021', 'build.rust_std=2021'],
rust_abi: 'rust',
dependencies: [
- qemu_api,
+ qemu_api_rs,
qemu_api_macros,
],
)
diff --git a/rust/meson.build b/rust/meson.build
index 331f11b7e72..45936a0a731 100644
--- a/rust/meson.build
+++ b/rust/meson.build
@@ -18,8 +18,6 @@ quote_rs_native = dependency('quote-1-rs', native: true)
syn_rs_native = dependency('syn-2-rs', native: true)
proc_macro2_rs_native = dependency('proc-macro2-1-rs', native: true)
-qemuutil_rs = qemuutil.partial_dependency(link_args: true, links: true)
-
genrs = []
subdir('qemu-api-macros')
diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build
index a090297c458..88875e723d8 100644
--- a/rust/qemu-api/meson.build
+++ b/rust/qemu-api/meson.build
@@ -79,15 +79,18 @@ _qemu_api_rs = static_library(
override_options: ['rust_std=2021', 'build.rust_std=2021'],
rust_abi: 'rust',
rust_args: _qemu_api_cfg,
- dependencies: [anyhow_rs, foreign_rs, libc_rs, qemu_api_macros, qemuutil_rs,
- qom, hwcore, chardev, migration],
+ # Cannot add qemuutil here; rustc adds it too early to the linker command line.
+ # Instead, we add it and all C static libraries to the executables only.
+ dependencies: [anyhow_rs, foreign_rs, libc_rs, qemu_api_macros],
)
-rust.test('rust-qemu-api-tests', _qemu_api_rs,
- suite: ['unit', 'rust'])
-
+qemu_api_rs = declare_dependency(link_with: _qemu_api_rs)
qemu_api = declare_dependency(link_with: [_qemu_api_rs],
- dependencies: [qemu_api_macros, qom, hwcore, chardev, migration])
+ dependencies: [qemu_api_macros, qom, hwcore, chardev, migration, qemuutil])
+
+rust.test('rust-qemu-api-tests', _qemu_api_rs,
+ suite: ['unit', 'rust'],
+ dependencies: [qemu_api_macros, qom, hwcore, chardev, migration, qemuutil])
# Doctests are essentially integration tests, so they need the same dependencies.
# Note that running them requires the object files for C code, so place them
--
2.50.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] meson: let Meson handle mixed-language linking of Rust and C objects
2025-08-11 16:17 [PATCH for-10.2 0/2] meson: let Meson handle mixed-language linking of Rust and C objects Paolo Bonzini
2025-08-11 16:17 ` [PATCH 1/2] rust: do not link C libraries into Rust rlibs Paolo Bonzini
@ 2025-08-11 16:17 ` Paolo Bonzini
1 sibling, 0 replies; 3+ messages in thread
From: Paolo Bonzini @ 2025-08-11 16:17 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, manos.pitsidianakis
Meson 1.9.0 can pass C objects into rustc so that the final link pass can
add the Rust libstd. Use that to eliminate the staticlib and allow
dynamic linking with libstd (also introduced by Meson 1.9.0, but not
for staticlib crates due to lack of support in rustc).
The main() function is still provided by C, which is possible by
declaring the main source file of the Rust executable (which is
created by scripts/rust/rust_root_crate.sh) as #![no_main].
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
meson.build | 19 ++++++++-----------
scripts/rust/rust_root_crate.sh | 1 +
2 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/meson.build b/meson.build
index e53cd5b4138..0a921272f57 100644
--- a/meson.build
+++ b/meson.build
@@ -4377,25 +4377,22 @@ foreach target : target_dirs
arch_srcs += target_specific.sources()
arch_deps += target_specific.dependencies()
+ main_rs = []
+ crates = []
if have_rust and target_type == 'system'
target_rust = rust_devices_ss.apply(config_target, strict: false)
- crates = []
+ arch_deps += target_rust.dependencies()
foreach dep : target_rust.dependencies()
crates += dep.get_variable('crate')
endforeach
if crates.length() > 0
- rlib_rs = custom_target('rust_' + target.underscorify() + '.rs',
+ main_rs = custom_target('rust_' + target.underscorify() + '.rs',
output: 'rust_' + target.underscorify() + '.rs',
command: [rust_root_crate, crates],
capture: true,
build_by_default: true,
build_always_stale: true)
- rlib = static_library('rust_' + target.underscorify(),
- structured_sources([], {'.': rlib_rs}),
- dependencies: target_rust.dependencies(),
- override_options: ['rust_std=2021', 'build.rust_std=2021'],
- rust_abi: 'c')
- arch_deps += declare_dependency(link_whole: [rlib])
+ main_rs = structured_sources(main_rs)
endif
endif
@@ -4419,14 +4416,14 @@ foreach target : target_dirs
execs = [{
'name': 'qemu-system-' + target_name,
'win_subsystem': 'console',
- 'sources': files('system/main.c'),
+ 'sources': [main_rs, files('system/main.c')],
'dependencies': [sdl]
}]
if host_os == 'windows' and (sdl.found() or gtk.found())
execs += [{
'name': 'qemu-system-' + target_name + 'w',
'win_subsystem': 'windows',
- 'sources': files('system/main.c'),
+ 'sources': [main_rs, files('system/main.c')],
'dependencies': [sdl]
}]
endif
@@ -4435,7 +4432,7 @@ foreach target : target_dirs
execs += [{
'name': 'qemu-fuzz-' + target_name,
'win_subsystem': 'console',
- 'sources': specific_fuzz.sources(),
+ 'sources': [main_rs, specific_fuzz.sources()],
'dependencies': specific_fuzz.dependencies(),
}]
endif
diff --git a/scripts/rust/rust_root_crate.sh b/scripts/rust/rust_root_crate.sh
index 975bddf7f1a..1ee88114ad9 100755
--- a/scripts/rust/rust_root_crate.sh
+++ b/scripts/rust/rust_root_crate.sh
@@ -6,6 +6,7 @@ cat <<EOF
// @generated
// This file is autogenerated by scripts/rust_root_crate.sh
+#![no_main]
EOF
for crate in $*; do
--
2.50.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-08-11 16:19 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-11 16:17 [PATCH for-10.2 0/2] meson: let Meson handle mixed-language linking of Rust and C objects Paolo Bonzini
2025-08-11 16:17 ` [PATCH 1/2] rust: do not link C libraries into Rust rlibs Paolo Bonzini
2025-08-11 16:17 ` [PATCH 2/2] meson: let Meson handle mixed-language linking of Rust and C objects Paolo Bonzini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).