^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #!/usr/bin/env python3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) # SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) # Copyright (C) Google LLC, 2020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) # Author: Nathan Huckleberry <nhuck@google.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) """A helper routine run clang-tidy and the clang static-analyzer on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) compile_commands.json.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) import argparse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) import json
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) import multiprocessing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) import os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) import subprocess
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) import sys
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) def parse_arguments():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) """Set up and parses command-line arguments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) args: Dict of parsed args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) Has keys: [path, type]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) usage = """Run clang-tidy or the clang static-analyzer on a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) compilation database."""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) parser = argparse.ArgumentParser(description=usage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) type_help = "Type of analysis to be performed"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) parser.add_argument("type",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) choices=["clang-tidy", "clang-analyzer"],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) help=type_help)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) path_help = "Path to the compilation database to parse"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) parser.add_argument("path", type=str, help=path_help)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return parser.parse_args()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) def init(l, a):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) global lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) global args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) lock = l
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) args = a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) def run_analysis(entry):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) # Disable all checks, then re-enable the ones we want
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) checks = "-checks=-*,"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if args.type == "clang-tidy":
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) checks += "linuxkernel-*"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) checks += "clang-analyzer-*"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) p = subprocess.run(["clang-tidy", "-p", args.path, checks, entry["file"]],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) stdout=subprocess.PIPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) stderr=subprocess.STDOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) cwd=entry["directory"])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) with lock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) sys.stderr.buffer.write(p.stdout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) def main():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) args = parse_arguments()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) lock = multiprocessing.Lock()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) pool = multiprocessing.Pool(initializer=init, initargs=(lock, args))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) # Read JSON data into the datastore variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) with open(args.path, "r") as f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) datastore = json.load(f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) pool.map(run_analysis, datastore)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if __name__ == "__main__":
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) main()