diff options
| author | Jonathon Anderson <anderson.jonathonm@gmail.com> | 2024-08-20 08:59:37 -0500 |
|---|---|---|
| committer | Dylan Baker <dylan@pnwbakers.com> | 2024-09-24 14:55:45 -0700 |
| commit | 8eaeff5b1f3057f827dfc95ac3987903c9bcb828 (patch) | |
| tree | f1ec6db6e77396b3f7b6cf142ee264a96122892b /mesonbuild/scripts | |
| parent | f3daf6265aa412c2d54784100c8618e9008a2f9d (diff) | |
| download | meson-8eaeff5b1f3057f827dfc95ac3987903c9bcb828.tar.gz | |
clang-tidy: Avoid spawning too many threads
The clang-tidy-fix target uses run-clang-tidy to do the fixing, however
this script itself spawns `os.cpu_count()` threads as part of its
internal parallelism. When combined with Meson's parallelism this
results in the creation of potentially thousands of unecessary threads.
This commit rewrites the clang-tidy-fix to perform the same task
run-clang-tidy does but exclusively on Meson's thread pool. "Fix-it"
snippets are saved to `meson-private/clang-tidy-fix/` by a parallel
clang-tidy phase, afterwards (to avoid races) all collected fixes are
applied with a single call to clang-apply-replacements.
Diffstat (limited to 'mesonbuild/scripts')
| -rw-r--r-- | mesonbuild/scripts/clangtidy.py | 50 |
1 files changed, 43 insertions, 7 deletions
diff --git a/mesonbuild/scripts/clangtidy.py b/mesonbuild/scripts/clangtidy.py index 1e0c4a5a3..a922f8514 100644 --- a/mesonbuild/scripts/clangtidy.py +++ b/mesonbuild/scripts/clangtidy.py @@ -6,15 +6,22 @@ from __future__ import annotations import argparse import subprocess from pathlib import Path +import tempfile +import os +import shutil +import sys from .run_tool import run_tool +from ..environment import detect_clangtidy, detect_clangapply import typing as T -def run_clang_tidy(fname: Path, builddir: Path) -> subprocess.CompletedProcess: - return subprocess.run(['clang-tidy', '-quiet', '-p', str(builddir), str(fname)]) - -def run_clang_tidy_fix(fname: Path, builddir: Path) -> subprocess.CompletedProcess: - return subprocess.run(['run-clang-tidy', '-fix', '-format', '-quiet', '-p', str(builddir), str(fname)]) +def run_clang_tidy(fname: Path, tidyexe: list, builddir: Path, fixesdir: T.Optional[Path]) -> subprocess.CompletedProcess: + args = [] + if fixesdir is not None: + handle, name = tempfile.mkstemp(prefix=fname.name + '.', suffix='.yaml', dir=fixesdir) + os.close(handle) + args.extend(['-export-fixes', name]) + return subprocess.run(tidyexe + args + ['-quiet', '-p', str(builddir), str(fname)]) def run(args: T.List[str]) -> int: parser = argparse.ArgumentParser() @@ -26,5 +33,34 @@ def run(args: T.List[str]) -> int: srcdir = Path(options.sourcedir) builddir = Path(options.builddir) - run_func = run_clang_tidy_fix if options.fix else run_clang_tidy - return run_tool('clang-tidy', srcdir, builddir, run_func, builddir) + tidyexe = detect_clangtidy() + if not tidyexe: + print(f'Could not execute clang-tidy "{" ".join(tidyexe)}"') + return 1 + + fixesdir: T.Optional[Path] = None + if options.fix: + applyexe = detect_clangapply() + if not applyexe: + print(f'Could not execute clang-apply-replacements "{" ".join(applyexe)}"') + return 1 + + fixesdir = builddir / 'meson-private' / 'clang-tidy-fix' + if fixesdir.is_dir(): + shutil.rmtree(fixesdir) + elif fixesdir.exists(): + fixesdir.unlink() + fixesdir.mkdir(parents=True) + + tidyret = run_tool('clang-tidy', srcdir, builddir, run_clang_tidy, tidyexe, builddir, fixesdir) + if fixesdir is not None: + print('Applying fix-its...') + applyret = subprocess.run(applyexe + ['-format', '-style=file', '-ignore-insert-conflict', fixesdir]).returncode + + if tidyret != 0: + print('Errors encountered while running clang-tidy', file=sys.stderr) + return tidyret + if fixesdir is not None and applyret != 0: + print('Errors encountered while running clang-apply-replacements', file=sys.stderr) + return applyret + return 0 |
