The Meson Build System
http://mesonbuild.com/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
76 lines
3.0 KiB
76 lines
3.0 KiB
# SPDX-License-Identifier: Apache-2.0 |
|
# Copyright 2024 The Meson development team |
|
|
|
from __future__ import annotations |
|
from collections import defaultdict |
|
import os |
|
import tempfile |
|
import typing as T |
|
|
|
from .run_tool import run_tool_on_targets, run_with_buffered_output |
|
from .. import build, mlog |
|
from ..mesonlib import MachineChoice, PerMachine |
|
|
|
if T.TYPE_CHECKING: |
|
from ..compilers.rust import RustCompiler |
|
|
|
class ClippyDriver: |
|
def __init__(self, build: build.Build, tempdir: str): |
|
self.tools: PerMachine[T.List[str]] = PerMachine([], []) |
|
self.warned: T.DefaultDict[str, bool] = defaultdict(lambda: False) |
|
self.tempdir = tempdir |
|
for machine in MachineChoice: |
|
compilers = build.environment.coredata.compilers[machine] |
|
if 'rust' in compilers: |
|
compiler = T.cast('RustCompiler', compilers['rust']) |
|
self.tools[machine] = compiler.get_rust_tool('clippy-driver', build.environment) |
|
|
|
def warn_missing_clippy(self, machine: str) -> None: |
|
if self.warned[machine]: |
|
return |
|
mlog.warning(f'clippy-driver not found for {machine} machine') |
|
self.warned[machine] = True |
|
|
|
def __call__(self, target: T.Dict[str, T.Any]) -> T.Iterable[T.Coroutine[None, None, int]]: |
|
for src_block in target['target_sources']: |
|
if 'compiler' in src_block and src_block['language'] == 'rust': |
|
clippy = getattr(self.tools, src_block['machine']) |
|
if not clippy: |
|
self.warn_missing_clippy(src_block['machine']) |
|
continue |
|
|
|
cmdlist = list(clippy) |
|
prev = None |
|
lints_cap = None |
|
for arg in src_block['parameters']: |
|
if prev == '--cap-lints': |
|
cmdlist.append(prev) |
|
lints_cap = arg |
|
prev = None |
|
elif prev: |
|
prev = None |
|
continue |
|
if arg in {'--emit', '--out-dir', '--cap-lints'}: |
|
prev = arg |
|
else: |
|
cmdlist.append(arg) |
|
|
|
# no use in running clippy if it wouldn't print anything anyway |
|
if lints_cap == 'allow': |
|
break |
|
|
|
cmdlist.extend(src_block['sources']) |
|
# the default for --emit is to go all the way to linking, |
|
# 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('--out-dir') |
|
cmdlist.append(self.tempdir) |
|
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))
|
|
|