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.

71 lines
2.4 KiB

# SPDX-License-Identifier: Apache-2.0
# Copyright 2019 The Meson development team
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_clang_tool, run_with_buffered_output
from ..environment import detect_clangtidy, detect_clangapply
import typing as T
async def run_clang_tidy(fname: Path, tidyexe: list, builddir: Path, fixesdir: T.Optional[Path]) -> int:
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 await run_with_buffered_output(tidyexe + args + ['-quiet', '-p', str(builddir), str(fname)])
def run(args: T.List[str]) -> int:
parser = argparse.ArgumentParser()
parser.add_argument('--fix', action='store_true')
scripts: make clang tools obey b_colorout Right now, the clang-tidy and clang-format targets use the program default and do not let b_colorout decide whether to colorize output. However, the wrappers that run the tool are going to be changed to buffer output, and that would disable colorization unconditionally. So pass a --color option to the tools and use it when building the command line. clang-format's -fcolor-diagnostics option simply does not work, and the "right" (or at least working) option is --color which is undocumented. --color is present all the way back to clang 10, but I digged into clang-format's source code to figure out what's happening. The problem is that -fcolor-diagnostics is a complete no-operation; in fact it is a bool that is initialized to true. gdb shows: (gdb) p ShowColors $2 = {<llvm::cl::Option> = { ... <llvm::cl::opt_storage<bool, false, false>> = {Value = true, ... }, ...} on entry to clang-format's main, meaning that specifying the option on the command line does nothing at all. To see how clang-format determines whether to use colors you need to look at enters SMDiagnostic::print, which simply does ColorMode Mode = ShowColors ? ColorMode::Auto : ColorMode::Disable; showing once more that in fact the option cannot force-on the colors ( -fno-color-diagnostics instead works). Continuing in SMDiagnostic::print, this RAII constructor would write the escape sequence to the terminal: WithColor S(OS, raw_ostream::SAVEDCOLOR, true, false, Mode); It ends up in WithColor::changeColor, which does if (colorsEnabled()) OS.changeColor(Color, Bold, BG); Digging further down, colorsEnabled() is where the Mode member is consulted: bool WithColor::colorsEnabled() { switch (Mode) { case ColorMode::Enable: return true; case ColorMode::Disable: return false; case ColorMode::Auto: return AutoDetectFunction(OS); } llvm_unreachable("All cases handled above."); } and the "AutoDetectFunction" is static bool DefaultAutoDetectFunction(const raw_ostream &OS) { return *UseColor == cl::BOU_UNSET ? OS.has_colors() : *UseColor == cl::BOU_TRUE; } UseColor is controlled by the "--color" option, so if that option was unset you go to OS.has_colors() even in the presence of -fcolor-diagnostics. This has been around for over 5 years in clang-format, and it was present even earlier, so use it in meson as well. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
3 months ago
parser.add_argument('--color', default='always')
parser.add_argument('sourcedir')
parser.add_argument('builddir')
options = parser.parse_args(args)
srcdir = Path(options.sourcedir)
builddir = Path(options.builddir)
tidyexe = detect_clangtidy()
if not tidyexe:
print(f'Could not execute clang-tidy "{" ".join(tidyexe)}"')
return 1
scripts: make clang tools obey b_colorout Right now, the clang-tidy and clang-format targets use the program default and do not let b_colorout decide whether to colorize output. However, the wrappers that run the tool are going to be changed to buffer output, and that would disable colorization unconditionally. So pass a --color option to the tools and use it when building the command line. clang-format's -fcolor-diagnostics option simply does not work, and the "right" (or at least working) option is --color which is undocumented. --color is present all the way back to clang 10, but I digged into clang-format's source code to figure out what's happening. The problem is that -fcolor-diagnostics is a complete no-operation; in fact it is a bool that is initialized to true. gdb shows: (gdb) p ShowColors $2 = {<llvm::cl::Option> = { ... <llvm::cl::opt_storage<bool, false, false>> = {Value = true, ... }, ...} on entry to clang-format's main, meaning that specifying the option on the command line does nothing at all. To see how clang-format determines whether to use colors you need to look at enters SMDiagnostic::print, which simply does ColorMode Mode = ShowColors ? ColorMode::Auto : ColorMode::Disable; showing once more that in fact the option cannot force-on the colors ( -fno-color-diagnostics instead works). Continuing in SMDiagnostic::print, this RAII constructor would write the escape sequence to the terminal: WithColor S(OS, raw_ostream::SAVEDCOLOR, true, false, Mode); It ends up in WithColor::changeColor, which does if (colorsEnabled()) OS.changeColor(Color, Bold, BG); Digging further down, colorsEnabled() is where the Mode member is consulted: bool WithColor::colorsEnabled() { switch (Mode) { case ColorMode::Enable: return true; case ColorMode::Disable: return false; case ColorMode::Auto: return AutoDetectFunction(OS); } llvm_unreachable("All cases handled above."); } and the "AutoDetectFunction" is static bool DefaultAutoDetectFunction(const raw_ostream &OS) { return *UseColor == cl::BOU_UNSET ? OS.has_colors() : *UseColor == cl::BOU_TRUE; } UseColor is controlled by the "--color" option, so if that option was unset you go to OS.has_colors() even in the presence of -fcolor-diagnostics. This has been around for over 5 years in clang-format, and it was present even earlier, so use it in meson as well. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
3 months ago
if options.color == 'always' or options.color == 'auto' and sys.stdout.isatty():
tidyexe += ['--use-color']
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_clang_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