97 lines
3.3 KiB
Python
Executable File
97 lines
3.3 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
|
#
|
|
# Use of this source code is governed by a BSD-style license
|
|
# that can be found in the LICENSE file in the root of the source
|
|
# tree. An additional intellectual property rights grant can be found
|
|
# in the file PATENTS. All contributing project authors may
|
|
# be found in the AUTHORS file in the root of the source tree.
|
|
|
|
"""Invoke clang-tidy tool.
|
|
|
|
Usage: clang_tidy.py file.cc [clang-tidy-args...]
|
|
|
|
Just a proof of concept!
|
|
We use an embedded clang-tidy whose version doesn't match clang++.
|
|
"""
|
|
|
|
import argparse
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
#pylint: disable=relative-import
|
|
from presubmit_checks_lib.build_helpers import GetClangTidyPath, \
|
|
GetCompilationCommand
|
|
|
|
|
|
# We enable all checkers by default for investigation purpose.
|
|
# This includes clang-analyzer-* checks.
|
|
# Individual checkers can be disabled via command line options.
|
|
# TODO(bugs.webrtc.com/10258): Select checkers relevant to webrtc guidelines.
|
|
CHECKER_OPTION = '-checks=*'
|
|
|
|
|
|
def Process(filepath, args):
|
|
# Build directory is needed to gather compilation flags.
|
|
# Create a temporary one (instead of reusing an existing one)
|
|
# to keep the CLI simple and unencumbered.
|
|
out_dir = tempfile.mkdtemp('clang_tidy')
|
|
|
|
try:
|
|
gn_args = [] # Use default build.
|
|
command = GetCompilationCommand(filepath, gn_args, out_dir)
|
|
|
|
# Remove warning flags. They aren't needed and they cause trouble
|
|
# when clang-tidy doesn't match most recent clang.
|
|
# Same battle for -f (e.g. -fcomplete-member-pointers).
|
|
command = [arg for arg in command if not (arg.startswith('-W') or
|
|
arg.startswith('-f'))]
|
|
|
|
# Path from build dir.
|
|
rel_path = os.path.relpath(os.path.abspath(filepath), out_dir)
|
|
|
|
# Replace clang++ by clang-tidy
|
|
command[0:1] = [GetClangTidyPath(),
|
|
CHECKER_OPTION,
|
|
rel_path] + args + ['--'] # Separator for clang flags.
|
|
print "Running: %s" % ' '.join(command)
|
|
# Run from build dir so that relative paths are correct.
|
|
p = subprocess.Popen(command, cwd=out_dir,
|
|
stdout=sys.stdout, stderr=sys.stderr)
|
|
p.communicate()
|
|
return p.returncode
|
|
finally:
|
|
shutil.rmtree(out_dir, ignore_errors=True)
|
|
|
|
|
|
def ValidateCC(filepath):
|
|
"""We can only analyze .cc files. Provide explicit message about that."""
|
|
if filepath.endswith('.cc'):
|
|
return filepath
|
|
msg = ('%s not supported.\n'
|
|
'For now, we can only analyze translation units (.cc files).' %
|
|
filepath)
|
|
raise argparse.ArgumentTypeError(msg)
|
|
|
|
|
|
def Main():
|
|
description = (
|
|
"Run clang-tidy on single cc file.\n"
|
|
"Use flags, defines and include paths as in default debug build.\n"
|
|
"WARNING, this is a POC version with rough edges.")
|
|
parser = argparse.ArgumentParser(description=description)
|
|
parser.add_argument('filepath',
|
|
help='Specifies the path of the .cc file to analyze.',
|
|
type=ValidateCC)
|
|
parser.add_argument('args',
|
|
nargs=argparse.REMAINDER,
|
|
help='Arguments passed to clang-tidy')
|
|
parsed_args = parser.parse_args()
|
|
return Process(parsed_args.filepath, parsed_args.args)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(Main())
|