* [PATCH 01/12] rust: apply --cfg MESON to all crates
[not found] <20241115163944.1917393-1-pbonzini@redhat.com>
@ 2024-11-15 16:40 ` Paolo Bonzini
2024-11-15 16:40 ` [PATCH 02/12] rust: allow using build-root bindings.rs from cargo Paolo Bonzini
` (10 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2024-11-15 16:40 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, berrange, junjie.mao, manos.pitsidianakis, kwolf
We might have more uses for --cfg MESON, even though right now it's only
qemu-api that has generated files. Since we're going to add more flags
to the add_project_arguments calls for Rust, it makes sense to also add
--cfg MESON everywhere.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
meson.build | 7 ++++---
rust/qemu-api/meson.build | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/meson.build b/meson.build
index e0b880e4e13..a6172524287 100644
--- a/meson.build
+++ b/meson.build
@@ -3422,10 +3422,11 @@ if have_rust
# is safe; https://github.com/rust-lang/rust/pull/54675 says that
# passing -nodefaultlibs to the linker "was more ideological to
# start with than anything".
- add_project_arguments(rustc_args + ['-C', 'default-linker-libraries'],
+ add_project_arguments(rustc_args +
+ ['--cfg', 'MESON', '-C', 'default-linker-libraries'],
native: false, language: 'rust')
-
- add_project_arguments(rustc_args, native: true, language: 'rust')
+ add_project_arguments(rustc_args + ['--cfg', 'MESON'],
+ native: true, language: 'rust')
endif
hxtool = find_program('scripts/hxtool')
diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build
index 6f637af7b1b..cad9ac4844e 100644
--- a/rust/qemu-api/meson.build
+++ b/rust/qemu-api/meson.build
@@ -1,4 +1,4 @@
-_qemu_api_cfg = ['--cfg', 'MESON']
+_qemu_api_cfg = []
# _qemu_api_cfg += ['--cfg', 'feature="allocator"']
if rustc.version().version_compare('>=1.77.0')
_qemu_api_cfg += ['--cfg', 'has_offset_of']
--
2.47.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 02/12] rust: allow using build-root bindings.rs from cargo
[not found] <20241115163944.1917393-1-pbonzini@redhat.com>
2024-11-15 16:40 ` [PATCH 01/12] rust: apply --cfg MESON to all crates Paolo Bonzini
@ 2024-11-15 16:40 ` Paolo Bonzini
2024-11-15 16:40 ` [PATCH 03/12] rust: build: move rustc_args.py invocation to qemu-api crate Paolo Bonzini
` (9 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2024-11-15 16:40 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, berrange, junjie.mao, manos.pitsidianakis, kwolf
Right now, using cargo with QEMU requires copying by hand the bindings.rs to the
source tree. Instead, we can use an include file to escape the cage of cargo's
mandated source directory structure.
By running cargo within meson's "devenv" and adding a MESON_BUILD_ROOT
environment variable, it is easy for build.rs to find the file. However, the
file must be symlinked into cargo's output directory for rust-analyzer to find
it.
Suggested-by: Junjie Mao <junjie.mao@hotmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
meson.build | 4 +++-
rust/hw/char/pl011/.gitignore | 2 --
rust/qemu-api/.gitignore | 2 +-
rust/qemu-api/README.md | 4 ++--
rust/qemu-api/build.rs | 34 +++++++++++++++++++++++++++-------
rust/qemu-api/meson.build | 1 +
rust/qemu-api/src/bindings.rs | 29 +++++++++++++++++++++++++++++
rust/qemu-api/src/lib.rs | 22 ----------------------
8 files changed, 63 insertions(+), 35 deletions(-)
delete mode 100644 rust/hw/char/pl011/.gitignore
create mode 100644 rust/qemu-api/src/bindings.rs
diff --git a/meson.build b/meson.build
index a6172524287..8def5f67bb5 100644
--- a/meson.build
+++ b/meson.build
@@ -3,6 +3,8 @@ project('qemu', ['c'], meson_version: '>=1.5.0',
'b_staticpic=false', 'stdsplit=false', 'optimization=2', 'b_pie=true'],
version: files('VERSION'))
+meson.add_devenv({ 'MESON_BUILD_ROOT' : meson.project_build_root() })
+
add_test_setup('quick', exclude_suites: ['slow', 'thorough'], is_default: true)
add_test_setup('slow', exclude_suites: ['thorough'], env: ['G_TEST_SLOW=1', 'SPEED=slow'])
add_test_setup('thorough', env: ['G_TEST_SLOW=1', 'SPEED=thorough'])
@@ -4090,7 +4092,7 @@ if have_rust
bindings_rs = rust.bindgen(
input: 'rust/wrapper.h',
dependencies: common_ss.all_dependencies(),
- output: 'bindings.rs',
+ output: 'bindings.inc.rs',
include_directories: include_directories('.', 'include'),
bindgen_version: ['>=0.60.0'],
args: bindgen_args,
diff --git a/rust/hw/char/pl011/.gitignore b/rust/hw/char/pl011/.gitignore
deleted file mode 100644
index 71eaff2035d..00000000000
--- a/rust/hw/char/pl011/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-# Ignore generated bindings file overrides.
-src/bindings.rs.inc
diff --git a/rust/qemu-api/.gitignore b/rust/qemu-api/.gitignore
index b9e7e004c86..df6c2163e03 100644
--- a/rust/qemu-api/.gitignore
+++ b/rust/qemu-api/.gitignore
@@ -1,2 +1,2 @@
# Ignore generated bindings file overrides.
-src/bindings.rs
+/src/bindings.inc.rs
diff --git a/rust/qemu-api/README.md b/rust/qemu-api/README.md
index 7588fa29ef3..53810f48882 100644
--- a/rust/qemu-api/README.md
+++ b/rust/qemu-api/README.md
@@ -5,7 +5,7 @@ This library exports helper Rust types, Rust macros and C FFI bindings for inter
The C bindings can be generated with `bindgen`, using this build target:
```console
-$ ninja bindings.rs
+$ ninja bindings.inc.rs
```
## Generate Rust documentation
@@ -13,5 +13,5 @@ $ ninja bindings.rs
To generate docs for this crate, including private items:
```sh
-cargo doc --no-deps --document-private-items
+pyvenv/bin/meson devenv -w ../rust cargo doc --no-deps --document-private-items
```
diff --git a/rust/qemu-api/build.rs b/rust/qemu-api/build.rs
index 20f8f718b90..06e79082b5f 100644
--- a/rust/qemu-api/build.rs
+++ b/rust/qemu-api/build.rs
@@ -2,22 +2,42 @@
// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
// SPDX-License-Identifier: GPL-2.0-or-later
-use std::path::Path;
+#[cfg(unix)]
+use std::os::unix::fs::symlink as symlink_file;
+#[cfg(windows)]
+use std::os::windows::fs::symlink_file;
+use std::{env, fs::remove_file, io::Result, path::Path};
use version_check as rustc;
-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."
- );
+fn main() -> Result<()> {
+ // Placing bindings.inc.rs in the source directory is supported
+ // but not documented or encouraged.
+ let path = env::var("MESON_BUILD_ROOT")
+ .unwrap_or_else(|_| format!("{}/src", env!("CARGO_MANIFEST_DIR")));
+
+ let file = format!("{}/bindings.inc.rs", path);
+ let file = Path::new(&file);
+ if !Path::new(&file).exists() {
+ panic!(concat!(
+ "No generated C bindings found! If you want to run `cargo`, start a subshell\n",
+ "with `meson devenv`, or point MESON_BUILD_ROOT to the top of the build tree."
+ ));
}
+ let out_dir = env::var("OUT_DIR").unwrap();
+ let dest_path = format!("{}/bindings.inc.rs", out_dir);
+ let dest_path = Path::new(&dest_path);
+ if dest_path.symlink_metadata().is_ok() {
+ remove_file(dest_path)?;
+ }
+ symlink_file(file, dest_path)?;
+
// Check for available rustc features
if rustc::is_min_version("1.77.0").unwrap_or(false) {
println!("cargo:rustc-cfg=has_offset_of");
}
println!("cargo:rerun-if-changed=build.rs");
+ Ok(())
}
diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build
index cad9ac4844e..3be7b7e5ced 100644
--- a/rust/qemu-api/meson.build
+++ b/rust/qemu-api/meson.build
@@ -9,6 +9,7 @@ _qemu_api_rs = static_library(
structured_sources(
[
'src/lib.rs',
+ 'src/bindings.rs',
'src/c_str.rs',
'src/definitions.rs',
'src/device_class.rs',
diff --git a/rust/qemu-api/src/bindings.rs b/rust/qemu-api/src/bindings.rs
new file mode 100644
index 00000000000..0b76ec58bee
--- /dev/null
+++ b/rust/qemu-api/src/bindings.rs
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#![allow(
+ dead_code,
+ improper_ctypes_definitions,
+ improper_ctypes,
+ non_camel_case_types,
+ non_snake_case,
+ non_upper_case_globals,
+ unsafe_op_in_unsafe_fn,
+ clippy::missing_const_for_fn,
+ clippy::too_many_arguments,
+ clippy::approx_constant,
+ clippy::use_self,
+ clippy::useless_transmute,
+ clippy::missing_safety_doc
+)]
+
+#[cfg(MESON)]
+include!("bindings.inc.rs");
+
+#[cfg(not(MESON))]
+include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs"));
+
+unsafe impl Send for Property {}
+unsafe impl Sync for Property {}
+unsafe impl Sync for TypeInfo {}
+unsafe impl Sync for VMStateDescription {}
+unsafe impl Sync for VMStateField {}
+unsafe impl Sync for VMStateInfo {}
diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs
index aa8d16ec94b..440aff3817d 100644
--- a/rust/qemu-api/src/lib.rs
+++ b/rust/qemu-api/src/lib.rs
@@ -4,31 +4,9 @@
#![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,
- unsafe_op_in_unsafe_fn,
- 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 {}
-unsafe impl Sync for bindings::VMStateField {}
-unsafe impl Sync for bindings::VMStateInfo {}
-
pub mod c_str;
pub mod definitions;
pub mod device_class;
--
2.47.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 03/12] rust: build: move rustc_args.py invocation to qemu-api crate
[not found] <20241115163944.1917393-1-pbonzini@redhat.com>
2024-11-15 16:40 ` [PATCH 01/12] rust: apply --cfg MESON to all crates Paolo Bonzini
2024-11-15 16:40 ` [PATCH 02/12] rust: allow using build-root bindings.rs from cargo Paolo Bonzini
@ 2024-11-15 16:40 ` Paolo Bonzini
2024-11-15 16:40 ` [PATCH 04/12] rust: build: restrict --cfg generation to only required symbols Paolo Bonzini
` (8 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2024-11-15 16:40 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, berrange, junjie.mao, manos.pitsidianakis, kwolf
Only qemu-api needs access to the symbols in config-host.h. Remove
the temptation to use them elsewhere by limiting the --cfg arguments to
the qemu-api crate.
Per-crate invocation of the script will also be needed to add --check-cfg
options for each crate's features (when more complex, build-time
configurable devices are added in the future).
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
meson.build | 56 +++++++++++++++++----------------------
rust/qemu-api/meson.build | 5 +++-
2 files changed, 29 insertions(+), 32 deletions(-)
diff --git a/meson.build b/meson.build
index 8def5f67bb5..b51add16d2f 100644
--- a/meson.build
+++ b/meson.build
@@ -120,7 +120,30 @@ if have_rust
endif
if have_rust
+ rustc_args = find_program('scripts/rust/rustc_args.py')
rustfmt = find_program('rustfmt', required: false)
+
+ # Prohibit code that is forbidden in Rust 2024
+ rustc_lint_args = ['-D', 'unsafe_op_in_unsafe_fn']
+
+ # Occasionally, we may need to silence warnings and clippy lints that
+ # were only introduced in newer Rust compiler versions. Do not croak
+ # in that case; a CI job with rust_strict_lints == true ensures that
+ # we do not have misspelled allow() attributes.
+ if not get_option('strict_rust_lints')
+ rustc_lint_args += ['-A', 'unknown_lints']
+ endif
+
+ # Apart from procedural macros, our Rust executables will often link
+ # with C code, so include all the libraries that C code needs. This
+ # is safe; https://github.com/rust-lang/rust/pull/54675 says that
+ # passing -nodefaultlibs to the linker "was more ideological to
+ # start with than anything".
+ add_project_arguments(rustc_lint_args +
+ ['--cfg', 'MESON', '-C', 'default-linker-libraries'],
+ native: false, language: 'rust')
+ add_project_arguments(rustc_lint_args + ['--cfg', 'MESON'],
+ native: true, language: 'rust')
endif
dtrace = not_found
@@ -3399,37 +3422,8 @@ endif
# Generated sources #
#####################
-genh += configure_file(output: 'config-host.h', configuration: config_host_data)
-
-if have_rust
- rustc_args = run_command(
- find_program('scripts/rust/rustc_args.py'),
- '--config-headers', meson.project_build_root() / 'config-host.h',
- capture : true,
- check: true).stdout().strip().split()
-
- # Prohibit code that is forbidden in Rust 2024
- rustc_args += ['-D', 'unsafe_op_in_unsafe_fn']
-
- # Occasionally, we may need to silence warnings and clippy lints that
- # were only introduced in newer Rust compiler versions. Do not croak
- # in that case; a CI job with rust_strict_lints == true ensures that
- # we do not have misspelled allow() attributes.
- if not get_option('strict_rust_lints')
- rustc_args += ['-A', 'unknown_lints']
- endif
-
- # Apart from procedural macros, our Rust executables will often link
- # with C code, so include all the libraries that C code needs. This
- # is safe; https://github.com/rust-lang/rust/pull/54675 says that
- # passing -nodefaultlibs to the linker "was more ideological to
- # start with than anything".
- add_project_arguments(rustc_args +
- ['--cfg', 'MESON', '-C', 'default-linker-libraries'],
- native: false, language: 'rust')
- add_project_arguments(rustc_args + ['--cfg', 'MESON'],
- native: true, language: 'rust')
-endif
+config_host_h = configure_file(output: 'config-host.h', configuration: config_host_data)
+genh += config_host_h
hxtool = find_program('scripts/hxtool')
shaderinclude = find_program('scripts/shaderinclude.py')
diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build
index 3be7b7e5ced..5df6b35bf88 100644
--- a/rust/qemu-api/meson.build
+++ b/rust/qemu-api/meson.build
@@ -1,4 +1,7 @@
-_qemu_api_cfg = []
+_qemu_api_cfg = run_command(rustc_args,
+ '--config-headers', config_host_h,
+ capture: true, check: true).stdout().strip().split()
+
# _qemu_api_cfg += ['--cfg', 'feature="allocator"']
if rustc.version().version_compare('>=1.77.0')
_qemu_api_cfg += ['--cfg', 'has_offset_of']
--
2.47.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 04/12] rust: build: restrict --cfg generation to only required symbols
[not found] <20241115163944.1917393-1-pbonzini@redhat.com>
` (2 preceding siblings ...)
2024-11-15 16:40 ` [PATCH 03/12] rust: build: move rustc_args.py invocation to qemu-api crate Paolo Bonzini
@ 2024-11-15 16:40 ` Paolo Bonzini
2024-11-15 16:40 ` [PATCH 05/12] rust: build: generate lint flags from Cargo.toml Paolo Bonzini
` (7 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2024-11-15 16:40 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, berrange, junjie.mao, manos.pitsidianakis, kwolf
Parse the Cargo.toml file, looking for the unexpected_cfgs
configuration. When generating --cfg options from the
config-host.h file, only use those that are included in the
configuration.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
rust/qemu-api/meson.build | 2 +-
scripts/rust/rustc_args.py | 61 ++++++++++++++++++++++++++++----------
2 files changed, 46 insertions(+), 17 deletions(-)
diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build
index 5df6b35bf88..2ff6d2ce3d0 100644
--- a/rust/qemu-api/meson.build
+++ b/rust/qemu-api/meson.build
@@ -1,5 +1,5 @@
_qemu_api_cfg = run_command(rustc_args,
- '--config-headers', config_host_h,
+ '--config-headers', config_host_h, files('Cargo.toml'),
capture: true, check: true).stdout().strip().split()
# _qemu_api_cfg += ['--cfg', 'feature="allocator"']
diff --git a/scripts/rust/rustc_args.py b/scripts/rust/rustc_args.py
index e4cc9720e16..942dd2b2bab 100644
--- a/scripts/rust/rustc_args.py
+++ b/scripts/rust/rustc_args.py
@@ -26,30 +26,51 @@
import argparse
import logging
+from pathlib import Path
+from typing import Any, Iterable, Mapping, Optional, Set
-from typing import List
+try:
+ import tomllib
+except ImportError:
+ import tomli as tomllib
-def generate_cfg_flags(header: str) -> List[str]:
+class CargoTOML:
+ tomldata: Mapping[Any, Any]
+ check_cfg: Set[str]
+
+ def __init__(self, path: str):
+ with open(path, 'rb') as f:
+ self.tomldata = tomllib.load(f)
+
+ self.check_cfg = set(self.find_check_cfg())
+
+ def find_check_cfg(self) -> Iterable[str]:
+ toml_lints = self.lints
+ rust_lints = toml_lints.get("rust", {})
+ cfg_lint = rust_lints.get("unexpected_cfgs", {})
+ return cfg_lint.get("check-cfg", [])
+
+ @property
+ def lints(self) -> Mapping[Any, Any]:
+ return self.get_table("lints")
+
+ def get_table(self, key: str) -> Mapping[Any, Any]:
+ table = self.tomldata.get(key, {})
+
+ return table
+
+
+def generate_cfg_flags(header: str, cargo_toml: CargoTOML) -> Iterable[str]:
"""Converts defines from config[..].h headers to rustc --cfg flags."""
- def cfg_name(name: str) -> str:
- """Filter function for C #defines"""
- if (
- name.startswith("CONFIG_")
- or name.startswith("TARGET_")
- or name.startswith("HAVE_")
- ):
- return name
- return ""
-
with open(header, encoding="utf-8") as cfg:
config = [l.split()[1:] for l in cfg if l.startswith("#define")]
cfg_list = []
for cfg in config:
- name = cfg_name(cfg[0])
- if not name:
+ name = cfg[0]
+ if f'cfg({name})' not in cargo_toml.check_cfg:
continue
if len(cfg) >= 2 and cfg[1] != "1":
continue
@@ -59,7 +80,6 @@ def cfg_name(name: str) -> str:
def main() -> None:
- # pylint: disable=missing-function-docstring
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--verbose", action="store_true")
parser.add_argument(
@@ -71,12 +91,21 @@ def main() -> None:
required=False,
default=[],
)
+ parser.add_argument(
+ metavar="TOML_FILE",
+ action="store",
+ dest="cargo_toml",
+ help="path to Cargo.toml file",
+ )
args = parser.parse_args()
if args.verbose:
logging.basicConfig(level=logging.DEBUG)
logging.debug("args: %s", args)
+
+ cargo_toml = CargoTOML(args.cargo_toml)
+
for header in args.config_headers:
- for tok in generate_cfg_flags(header):
+ for tok in generate_cfg_flags(header, cargo_toml):
print(tok)
--
2.47.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 05/12] rust: build: generate lint flags from Cargo.toml
[not found] <20241115163944.1917393-1-pbonzini@redhat.com>
` (3 preceding siblings ...)
2024-11-15 16:40 ` [PATCH 04/12] rust: build: restrict --cfg generation to only required symbols Paolo Bonzini
@ 2024-11-15 16:40 ` Paolo Bonzini
2024-11-15 16:40 ` [PATCH 06/12] rust: cargo: store desired warning levels in workspace Cargo.toml Paolo Bonzini
` (6 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2024-11-15 16:40 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, berrange, junjie.mao, manos.pitsidianakis, kwolf
Cargo.toml makes it possible to describe the desired lint level settings
in a nice format. We can extend this to Meson-built crates, by teaching
rustc_args.py to fetch lint and --check-cfg arguments from Cargo.toml.
--check-cfg arguments come from the unexpected_cfgs lint as well as crate
features
Start with qemu-api, since it already has a [lints.rust] table and
an invocation of rustc_args.py.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
meson.build | 3 +-
rust/qemu-api/meson.build | 4 +-
scripts/rust/rustc_args.py | 83 +++++++++++++++++++++++++++++++++++++-
3 files changed, 86 insertions(+), 4 deletions(-)
diff --git a/meson.build b/meson.build
index b51add16d2f..231fccf3928 100644
--- a/meson.build
+++ b/meson.build
@@ -120,7 +120,8 @@ if have_rust
endif
if have_rust
- rustc_args = find_program('scripts/rust/rustc_args.py')
+ rustc_args = [find_program('scripts/rust/rustc_args.py'),
+ '--rustc-version', rustc.version()]
rustfmt = find_program('rustfmt', required: false)
# Prohibit code that is forbidden in Rust 2024
diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build
index 2ff6d2ce3d0..1ed79672cc9 100644
--- a/rust/qemu-api/meson.build
+++ b/rust/qemu-api/meson.build
@@ -1,6 +1,6 @@
_qemu_api_cfg = run_command(rustc_args,
- '--config-headers', config_host_h, files('Cargo.toml'),
- capture: true, check: true).stdout().strip().split()
+ '--config-headers', config_host_h, '--features', '--lints', files('Cargo.toml'),
+ capture: true, check: true).stdout().strip().splitlines()
# _qemu_api_cfg += ['--cfg', 'feature="allocator"']
if rustc.version().version_compare('>=1.77.0')
diff --git a/scripts/rust/rustc_args.py b/scripts/rust/rustc_args.py
index 942dd2b2bab..9b9778a1cac 100644
--- a/scripts/rust/rustc_args.py
+++ b/scripts/rust/rustc_args.py
@@ -25,9 +25,10 @@
"""
import argparse
+from dataclasses import dataclass
import logging
from pathlib import Path
-from typing import Any, Iterable, Mapping, Optional, Set
+from typing import Any, Iterable, List, Mapping, Optional, Set
try:
import tomllib
@@ -61,6 +62,45 @@ def get_table(self, key: str) -> Mapping[Any, Any]:
return table
+@dataclass
+class LintFlag:
+ flags: List[str]
+ priority: int
+
+
+def generate_lint_flags(cargo_toml: CargoTOML) -> Iterable[str]:
+ """Converts Cargo.toml lints to rustc -A/-D/-F/-W flags."""
+
+ toml_lints = cargo_toml.lints
+
+ lint_list = []
+ for k, v in toml_lints.items():
+ prefix = "" if k == "rust" else k + "::"
+ for lint, data in v.items():
+ level = data if isinstance(data, str) else data["level"]
+ priority = 0 if isinstance(data, str) else data.get("priority", 0)
+ if level == "deny":
+ flag = "-D"
+ elif level == "allow":
+ flag = "-A"
+ elif level == "warn":
+ flag = "-W"
+ elif level == "forbid":
+ flag = "-F"
+ else:
+ raise Exception(f"invalid level {level} for {prefix}{lint}")
+
+ # This may change if QEMU ever invokes clippy-driver or rustdoc by
+ # hand. For now, check the syntax but do not add non-rustc lints to
+ # the command line.
+ if k == "rust":
+ lint_list.append(LintFlag(flags=[flag, prefix + lint], priority=priority))
+
+ lint_list.sort(key=lambda x: x.priority)
+ for lint in lint_list:
+ yield from lint.flags
+
+
def generate_cfg_flags(header: str, cargo_toml: CargoTOML) -> Iterable[str]:
"""Converts defines from config[..].h headers to rustc --cfg flags."""
@@ -97,13 +137,54 @@ def main() -> None:
dest="cargo_toml",
help="path to Cargo.toml file",
)
+ parser.add_argument(
+ "--features",
+ action="store_true",
+ dest="features",
+ help="generate --check-cfg arguments for features",
+ required=False,
+ default=None,
+ )
+ parser.add_argument(
+ "--lints",
+ action="store_true",
+ dest="lints",
+ help="generate arguments from [lints] table",
+ required=False,
+ default=None,
+ )
+ parser.add_argument(
+ "--rustc-version",
+ metavar="VERSION",
+ dest="rustc_version",
+ action="store",
+ help="version of rustc",
+ required=False,
+ default="1.0.0",
+ )
args = parser.parse_args()
if args.verbose:
logging.basicConfig(level=logging.DEBUG)
logging.debug("args: %s", args)
+ rustc_version = tuple((int(x) for x in args.rustc_version.split('.')[0:2]))
cargo_toml = CargoTOML(args.cargo_toml)
+ if args.lints:
+ for tok in generate_lint_flags(cargo_toml):
+ print(tok)
+
+ if rustc_version >= (1, 80):
+ if args.lints:
+ for cfg in sorted(cargo_toml.check_cfg):
+ print("--check-cfg")
+ print(cfg)
+ if args.features:
+ for feature in cargo_toml.get_table("features"):
+ if feature != "default":
+ print("--check-cfg")
+ print(f'cfg(feature,values("{feature}"))')
+
for header in args.config_headers:
for tok in generate_cfg_flags(header, cargo_toml):
print(tok)
--
2.47.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 06/12] rust: cargo: store desired warning levels in workspace Cargo.toml
[not found] <20241115163944.1917393-1-pbonzini@redhat.com>
` (4 preceding siblings ...)
2024-11-15 16:40 ` [PATCH 05/12] rust: build: generate lint flags from Cargo.toml Paolo Bonzini
@ 2024-11-15 16:40 ` Paolo Bonzini
2024-11-15 16:40 ` [PATCH 07/12] rust: build: move strict lints handling to rustc_args.py Paolo Bonzini
` (5 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2024-11-15 16:40 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, berrange, junjie.mao, manos.pitsidianakis, kwolf
An extra benefit of workspaces is that they allow to place lint level
settings in a single Cargo.toml; the settings are then inherited by
packages in the workspace.
Correspondingly, teach rustc_args.py to get the unexpected_cfgs
configuration from the workspace Cargo.toml.
Note that it is still possible to allow or deny warnings per crate or
module, via the #![] attribute syntax. The rust/qemu-api/src/bindings.rs
file is an example.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
meson.build | 7 +++---
rust/Cargo.toml | 8 +++++++
rust/hw/char/pl011/Cargo.toml | 3 +++
rust/qemu-api-macros/Cargo.toml | 3 +++
rust/qemu-api/Cargo.toml | 5 ++---
rust/qemu-api/meson.build | 2 +-
scripts/rust/rustc_args.py | 38 +++++++++++++++++++++++++++------
7 files changed, 53 insertions(+), 13 deletions(-)
diff --git a/meson.build b/meson.build
index 231fccf3928..21e2a332d6c 100644
--- a/meson.build
+++ b/meson.build
@@ -121,11 +121,12 @@ endif
if have_rust
rustc_args = [find_program('scripts/rust/rustc_args.py'),
- '--rustc-version', rustc.version()]
+ '--rustc-version', rustc.version(),
+ '--workspace', meson.project_source_root() / 'rust']
rustfmt = find_program('rustfmt', required: false)
- # Prohibit code that is forbidden in Rust 2024
- rustc_lint_args = ['-D', 'unsafe_op_in_unsafe_fn']
+ rustc_lint_args = run_command(rustc_args, '--lints',
+ capture: true, check: true).stdout().strip().splitlines()
# Occasionally, we may need to silence warnings and clippy lints that
# were only introduced in newer Rust compiler versions. Do not croak
diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index 0c94d5037da..4bb52bf0bd5 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -5,3 +5,11 @@ members = [
"qemu-api",
"hw/char/pl011",
]
+
+[workspace.lints.rust]
+unexpected_cfgs = { level = "deny", check-cfg = [
+ 'cfg(MESON)', 'cfg(HAVE_GLIB_WITH_ALIGNED_ALLOC)',
+ 'cfg(has_offset_of)'] }
+
+# Prohibit code that is forbidden in Rust 2024
+unsafe_op_in_unsafe_fn = "deny"
diff --git a/rust/hw/char/pl011/Cargo.toml b/rust/hw/char/pl011/Cargo.toml
index a373906b9fb..58f3e859f7e 100644
--- a/rust/hw/char/pl011/Cargo.toml
+++ b/rust/hw/char/pl011/Cargo.toml
@@ -21,3 +21,6 @@ bilge = { version = "0.2.0" }
bilge-impl = { version = "0.2.0" }
qemu_api = { path = "../../../qemu-api" }
qemu_api_macros = { path = "../../../qemu-api-macros" }
+
+[lints]
+workspace = true
diff --git a/rust/qemu-api-macros/Cargo.toml b/rust/qemu-api-macros/Cargo.toml
index a8f7377106b..5a27b52ee6e 100644
--- a/rust/qemu-api-macros/Cargo.toml
+++ b/rust/qemu-api-macros/Cargo.toml
@@ -20,3 +20,6 @@ proc-macro = true
proc-macro2 = "1"
quote = "1"
syn = { version = "2", features = ["extra-traits"] }
+
+[lints]
+workspace = true
diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml
index cc716d75d46..669f288d1cb 100644
--- a/rust/qemu-api/Cargo.toml
+++ b/rust/qemu-api/Cargo.toml
@@ -23,6 +23,5 @@ version_check = "~0.9"
default = []
allocator = []
-[lints.rust]
-unexpected_cfgs = { level = "warn", check-cfg = ['cfg(MESON)', 'cfg(HAVE_GLIB_WITH_ALIGNED_ALLOC)',
- 'cfg(has_offset_of)'] }
+[lints]
+workspace = true
diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build
index 1ed79672cc9..d719c13f46d 100644
--- a/rust/qemu-api/meson.build
+++ b/rust/qemu-api/meson.build
@@ -1,5 +1,5 @@
_qemu_api_cfg = run_command(rustc_args,
- '--config-headers', config_host_h, '--features', '--lints', files('Cargo.toml'),
+ '--config-headers', config_host_h, '--features', files('Cargo.toml'),
capture: true, check: true).stdout().strip().splitlines()
# _qemu_api_cfg += ['--cfg', 'feature="allocator"']
diff --git a/scripts/rust/rustc_args.py b/scripts/rust/rustc_args.py
index 9b9778a1cac..9df131a02bd 100644
--- a/scripts/rust/rustc_args.py
+++ b/scripts/rust/rustc_args.py
@@ -38,11 +38,21 @@
class CargoTOML:
tomldata: Mapping[Any, Any]
+ workspace_data: Mapping[Any, Any]
check_cfg: Set[str]
- def __init__(self, path: str):
- with open(path, 'rb') as f:
- self.tomldata = tomllib.load(f)
+ def __init__(self, path: Optional[str], workspace: Optional[str]):
+ if path is not None:
+ with open(path, 'rb') as f:
+ self.tomldata = tomllib.load(f)
+ else:
+ self.tomldata = {"lints": {"workspace": True}}
+
+ if workspace is not None:
+ with open(workspace, 'rb') as f:
+ self.workspace_data = tomllib.load(f)
+ if "workspace" not in self.workspace_data:
+ self.workspace_data["workspace"] = {}
self.check_cfg = set(self.find_check_cfg())
@@ -54,10 +64,12 @@ def find_check_cfg(self) -> Iterable[str]:
@property
def lints(self) -> Mapping[Any, Any]:
- return self.get_table("lints")
+ return self.get_table("lints", True)
- def get_table(self, key: str) -> Mapping[Any, Any]:
+ def get_table(self, key: str, can_be_workspace: bool = False) -> Mapping[Any, Any]:
table = self.tomldata.get(key, {})
+ if can_be_workspace and table.get("workspace", False) is True:
+ table = self.workspace_data["workspace"].get(key, {})
return table
@@ -136,6 +148,16 @@ def main() -> None:
action="store",
dest="cargo_toml",
help="path to Cargo.toml file",
+ nargs='?',
+ )
+ parser.add_argument(
+ "--workspace",
+ metavar="DIR",
+ action="store",
+ dest="workspace",
+ help="path to root of the workspace",
+ required=False,
+ default=None,
)
parser.add_argument(
"--features",
@@ -168,7 +190,11 @@ def main() -> None:
logging.debug("args: %s", args)
rustc_version = tuple((int(x) for x in args.rustc_version.split('.')[0:2]))
- cargo_toml = CargoTOML(args.cargo_toml)
+ if args.workspace:
+ workspace_cargo_toml = Path(args.workspace, "Cargo.toml").resolve()
+ cargo_toml = CargoTOML(args.cargo_toml, str(workspace_cargo_toml))
+ else:
+ cargo_toml = CargoTOML(args.cargo_toml, None)
if args.lints:
for tok in generate_lint_flags(cargo_toml):
--
2.47.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 07/12] rust: build: move strict lints handling to rustc_args.py
[not found] <20241115163944.1917393-1-pbonzini@redhat.com>
` (5 preceding siblings ...)
2024-11-15 16:40 ` [PATCH 06/12] rust: cargo: store desired warning levels in workspace Cargo.toml Paolo Bonzini
@ 2024-11-15 16:40 ` Paolo Bonzini
2024-11-15 16:40 ` [PATCH 08/12] rust: fix a couple style issues from clippy Paolo Bonzini
` (4 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2024-11-15 16:40 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, berrange, junjie.mao, manos.pitsidianakis, kwolf
Make Cargo use unknown_lints = "allow" as well. This is more future
proof as we might add new lints to rust/Cargo.toml that are not supported
by older versions of rustc or clippy.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
meson.build | 12 ++++--------
rust/Cargo.toml | 6 ++++++
scripts/rust/rustc_args.py | 19 ++++++++++++++++---
3 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/meson.build b/meson.build
index 21e2a332d6c..a807e2a6354 100644
--- a/meson.build
+++ b/meson.build
@@ -123,19 +123,15 @@ if have_rust
rustc_args = [find_program('scripts/rust/rustc_args.py'),
'--rustc-version', rustc.version(),
'--workspace', meson.project_source_root() / 'rust']
+ if get_option('strict_rust_lints')
+ rustc_args += ['--strict-lints']
+ endif
+
rustfmt = find_program('rustfmt', required: false)
rustc_lint_args = run_command(rustc_args, '--lints',
capture: true, check: true).stdout().strip().splitlines()
- # Occasionally, we may need to silence warnings and clippy lints that
- # were only introduced in newer Rust compiler versions. Do not croak
- # in that case; a CI job with rust_strict_lints == true ensures that
- # we do not have misspelled allow() attributes.
- if not get_option('strict_rust_lints')
- rustc_lint_args += ['-A', 'unknown_lints']
- endif
-
# Apart from procedural macros, our Rust executables will often link
# with C code, so include all the libraries that C code needs. This
# is safe; https://github.com/rust-lang/rust/pull/54675 says that
diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index 4bb52bf0bd5..358c517bc56 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -11,5 +11,11 @@ unexpected_cfgs = { level = "deny", check-cfg = [
'cfg(MESON)', 'cfg(HAVE_GLIB_WITH_ALIGNED_ALLOC)',
'cfg(has_offset_of)'] }
+# Occasionally, we may need to silence warnings and clippy lints that
+# were only introduced in newer Rust compiler versions. Do not croak
+# in that case; a CI job with rust_strict_lints == true disables this
+# and ensures that we do not have misspelled allow() attributes.
+unknown_lints = "allow"
+
# Prohibit code that is forbidden in Rust 2024
unsafe_op_in_unsafe_fn = "deny"
diff --git a/scripts/rust/rustc_args.py b/scripts/rust/rustc_args.py
index 9df131a02bd..5525b3886fa 100644
--- a/scripts/rust/rustc_args.py
+++ b/scripts/rust/rustc_args.py
@@ -35,6 +35,8 @@
except ImportError:
import tomli as tomllib
+STRICT_LINTS = {"unknown_lints", "warnings"}
+
class CargoTOML:
tomldata: Mapping[Any, Any]
@@ -80,7 +82,7 @@ class LintFlag:
priority: int
-def generate_lint_flags(cargo_toml: CargoTOML) -> Iterable[str]:
+def generate_lint_flags(cargo_toml: CargoTOML, strict_lints: bool) -> Iterable[str]:
"""Converts Cargo.toml lints to rustc -A/-D/-F/-W flags."""
toml_lints = cargo_toml.lints
@@ -105,9 +107,13 @@ def generate_lint_flags(cargo_toml: CargoTOML) -> Iterable[str]:
# This may change if QEMU ever invokes clippy-driver or rustdoc by
# hand. For now, check the syntax but do not add non-rustc lints to
# the command line.
- if k == "rust":
+ if k == "rust" and not (strict_lints and lint in STRICT_LINTS):
lint_list.append(LintFlag(flags=[flag, prefix + lint], priority=priority))
+ if strict_lints:
+ for lint in STRICT_LINTS:
+ lint_list.append(LintFlag(flags=["-D", lint], priority=1000000))
+
lint_list.sort(key=lambda x: x.priority)
for lint in lint_list:
yield from lint.flags
@@ -184,6 +190,13 @@ def main() -> None:
required=False,
default="1.0.0",
)
+ parser.add_argument(
+ "--strict-lints",
+ action="store_true",
+ dest="strict_lints",
+ help="apply stricter checks (for nightly Rust)",
+ default=False,
+ )
args = parser.parse_args()
if args.verbose:
logging.basicConfig(level=logging.DEBUG)
@@ -197,7 +210,7 @@ def main() -> None:
cargo_toml = CargoTOML(args.cargo_toml, None)
if args.lints:
- for tok in generate_lint_flags(cargo_toml):
+ for tok in generate_lint_flags(cargo_toml, args.strict_lints):
print(tok)
if rustc_version >= (1, 80):
--
2.47.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 08/12] rust: fix a couple style issues from clippy
[not found] <20241115163944.1917393-1-pbonzini@redhat.com>
` (6 preceding siblings ...)
2024-11-15 16:40 ` [PATCH 07/12] rust: build: move strict lints handling to rustc_args.py Paolo Bonzini
@ 2024-11-15 16:40 ` Paolo Bonzini
2024-11-15 16:40 ` [PATCH 09/12] rust: build: establish a baseline of lints across all crates Paolo Bonzini
` (3 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2024-11-15 16:40 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, berrange, junjie.mao, manos.pitsidianakis, kwolf
These are reported as clippy::semicolon_inside_block and clippy::as_ptr_cast_mut.
clippy::semicolon_inside_block can be configured not to lint single-line
blocks; just go with the default.
Reviewed-by: Junjie Mao <junjie.mao@hotmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
rust/hw/char/pl011/src/device.rs | 8 +++++---
rust/hw/char/pl011/src/memory_ops.rs | 4 +++-
rust/qemu-api/tests/tests.rs | 2 +-
3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/device.rs
index 6556865fc22..e582a31e4d3 100644
--- a/rust/hw/char/pl011/src/device.rs
+++ b/rust/hw/char/pl011/src/device.rs
@@ -2,7 +2,7 @@
// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
// SPDX-License-Identifier: GPL-2.0-or-later
-use core::ptr::{addr_of, addr_of_mut, NonNull};
+use core::ptr::{addr_of_mut, NonNull};
use std::{
ffi::CStr,
os::raw::{c_int, c_uchar, c_uint, c_void},
@@ -499,7 +499,9 @@ pub fn update(&self) {
let flags = self.int_level & self.int_enabled;
for (irq, i) in self.interrupts.iter().zip(IRQMASK) {
// SAFETY: self.interrupts have been initialized in init().
- unsafe { qemu_set_irq(*irq, i32::from(flags & i != 0)) };
+ unsafe {
+ qemu_set_irq(*irq, i32::from(flags & i != 0));
+ }
}
}
@@ -601,7 +603,7 @@ pub fn post_load(&mut self, _version_id: u32) -> Result<(), ()> {
let sysbus: *mut SysBusDevice = dev.cast::<SysBusDevice>();
qdev_prop_set_chr(dev, c_str!("chardev").as_ptr(), chr);
- sysbus_realize_and_unref(sysbus, addr_of!(error_fatal) as *mut *mut Error);
+ sysbus_realize_and_unref(sysbus, addr_of_mut!(error_fatal));
sysbus_mmio_map(sysbus, 0, addr);
sysbus_connect_irq(sysbus, 0, irq);
dev
diff --git a/rust/hw/char/pl011/src/memory_ops.rs b/rust/hw/char/pl011/src/memory_ops.rs
index 169d485a4d2..c4e8599ba43 100644
--- a/rust/hw/char/pl011/src/memory_ops.rs
+++ b/rust/hw/char/pl011/src/memory_ops.rs
@@ -33,7 +33,9 @@
// SAFETY: self.char_backend is a valid CharBackend instance after it's been
// initialized in realize().
let cb_ptr = unsafe { core::ptr::addr_of_mut!(state.as_mut().char_backend) };
- unsafe { qemu_chr_fe_accept_input(cb_ptr) };
+ unsafe {
+ qemu_chr_fe_accept_input(cb_ptr);
+ }
val
}
diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs
index 43a4827de12..925f5a3c77b 100644
--- a/rust/qemu-api/tests/tests.rs
+++ b/rust/qemu-api/tests/tests.rs
@@ -74,6 +74,6 @@ impl Class for DummyClass {
unsafe {
module_call_init(module_init_type::MODULE_INIT_QOM);
- object_unref(object_new(DummyState::TYPE_NAME.as_ptr()) as *mut _);
+ object_unref(object_new(DummyState::TYPE_NAME.as_ptr()).cast());
}
}
--
2.47.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 09/12] rust: build: establish a baseline of lints across all crates
[not found] <20241115163944.1917393-1-pbonzini@redhat.com>
` (7 preceding siblings ...)
2024-11-15 16:40 ` [PATCH 08/12] rust: fix a couple style issues from clippy Paolo Bonzini
@ 2024-11-15 16:40 ` Paolo Bonzini
2024-11-15 16:40 ` [PATCH 10/12] rust: build: add "make clippy", "make rustfmt", "make rustdoc" Paolo Bonzini
` (2 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2024-11-15 16:40 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, berrange, junjie.mao, manos.pitsidianakis, kwolf
Many lints that default to allow can be helpful in detecting bugs or
keeping the code style homogeneous. Add them liberally, though perhaps
not as liberally as in hw/char/pl011/src/lib.rs. In particular, enabling
entire groups can be problematic because of bitrot when new links are
added in the future.
For Clippy, this is actually a feature that is only present in Cargo
1.74.0 but, since we are not using Cargo to *build* QEMU, only developers
will need a new-enough cargo and only to run tools such as clippy.
The requirement does not apply to distros that are building QEMU.
Reviewed-by: Junjie Mao <junjie.mao@hotmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
rust/Cargo.toml | 65 +++++++++++++++++++++++++++++++++++
rust/hw/char/pl011/src/lib.rs | 19 ++--------
rust/qemu-api/src/bindings.rs | 6 ++--
3 files changed, 71 insertions(+), 19 deletions(-)
diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index 358c517bc56..c3f7142d264 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -19,3 +19,68 @@ unknown_lints = "allow"
# Prohibit code that is forbidden in Rust 2024
unsafe_op_in_unsafe_fn = "deny"
+
+[workspace.lints.rustdoc]
+broken_intra_doc_links = "deny"
+invalid_html_tags = "deny"
+invalid_rust_codeblocks = "deny"
+bare_urls = "deny"
+unescaped_backticks = "deny"
+redundant_explicit_links = "deny"
+
+[workspace.lints.clippy]
+# default-warn lints
+result_unit_err = "allow"
+should_implement_trait = "deny"
+
+# default-allow lints
+as_underscore = "deny"
+assertions_on_result_states = "deny"
+bool_to_int_with_if = "deny"
+borrow_as_ptr = "deny"
+cast_lossless = "deny"
+dbg_macro = "deny"
+debug_assert_with_mut_call = "deny"
+derive_partial_eq_without_eq = "deny"
+doc_markdown = "deny"
+empty_structs_with_brackets = "deny"
+ignored_unit_patterns = "deny"
+implicit_clone = "deny"
+macro_use_imports = "deny"
+missing_const_for_fn = "deny"
+missing_safety_doc = "deny"
+multiple_crate_versions = "deny"
+mut_mut = "deny"
+needless_bitwise_bool = "deny"
+needless_pass_by_ref_mut = "deny"
+no_effect_underscore_binding = "deny"
+option_option = "deny"
+or_fun_call = "deny"
+ptr_as_ptr = "deny"
+pub_underscore_fields = "deny"
+redundant_clone = "deny"
+redundant_closure_for_method_calls = "deny"
+redundant_else = "deny"
+redundant_pub_crate = "deny"
+ref_binding_to_reference = "deny"
+ref_option_ref = "deny"
+return_self_not_must_use = "deny"
+same_name_method = "deny"
+semicolon_inside_block = "deny"
+shadow_unrelated = "deny"
+significant_drop_in_scrutinee = "deny"
+significant_drop_tightening = "deny"
+suspicious_operation_groupings = "deny"
+transmute_ptr_to_ptr = "deny"
+transmute_undefined_repr = "deny"
+type_repetition_in_bounds = "deny"
+unused_self = "deny"
+used_underscore_binding = "deny"
+
+# nice to have, but cannot be enabled yet
+#wildcard_imports = "deny" # still have many bindings::* imports
+#ptr_cast_constness = "deny" # needs 1.65.0 for cast_mut()/cast_const()
+
+# these may have false positives
+#option_if_let_else = "deny"
+cognitive_complexity = "deny"
diff --git a/rust/hw/char/pl011/src/lib.rs b/rust/hw/char/pl011/src/lib.rs
index cd0a49acb91..4dc0e8f345f 100644
--- a/rust/hw/char/pl011/src/lib.rs
+++ b/rust/hw/char/pl011/src/lib.rs
@@ -14,28 +14,15 @@
//! the [`registers`] module for register types.
#![deny(
- rustdoc::broken_intra_doc_links,
- rustdoc::redundant_explicit_links,
clippy::correctness,
clippy::suspicious,
clippy::complexity,
clippy::perf,
clippy::cargo,
clippy::nursery,
- clippy::style,
- // restriction group
- clippy::dbg_macro,
- clippy::as_underscore,
- clippy::assertions_on_result_states,
- // pedantic group
- clippy::doc_markdown,
- clippy::borrow_as_ptr,
- clippy::cast_lossless,
- clippy::option_if_let_else,
- clippy::missing_const_for_fn,
- clippy::cognitive_complexity,
- clippy::missing_safety_doc,
- )]
+ clippy::style
+)]
+#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::result_unit_err)]
extern crate bilge;
diff --git a/rust/qemu-api/src/bindings.rs b/rust/qemu-api/src/bindings.rs
index 0b76ec58bee..8a9b821bb91 100644
--- a/rust/qemu-api/src/bindings.rs
+++ b/rust/qemu-api/src/bindings.rs
@@ -7,10 +7,10 @@
non_snake_case,
non_upper_case_globals,
unsafe_op_in_unsafe_fn,
+ clippy::pedantic,
+ clippy::restriction,
+ clippy::style,
clippy::missing_const_for_fn,
- clippy::too_many_arguments,
- clippy::approx_constant,
- clippy::use_self,
clippy::useless_transmute,
clippy::missing_safety_doc
)]
--
2.47.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 10/12] rust: build: add "make clippy", "make rustfmt", "make rustdoc"
[not found] <20241115163944.1917393-1-pbonzini@redhat.com>
` (8 preceding siblings ...)
2024-11-15 16:40 ` [PATCH 09/12] rust: build: establish a baseline of lints across all crates Paolo Bonzini
@ 2024-11-15 16:40 ` Paolo Bonzini
2024-11-15 16:40 ` [PATCH 11/12] rust: ci: add job that runs Rust tools Paolo Bonzini
2024-11-15 16:40 ` [PATCH 12/12] rust: fix doc test syntax Paolo Bonzini
11 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2024-11-15 16:40 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, berrange, junjie.mao, manos.pitsidianakis, kwolf
Abstract common invocations of "cargo", that do not require copying
the generated bindgen file or setting up MESON_BUILD_ROOT.
In the future these could also do completely without cargo and invoke
the underlying programs directly.
Reviewed-by: Junjie Mao <junjie.mao@hotmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
rust/meson.build | 22 ++++++++++++++++++++++
rust/qemu-api/README.md | 10 ++++++----
rust/qemu-api/build.rs | 9 +++++++--
3 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/rust/meson.build b/rust/meson.build
index def77389cdd..91e52b8fb8e 100644
--- a/rust/meson.build
+++ b/rust/meson.build
@@ -2,3 +2,25 @@ subdir('qemu-api-macros')
subdir('qemu-api')
subdir('hw')
+
+cargo = find_program('cargo', required: false)
+
+if cargo.found()
+ run_target('clippy',
+ command: [config_host['MESON'], 'devenv',
+ '--workdir', '@CURRENT_SOURCE_DIR@',
+ cargo, 'clippy', '--tests'],
+ depends: bindings_rs)
+
+ run_target('rustfmt',
+ command: [config_host['MESON'], 'devenv',
+ '--workdir', '@CURRENT_SOURCE_DIR@',
+ cargo, 'fmt'],
+ depends: bindings_rs)
+
+ run_target('rustdoc',
+ command: [config_host['MESON'], 'devenv',
+ '--workdir', '@CURRENT_SOURCE_DIR@',
+ cargo, 'doc', '--no-deps', '--document-private-items'],
+ depends: bindings_rs)
+endif
diff --git a/rust/qemu-api/README.md b/rust/qemu-api/README.md
index 53810f48882..ed1b7ab263d 100644
--- a/rust/qemu-api/README.md
+++ b/rust/qemu-api/README.md
@@ -5,13 +5,15 @@ This library exports helper Rust types, Rust macros and C FFI bindings for inter
The C bindings can be generated with `bindgen`, using this build target:
```console
-$ ninja bindings.inc.rs
+$ make bindings.inc.rs
```
## Generate Rust documentation
-To generate docs for this crate, including private items:
+Common Cargo tasks can be performed from the QEMU build directory
-```sh
-pyvenv/bin/meson devenv -w ../rust cargo doc --no-deps --document-private-items
+```console
+$ make clippy
+$ make rustfmt
+$ make rustdoc
```
diff --git a/rust/qemu-api/build.rs b/rust/qemu-api/build.rs
index 06e79082b5f..33e7968ee76 100644
--- a/rust/qemu-api/build.rs
+++ b/rust/qemu-api/build.rs
@@ -20,8 +20,13 @@ fn main() -> Result<()> {
let file = Path::new(&file);
if !Path::new(&file).exists() {
panic!(concat!(
- "No generated C bindings found! If you want to run `cargo`, start a subshell\n",
- "with `meson devenv`, or point MESON_BUILD_ROOT to the top of the build tree."
+ "\n",
+ " No generated C bindings found! Maybe you wanted one of\n",
+ " `make clippy`, `make rustfmt`, `make rustdoc`?\n",
+ "\n",
+ " For other uses of `cargo`, start a subshell with\n",
+ " `pyvenv/bin/meson devenv`, or point MESON_BUILD_ROOT to\n",
+ " the top of the build tree."
));
}
--
2.47.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 11/12] rust: ci: add job that runs Rust tools
[not found] <20241115163944.1917393-1-pbonzini@redhat.com>
` (9 preceding siblings ...)
2024-11-15 16:40 ` [PATCH 10/12] rust: build: add "make clippy", "make rustfmt", "make rustdoc" Paolo Bonzini
@ 2024-11-15 16:40 ` Paolo Bonzini
2024-11-15 16:40 ` [PATCH 12/12] rust: fix doc test syntax Paolo Bonzini
11 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2024-11-15 16:40 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, berrange, junjie.mao, manos.pitsidianakis, kwolf
Code checks, as well as documentation generation, are not yet tied
to "make check" because they need new version of the Rust toolchain
(even nightly in the case of "rustfmt"). Run them in CI using the
existing nightly-Rust container.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
.gitlab-ci.d/static_checks.yml | 23 +++++++++++++++++++
.../dockerfiles/fedora-rust-nightly.docker | 4 ++++
tests/lcitool/refresh | 4 ++++
3 files changed, 31 insertions(+)
diff --git a/.gitlab-ci.d/static_checks.yml b/.gitlab-ci.d/static_checks.yml
index ad9f426a52f..f6f22875265 100644
--- a/.gitlab-ci.d/static_checks.yml
+++ b/.gitlab-ci.d/static_checks.yml
@@ -46,3 +46,26 @@ check-python-tox:
QEMU_JOB_OPTIONAL: 1
needs:
job: python-container
+
+check-rust-tools-nightly:
+ extends: .base_job_template
+ stage: test
+ image: $CI_REGISTRY_IMAGE/qemu/fedora-rust-nightly:$QEMU_CI_CONTAINER_TAG
+ script:
+ - source scripts/ci/gitlab-ci-section
+ - section_start test "Running Rust code checks"
+ - cd build
+ - pyvenv/bin/meson devenv -w ../rust ${CARGO-cargo} fmt --check
+ - make clippy
+ - make rustdoc
+ - section_end test
+ variables:
+ GIT_DEPTH: 1
+ needs:
+ - job: build-system-fedora-rust-nightly
+ artifacts: true
+ artifacts:
+ when: on_success
+ expire_in: 2 days
+ paths:
+ - rust/target/doc
diff --git a/tests/docker/dockerfiles/fedora-rust-nightly.docker b/tests/docker/dockerfiles/fedora-rust-nightly.docker
index 9180c8b5222..a8e4fb279a7 100644
--- a/tests/docker/dockerfiles/fedora-rust-nightly.docker
+++ b/tests/docker/dockerfiles/fedora-rust-nightly.docker
@@ -155,6 +155,7 @@ ENV PYTHON "/usr/bin/python3"
RUN dnf install -y wget
ENV RUSTUP_HOME=/usr/local/rustup CARGO_HOME=/usr/local/cargo
ENV RUSTC=/usr/local/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/rustc
+ENV CARGO=/usr/local/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo
RUN set -eux && \
rustArch='x86_64-unknown-linux-gnu' && \
rustupSha256='6aeece6993e902708983b209d04c0d1dbb14ebb405ddb87def578d41f920f56d' && \
@@ -165,10 +166,13 @@ RUN set -eux && \
./rustup-init -y --no-modify-path --profile default --default-toolchain nightly --default-host ${rustArch} && \
chmod -R a+w $RUSTUP_HOME $CARGO_HOME && \
/usr/local/cargo/bin/rustup --version && \
+ /usr/local/cargo/bin/rustup run nightly cargo --version && \
/usr/local/cargo/bin/rustup run nightly rustc --version && \
+ test "$CARGO" = "$(/usr/local/cargo/bin/rustup +nightly which cargo)" && \
test "$RUSTC" = "$(/usr/local/cargo/bin/rustup +nightly which rustc)"
ENV PATH=$CARGO_HOME/bin:$PATH
RUN /usr/local/cargo/bin/rustup run nightly cargo install bindgen-cli
+RUN $CARGO --list
# As a final step configure the user (if env is defined)
ARG USER
ARG UID
diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh
index 51012783c0f..6720516b942 100755
--- a/tests/lcitool/refresh
+++ b/tests/lcitool/refresh
@@ -121,6 +121,7 @@ fedora_rustup_nightly_extras = [
"RUN dnf install -y wget\n",
"ENV RUSTUP_HOME=/usr/local/rustup CARGO_HOME=/usr/local/cargo\n",
"ENV RUSTC=/usr/local/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/rustc\n",
+ "ENV CARGO=/usr/local/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo\n",
"RUN set -eux && \\\n",
" rustArch='x86_64-unknown-linux-gnu' && \\\n",
" rustupSha256='6aeece6993e902708983b209d04c0d1dbb14ebb405ddb87def578d41f920f56d' && \\\n",
@@ -131,10 +132,13 @@ fedora_rustup_nightly_extras = [
" ./rustup-init -y --no-modify-path --profile default --default-toolchain nightly --default-host ${rustArch} && \\\n",
" chmod -R a+w $RUSTUP_HOME $CARGO_HOME && \\\n",
" /usr/local/cargo/bin/rustup --version && \\\n",
+ " /usr/local/cargo/bin/rustup run nightly cargo --version && \\\n",
" /usr/local/cargo/bin/rustup run nightly rustc --version && \\\n",
+ ' test "$CARGO" = "$(/usr/local/cargo/bin/rustup +nightly which cargo)" && \\\n',
' test "$RUSTC" = "$(/usr/local/cargo/bin/rustup +nightly which rustc)"\n',
'ENV PATH=$CARGO_HOME/bin:$PATH\n',
'RUN /usr/local/cargo/bin/rustup run nightly cargo install bindgen-cli\n',
+ 'RUN $CARGO --list\n',
]
ubuntu2204_bindgen_extras = [
--
2.47.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 12/12] rust: fix doc test syntax
[not found] <20241115163944.1917393-1-pbonzini@redhat.com>
` (10 preceding siblings ...)
2024-11-15 16:40 ` [PATCH 11/12] rust: ci: add job that runs Rust tools Paolo Bonzini
@ 2024-11-15 16:40 ` Paolo Bonzini
11 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2024-11-15 16:40 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-rust, berrange, junjie.mao, manos.pitsidianakis, kwolf
Allow "cargo test --doc" to pass.
Reviewed-by: Junjie Mao <junjie.mao@hotmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
rust/qemu-api/src/zeroable.rs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/rust/qemu-api/src/zeroable.rs b/rust/qemu-api/src/zeroable.rs
index 13cdb2ccba5..6125aeed8b4 100644
--- a/rust/qemu-api/src/zeroable.rs
+++ b/rust/qemu-api/src/zeroable.rs
@@ -7,9 +7,9 @@
/// behavior. This trait in principle could be implemented as just:
///
/// ```
-/// const ZERO: Self = unsafe {
-/// ::core::mem::MaybeUninit::<$crate::bindings::Property>::zeroed().assume_init()
-/// },
+/// pub unsafe trait Zeroable: Default {
+/// const ZERO: Self = unsafe { ::core::mem::MaybeUninit::<Self>::zeroed().assume_init() };
+/// }
/// ```
///
/// The need for a manual implementation is only because `zeroed()` cannot
--
2.47.0
^ permalink raw reply related [flat|nested] 12+ messages in thread