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