X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ceph%2Fsrc%2Farrow%2Fcpp%2Fbuild-support%2Frun_clang_tidy.py;fp=ceph%2Fsrc%2Farrow%2Fcpp%2Fbuild-support%2Frun_clang_tidy.py;h=e5211be84e554e85c59510b3ea806522c1faa763;hb=1d09f67e50a235260a0812cca2fb044674d88150;hp=0000000000000000000000000000000000000000;hpb=a653f20b2fb9a1c0c3e465a23074d91f26031b5d;p=ceph.git diff --git a/ceph/src/arrow/cpp/build-support/run_clang_tidy.py b/ceph/src/arrow/cpp/build-support/run_clang_tidy.py new file mode 100755 index 000000000..e5211be84 --- /dev/null +++ b/ceph/src/arrow/cpp/build-support/run_clang_tidy.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from __future__ import print_function +import argparse +import multiprocessing as mp +import lintutils +from subprocess import PIPE +import sys +from functools import partial + + +def _get_chunk_key(filenames): + # lists are not hashable so key on the first filename in a chunk + return filenames[0] + + +# clang-tidy outputs complaints in '/path:line_number: complaint' format, +# so we can scan its output to get a list of files to fix +def _check_some_files(completed_processes, filenames): + result = completed_processes[_get_chunk_key(filenames)] + return lintutils.stdout_pathcolonline(result, filenames) + + +def _check_all(cmd, filenames): + # each clang-tidy instance will process 16 files + chunks = lintutils.chunk(filenames, 16) + cmds = [cmd + some for some in chunks] + results = lintutils.run_parallel(cmds, stderr=PIPE, stdout=PIPE) + error = False + # record completed processes (keyed by the first filename in the input + # chunk) for lookup in _check_some_files + completed_processes = { + _get_chunk_key(some): result + for some, result in zip(chunks, results) + } + checker = partial(_check_some_files, completed_processes) + pool = mp.Pool() + try: + # check output of completed clang-tidy invocations in parallel + for problem_files, stdout in pool.imap(checker, chunks): + if problem_files: + msg = "clang-tidy suggested fixes for {}" + print("\n".join(map(msg.format, problem_files))) + error = True + except Exception: + error = True + raise + finally: + pool.terminate() + pool.join() + + if error: + sys.exit(1) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Runs clang-tidy on all ") + parser.add_argument("--clang_tidy_binary", + required=True, + help="Path to the clang-tidy binary") + parser.add_argument("--exclude_globs", + help="Filename containing globs for files " + "that should be excluded from the checks") + parser.add_argument("--compile_commands", + required=True, + help="compile_commands.json to pass clang-tidy") + parser.add_argument("--source_dir", + required=True, + help="Root directory of the source code") + parser.add_argument("--fix", default=False, + action="store_true", + help="If specified, will attempt to fix the " + "source code instead of recommending fixes, " + "defaults to %(default)s") + parser.add_argument("--quiet", default=False, + action="store_true", + help="If specified, only print errors") + arguments = parser.parse_args() + + exclude_globs = [] + if arguments.exclude_globs: + for line in open(arguments.exclude_globs): + exclude_globs.append(line.strip()) + + linted_filenames = [] + for path in lintutils.get_sources(arguments.source_dir, exclude_globs): + linted_filenames.append(path) + + if not arguments.quiet: + msg = 'Tidying {}' if arguments.fix else 'Checking {}' + print("\n".join(map(msg.format, linted_filenames))) + + cmd = [ + arguments.clang_tidy_binary, + '-p', + arguments.compile_commands + ] + if arguments.fix: + cmd.append('-fix') + results = lintutils.run_parallel( + [cmd + some for some in lintutils.chunk(linted_filenames, 16)]) + for returncode, stdout, stderr in results: + if returncode != 0: + sys.exit(returncode) + + else: + _check_all(cmd, linted_filenames)