1b8021494Sopenharmony_ci#!/usr/bin/env python3 2b8021494Sopenharmony_ci 3b8021494Sopenharmony_ci# Copyright 2019, VIXL authors 4b8021494Sopenharmony_ci# All rights reserved. 5b8021494Sopenharmony_ci# 6b8021494Sopenharmony_ci# Redistribution and use in source and binary forms, with or without 7b8021494Sopenharmony_ci# modification, are permitted provided that the following conditions are met: 8b8021494Sopenharmony_ci# 9b8021494Sopenharmony_ci# * Redistributions of source code must retain the above copyright notice, 10b8021494Sopenharmony_ci# this list of conditions and the following disclaimer. 11b8021494Sopenharmony_ci# * Redistributions in binary form must reproduce the above copyright notice, 12b8021494Sopenharmony_ci# this list of conditions and the following disclaimer in the documentation 13b8021494Sopenharmony_ci# and/or other materials provided with the distribution. 14b8021494Sopenharmony_ci# * Neither the name of ARM Limited nor the names of its contributors may be 15b8021494Sopenharmony_ci# used to endorse or promote products derived from this software without 16b8021494Sopenharmony_ci# specific prior written permission. 17b8021494Sopenharmony_ci# 18b8021494Sopenharmony_ci# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 19b8021494Sopenharmony_ci# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20b8021494Sopenharmony_ci# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21b8021494Sopenharmony_ci# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22b8021494Sopenharmony_ci# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23b8021494Sopenharmony_ci# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24b8021494Sopenharmony_ci# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25b8021494Sopenharmony_ci# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26b8021494Sopenharmony_ci# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27b8021494Sopenharmony_ci# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28b8021494Sopenharmony_ciimport argparse 29b8021494Sopenharmony_ciimport multiprocessing 30b8021494Sopenharmony_ciimport os 31b8021494Sopenharmony_ciimport re 32b8021494Sopenharmony_ciimport sys 33b8021494Sopenharmony_ciimport subprocess 34b8021494Sopenharmony_ci 35b8021494Sopenharmony_cifrom clang_format import detect_clang_tool 36b8021494Sopenharmony_cifrom threaded_tests import Test, TestQueue 37b8021494Sopenharmony_ciimport config 38b8021494Sopenharmony_ciimport printer 39b8021494Sopenharmony_ciimport util 40b8021494Sopenharmony_ci 41b8021494Sopenharmony_ciDEFAULT_CLANG_TIDY = 'clang-tidy' 42b8021494Sopenharmony_ci 43b8021494Sopenharmony_cidef BuildOptions(): 44b8021494Sopenharmony_ci parser = argparse.ArgumentParser( 45b8021494Sopenharmony_ci description = '''This tool runs `clang-tidy` on C++ files.''', 46b8021494Sopenharmony_ci # Print default values. 47b8021494Sopenharmony_ci formatter_class = argparse.ArgumentDefaultsHelpFormatter) 48b8021494Sopenharmony_ci parser.add_argument('files', nargs='*') 49b8021494Sopenharmony_ci parser.add_argument('--jobs', '-j', metavar='N', type=int, nargs='?', 50b8021494Sopenharmony_ci default=multiprocessing.cpu_count(), 51b8021494Sopenharmony_ci const=multiprocessing.cpu_count(), 52b8021494Sopenharmony_ci help='''Runs the tests using N jobs. If the option is set 53b8021494Sopenharmony_ci but no value is provided, the script will use as many jobs 54b8021494Sopenharmony_ci as it thinks useful.''') 55b8021494Sopenharmony_ci parser.add_argument('--clang-tidy', default=DEFAULT_CLANG_TIDY, 56b8021494Sopenharmony_ci help='Path to clang-tidy.') 57b8021494Sopenharmony_ci return parser.parse_args() 58b8021494Sopenharmony_ci 59b8021494Sopenharmony_cidef FilterClangTidyLines(lines): 60b8021494Sopenharmony_ci out = [] 61b8021494Sopenharmony_ci print_context = False 62b8021494Sopenharmony_ci for line in lines: 63b8021494Sopenharmony_ci if ("Error: no checks enabled" in line) or ("USAGE" in line): 64b8021494Sopenharmony_ci # We've incorrectly invoked or configured clang-tidy. This should never 65b8021494Sopenharmony_ci # happen, but it if it does, make sure that the test fails. 66b8021494Sopenharmony_ci return line 67b8021494Sopenharmony_ci elif "error:" in line: 68b8021494Sopenharmony_ci out.append(line) 69b8021494Sopenharmony_ci print_context = True 70b8021494Sopenharmony_ci elif "warning:" in line: 71b8021494Sopenharmony_ci out.append(line) 72b8021494Sopenharmony_ci print_context = True 73b8021494Sopenharmony_ci elif print_context: 74b8021494Sopenharmony_ci out.append(line) 75b8021494Sopenharmony_ci return "\n".join(out) 76b8021494Sopenharmony_ci 77b8021494Sopenharmony_cidef FilterFiles(list_files): 78b8021494Sopenharmony_ci return [x for x in list_files if x.endswith('.cc')] 79b8021494Sopenharmony_ci 80b8021494Sopenharmony_cidef RunTest(test): 81b8021494Sopenharmony_ci cmd = " ".join(test.args['command']) 82b8021494Sopenharmony_ci rc, p_out = util.getstatusoutput(cmd) 83b8021494Sopenharmony_ci if rc != 0: 84b8021494Sopenharmony_ci # This usually happens when the compiler hits a '#error' because of 85b8021494Sopenharmony_ci # a missing define. 86b8021494Sopenharmony_ci printer.Print("%sFATAL ERROR: failed to run command '%s': %s%s" % 87b8021494Sopenharmony_ci (printer.COLOUR_RED, cmd, p_out, printer.NO_COLOUR)) 88b8021494Sopenharmony_ci p_out = FilterClangTidyLines(p_out.split('\n')) 89b8021494Sopenharmony_ci 90b8021494Sopenharmony_ci failed = (len(p_out) > 0) or (rc != 0) 91b8021494Sopenharmony_ci 92b8021494Sopenharmony_ci if failed: 93b8021494Sopenharmony_ci with Test.n_tests_failed.get_lock(): Test.n_tests_failed.value += 1 94b8021494Sopenharmony_ci else: 95b8021494Sopenharmony_ci with Test.n_tests_passed.get_lock(): Test.n_tests_passed.value += 1 96b8021494Sopenharmony_ci 97b8021494Sopenharmony_ci printer.__print_lock__.acquire() 98b8021494Sopenharmony_ci 99b8021494Sopenharmony_ci printer.UpdateProgress(test.shared.start_time, 100b8021494Sopenharmony_ci Test.n_tests_passed.value, 101b8021494Sopenharmony_ci Test.n_tests_failed.value, 102b8021494Sopenharmony_ci test.shared.n_tests, 103b8021494Sopenharmony_ci Test.n_tests_skipped.value, 104b8021494Sopenharmony_ci test.shared.n_known_failures, 105b8021494Sopenharmony_ci test.name, 106b8021494Sopenharmony_ci prevent_next_overwrite = failed , 107b8021494Sopenharmony_ci has_lock = True, 108b8021494Sopenharmony_ci prefix = test.shared.progress_prefix) 109b8021494Sopenharmony_ci 110b8021494Sopenharmony_ci if failed: 111b8021494Sopenharmony_ci printer.Print(printer.COLOUR_RED + 'FAILED: '+ cmd + printer.NO_COLOUR, 112b8021494Sopenharmony_ci has_lock = True) 113b8021494Sopenharmony_ci printer.Print(p_out, has_lock = True) 114b8021494Sopenharmony_ci 115b8021494Sopenharmony_ci printer.__print_lock__.release() 116b8021494Sopenharmony_ci 117b8021494Sopenharmony_cidef ClangTidyFiles(files, clang_tidy, jobs = 1, progress_prefix = ''): 118b8021494Sopenharmony_ci 119b8021494Sopenharmony_ci clang_tidy = detect_clang_tool("clang-tidy") 120b8021494Sopenharmony_ci 121b8021494Sopenharmony_ci if not clang_tidy: 122b8021494Sopenharmony_ci error_message = "clang-tidy not found. Please ensure it " \ 123b8021494Sopenharmony_ci "is installed, in your PATH and the correct version." 124b8021494Sopenharmony_ci print(printer.COLOUR_RED + error_message + printer.NO_COLOUR) 125b8021494Sopenharmony_ci return -1 126b8021494Sopenharmony_ci 127b8021494Sopenharmony_ci opts = ['--', '-DVIXL_INCLUDE_TARGET_AARCH64', '-DVIXL_CODE_BUFFER_MALLOC', 128b8021494Sopenharmony_ci '-DVIXL_DEBUG','-DVIXL_INCLUDE_SIMULATOR_AARCH64', 129b8021494Sopenharmony_ci '-DVIXL_INCLUDE_TARGET_A32','-DVIXL_INCLUDE_TARGET_T32', 130b8021494Sopenharmony_ci '-DVIXL_INCLUDE_TARGET_A64'] 131b8021494Sopenharmony_ci opts += ['-I%s' % config.dir_src_vixl] 132b8021494Sopenharmony_ci opts += ['-I%s' % config.dir_tests] 133b8021494Sopenharmony_ci opts += ['-I%s' % config.dir_aarch64_examples] 134b8021494Sopenharmony_ci opts += ['-I%s' % config.dir_aarch32_examples] 135b8021494Sopenharmony_ci 136b8021494Sopenharmony_ci to_check = FilterFiles(files) 137b8021494Sopenharmony_ci printer.Print("clang-tidy: %d files to check" % len(to_check)) 138b8021494Sopenharmony_ci 139b8021494Sopenharmony_ci queue = TestQueue(prefix = progress_prefix) 140b8021494Sopenharmony_ci 141b8021494Sopenharmony_ci for file in to_check: 142b8021494Sopenharmony_ci for cpp_version in config.tested_cpp_standards: 143b8021494Sopenharmony_ci command = [clang_tidy, file] + opts + ['-std=%s' % cpp_version] 144b8021494Sopenharmony_ci queue.AddTest(file, command=command) 145b8021494Sopenharmony_ci 146b8021494Sopenharmony_ci return queue.Run(jobs, True, RunTest) 147b8021494Sopenharmony_ci 148b8021494Sopenharmony_ciif __name__ == '__main__': 149b8021494Sopenharmony_ci # Parse the arguments. 150b8021494Sopenharmony_ci args = BuildOptions() 151b8021494Sopenharmony_ci files = args.files or util.get_source_files() 152b8021494Sopenharmony_ci 153b8021494Sopenharmony_ci rc = ClangTidyFiles(files, args.clang_tidy, args.jobs) 154b8021494Sopenharmony_ci 155b8021494Sopenharmony_ci sys.exit(rc) 156