diff options
-rw-r--r-- | meson.build | 3 | ||||
-rw-r--r-- | rust/qemu-api/meson.build | 4 | ||||
-rw-r--r-- | scripts/rust/rustc_args.py | 83 |
3 files changed, 86 insertions, 4 deletions
diff --git a/meson.build b/meson.build index 2f1f2ae..1e1d8f5 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 2ff6d2c..1ed7967 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 942dd2b..9b9778a 100644 --- a/scripts/rust/rustc_args.py +++ b/scripts/rust/rustc_args.py @@ -25,9 +25,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. """ 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 @@ class CargoTOML: 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) |