From d2ea7cdad6868411c09b39fa3d8978a77ac336d7 Mon Sep 17 00:00:00 2001 From: John Turner Date: Sun, 30 Nov 2025 15:00:14 -0500 Subject: [PATCH] add clippy-json target Add a clippy-json target to the ninja script. This is useful for rust-analyzer, which requires an "external check command" to function when not using cargo. This also changes the --emit option in the clippy script to "emit", without this, clippy will fail with errors about missing libraries. These would normally be created with the normal compilation target, but we can't rely on that, because if it fails, clippy-json never runs, and you won't get error messages to the LSP. --- mesonbuild/backend/ninjabackend.py | 12 ++++++++++++ mesonbuild/scripts/clippy.py | 8 +++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 086d19566adf..34d1b9aac920 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -3947,6 +3947,17 @@ def generate_clippy(self) -> None: elem.add_dep(list(self.all_structured_sources)) self.add_build(elem) + def generate_clippy_json(self) -> None: + if 'clippy-json' in self.all_outputs or not self.have_language('rust'): + return + + cmd = self.environment.get_build_command() + \ + ['--internal', 'clippy', self.environment.build_dir, '--error-format=json'] + elem = self.create_phony_target('clippy-json', 'CUSTOM_COMMAND', 'PHONY') + elem.add_item('COMMAND', cmd) + elem.add_item('pool', 'console') + self.add_build(elem) + def generate_rustdoc(self) -> None: if 'rustdoc' in self.all_outputs or not self.have_language('rust'): return @@ -4036,6 +4047,7 @@ def generate_utils(self) -> None: self.generate_clangformat() self.generate_clangtidy() self.generate_clippy() + self.generate_clippy_json() self.generate_rustdoc() self.generate_tags('etags', 'TAGS') self.generate_tags('ctags', 'ctags') diff --git a/mesonbuild/scripts/clippy.py b/mesonbuild/scripts/clippy.py index 0ea7a3429cda..0a8d857795ab 100644 --- a/mesonbuild/scripts/clippy.py +++ b/mesonbuild/scripts/clippy.py @@ -15,7 +15,7 @@ from ..compilers.rust import RustCompiler class ClippyDriver: - def __init__(self, build: build.Build, tempdir: str): + def __init__(self, build: build.Build, tempdir: str, args: list[str]): self.tools: PerMachine[T.List[str]] = PerMachine([], []) self.warned: T.DefaultDict[str, bool] = defaultdict(lambda: False) self.tempdir = tempdir @@ -24,6 +24,7 @@ def __init__(self, build: build.Build, tempdir: str): if 'rust' in compilers: compiler = T.cast('RustCompiler', compilers['rust']) self.tools[machine] = compiler.get_rust_tool('clippy-driver') + self.args = args def warn_missing_clippy(self, machine: str) -> None: if self.warned[machine]: @@ -64,13 +65,14 @@ def __call__(self, target: T.Dict[str, T.Any]) -> T.Iterable[T.Coroutine[None, N # and --emit dep-info= is not enough for clippy to do # enough analysis, so use --emit metadata. cmdlist.append('--emit') - cmdlist.append('metadata') + cmdlist.append('link') cmdlist.append('--out-dir') cmdlist.append(self.tempdir) + cmdlist += self.args yield run_with_buffered_output(cmdlist) def run(args: T.List[str]) -> int: os.chdir(args[0]) build_data = build.load(os.getcwd()) with tempfile.TemporaryDirectory() as d: - return run_tool_on_targets(ClippyDriver(build_data, d)) + return run_tool_on_targets(ClippyDriver(build_data, d, args[1:]))