1*d9f75844SAndroid Build Coastguard Worker#!/usr/bin/env vpython3 2*d9f75844SAndroid Build Coastguard Worker 3*d9f75844SAndroid Build Coastguard Worker# Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. 4*d9f75844SAndroid Build Coastguard Worker# 5*d9f75844SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license 6*d9f75844SAndroid Build Coastguard Worker# that can be found in the LICENSE file in the root of the source 7*d9f75844SAndroid Build Coastguard Worker# tree. An additional intellectual property rights grant can be found 8*d9f75844SAndroid Build Coastguard Worker# in the file PATENTS. All contributing project authors may 9*d9f75844SAndroid Build Coastguard Worker# be found in the AUTHORS file in the root of the source tree. 10*d9f75844SAndroid Build Coastguard Worker"""Invoke clang-tidy tool. 11*d9f75844SAndroid Build Coastguard Worker 12*d9f75844SAndroid Build Coastguard WorkerUsage: clang_tidy.py file.cc [clang-tidy-args...] 13*d9f75844SAndroid Build Coastguard Worker 14*d9f75844SAndroid Build Coastguard WorkerJust a proof of concept! 15*d9f75844SAndroid Build Coastguard WorkerWe use an embedded clang-tidy whose version doesn't match clang++. 16*d9f75844SAndroid Build Coastguard Worker""" 17*d9f75844SAndroid Build Coastguard Worker 18*d9f75844SAndroid Build Coastguard Workerimport argparse 19*d9f75844SAndroid Build Coastguard Workerimport os 20*d9f75844SAndroid Build Coastguard Workerimport shutil 21*d9f75844SAndroid Build Coastguard Workerimport subprocess 22*d9f75844SAndroid Build Coastguard Workerimport sys 23*d9f75844SAndroid Build Coastguard Workerimport tempfile 24*d9f75844SAndroid Build Coastguard Workerfrom presubmit_checks_lib.build_helpers import (GetClangTidyPath, 25*d9f75844SAndroid Build Coastguard Worker GetCompilationCommand) 26*d9f75844SAndroid Build Coastguard Worker 27*d9f75844SAndroid Build Coastguard Worker# We enable all checkers by default for investigation purpose. 28*d9f75844SAndroid Build Coastguard Worker# This includes clang-analyzer-* checks. 29*d9f75844SAndroid Build Coastguard Worker# Individual checkers can be disabled via command line options. 30*d9f75844SAndroid Build Coastguard Worker# TODO(bugs.webrtc.com/10258): Select checkers relevant to webrtc guidelines. 31*d9f75844SAndroid Build Coastguard WorkerCHECKER_OPTION = '-checks=*' 32*d9f75844SAndroid Build Coastguard Worker 33*d9f75844SAndroid Build Coastguard Worker 34*d9f75844SAndroid Build Coastguard Workerdef Process(filepath, args): 35*d9f75844SAndroid Build Coastguard Worker # Build directory is needed to gather compilation flags. 36*d9f75844SAndroid Build Coastguard Worker # Create a temporary one (instead of reusing an existing one) 37*d9f75844SAndroid Build Coastguard Worker # to keep the CLI simple and unencumbered. 38*d9f75844SAndroid Build Coastguard Worker out_dir = tempfile.mkdtemp('clang_tidy') 39*d9f75844SAndroid Build Coastguard Worker 40*d9f75844SAndroid Build Coastguard Worker try: 41*d9f75844SAndroid Build Coastguard Worker gn_args = [] # Use default build. 42*d9f75844SAndroid Build Coastguard Worker command = GetCompilationCommand(filepath, gn_args, out_dir) 43*d9f75844SAndroid Build Coastguard Worker 44*d9f75844SAndroid Build Coastguard Worker # Remove warning flags. They aren't needed and they cause trouble 45*d9f75844SAndroid Build Coastguard Worker # when clang-tidy doesn't match most recent clang. 46*d9f75844SAndroid Build Coastguard Worker # Same battle for -f (e.g. -fcomplete-member-pointers). 47*d9f75844SAndroid Build Coastguard Worker command = [ 48*d9f75844SAndroid Build Coastguard Worker arg for arg in command 49*d9f75844SAndroid Build Coastguard Worker if not (arg.startswith('-W') or arg.startswith('-f')) 50*d9f75844SAndroid Build Coastguard Worker ] 51*d9f75844SAndroid Build Coastguard Worker 52*d9f75844SAndroid Build Coastguard Worker # Path from build dir. 53*d9f75844SAndroid Build Coastguard Worker rel_path = os.path.relpath(os.path.abspath(filepath), out_dir) 54*d9f75844SAndroid Build Coastguard Worker 55*d9f75844SAndroid Build Coastguard Worker # Replace clang++ by clang-tidy 56*d9f75844SAndroid Build Coastguard Worker command[0:1] = [GetClangTidyPath(), CHECKER_OPTION, rel_path 57*d9f75844SAndroid Build Coastguard Worker ] + args + ['--'] # Separator for clang flags. 58*d9f75844SAndroid Build Coastguard Worker print("Running: %s" % ' '.join(command)) 59*d9f75844SAndroid Build Coastguard Worker # Run from build dir so that relative paths are correct. 60*d9f75844SAndroid Build Coastguard Worker p = subprocess.Popen(command, 61*d9f75844SAndroid Build Coastguard Worker cwd=out_dir, 62*d9f75844SAndroid Build Coastguard Worker stdout=sys.stdout, 63*d9f75844SAndroid Build Coastguard Worker stderr=sys.stderr) 64*d9f75844SAndroid Build Coastguard Worker p.communicate() 65*d9f75844SAndroid Build Coastguard Worker return p.returncode 66*d9f75844SAndroid Build Coastguard Worker finally: 67*d9f75844SAndroid Build Coastguard Worker shutil.rmtree(out_dir, ignore_errors=True) 68*d9f75844SAndroid Build Coastguard Worker 69*d9f75844SAndroid Build Coastguard Worker 70*d9f75844SAndroid Build Coastguard Workerdef ValidateCC(filepath): 71*d9f75844SAndroid Build Coastguard Worker """We can only analyze .cc files. Provide explicit message about that.""" 72*d9f75844SAndroid Build Coastguard Worker if filepath.endswith('.cc'): 73*d9f75844SAndroid Build Coastguard Worker return filepath 74*d9f75844SAndroid Build Coastguard Worker msg = ('%s not supported.\n' 75*d9f75844SAndroid Build Coastguard Worker 'For now, we can only analyze translation units (.cc files).' % 76*d9f75844SAndroid Build Coastguard Worker filepath) 77*d9f75844SAndroid Build Coastguard Worker raise argparse.ArgumentTypeError(msg) 78*d9f75844SAndroid Build Coastguard Worker 79*d9f75844SAndroid Build Coastguard Worker 80*d9f75844SAndroid Build Coastguard Workerdef Main(): 81*d9f75844SAndroid Build Coastguard Worker description = ( 82*d9f75844SAndroid Build Coastguard Worker "Run clang-tidy on single cc file.\n" 83*d9f75844SAndroid Build Coastguard Worker "Use flags, defines and include paths as in default debug build.\n" 84*d9f75844SAndroid Build Coastguard Worker "WARNING, this is a POC version with rough edges.") 85*d9f75844SAndroid Build Coastguard Worker parser = argparse.ArgumentParser(description=description) 86*d9f75844SAndroid Build Coastguard Worker parser.add_argument('filepath', 87*d9f75844SAndroid Build Coastguard Worker help='Specifies the path of the .cc file to analyze.', 88*d9f75844SAndroid Build Coastguard Worker type=ValidateCC) 89*d9f75844SAndroid Build Coastguard Worker parser.add_argument('args', 90*d9f75844SAndroid Build Coastguard Worker nargs=argparse.REMAINDER, 91*d9f75844SAndroid Build Coastguard Worker help='Arguments passed to clang-tidy') 92*d9f75844SAndroid Build Coastguard Worker parsed_args = parser.parse_args() 93*d9f75844SAndroid Build Coastguard Worker return Process(parsed_args.filepath, parsed_args.args) 94*d9f75844SAndroid Build Coastguard Worker 95*d9f75844SAndroid Build Coastguard Worker 96*d9f75844SAndroid Build Coastguard Workerif __name__ == '__main__': 97*d9f75844SAndroid Build Coastguard Worker sys.exit(Main()) 98