diff --git a/meson/clang-tidy/clang-tidy-runner.py b/meson/clang-tidy/clang-tidy-runner.py new file mode 100755 index 000000000..c36e66b41 --- /dev/null +++ b/meson/clang-tidy/clang-tidy-runner.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +""" +Runs run-clang-tidy. A bit meta. Maybe it will replace run-clang-tidy one day +because the run-clang-tidy UX is so questionable. +""" + +# I hereby dedicate this script to fuck you meson. +# I cannot simply write my code to invoke a subprocess in a meson file because +# Meson corrupts backslashes in command line args to subprocesses. +# This is allegedly for "Windows support", but last time I checked Windows +# neither needs nor wants you to corrupt its command lines. +# https://github.com/mesonbuild/meson/issues/1564 + +import multiprocessing +import subprocess +import os +import sys +from pathlib import Path + + +def default_concurrency(): + return min(multiprocessing.cpu_count(), + int(os.environ.get("NIX_BUILD_CORES", "16"))) + + +def go(exe: str, plugin_path: Path, compile_commands_json_dir: Path, jobs: int, + paths: list[Path], werror: bool, fix: bool): + args = [ + # XXX: This explicitly invokes it with python because of a nixpkgs bug + # where clang-unwrapped does not patch interpreters in run-clang-tidy. + # However, making clang-unwrapped depend on python is also silly, so idk. + sys.executable, + exe, + '-quiet', + '-load', + plugin_path, + '-p', + compile_commands_json_dir, + '-j', + str(jobs), + '-header-filter', + r'src/[^/]+/.*\.hh' + ] + if werror: + args += ['-warnings-as-errors', '*'] + if fix: + args += ['-fix'] + args += ['--'] + args += paths + os.execvp(sys.executable, args) + + +def main(): + import argparse + + ap = argparse.ArgumentParser(description='Runs run-clang-tidy for you') + ap.add_argument('--jobs', + '-j', + type=int, + default=default_concurrency(), + help='Parallel linting jobs to run') + ap.add_argument('--plugin-path', + type=Path, + help='Path to the Lix clang-tidy plugin') + # FIXME: maybe we should integrate this so it just fixes the compdb for you and throws it in a tempdir? + ap.add_argument( + '--compdb-path', + type=Path, + help= + 'Path to the directory containing the fixed-up compilation database from clean_compdb' + ) + ap.add_argument('--werror', + action='store_true', + help='Warnings get turned into errors') + ap.add_argument('--fix', + action='store_true', + help='Apply fixes for warnings') + ap.add_argument('--run-clang-tidy-path', + default='run-clang-tidy', + help='Path to run-clang-tidy') + ap.add_argument('paths', nargs='*', help='Source paths to check') + args = ap.parse_args() + + go(args.run_clang_tidy_path, args.plugin_path, args.compdb_path, args.jobs, + args.paths, args.werror, args.fix) + + +if __name__ == '__main__': + main() diff --git a/meson/clang-tidy/clean_compdb.py b/meson/clang-tidy/clean_compdb.py index a3fc77204..461488f27 100755 --- a/meson/clang-tidy/clean_compdb.py +++ b/meson/clang-tidy/clean_compdb.py @@ -13,8 +13,8 @@ def process_compdb(compdb: list[dict]) -> list[dict]: out = [] eat_next = False for i, arg in enumerate(args): - if arg == '-fpch-preprocess': - # as used with gcc + if arg in ['-fpch-preprocess', '-fpch-instantiate-templates']: + # -fpch-preprocess as used with gcc, -fpch-instantiate-templates as used by clang continue elif arg == '-include-pch' or (arg == '-include' and args[i + 1] == 'precompiled-headers.hh'): # -include-pch some-pch (clang), or -include some-pch (gcc) diff --git a/meson/clang-tidy/meson.build b/meson/clang-tidy/meson.build index 1cd85a708..1da0661f9 100644 --- a/meson/clang-tidy/meson.build +++ b/meson/clang-tidy/meson.build @@ -57,34 +57,18 @@ build_all_generated_headers = custom_target( ) if lix_clang_tidy_so_found - default_concurrency = run_command(python, '-c', ''' -import multiprocessing -import os -print(min(multiprocessing.cpu_count(), int(os.environ.get("NIX_BUILD_CORES", "16")))) - ''', check : true).stdout() - run_clang_tidy_args = [ - '-load', - lix_clang_tidy_so, - '-p', - # We have to workaround a run-clang-tidy bug too, so we must give the - # directory name rather than the actual compdb file. - # https://github.com/llvm/llvm-project/issues/101440 - meson.current_build_dir(), - '-quiet', - '-j', default_concurrency, + meson.current_source_dir() / 'clang-tidy-runner.py', + '--run-clang-tidy-path', run_clang_tidy, + '--compdb-path', meson.current_build_dir(), + '--plugin-path', lix_clang_tidy_so, ] run_target( 'clang-tidy', command : [ - # XXX: This explicitly invokes it with python because of a nixpkgs bug - # where clang-unwrapped does not patch interpreters in run-clang-tidy. - # However, making clang-unwrapped depend on python is also silly, so idk. python, - run_clang_tidy, run_clang_tidy_args, - '-warnings-as-errors', - '*', + '--werror', ], depends : [ build_all_generated_headers, @@ -94,9 +78,8 @@ print(min(multiprocessing.cpu_count(), int(os.environ.get("NIX_BUILD_CORES", "16 'clang-tidy-fix', command : [ python, - run_clang_tidy, run_clang_tidy_args, - '-fix', + '--fix', ], depends : [ build_all_generated_headers,