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