1*074075aeSMasahiro Yamada#!/usr/bin/env python3 26ad7cbc0SNathan Huckleberry# SPDX-License-Identifier: GPL-2.0 36ad7cbc0SNathan Huckleberry# 46ad7cbc0SNathan Huckleberry# Copyright (C) Google LLC, 2020 56ad7cbc0SNathan Huckleberry# 66ad7cbc0SNathan Huckleberry# Author: Nathan Huckleberry <nhuck@google.com> 76ad7cbc0SNathan Huckleberry# 86ad7cbc0SNathan Huckleberry"""A helper routine run clang-tidy and the clang static-analyzer on 96ad7cbc0SNathan Huckleberrycompile_commands.json. 106ad7cbc0SNathan Huckleberry""" 116ad7cbc0SNathan Huckleberry 126ad7cbc0SNathan Huckleberryimport argparse 136ad7cbc0SNathan Huckleberryimport json 146ad7cbc0SNathan Huckleberryimport multiprocessing 156ad7cbc0SNathan Huckleberryimport os 166ad7cbc0SNathan Huckleberryimport subprocess 176ad7cbc0SNathan Huckleberryimport sys 186ad7cbc0SNathan Huckleberry 196ad7cbc0SNathan Huckleberry 206ad7cbc0SNathan Huckleberrydef parse_arguments(): 216ad7cbc0SNathan Huckleberry """Set up and parses command-line arguments. 226ad7cbc0SNathan Huckleberry Returns: 236ad7cbc0SNathan Huckleberry args: Dict of parsed args 246ad7cbc0SNathan Huckleberry Has keys: [path, type] 256ad7cbc0SNathan Huckleberry """ 266ad7cbc0SNathan Huckleberry usage = """Run clang-tidy or the clang static-analyzer on a 276ad7cbc0SNathan Huckleberry compilation database.""" 286ad7cbc0SNathan Huckleberry parser = argparse.ArgumentParser(description=usage) 296ad7cbc0SNathan Huckleberry 306ad7cbc0SNathan Huckleberry type_help = "Type of analysis to be performed" 316ad7cbc0SNathan Huckleberry parser.add_argument("type", 326ad7cbc0SNathan Huckleberry choices=["clang-tidy", "clang-analyzer"], 336ad7cbc0SNathan Huckleberry help=type_help) 346ad7cbc0SNathan Huckleberry path_help = "Path to the compilation database to parse" 356ad7cbc0SNathan Huckleberry parser.add_argument("path", type=str, help=path_help) 366ad7cbc0SNathan Huckleberry 376ad7cbc0SNathan Huckleberry return parser.parse_args() 386ad7cbc0SNathan Huckleberry 396ad7cbc0SNathan Huckleberry 406ad7cbc0SNathan Huckleberrydef init(l, a): 416ad7cbc0SNathan Huckleberry global lock 426ad7cbc0SNathan Huckleberry global args 436ad7cbc0SNathan Huckleberry lock = l 446ad7cbc0SNathan Huckleberry args = a 456ad7cbc0SNathan Huckleberry 466ad7cbc0SNathan Huckleberry 476ad7cbc0SNathan Huckleberrydef run_analysis(entry): 486ad7cbc0SNathan Huckleberry # Disable all checks, then re-enable the ones we want 496ad7cbc0SNathan Huckleberry checks = "-checks=-*," 506ad7cbc0SNathan Huckleberry if args.type == "clang-tidy": 516ad7cbc0SNathan Huckleberry checks += "linuxkernel-*" 526ad7cbc0SNathan Huckleberry else: 536ad7cbc0SNathan Huckleberry checks += "clang-analyzer-*" 546ad7cbc0SNathan Huckleberry p = subprocess.run(["clang-tidy", "-p", args.path, checks, entry["file"]], 556ad7cbc0SNathan Huckleberry stdout=subprocess.PIPE, 566ad7cbc0SNathan Huckleberry stderr=subprocess.STDOUT, 576ad7cbc0SNathan Huckleberry cwd=entry["directory"]) 586ad7cbc0SNathan Huckleberry with lock: 596ad7cbc0SNathan Huckleberry sys.stderr.buffer.write(p.stdout) 606ad7cbc0SNathan Huckleberry 616ad7cbc0SNathan Huckleberry 626ad7cbc0SNathan Huckleberrydef main(): 636ad7cbc0SNathan Huckleberry args = parse_arguments() 646ad7cbc0SNathan Huckleberry 656ad7cbc0SNathan Huckleberry lock = multiprocessing.Lock() 666ad7cbc0SNathan Huckleberry pool = multiprocessing.Pool(initializer=init, initargs=(lock, args)) 676ad7cbc0SNathan Huckleberry # Read JSON data into the datastore variable 686ad7cbc0SNathan Huckleberry with open(args.path, "r") as f: 696ad7cbc0SNathan Huckleberry datastore = json.load(f) 706ad7cbc0SNathan Huckleberry pool.map(run_analysis, datastore) 716ad7cbc0SNathan Huckleberry 726ad7cbc0SNathan Huckleberry 736ad7cbc0SNathan Huckleberryif __name__ == "__main__": 746ad7cbc0SNathan Huckleberry main() 75