rust: switch to cargo subprojects
Let Meson parse Cargo.lock and Cargo.toml and figure out the set of Rust build dependencies. For now, the only change is that subprojects are retrieved with "cargo_ws.subproject('NAME')" instead of "subproject('NAME-API-rs')". However, just calling "import('rust').workspace()" enables extra functionality that operates by parsing Cargo.toml; it will be introduced a step at a time in subsequent commits. Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Paolo Bonzini committed
Oct 17, 2025 at 14:06 UTC
6d28fc60891fd5643f2fbc8bf4c6ff57f21b5070
23 files changed
+40
-52
.gitlab-ci.d/static_checks.yml
+2
-2
@@ -55,7 +55,7 @@ check-rust-tools-nightly:
55
- source scripts/ci/gitlab-ci-section
56
- section_start test "Running Rust code checks"
57
- cd build
58
- - pyvenv/bin/meson devenv -w ../rust ${CARGO-cargo} fmt --check
58
+ - pyvenv/bin/meson devenv -w ../ ${CARGO-cargo} fmt --check
59
- make clippy
60
- make rustdoc
61
- section_end test
@@ -69,7 +69,7 @@ check-rust-tools-nightly:
69
when: on_success
70
expire_in: 2 days
71
paths:
72
- - rust/target/doc
72
+ - target/doc
73
74
check-build-units:
75
extends: .base_job_template
Cargo.lock
renamed
Cargo.toml
renamed
+3
-3
@@ -1,9 +1,9 @@
1
[workspace]
2
resolver = "2"
3
members = [
4
- "hw/char/pl011",
5
- "hw/timer/hpet",
6
- "tests",
4
+ "rust/hw/char/pl011",
5
+ "rust/hw/timer/hpet",
6
+ "rust/tests",
7
]
8
9
[workspace.package]
docs/devel/rust.rst
+4
-4
@@ -26,14 +26,14 @@ are accustomed to the more "normal" Cargo-based development workflow.
26
In particular:
27
28
* the set of warnings and lints that are used to build QEMU always
29
- comes from the ``rust/Cargo.toml`` workspace file
29
+ comes from the ``Cargo.toml`` workspace file
30
31
* it is also possible to use ``cargo`` for common Rust-specific coding
32
tasks, in particular to invoke ``clippy``, ``rustfmt`` and ``rustdoc``.
33
34
To this end, QEMU includes a ``build.rs`` build script that picks up
35
generated sources from QEMU's build directory and puts it in Cargo's
36
-output directory (typically ``rust/target/``). A vanilla invocation
36
+output directory (typically ``target/``). A vanilla invocation
37
of Cargo will complain that it cannot find the generated sources,
38
which can be fixed in different ways:
39
@@ -475,8 +475,8 @@ files, it is still highly experimental and is therefore not used.
475
476
Therefore, external crates must be added as subprojects for Meson to
477
learn how to build them, as well as to the relevant ``Cargo.toml`` files.
478
-The versions specified in ``rust/Cargo.lock`` must be the same as the
479
-subprojects; note that the ``rust/`` directory forms a Cargo `workspace`__,
478
+The versions specified in ``Cargo.lock`` must be the same as the
479
+subprojects; note that the QEMU source tree forms a Cargo `workspace`__,
480
and therefore there is a single lock file for the whole build.
481
482
__ https://doc.rust-lang.org/cargo/reference/workspaces.html#virtual-workspace
meson.build
+2
-1
@@ -130,7 +130,8 @@ endif
130
if have_rust
131
rustc_args = [find_program('scripts/rust/rustc_args.py'),
132
'--rustc-version', rustc.version(),
133
- '--workspace', meson.project_source_root() / 'rust']
133
+ '--workspace', meson.project_source_root()]
134
+
135
rustfmt = find_program('rustfmt', required: false)
136
137
rustc_lint_args = run_command(rustc_args, '--lints',
rust/meson.build
+12
-25
@@ -4,31 +4,18 @@ else
4
message('Rust enabled but it is only used by system emulators.')
5
endif
6
7
-subproject('anyhow-1-rs', required: true)
8
-subproject('bilge-0.2-rs', required: true)
9
-subproject('bilge-impl-0.2-rs', required: true)
10
-subproject('foreign-0.3-rs', required: true)
11
-subproject('glib-sys-0.21-rs', required: true)
12
-subproject('libc-0.2-rs', required: true)
13
-subproject('probe-0.5-rs', required: true)
14
-
15
-anyhow_rs = dependency('anyhow-1-rs')
16
-bilge_rs = dependency('bilge-0.2-rs')
17
-bilge_impl_rs = dependency('bilge-impl-0.2-rs')
18
-foreign_rs = dependency('foreign-0.3-rs')
19
-glib_sys_rs = dependency('glib-sys-0.21-rs')
20
-libc_rs = dependency('libc-0.2-rs')
21
-probe_rs = dependency('probe-0.5-rs')
22
-
23
-subproject('proc-macro2-1-rs', required: true)
24
-subproject('quote-1-rs', required: true)
25
-subproject('syn-2-rs', required: true)
26
-subproject('attrs-0.2-rs', required: true)
27
-
28
-quote_rs_native = dependency('quote-1-rs', native: true)
29
-syn_rs_native = dependency('syn-2-rs', native: true)
30
-proc_macro2_rs_native = dependency('proc-macro2-1-rs', native: true)
31
-attrs_rs_native = dependency('attrs-0.2-rs', native: true)
7
+cargo_ws = import('rust').workspace()
8
+anyhow_rs = cargo_ws.subproject('anyhow').dependency()
9
+bilge_rs = cargo_ws.subproject('bilge').dependency()
10
+bilge_impl_rs = cargo_ws.subproject('bilge-impl').dependency()
11
+foreign_rs = cargo_ws.subproject('foreign').dependency()
12
+glib_sys_rs = cargo_ws.subproject('glib-sys').dependency()
13
+libc_rs = cargo_ws.subproject('libc').dependency()
14
+probe_rs = cargo_ws.subproject('probe').dependency()
15
+quote_rs_native = cargo_ws.subproject('quote').dependency()
16
+syn_rs_native = cargo_ws.subproject('syn').dependency()
17
+proc_macro2_rs_native = cargo_ws.subproject('proc-macro2').dependency()
18
+attrs_rs_native = cargo_ws.subproject('attrs').dependency()
19
20
genrs = []
21
subprojects/anyhow-1-rs.wrap
+1
-1
@@ -3,5 +3,5 @@ directory = anyhow-1.0.98
3
source_url = https://crates.io/api/v1/crates/anyhow/1.0.98/download
4
source_filename = anyhow-1.0.98.tar.gz
5
source_hash = e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487
6
-#method = cargo
6
+method = cargo
7
patch_directory = anyhow-1-rs
subprojects/arbitrary-int-1-rs.wrap
+1
-1
@@ -3,7 +3,7 @@ directory = arbitrary-int-1.2.7
3
source_url = https://crates.io/api/v1/crates/arbitrary-int/1.2.7/download
4
source_filename = arbitrary-int-1.2.7.tar.gz
5
source_hash = c84fc003e338a6f69fbd4f7fe9f92b535ff13e9af8997f3b14b6ddff8b1df46d
6
-#method = cargo
6
+method = cargo
7
patch_directory = arbitrary-int-1-rs
8
9
# bump this version number on every change to meson.build or the patches:
subprojects/attrs-0.2-rs.wrap
+1
-1
@@ -3,5 +3,5 @@ directory = attrs-0.2.9
3
source_url = https://crates.io/api/v1/crates/attrs/0.2.9/download
4
source_filename = attrs-0.2.9.tar.gz
5
source_hash = 2a207d40f43de65285f3de0509bb6cb16bc46098864fce957122bbacce327e5f
6
-#method = cargo
6
+method = cargo
7
patch_directory = attrs-0.2-rs
subprojects/bilge-0.2-rs.wrap
+1
-1
@@ -3,7 +3,7 @@ directory = bilge-0.2.0
3
source_url = https://crates.io/api/v1/crates/bilge/0.2.0/download
4
source_filename = bilge-0.2.0.tar.gz
5
source_hash = dc707ed8ebf81de5cd6c7f48f54b4c8621760926cdf35a57000747c512e67b57
6
-#method = cargo
6
+method = cargo
7
patch_directory = bilge-0.2-rs
8
9
# bump this version number on every change to meson.build or the patches:
subprojects/bilge-impl-0.2-rs.wrap
+1
-1
@@ -3,7 +3,7 @@ directory = bilge-impl-0.2.0
3
source_url = https://crates.io/api/v1/crates/bilge-impl/0.2.0/download
4
source_filename = bilge-impl-0.2.0.tar.gz
5
source_hash = feb11e002038ad243af39c2068c8a72bcf147acf05025dcdb916fcc000adb2d8
6
-#method = cargo
6
+method = cargo
7
patch_directory = bilge-impl-0.2-rs
8
9
# bump this version number on every change to meson.build or the patches:
subprojects/either-1-rs.wrap
+1
-1
@@ -3,7 +3,7 @@ directory = either-1.12.0
3
source_url = https://crates.io/api/v1/crates/either/1.12.0/download
4
source_filename = either-1.12.0.tar.gz
5
source_hash = 3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b
6
-#method = cargo
6
+method = cargo
7
patch_directory = either-1-rs
8
9
# bump this version number on every change to meson.build or the patches:
subprojects/foreign-0.3-rs.wrap
+1
-1
@@ -3,5 +3,5 @@ directory = foreign-0.3.1
3
source_url = https://crates.io/api/v1/crates/foreign/0.3.1/download
4
source_filename = foreign-0.3.1.tar.gz
5
source_hash = 17ca1b5be8c9d320daf386f1809c7acc0cb09accbae795c2001953fa50585846
6
-#method = cargo
6
+method = cargo
7
patch_directory = foreign-0.3-rs
subprojects/glib-sys-0.21-rs.wrap
+1
-1
@@ -3,5 +3,5 @@ directory = glib-sys-0.21.2
3
source_url = https://crates.io/api/v1/crates/glib-sys/0.21.2/download
4
source_filename = glib-sys-0.21.2.tar.gz
5
source_hash = d09d3d0fddf7239521674e57b0465dfbd844632fec54f059f7f56112e3f927e1
6
-#method = cargo
6
+method = cargo
7
patch_directory = glib-sys-0.21-rs
subprojects/itertools-0.11-rs.wrap
+1
-1
@@ -3,7 +3,7 @@ directory = itertools-0.11.0
3
source_url = https://crates.io/api/v1/crates/itertools/0.11.0/download
4
source_filename = itertools-0.11.0.tar.gz
5
source_hash = b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57
6
-#method = cargo
6
+method = cargo
7
patch_directory = itertools-0.11-rs
8
9
# bump this version number on every change to meson.build or the patches:
subprojects/libc-0.2-rs.wrap
+1
-1
@@ -3,5 +3,5 @@ directory = libc-0.2.162
3
source_url = https://crates.io/api/v1/crates/libc/0.2.162/download
4
source_filename = libc-0.2.162.tar.gz
5
source_hash = 18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398
6
-#method = cargo
6
+method = cargo
7
patch_directory = libc-0.2-rs
subprojects/probe-0.5-rs.wrap
+1
-1
@@ -3,5 +3,5 @@ directory = probe-0.5.2
3
source_url = https://crates.io/api/v1/crates/probe/0.5.2/download
4
source_filename = probe-0.5.2.tar.gz
5
source_hash = 136558b6e1ebaecc92755d0ffaf9421f519531bed30cc2ad23b22cb00965cc5e
6
-#method = cargo
6
+method = cargo
7
patch_directory = probe-0.5-rs
subprojects/proc-macro-error-1-rs.wrap
+1
-1
@@ -3,7 +3,7 @@ directory = proc-macro-error-1.0.4
3
source_url = https://crates.io/api/v1/crates/proc-macro-error/1.0.4/download
4
source_filename = proc-macro-error-1.0.4.tar.gz
5
source_hash = da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c
6
-#method = cargo
6
+method = cargo
7
patch_directory = proc-macro-error-1-rs
8
9
# bump this version number on every change to meson.build or the patches:
subprojects/proc-macro-error-attr-1-rs.wrap
+1
-1
@@ -3,7 +3,7 @@ directory = proc-macro-error-attr-1.0.4
3
source_url = https://crates.io/api/v1/crates/proc-macro-error-attr/1.0.4/download
4
source_filename = proc-macro-error-attr-1.0.4.tar.gz
5
source_hash = a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869
6
-#method = cargo
6
+method = cargo
7
patch_directory = proc-macro-error-attr-1-rs
8
9
# bump this version number on every change to meson.build or the patches:
subprojects/proc-macro2-1-rs.wrap
+1
-1
@@ -3,7 +3,7 @@ directory = proc-macro2-1.0.95
3
source_url = https://crates.io/api/v1/crates/proc-macro2/1.0.95/download
4
source_filename = proc-macro2-1.0.95.0.tar.gz
5
source_hash = 02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778
6
-#method = cargo
6
+method = cargo
7
patch_directory = proc-macro2-1-rs
8
9
# bump this version number on every change to meson.build or the patches:
subprojects/quote-1-rs.wrap
+1
-1
@@ -3,7 +3,7 @@ directory = quote-1.0.36
3
source_url = https://crates.io/api/v1/crates/quote/1.0.36/download
4
source_filename = quote-1.0.36.0.tar.gz
5
source_hash = 0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7
6
-#method = cargo
6
+method = cargo
7
patch_directory = quote-1-rs
8
9
# bump this version number on every change to meson.build or the patches:
subprojects/syn-2-rs.wrap
+1
-1
@@ -3,7 +3,7 @@ directory = syn-2.0.104
3
source_url = https://crates.io/api/v1/crates/syn/2.0.104/download
4
source_filename = syn-2.0.104.0.tar.gz
5
source_hash = 17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40
6
-#method = cargo
6
+method = cargo
7
patch_directory = syn-2-rs
8
9
# bump this version number on every change to meson.build or the patches:
subprojects/unicode-ident-1-rs.wrap
+1
-1
@@ -3,7 +3,7 @@ directory = unicode-ident-1.0.12
3
source_url = https://crates.io/api/v1/crates/unicode-ident/1.0.12/download
4
source_filename = unicode-ident-1.0.12.tar.gz
5
source_hash = 3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b
6
-#method = cargo
6
+method = cargo
7
patch_directory = unicode-ident-1-rs
8
9
# bump this version number on every change to meson.build or the patches: