1*f5c631daSSadaf Ebrahimi#!/usr/bin/env python2.7 2*f5c631daSSadaf Ebrahimi 3*f5c631daSSadaf Ebrahimi# Copyright 2015, VIXL authors 4*f5c631daSSadaf Ebrahimi# All rights reserved. 5*f5c631daSSadaf Ebrahimi# 6*f5c631daSSadaf Ebrahimi# Redistribution and use in source and binary forms, with or without 7*f5c631daSSadaf Ebrahimi# modification, are permitted provided that the following conditions are met: 8*f5c631daSSadaf Ebrahimi# 9*f5c631daSSadaf Ebrahimi# * Redistributions of source code must retain the above copyright notice, 10*f5c631daSSadaf Ebrahimi# this list of conditions and the following disclaimer. 11*f5c631daSSadaf Ebrahimi# * Redistributions in binary form must reproduce the above copyright notice, 12*f5c631daSSadaf Ebrahimi# this list of conditions and the following disclaimer in the documentation 13*f5c631daSSadaf Ebrahimi# and/or other materials provided with the distribution. 14*f5c631daSSadaf Ebrahimi# * Neither the name of ARM Limited nor the names of its contributors may be 15*f5c631daSSadaf Ebrahimi# used to endorse or promote products derived from this software without 16*f5c631daSSadaf Ebrahimi# specific prior written permission. 17*f5c631daSSadaf Ebrahimi# 18*f5c631daSSadaf Ebrahimi# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 19*f5c631daSSadaf Ebrahimi# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20*f5c631daSSadaf Ebrahimi# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21*f5c631daSSadaf Ebrahimi# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22*f5c631daSSadaf Ebrahimi# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23*f5c631daSSadaf Ebrahimi# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24*f5c631daSSadaf Ebrahimi# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25*f5c631daSSadaf Ebrahimi# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26*f5c631daSSadaf Ebrahimi# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27*f5c631daSSadaf Ebrahimi# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*f5c631daSSadaf Ebrahimi 29*f5c631daSSadaf Ebrahimiimport argparse 30*f5c631daSSadaf Ebrahimiimport fcntl 31*f5c631daSSadaf Ebrahimiimport git 32*f5c631daSSadaf Ebrahimiimport itertools 33*f5c631daSSadaf Ebrahimiimport multiprocessing 34*f5c631daSSadaf Ebrahimiimport os 35*f5c631daSSadaf Ebrahimifrom os.path import join 36*f5c631daSSadaf Ebrahimiimport platform 37*f5c631daSSadaf Ebrahimiimport subprocess 38*f5c631daSSadaf Ebrahimiimport sys 39*f5c631daSSadaf Ebrahimiimport time 40*f5c631daSSadaf Ebrahimi 41*f5c631daSSadaf Ebrahimiimport config 42*f5c631daSSadaf Ebrahimiimport clang_format 43*f5c631daSSadaf Ebrahimiimport clang_tidy 44*f5c631daSSadaf Ebrahimiimport lint 45*f5c631daSSadaf Ebrahimiimport printer 46*f5c631daSSadaf Ebrahimiimport test 47*f5c631daSSadaf Ebrahimiimport test_runner 48*f5c631daSSadaf Ebrahimiimport util 49*f5c631daSSadaf Ebrahimi 50*f5c631daSSadaf Ebrahimi 51*f5c631daSSadaf Ebrahimidir_root = config.dir_root 52*f5c631daSSadaf Ebrahimi 53*f5c631daSSadaf Ebrahimi 54*f5c631daSSadaf Ebrahimi# Remove duplicates from a list 55*f5c631daSSadaf Ebrahimidef RemoveDuplicates(values): 56*f5c631daSSadaf Ebrahimi # Convert the list into a set and back to list 57*f5c631daSSadaf Ebrahimi # as sets guarantee items are unique. 58*f5c631daSSadaf Ebrahimi return list(set(values)) 59*f5c631daSSadaf Ebrahimi 60*f5c631daSSadaf Ebrahimi 61*f5c631daSSadaf Ebrahimi# Custom argparse.Action to automatically add and handle an 'all' option. 62*f5c631daSSadaf Ebrahimi# If no 'default' value is set, it will default to 'all. 63*f5c631daSSadaf Ebrahimi# If accepted options are set using 'choices' then only these values will be 64*f5c631daSSadaf Ebrahimi# allowed. 65*f5c631daSSadaf Ebrahimi# If they're set using 'soft_choices' then 'all' will default to these values, 66*f5c631daSSadaf Ebrahimi# but other values will also be accepted. 67*f5c631daSSadaf Ebrahimiclass AllChoiceAction(argparse.Action): 68*f5c631daSSadaf Ebrahimi 69*f5c631daSSadaf Ebrahimi # At least one option was set by the user. 70*f5c631daSSadaf Ebrahimi WasSetByUser = False 71*f5c631daSSadaf Ebrahimi 72*f5c631daSSadaf Ebrahimi def __init__(self, **kwargs): 73*f5c631daSSadaf Ebrahimi if 'choices' in kwargs: 74*f5c631daSSadaf Ebrahimi assert 'soft_choices' not in kwargs,\ 75*f5c631daSSadaf Ebrahimi "Can't have both 'choices' and 'soft_choices' options" 76*f5c631daSSadaf Ebrahimi self.all_choices = list(kwargs['choices']) 77*f5c631daSSadaf Ebrahimi kwargs['choices'].append('all') 78*f5c631daSSadaf Ebrahimi else: 79*f5c631daSSadaf Ebrahimi self.all_choices = kwargs['soft_choices'] 80*f5c631daSSadaf Ebrahimi kwargs['help'] += ' Supported values: {' + ','.join( 81*f5c631daSSadaf Ebrahimi ['all'] + self.all_choices) + '}' 82*f5c631daSSadaf Ebrahimi del kwargs['soft_choices'] 83*f5c631daSSadaf Ebrahimi if 'default' not in kwargs: 84*f5c631daSSadaf Ebrahimi kwargs['default'] = self.all_choices 85*f5c631daSSadaf Ebrahimi super(AllChoiceAction, self).__init__(**kwargs) 86*f5c631daSSadaf Ebrahimi 87*f5c631daSSadaf Ebrahimi def __call__(self, parser, namespace, values, option_string=None): 88*f5c631daSSadaf Ebrahimi AllChoiceAction.WasSetByUser = True 89*f5c631daSSadaf Ebrahimi if 'all' in values: 90*f5c631daSSadaf Ebrahimi # Substitute 'all' by the actual values. 91*f5c631daSSadaf Ebrahimi values = self.all_choices + [value for value in values if value != 'all'] 92*f5c631daSSadaf Ebrahimi 93*f5c631daSSadaf Ebrahimi setattr(namespace, self.dest, RemoveDuplicates(values)) 94*f5c631daSSadaf Ebrahimi 95*f5c631daSSadaf Ebrahimi 96*f5c631daSSadaf Ebrahimidef BuildOptions(): 97*f5c631daSSadaf Ebrahimi args = argparse.ArgumentParser( 98*f5c631daSSadaf Ebrahimi description = 99*f5c631daSSadaf Ebrahimi '''This tool runs all tests matching the specified filters for multiple 100*f5c631daSSadaf Ebrahimi environment, build options, and runtime options configurations.''', 101*f5c631daSSadaf Ebrahimi # Print default values. 102*f5c631daSSadaf Ebrahimi formatter_class=argparse.ArgumentDefaultsHelpFormatter) 103*f5c631daSSadaf Ebrahimi 104*f5c631daSSadaf Ebrahimi args.add_argument('filters', metavar='filter', nargs='*', 105*f5c631daSSadaf Ebrahimi help='Run tests matching all of the (regexp) filters.') 106*f5c631daSSadaf Ebrahimi 107*f5c631daSSadaf Ebrahimi # We automatically build the script options from the options to be tested. 108*f5c631daSSadaf Ebrahimi test_arguments = args.add_argument_group( 109*f5c631daSSadaf Ebrahimi 'Test options', 110*f5c631daSSadaf Ebrahimi 'These options indicate what should be tested') 111*f5c631daSSadaf Ebrahimi test_arguments.add_argument( 112*f5c631daSSadaf Ebrahimi '--negative_testing', 113*f5c631daSSadaf Ebrahimi help='Tests with negative testing enabled.', 114*f5c631daSSadaf Ebrahimi action='store_const', 115*f5c631daSSadaf Ebrahimi const='on', 116*f5c631daSSadaf Ebrahimi default='off') 117*f5c631daSSadaf Ebrahimi test_arguments.add_argument( 118*f5c631daSSadaf Ebrahimi '--compiler', 119*f5c631daSSadaf Ebrahimi help='Test for the specified compilers.', 120*f5c631daSSadaf Ebrahimi soft_choices=config.tested_compilers, 121*f5c631daSSadaf Ebrahimi action=AllChoiceAction, 122*f5c631daSSadaf Ebrahimi nargs="+") 123*f5c631daSSadaf Ebrahimi test_arguments.add_argument( 124*f5c631daSSadaf Ebrahimi '--mode', 125*f5c631daSSadaf Ebrahimi help='Test with the specified build modes.', 126*f5c631daSSadaf Ebrahimi choices=config.build_options_modes, 127*f5c631daSSadaf Ebrahimi action=AllChoiceAction, 128*f5c631daSSadaf Ebrahimi nargs="+") 129*f5c631daSSadaf Ebrahimi test_arguments.add_argument( 130*f5c631daSSadaf Ebrahimi '--std', 131*f5c631daSSadaf Ebrahimi help='Test with the specified C++ standard.', 132*f5c631daSSadaf Ebrahimi soft_choices=config.tested_cpp_standards, 133*f5c631daSSadaf Ebrahimi action=AllChoiceAction, 134*f5c631daSSadaf Ebrahimi nargs="+") 135*f5c631daSSadaf Ebrahimi test_arguments.add_argument( 136*f5c631daSSadaf Ebrahimi '--target', 137*f5c631daSSadaf Ebrahimi help='Test with the specified isa enabled.', 138*f5c631daSSadaf Ebrahimi soft_choices=config.build_options_target, 139*f5c631daSSadaf Ebrahimi action=AllChoiceAction, 140*f5c631daSSadaf Ebrahimi nargs="+") 141*f5c631daSSadaf Ebrahimi 142*f5c631daSSadaf Ebrahimi general_arguments = args.add_argument_group('General options') 143*f5c631daSSadaf Ebrahimi general_arguments.add_argument('--dry-run', action='store_true', 144*f5c631daSSadaf Ebrahimi help='''Don't actually build or run anything, 145*f5c631daSSadaf Ebrahimi but print the configurations that would be 146*f5c631daSSadaf Ebrahimi tested.''') 147*f5c631daSSadaf Ebrahimi general_arguments.add_argument('--verbose', action='store_true', 148*f5c631daSSadaf Ebrahimi help='''Print extra information.''') 149*f5c631daSSadaf Ebrahimi general_arguments.add_argument( 150*f5c631daSSadaf Ebrahimi '--jobs', '-j', metavar='N', type=int, nargs='?', 151*f5c631daSSadaf Ebrahimi default=multiprocessing.cpu_count(), 152*f5c631daSSadaf Ebrahimi const=multiprocessing.cpu_count(), 153*f5c631daSSadaf Ebrahimi help='''Runs the tests using N jobs. If the option is set but no value is 154*f5c631daSSadaf Ebrahimi provided, the script will use as many jobs as it thinks useful.''') 155*f5c631daSSadaf Ebrahimi general_arguments.add_argument('--clang-format', 156*f5c631daSSadaf Ebrahimi default=clang_format.DEFAULT_CLANG_FORMAT, 157*f5c631daSSadaf Ebrahimi help='Path to clang-format.') 158*f5c631daSSadaf Ebrahimi general_arguments.add_argument('--clang-tidy', 159*f5c631daSSadaf Ebrahimi default=clang_tidy.DEFAULT_CLANG_TIDY, 160*f5c631daSSadaf Ebrahimi help='Path to clang-tidy.') 161*f5c631daSSadaf Ebrahimi general_arguments.add_argument('--nobench', action='store_true', 162*f5c631daSSadaf Ebrahimi help='Do not run benchmarks.') 163*f5c631daSSadaf Ebrahimi general_arguments.add_argument('--nolint', action='store_true', 164*f5c631daSSadaf Ebrahimi help='Do not run the linter.') 165*f5c631daSSadaf Ebrahimi general_arguments.add_argument('--noclang-format', action='store_true', 166*f5c631daSSadaf Ebrahimi help='Do not run clang-format.') 167*f5c631daSSadaf Ebrahimi general_arguments.add_argument('--noclang-tidy', action='store_true', 168*f5c631daSSadaf Ebrahimi help='Do not run clang-tidy.') 169*f5c631daSSadaf Ebrahimi general_arguments.add_argument('--notest', action='store_true', 170*f5c631daSSadaf Ebrahimi help='Do not run tests.') 171*f5c631daSSadaf Ebrahimi general_arguments.add_argument('--nocheck-code-coverage', action='store_true', 172*f5c631daSSadaf Ebrahimi help='Do not check code coverage results log.') 173*f5c631daSSadaf Ebrahimi general_arguments.add_argument('--fail-early', action='store_true', 174*f5c631daSSadaf Ebrahimi help='Exit as soon as a test fails.') 175*f5c631daSSadaf Ebrahimi general_arguments.add_argument( 176*f5c631daSSadaf Ebrahimi '--under_valgrind', action='store_true', 177*f5c631daSSadaf Ebrahimi help='''Run the test-runner commands under Valgrind. 178*f5c631daSSadaf Ebrahimi Note that a few tests are known to fail because of 179*f5c631daSSadaf Ebrahimi issues in Valgrind''') 180*f5c631daSSadaf Ebrahimi return args.parse_args() 181*f5c631daSSadaf Ebrahimi 182*f5c631daSSadaf Ebrahimi 183*f5c631daSSadaf Ebrahimidef RunCommand(command, environment_options = None): 184*f5c631daSSadaf Ebrahimi # Create a copy of the environment. We do not want to pollute the environment 185*f5c631daSSadaf Ebrahimi # of future commands run. 186*f5c631daSSadaf Ebrahimi environment = os.environ.copy() 187*f5c631daSSadaf Ebrahimi 188*f5c631daSSadaf Ebrahimi printable_command = '' 189*f5c631daSSadaf Ebrahimi if environment_options: 190*f5c631daSSadaf Ebrahimi # Add the environment options to the environment: 191*f5c631daSSadaf Ebrahimi environment.update(environment_options) 192*f5c631daSSadaf Ebrahimi printable_command += ' ' + DictToString(environment_options) + ' ' 193*f5c631daSSadaf Ebrahimi printable_command += ' '.join(command) 194*f5c631daSSadaf Ebrahimi 195*f5c631daSSadaf Ebrahimi printable_command_orange = \ 196*f5c631daSSadaf Ebrahimi printer.COLOUR_ORANGE + printable_command + printer.NO_COLOUR 197*f5c631daSSadaf Ebrahimi printer.PrintOverwritableLine(printable_command_orange) 198*f5c631daSSadaf Ebrahimi sys.stdout.flush() 199*f5c631daSSadaf Ebrahimi 200*f5c631daSSadaf Ebrahimi # Start a process for the command. 201*f5c631daSSadaf Ebrahimi # Interleave `stderr` and `stdout`. 202*f5c631daSSadaf Ebrahimi p = subprocess.Popen(command, 203*f5c631daSSadaf Ebrahimi stdout=subprocess.PIPE, 204*f5c631daSSadaf Ebrahimi stderr=subprocess.STDOUT, 205*f5c631daSSadaf Ebrahimi env=environment) 206*f5c631daSSadaf Ebrahimi 207*f5c631daSSadaf Ebrahimi # We want to be able to display a continuously updated 'work indicator' while 208*f5c631daSSadaf Ebrahimi # the process is running. Since the process can hang if the `stdout` pipe is 209*f5c631daSSadaf Ebrahimi # full, we need to pull from it regularly. We cannot do so via the 210*f5c631daSSadaf Ebrahimi # `readline()` function because it is blocking, and would thus cause the 211*f5c631daSSadaf Ebrahimi # indicator to not be updated properly. So use file control mechanisms 212*f5c631daSSadaf Ebrahimi # instead. 213*f5c631daSSadaf Ebrahimi indicator = ' (still working: %d seconds elapsed)' 214*f5c631daSSadaf Ebrahimi 215*f5c631daSSadaf Ebrahimi # Mark the process output as non-blocking. 216*f5c631daSSadaf Ebrahimi flags = fcntl.fcntl(p.stdout, fcntl.F_GETFL) 217*f5c631daSSadaf Ebrahimi fcntl.fcntl(p.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK) 218*f5c631daSSadaf Ebrahimi 219*f5c631daSSadaf Ebrahimi t_start = time.time() 220*f5c631daSSadaf Ebrahimi t_current = t_start 221*f5c631daSSadaf Ebrahimi t_last_indication = t_start 222*f5c631daSSadaf Ebrahimi t_current = t_start 223*f5c631daSSadaf Ebrahimi process_output = '' 224*f5c631daSSadaf Ebrahimi 225*f5c631daSSadaf Ebrahimi # Keep looping as long as the process is running. 226*f5c631daSSadaf Ebrahimi while p.poll() is None: 227*f5c631daSSadaf Ebrahimi # Avoid polling too often. 228*f5c631daSSadaf Ebrahimi time.sleep(0.1) 229*f5c631daSSadaf Ebrahimi # Update the progress indicator. 230*f5c631daSSadaf Ebrahimi t_current = time.time() 231*f5c631daSSadaf Ebrahimi if (t_current - t_start >= 2) and (t_current - t_last_indication >= 1): 232*f5c631daSSadaf Ebrahimi printer.PrintOverwritableLine( 233*f5c631daSSadaf Ebrahimi printable_command_orange + indicator % int(t_current - t_start)) 234*f5c631daSSadaf Ebrahimi sys.stdout.flush() 235*f5c631daSSadaf Ebrahimi t_last_indication = t_current 236*f5c631daSSadaf Ebrahimi # Pull from the process output. 237*f5c631daSSadaf Ebrahimi while True: 238*f5c631daSSadaf Ebrahimi try: 239*f5c631daSSadaf Ebrahimi line = os.read(p.stdout.fileno(), 1024) 240*f5c631daSSadaf Ebrahimi except OSError: 241*f5c631daSSadaf Ebrahimi line = '' 242*f5c631daSSadaf Ebrahimi break 243*f5c631daSSadaf Ebrahimi if line == '': break 244*f5c631daSSadaf Ebrahimi process_output += line 245*f5c631daSSadaf Ebrahimi 246*f5c631daSSadaf Ebrahimi # The process has exited. Don't forget to retrieve the rest of its output. 247*f5c631daSSadaf Ebrahimi out, err = p.communicate() 248*f5c631daSSadaf Ebrahimi rc = p.poll() 249*f5c631daSSadaf Ebrahimi process_output += out 250*f5c631daSSadaf Ebrahimi 251*f5c631daSSadaf Ebrahimi printable_command += ' (took %d seconds)' % int(t_current - t_start) 252*f5c631daSSadaf Ebrahimi if rc == 0: 253*f5c631daSSadaf Ebrahimi printer.Print(printer.COLOUR_GREEN + printable_command + printer.NO_COLOUR) 254*f5c631daSSadaf Ebrahimi else: 255*f5c631daSSadaf Ebrahimi printer.Print(printer.COLOUR_RED + printable_command + printer.NO_COLOUR) 256*f5c631daSSadaf Ebrahimi printer.Print(process_output) 257*f5c631daSSadaf Ebrahimi return rc 258*f5c631daSSadaf Ebrahimi 259*f5c631daSSadaf Ebrahimi 260*f5c631daSSadaf Ebrahimidef RunLinter(jobs): 261*f5c631daSSadaf Ebrahimi return lint.RunLinter(map(lambda x: join(dir_root, x), 262*f5c631daSSadaf Ebrahimi util.get_source_files()), 263*f5c631daSSadaf Ebrahimi jobs = args.jobs, progress_prefix = 'cpp lint: ') 264*f5c631daSSadaf Ebrahimi 265*f5c631daSSadaf Ebrahimi 266*f5c631daSSadaf Ebrahimidef RunClangFormat(clang_path, jobs): 267*f5c631daSSadaf Ebrahimi return clang_format.ClangFormatFiles(util.get_source_files(), 268*f5c631daSSadaf Ebrahimi clang_path, 269*f5c631daSSadaf Ebrahimi jobs = jobs, 270*f5c631daSSadaf Ebrahimi progress_prefix = 'clang-format: ') 271*f5c631daSSadaf Ebrahimi 272*f5c631daSSadaf Ebrahimidef RunClangTidy(clang_path, jobs): 273*f5c631daSSadaf Ebrahimi return clang_tidy.ClangTidyFiles(util.get_source_files(), 274*f5c631daSSadaf Ebrahimi clang_path, 275*f5c631daSSadaf Ebrahimi jobs = jobs, 276*f5c631daSSadaf Ebrahimi progress_prefix = 'clang-tidy: ') 277*f5c631daSSadaf Ebrahimi 278*f5c631daSSadaf Ebrahimidef CheckCodeCoverage(): 279*f5c631daSSadaf Ebrahimi command = ['tools/check_recent_coverage.sh'] 280*f5c631daSSadaf Ebrahimi return RunCommand(command) 281*f5c631daSSadaf Ebrahimi 282*f5c631daSSadaf Ebrahimidef BuildAll(build_options, jobs, environment_options): 283*f5c631daSSadaf Ebrahimi scons_command = ['scons', '-C', dir_root, 'all', '-j', str(jobs)] 284*f5c631daSSadaf Ebrahimi if util.IsCommandAvailable('ccache'): 285*f5c631daSSadaf Ebrahimi scons_command += ['compiler_wrapper=ccache'] 286*f5c631daSSadaf Ebrahimi # Fixes warnings for ccache 3.3.1 and lower: 287*f5c631daSSadaf Ebrahimi environment_options = environment_options.copy() 288*f5c631daSSadaf Ebrahimi environment_options["CCACHE_CPP2"] = 'yes' 289*f5c631daSSadaf Ebrahimi scons_command += DictToString(build_options).split() 290*f5c631daSSadaf Ebrahimi return RunCommand(scons_command, environment_options) 291*f5c631daSSadaf Ebrahimi 292*f5c631daSSadaf Ebrahimi 293*f5c631daSSadaf Ebrahimidef CanRunAarch64(options, args): 294*f5c631daSSadaf Ebrahimi for target in options['target']: 295*f5c631daSSadaf Ebrahimi if target in ['aarch64', 'a64']: 296*f5c631daSSadaf Ebrahimi return True 297*f5c631daSSadaf Ebrahimi 298*f5c631daSSadaf Ebrahimi return False 299*f5c631daSSadaf Ebrahimi 300*f5c631daSSadaf Ebrahimi 301*f5c631daSSadaf Ebrahimidef CanRunAarch32(options, args): 302*f5c631daSSadaf Ebrahimi for target in options['target']: 303*f5c631daSSadaf Ebrahimi if target in ['aarch32', 'a32', 't32']: 304*f5c631daSSadaf Ebrahimi return True 305*f5c631daSSadaf Ebrahimi return False 306*f5c631daSSadaf Ebrahimi 307*f5c631daSSadaf Ebrahimi 308*f5c631daSSadaf Ebrahimidef RunBenchmarks(options, args): 309*f5c631daSSadaf Ebrahimi rc = 0 310*f5c631daSSadaf Ebrahimi if CanRunAarch32(options, args): 311*f5c631daSSadaf Ebrahimi benchmark_names = util.ListCCFilesWithoutExt(config.dir_aarch32_benchmarks) 312*f5c631daSSadaf Ebrahimi for bench in benchmark_names: 313*f5c631daSSadaf Ebrahimi rc |= RunCommand( 314*f5c631daSSadaf Ebrahimi [os.path.realpath( 315*f5c631daSSadaf Ebrahimi join(config.dir_build_latest, 'benchmarks/aarch32', bench)), '10']) 316*f5c631daSSadaf Ebrahimi if CanRunAarch64(options, args): 317*f5c631daSSadaf Ebrahimi benchmark_names = util.ListCCFilesWithoutExt(config.dir_aarch64_benchmarks) 318*f5c631daSSadaf Ebrahimi for bench in benchmark_names: 319*f5c631daSSadaf Ebrahimi rc |= RunCommand( 320*f5c631daSSadaf Ebrahimi [util.relrealpath( 321*f5c631daSSadaf Ebrahimi join(config.dir_build_latest, 322*f5c631daSSadaf Ebrahimi 'benchmarks/aarch64', bench)), '10']) 323*f5c631daSSadaf Ebrahimi return rc 324*f5c631daSSadaf Ebrahimi 325*f5c631daSSadaf Ebrahimi 326*f5c631daSSadaf Ebrahimi 327*f5c631daSSadaf Ebrahimi# It is a precommit run if the user did not specify any of the 328*f5c631daSSadaf Ebrahimi# options that would affect the automatically generated combinations. 329*f5c631daSSadaf Ebrahimidef IsPrecommitRun(args): 330*f5c631daSSadaf Ebrahimi return args.negative_testing == "off" and not AllChoiceAction.WasSetByUser 331*f5c631daSSadaf Ebrahimi 332*f5c631daSSadaf Ebrahimi# Generate a list of all the possible combinations of the passed list: 333*f5c631daSSadaf Ebrahimi# ListCombinations( a = [a0, a1], b = [b0, b1] ) will return 334*f5c631daSSadaf Ebrahimi# [ {a : a0, b : b0}, {a : a0, b : b1}, {a: a1, b : b0}, {a : a1, b : b1}] 335*f5c631daSSadaf Ebrahimidef ListCombinations(**kwargs): 336*f5c631daSSadaf Ebrahimi # End of recursion: no options passed 337*f5c631daSSadaf Ebrahimi if not kwargs: 338*f5c631daSSadaf Ebrahimi return [{}] 339*f5c631daSSadaf Ebrahimi option, values = kwargs.popitem() 340*f5c631daSSadaf Ebrahimi configs = ListCombinations(**kwargs) 341*f5c631daSSadaf Ebrahimi retval = [] 342*f5c631daSSadaf Ebrahimi if not isinstance(values, list): 343*f5c631daSSadaf Ebrahimi values = [values] 344*f5c631daSSadaf Ebrahimi for value in values: 345*f5c631daSSadaf Ebrahimi for config in configs: 346*f5c631daSSadaf Ebrahimi new_config = config.copy() 347*f5c631daSSadaf Ebrahimi new_config[option] = value 348*f5c631daSSadaf Ebrahimi retval.append(new_config) 349*f5c631daSSadaf Ebrahimi return retval 350*f5c631daSSadaf Ebrahimi 351*f5c631daSSadaf Ebrahimi# Convert a dictionary into a space separated string 352*f5c631daSSadaf Ebrahimi# {a : a0, b : b0} --> "a=a0 b=b0" 353*f5c631daSSadaf Ebrahimidef DictToString(options): 354*f5c631daSSadaf Ebrahimi return " ".join( 355*f5c631daSSadaf Ebrahimi ["{}={}".format(option, value) for option, value in options.items()]) 356*f5c631daSSadaf Ebrahimi 357*f5c631daSSadaf Ebrahimi 358*f5c631daSSadaf Ebrahimiif __name__ == '__main__': 359*f5c631daSSadaf Ebrahimi util.require_program('scons') 360*f5c631daSSadaf Ebrahimi 361*f5c631daSSadaf Ebrahimi args = BuildOptions() 362*f5c631daSSadaf Ebrahimi 363*f5c631daSSadaf Ebrahimi rc = util.ReturnCode(args.fail_early, printer.Print) 364*f5c631daSSadaf Ebrahimi 365*f5c631daSSadaf Ebrahimi if args.under_valgrind: 366*f5c631daSSadaf Ebrahimi util.require_program('valgrind') 367*f5c631daSSadaf Ebrahimi 368*f5c631daSSadaf Ebrahimi if not args.nocheck_code_coverage: 369*f5c631daSSadaf Ebrahimi rc.Combine(CheckCodeCoverage()) 370*f5c631daSSadaf Ebrahimi 371*f5c631daSSadaf Ebrahimi tests = test_runner.TestQueue() 372*f5c631daSSadaf Ebrahimi if not args.nolint and not args.dry_run: 373*f5c631daSSadaf Ebrahimi rc.Combine(RunLinter(args.jobs)) 374*f5c631daSSadaf Ebrahimi 375*f5c631daSSadaf Ebrahimi if not args.noclang_format and not args.dry_run: 376*f5c631daSSadaf Ebrahimi rc.Combine(RunClangFormat(args.clang_format, args.jobs)) 377*f5c631daSSadaf Ebrahimi 378*f5c631daSSadaf Ebrahimi if not args.noclang_tidy and not args.dry_run: 379*f5c631daSSadaf Ebrahimi rc.Combine(RunClangTidy(args.clang_tidy, args.jobs)) 380*f5c631daSSadaf Ebrahimi 381*f5c631daSSadaf Ebrahimi list_options = [] 382*f5c631daSSadaf Ebrahimi if IsPrecommitRun(args): 383*f5c631daSSadaf Ebrahimi # Maximize the coverage for precommit testing. 384*f5c631daSSadaf Ebrahimi 385*f5c631daSSadaf Ebrahimi # Debug builds with negative testing and all targets enabled. 386*f5c631daSSadaf Ebrahimi list_options += ListCombinations( 387*f5c631daSSadaf Ebrahimi compiler = args.compiler, 388*f5c631daSSadaf Ebrahimi negative_testing = 'on', 389*f5c631daSSadaf Ebrahimi std = args.std, 390*f5c631daSSadaf Ebrahimi mode = 'debug', 391*f5c631daSSadaf Ebrahimi target = 'a64,a32,t32') 392*f5c631daSSadaf Ebrahimi 393*f5c631daSSadaf Ebrahimi # Release builds with all targets enabled. 394*f5c631daSSadaf Ebrahimi list_options += ListCombinations( 395*f5c631daSSadaf Ebrahimi compiler = args.compiler, 396*f5c631daSSadaf Ebrahimi negative_testing = 'off', 397*f5c631daSSadaf Ebrahimi std = args.std, 398*f5c631daSSadaf Ebrahimi mode = 'release', 399*f5c631daSSadaf Ebrahimi target = 'a64,a32,t32') 400*f5c631daSSadaf Ebrahimi 401*f5c631daSSadaf Ebrahimi # Debug builds for individual targets. 402*f5c631daSSadaf Ebrahimi list_options += ListCombinations( 403*f5c631daSSadaf Ebrahimi compiler = args.compiler[0], 404*f5c631daSSadaf Ebrahimi negative_testing = 'off', 405*f5c631daSSadaf Ebrahimi std = args.std, 406*f5c631daSSadaf Ebrahimi mode = 'debug', 407*f5c631daSSadaf Ebrahimi target = ['a32', 't32', 'a64']) 408*f5c631daSSadaf Ebrahimi else: 409*f5c631daSSadaf Ebrahimi list_options = ListCombinations( 410*f5c631daSSadaf Ebrahimi compiler = args.compiler, 411*f5c631daSSadaf Ebrahimi negative_testing = args.negative_testing, 412*f5c631daSSadaf Ebrahimi std = args.std, 413*f5c631daSSadaf Ebrahimi mode = args.mode, 414*f5c631daSSadaf Ebrahimi target = args.target) 415*f5c631daSSadaf Ebrahimi 416*f5c631daSSadaf Ebrahimi for options in list_options: 417*f5c631daSSadaf Ebrahimi if (args.dry_run): 418*f5c631daSSadaf Ebrahimi print(DictToString(options)) 419*f5c631daSSadaf Ebrahimi continue 420*f5c631daSSadaf Ebrahimi # Convert 'compiler' into an environment variable: 421*f5c631daSSadaf Ebrahimi environment_options = {'CXX': options['compiler']} 422*f5c631daSSadaf Ebrahimi del options['compiler'] 423*f5c631daSSadaf Ebrahimi 424*f5c631daSSadaf Ebrahimi # Avoid going through the build stage if we are not using the build 425*f5c631daSSadaf Ebrahimi # result. 426*f5c631daSSadaf Ebrahimi if not (args.notest and args.nobench): 427*f5c631daSSadaf Ebrahimi build_rc = BuildAll(options, args.jobs, environment_options) 428*f5c631daSSadaf Ebrahimi # Don't run the tests for this configuration if the build failed. 429*f5c631daSSadaf Ebrahimi if build_rc != 0: 430*f5c631daSSadaf Ebrahimi rc.Combine(build_rc) 431*f5c631daSSadaf Ebrahimi continue 432*f5c631daSSadaf Ebrahimi 433*f5c631daSSadaf Ebrahimi # Use the realpath of the test executable so that the commands printed 434*f5c631daSSadaf Ebrahimi # can be copy-pasted and run. 435*f5c631daSSadaf Ebrahimi test_executable = util.relrealpath( 436*f5c631daSSadaf Ebrahimi join(config.dir_build_latest, 'test', 'test-runner')) 437*f5c631daSSadaf Ebrahimi 438*f5c631daSSadaf Ebrahimi if not args.notest: 439*f5c631daSSadaf Ebrahimi printer.Print(test_executable) 440*f5c631daSSadaf Ebrahimi tests.AddTests( 441*f5c631daSSadaf Ebrahimi test_executable, 442*f5c631daSSadaf Ebrahimi args.filters, 443*f5c631daSSadaf Ebrahimi list(), 444*f5c631daSSadaf Ebrahimi args.under_valgrind) 445*f5c631daSSadaf Ebrahimi 446*f5c631daSSadaf Ebrahimi if not args.nobench: 447*f5c631daSSadaf Ebrahimi rc.Combine(RunBenchmarks(options, args)) 448*f5c631daSSadaf Ebrahimi 449*f5c631daSSadaf Ebrahimi rc.Combine(tests.Run(args.jobs, args.verbose)) 450*f5c631daSSadaf Ebrahimi if not args.dry_run: 451*f5c631daSSadaf Ebrahimi rc.PrintStatus() 452*f5c631daSSadaf Ebrahimi 453*f5c631daSSadaf Ebrahimi sys.exit(rc.Value) 454