Another rust tool, another rough copy of the code to run clippy. Apart from the slightly different command lines, the output is in a directory and test targets are skipped. Knowing the output directory can be useful, so print that on successful execution of rustdoc. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>pull/14213/head
parent
ea678ed829
commit
41d1e78f15
3 changed files with 135 additions and 0 deletions
@ -0,0 +1,101 @@ |
||||
# 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 |
||||
from ..wrap import WrapMode, wrap |
||||
|
||||
if T.TYPE_CHECKING: |
||||
from ..compilers.rust import RustCompiler |
||||
|
||||
async def run_and_confirm_success(cmdlist: T.List[str], crate: str) -> int: |
||||
returncode = await run_with_buffered_output(cmdlist) |
||||
if returncode == 0: |
||||
print(mlog.green('Generated'), os.path.join('doc', crate)) |
||||
return returncode |
||||
|
||||
class Rustdoc: |
||||
def __init__(self, build: build.Build, tempdir: str, subprojects: T.Set[str]) -> None: |
||||
self.tools: PerMachine[T.List[str]] = PerMachine([], []) |
||||
self.warned: T.DefaultDict[str, bool] = defaultdict(lambda: False) |
||||
self.tempdir = tempdir |
||||
self.subprojects = subprojects |
||||
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('rustdoc', build.environment) |
||||
|
||||
def warn_missing_rustdoc(self, machine: str) -> None: |
||||
if self.warned[machine]: |
||||
return |
||||
mlog.warning(f'rustdoc 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]]: |
||||
if target['subproject'] is not None and target['subproject'] not in self.subprojects: |
||||
return |
||||
|
||||
for src_block in target['target_sources']: |
||||
if 'compiler' in src_block and src_block['language'] == 'rust': |
||||
rustdoc = getattr(self.tools, src_block['machine']) |
||||
if not rustdoc: |
||||
self.warn_missing_rustdoc(src_block['machine']) |
||||
continue |
||||
|
||||
cmdlist = list(rustdoc) |
||||
prev = None |
||||
crate_name = None |
||||
is_test = False |
||||
for arg in src_block['parameters']: |
||||
if prev: |
||||
if prev == '--crate-name': |
||||
cmdlist.extend((prev, arg)) |
||||
crate_name = arg |
||||
prev = None |
||||
continue |
||||
|
||||
if arg == '--test': |
||||
is_test = True |
||||
break |
||||
elif arg in {'--crate-name', '--emit', '--out-dir', '-l'}: |
||||
prev = arg |
||||
elif arg != '-g' and not arg.startswith('-l'): |
||||
cmdlist.append(arg) |
||||
|
||||
if is_test: |
||||
# --test has a completely different meaning for rustc and rustdoc; |
||||
# when using rust.test(), only the non-test target is documented |
||||
continue |
||||
if crate_name: |
||||
cmdlist.extend(src_block['sources']) |
||||
# Assume documentation is generated for the developer's use |
||||
cmdlist.append('--document-private-items') |
||||
cmdlist.append('-o') |
||||
cmdlist.append('doc') |
||||
yield run_and_confirm_success(cmdlist, crate_name) |
||||
else: |
||||
print(mlog.yellow('Skipping'), target['name'], '(no crate name)') |
||||
|
||||
def get_nonwrap_subprojects(build_data: build.Build) -> T.Set[str]: |
||||
wrap_resolver = wrap.Resolver( |
||||
build_data.environment.get_source_dir(), |
||||
build_data.subproject_dir, |
||||
wrap_mode=WrapMode.nodownload) |
||||
return set(sp |
||||
for sp in build_data.environment.coredata.initialized_subprojects |
||||
if sp and (sp not in wrap_resolver.wraps or wrap_resolver.wraps[sp].type is None)) |
||||
|
||||
def run(args: T.List[str]) -> int: |
||||
os.chdir(args[0]) |
||||
build_data = build.load(os.getcwd()) |
||||
subproject_list = get_nonwrap_subprojects(build_data) |
||||
with tempfile.TemporaryDirectory() as d: |
||||
return run_tool_on_targets(Rustdoc(build_data, d, subproject_list)) |
Loading…
Reference in new issue