1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# 4# Copyright (c) 2022-2024 Huawei Device Co., Ltd. 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18from __future__ import print_function 19from datetime import datetime 20from fnmatch import fnmatch 21import errno 22import json 23import os 24import platform 25import subprocess 26import sys 27from typing import List, Any, Tuple, Union, Optional 28 29CURRENT_FILENAME = os.path.basename(__file__) 30 31 32def str_of_time_now() -> str: 33 return datetime.now().strftime("%Y-%m-%d-%H-%M-%S-%f")[:-3] 34 35 36def _call(cmd: str): 37 print("# %s" % cmd) 38 return subprocess.call(cmd, shell=True) 39 40 41def _write(filename: str, content: str, mode: str): 42 with open(filename, mode) as f: 43 f.write(content) 44 45 46def call_with_output(cmd: str, file: str): 47 print("# %s" % cmd) 48 host = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) 49 while True: 50 try: 51 build_data = host.stdout.readline().decode('utf-8') 52 sys.stdout.flush() 53 print(build_data) 54 _write(file, build_data, "a") 55 except OSError as error: 56 if error == errno.ENOENT: 57 print("no such file") 58 elif error == errno.EPERM: 59 print("permission denied") 60 break 61 if not build_data: 62 break 63 host.wait() 64 return host.returncode 65 66 67def enable_ccache(): 68 try: 69 ccache_path = subprocess.check_output(['which', 'ccache']).strip().decode() 70 except subprocess.CalledProcessError: 71 print("Error: ccache not found.") 72 return 73 os.environ['CCACHE_EXEC'] = ccache_path 74 os.environ['USE_CCACHE'] = "1" 75 76 77def backup(file: str, mode: str): 78 if os.path.exists(file): 79 with open(file, 'r+') as src_file: 80 src_content = src_file.read() 81 src_file.seek(0) 82 src_file.truncate() 83 84 with open(file[:-4] + "_last.log", mode) as dst_file: 85 dst_file.write(src_content) 86 87 88class ArkPy: 89 # constants determined by designer of this class 90 NAME_OF_OUT_DIR_OF_FIRST_LEVEL = "out" 91 DELIMITER_BETWEEN_OS_CPU_MODE_FOR_COMMAND = "." 92 DELIMITER_FOR_SECOND_OUT_DIR_NAME = "." 93 GN_TARGET_LOG_FILE_NAME = "build.log" 94 UNITTEST_LOG_FILE_NAME = "unittest.log" 95 RUNTIME_CORE_UNITTEST_LOG_FILE_NAME = "runtime_core_unittest.log" 96 TEST262_LOG_FILE_NAME = "test262.log" 97 REGRESS_TEST_LOG_FILE_NAME = "regresstest.log" 98 PREBUILTS_DOWNLOAD_CONFIG_FILE_PATH = \ 99 "./arkcompiler/toolchain/build/prebuilts_download/prebuilts_download_config.json" 100 INDENTATION_STRING_PER_LEVEL = " " # for help message 101 # In ARG_DICT, "flags" and "description" are must-keys for the leaf-dicts in it. 102 # (Future designer need know.) 103 ARG_DICT = { 104 "os_cpu": { 105 "linux_x64": { 106 "flags": ["linux_x64", "x64"], 107 "description": 108 "Build for arkcompiler target of target-operating-system linux and " 109 "target-central-processing-unit x64.", 110 "gn_args": ["target_os=\"linux\"", "target_cpu=\"x64\""], 111 "prefix_of_name_of_out_dir_of_second_level": "x64", 112 }, 113 "linux_x86": { 114 "flags": ["linux_x86", "x86"], 115 "description": 116 "Build for arkcompiler target of target-operating-system linux and " 117 "target-central-processing-unit x86.", 118 "gn_args": ["target_os=\"linux\"", "target_cpu=\"x86\""], 119 "prefix_of_name_of_out_dir_of_second_level": "x86", 120 }, 121 "ohos_arm": { 122 "flags": ["ohos_arm", "arm"], 123 "description": 124 "Build for arkcompiler target of target-operating-system ohos and " 125 "target-central-processing-unit arm.", 126 "gn_args": ["target_os=\"ohos\"", "target_cpu=\"arm\""], 127 "prefix_of_name_of_out_dir_of_second_level": "arm", 128 }, 129 "ohos_arm64": { 130 "flags": ["ohos_arm64", "arm64"], 131 "description": 132 "Build for arkcompiler target of target-operating-system ohos and " 133 "target-central-processing-unit arm64.", 134 "gn_args": ["target_os=\"ohos\"", "target_cpu=\"arm64\""], 135 "prefix_of_name_of_out_dir_of_second_level": "arm64", 136 }, 137 "android_arm64": { 138 "flags": ["android_arm64"], 139 "description": 140 "Build for arkcompiler target of target-operating-system android and " 141 "target-central-processing-unit arm64.", 142 "gn_args": ["target_os=\"android\"", "target_cpu=\"arm64\""], 143 "prefix_of_name_of_out_dir_of_second_level": "android_arm64", 144 }, 145 "mingw_x86_64": { 146 "flags": ["mingw_x86_64"], 147 "description": 148 "Build for arkcompiler target of target-operating-system MinGW(Minimalist GNU on Windows) and " 149 "target-central-processing-unit x86_64.", 150 "gn_args": ["target_os=\"mingw\"", "target_cpu=\"x86_64\""], 151 "prefix_of_name_of_out_dir_of_second_level": "mingw_x86_64", 152 }, 153 "ohos_mipsel": { 154 "flags": ["ohos_mipsel", "mipsel"], 155 "description": 156 "Build for arkcompiler target of target-operating-system ohos and " 157 "target-central-processing-unit mipsel(32-bit little-endian mips).", 158 "gn_args": ["target_os=\"ohos\"", "target_cpu=\"mipsel\""], 159 "prefix_of_name_of_out_dir_of_second_level": "mipsel", 160 }, 161 "mac_arm64": { 162 "flags": ["mac_arm64", "arm64"], 163 "description": 164 "Build for arkcompiler target of target-operating-system linux and " 165 "target-central-processing-unit arm64.", 166 "gn_args": ["target_os=\"mac\"", "target_cpu=\"arm64\""], 167 "prefix_of_name_of_out_dir_of_second_level": "mac_arm64", 168 }, 169 "mac_x86": { 170 "flags": ["mac_x86", "x86"], 171 "description": 172 "Build for arkcompiler target of target-operating-system mac and " 173 "target-central-processing-unit x86.", 174 "gn_args": ["target_os=\"mac\"", "target_cpu=\"x86\""], 175 "prefix_of_name_of_out_dir_of_second_level": "mac_x86", 176 }, 177 }, 178 "mode": { 179 "release": { 180 "flags": ["release", "r"], 181 "description": "Build for arkcompiler target(executables and libraries) for distribution.", 182 "gn_args": ["is_debug=false"], 183 "suffix_of_name_of_out_dir_of_second_level": "release", 184 }, 185 "debug": { 186 "flags": ["debug", "d"], 187 "description": "Build for arkcompiler target(executables and libraries) for debugging.", 188 "gn_args": ["is_debug=true"], 189 "suffix_of_name_of_out_dir_of_second_level": "debug", 190 }, 191 "fastverify": { 192 "flags": ["fastverify", "fv"], 193 "description": "Build for arkcompiler target(executables and libraries) for fastverify.", 194 "gn_args": ["is_debug=true is_fastverify=true"], 195 "suffix_of_name_of_out_dir_of_second_level": "fastverify", 196 }, 197 }, 198 "target": { 199 "test262": { 200 "flags": ["test262", "test-262", "test_262", "262test", "262-test", "262_test", "262"], 201 "description": "Compile arkcompiler target and run test262 with arkcompiler target.", 202 "gn_targets_depend_on": ["default"], 203 "arm64_gn_targets_depend_on": ["ark_js_packages"], 204 }, 205 "unittest": { 206 "flags": ["unittest", "ut"], 207 "description": 208 "Compile and run unittest of arkcompiler target. " 209 "Add --keep-going=N to keep running unittest when errors occured less than N. " 210 "Add --gn-args=\"run_with_qemu=true\" timeout=\"1200\"\ 211 \"disable_force_gc=true\" to command when running unittest of non-host type with qemu.", 212 "gn_targets_depend_on": ["unittest_packages"], 213 }, 214 "runtime_core_unittest": { 215 "flags": ["runtime_core_unittest"], 216 "description": 217 "Compile and run runtime_core_unittest of arkcompiler target. " 218 "Add --keep-going=N to keep running runtime_core_unittest when errors occured less than N. ", 219 "gn_targets_depend_on": ["runtime_core_unittest_packages"], 220 }, 221 "workload": { 222 "flags": ["workload", "work-load", "work_load"], 223 "description": "Compile arkcompiler target and run workload with arkcompiler target.", 224 "gn_targets_depend_on": ["default"], 225 }, 226 "regresstest": { 227 "flags": ["regresstest", "regress_test", "regress", "testregress", "test_regress"], 228 "description": "Compile arkcompiler target and run regresstest with arkcompiler target.", 229 "gn_targets_depend_on": ["default"], 230 }, 231 "gn_target": { 232 "flags": ["<name of target in \"*.gn*\" file>"], # any other flags 233 "description": 234 "Build for arkcompiler target assigned by user. Targets include group(ets_runtime), " 235 "ohos_executable(ark_js_vm), ohos_shared_library(libark_jsruntime), " 236 "ohos_static_library(static_icuuc), ohos_source_set(libark_jsruntime_set), " 237 "ohos_unittest(EcmaVm_001_Test), action(EcmaVm_001_TestAction) and other target of user-defined " 238 "template type in \"*.gn*\" file.", 239 "gn_targets_depend_on": [], # not need, depend on deps of itself in "*.gn*" file 240 }, 241 }, 242 "option": { 243 "clean": { 244 "flags": ["--clean", "-clean"], 245 "description": 246 "Clean the root-out-dir(x64.release-->out/x64.release) execept for file args.gn. " 247 "Then exit.", 248 }, 249 "clean-continue": { 250 "flags": ["--clean-continue", "-clean-continue"], 251 "description": 252 "Clean the root-out-dir(x64.release-->out/x64.release) execept for file args.gn. " 253 "Then continue to build.", 254 }, 255 "gn-args": { 256 "flags": ["--gn-args=*", "-gn-args=*"], 257 "description": 258 "Pass args(*) to gn command. Example: python3 ark.py x64.release " 259 "--gn-args=\"bool_declared_in_src_gn=true string_declared_in_src_gn=\\\"abcd\\\" " 260 "list_declared_in_src_gn=[ \\\"element0\\\", \\\"element1\\\" ] print(list_declared_in_src_gn) " 261 "exec_script(\\\"script_in_src\\\", [ \\\"arg_to_script\\\" ])\" .", 262 }, 263 "keepdepfile": { 264 "flags": ["--keepdepfile", "-keepdepfile"], 265 "description": 266 "Keep depfile(\"*.o.d\") generated by commands(CXX, CC ...) called by ninja during compilation.", 267 }, 268 "verbose": { 269 "flags": ["--verbose", "-verbose"], 270 "description": "Print full commands(CXX, CC, LINK ...) called by ninja during compilation.", 271 }, 272 "keep-going": { 273 "flags": ["--keep-going=*", "-keep-going=*"], 274 "description": "Keep running unittest etc. until errors occured less than N times" 275 " (use 0 to ignore all errors).", 276 }, 277 }, 278 "help": { 279 "flags": ["help", "--help", "--h", "-help", "-h"], 280 "description": "Show the usage of ark.py.", 281 }, 282 } 283 284 # variables which would change with the change of host_os or host_cpu 285 gn_binary_path = "" 286 ninja_binary_path = "" 287 288 # variables which would change with the change of ark.py command 289 has_cleaned = False 290 enable_verbose = False 291 enable_keepdepfile = False 292 ignore_errors = 1 293 294 def __main__(self, arg_list: list): 295 enable_ccache() 296 # delete duplicate arg in arg_list 297 arg_list = list(dict.fromkeys(arg_list)) 298 # match [help] flag 299 if len(arg_list) == 0 or ( 300 True in [self.is_dict_flags_match_arg(self.ARG_DICT.get("help"), arg) for arg in arg_list]): 301 print(self.get_help_msg_of_all()) 302 return 303 # match [[os_cpu].[mode]] flag 304 [match_success, key_to_dict_in_os_cpu, key_to_dict_in_mode] = self.dict_in_os_cpu_mode_match_arg(arg_list[0]) 305 if match_success: 306 self.start_for_matched_os_cpu_mode(key_to_dict_in_os_cpu, key_to_dict_in_mode, arg_list[1:]) 307 else: 308 print("\033[92mThe command is not supported! Help message shows below.\033[0m\n{}".format( 309 self.get_help_msg_of_all())) 310 return 311 312 @staticmethod 313 def is_dict_flags_match_arg(dict_to_match: dict, arg_to_match: str) -> bool: 314 for flag in dict_to_match["flags"]: 315 if fnmatch(arg_to_match, flag): 316 return True 317 return False 318 319 @staticmethod 320 def libs_dir(is_arm, is_aot, is_pgo, out_dir, x64_out_dir) -> str: 321 if is_arm and is_aot and is_pgo: 322 return (f"--libs-dir ../../{out_dir}/arkcompiler/ets_runtime:" 323 f"../../{out_dir}/thirdparty/icu:" 324 f"../../{out_dir}/third_party/icu:" 325 f"../../thirdparty/zlib:" 326 f"../../prebuilts/clang/ohos/linux-x86_64/llvm/lib") 327 if is_arm and is_aot and not is_pgo: 328 return ("--libs-dir ../../prebuilts/clang/ohos/linux-x86_64/llvm/lib" 329 f":../../{x64_out_dir}/thirdparty/icu/") 330 if not is_arm and is_aot: 331 return (f"--libs-dir ../../{out_dir}/arkcompiler/ets_runtime" 332 f":../../{out_dir}/thirdparty/icu:" 333 f"../../{out_dir}/third_party/icu:" 334 f"../../thirdparty/zlib:" 335 f"../../prebuilts/clang/ohos/linux-x86_64/llvm/lib") 336 # not is_arm and not is_aot 337 return " --libs-dir ../../prebuilts/clang/ohos/linux-x86_64/llvm/lib" 338 339 @staticmethod 340 def get_cmd(test_suite, test_script_name, test_script_path, gn_args, out_path, x64_out_path, aot_mode, run_pgo, 341 enable_litecg, args_to_cmd, timeout, ignore_list: Optional[str] = None): 342 cmd = [ 343 f"cd {test_script_path}", 344 f"&& python3 {test_script_name} {args_to_cmd}", 345 f"--timeout {timeout}", 346 f"--ark-tool=../../{out_path}/arkcompiler/ets_runtime/ark_js_vm", 347 "--ark-frontend=es2panda" 348 ] 349 is_arm = any('target_cpu="arm64"' in arg for arg in gn_args) 350 if is_arm: 351 cmd.append("--ark-arch aarch64") 352 cmd.append(f"--ark-arch-root=../../{out_path}/common/common/libc/") 353 cmd.append(f"--ark-frontend-binary=../../{x64_out_path}/arkcompiler/ets_frontend/es2abc") 354 cmd.append(f"--merge-abc-binary=../../{x64_out_path}/arkcompiler/ets_frontend/merge_abc") 355 if aot_mode: 356 cmd.append(f"--ark-aot-tool=../../{out_path}/arkcompiler/ets_runtime/ark_aot_compiler") 357 if test_suite == "regresstest": 358 cmd.append(f"--stub-path=../../{out_path}/gen/arkcompiler/ets_runtime/stub.an") 359 else: 360 cmd.append(f"--ark-frontend-binary=../../{out_path}/arkcompiler/ets_frontend/es2abc") 361 cmd.append(f"--merge-abc-binary=../../{out_path}/arkcompiler/ets_frontend/merge_abc") 362 if aot_mode: 363 cmd.append(f"--ark-aot-tool=../../{out_path}/arkcompiler/ets_runtime/ark_aot_compiler") 364 if test_suite == "regresstest": 365 cmd.append(f"--stub-path=../../{out_path}/gen/arkcompiler/ets_runtime/stub.an") 366 367 cmd.append(ArkPy.libs_dir( 368 is_arm=is_arm, 369 is_aot=aot_mode, 370 is_pgo=run_pgo, 371 out_dir=out_path, 372 x64_out_dir=x64_out_path 373 )) 374 375 if aot_mode: 376 cmd.append("--ark-aot") 377 mode = ["AOT"] 378 if run_pgo: 379 cmd.append("--run-pgo") 380 mode.append("PGO") 381 if enable_litecg: 382 cmd.append("--enable-litecg") 383 mode.append("LiteCG") 384 mode_str = " ".join(mode) 385 print(f"Running {test_suite} in {mode_str} Mode\n") 386 387 if test_suite == "regresstest" and ignore_list: 388 cmd.append(f"--ignore-list {ignore_list}") 389 390 if test_suite == "regresstest": 391 cmd.append(f"--out-dir ../../{out_path}") 392 393 return " ".join(cmd) 394 395 @staticmethod 396 def get_test262_aot_cmd(gn_args, out_path, x64_out_path, run_pgo, enable_litecg, args_to_test262_cmd, 397 timeout): 398 print("running test262 in AotMode\n") 399 if any('target_cpu="arm64"' in arg for arg in gn_args): 400 if run_pgo: 401 test262_cmd = f"cd arkcompiler/ets_frontend && python3 test262/run_test262.py {args_to_test262_cmd}" \ 402 f" --timeout {timeout}" \ 403 f" --libs-dir ../../{out_path}/arkcompiler/ets_runtime:../../{out_path}/thirdparty/icu:" \ 404 f"../../{out_path}/thirdparty/zlib:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib" \ 405 " --ark-arch aarch64" \ 406 f" --ark-arch-root=../../{out_path}/common/common/libc/" \ 407 f" --ark-tool=../../{out_path}/arkcompiler/ets_runtime/ark_js_vm" \ 408 f" --ark-aot-tool=../../{out_path}/arkcompiler/ets_runtime/ark_aot_compiler" \ 409 f" --ark-frontend-binary=../../{x64_out_path}/arkcompiler/ets_frontend/es2abc" \ 410 f" --merge-abc-binary=../../{x64_out_path}/arkcompiler/ets_frontend/merge_abc" \ 411 " --ark-aot" \ 412 " --ark-frontend=es2panda" \ 413 " --run-pgo" 414 else: 415 test262_cmd = "cd arkcompiler/ets_frontend && python3 test262/run_test262.py {0} --timeout {3}" \ 416 " --libs-dir ../../prebuilts/clang/ohos/linux-x86_64/llvm/lib:../../{2}/thirdparty/icu/" \ 417 " --ark-arch aarch64" \ 418 " --ark-arch-root=../../{1}/common/common/libc/" \ 419 " --ark-aot" \ 420 " --ark-aot-tool=../../{2}/arkcompiler/ets_runtime/ark_aot_compiler" \ 421 " --ark-tool=../../{1}/arkcompiler/ets_runtime/ark_js_vm" \ 422 " --ark-frontend-binary=../../{2}/arkcompiler/ets_frontend/es2abc" \ 423 " --merge-abc-binary=../../{2}/arkcompiler/ets_frontend/merge_abc" \ 424 " --ark-frontend=es2panda".format(args_to_test262_cmd, out_path, x64_out_path, timeout) 425 else: 426 run_pgo_arg = " --run-pgo" if run_pgo else "" 427 test262_cmd = f"cd arkcompiler/ets_frontend && python3 test262/run_test262.py {args_to_test262_cmd}" \ 428 f" --timeout {timeout}" \ 429 f" --libs-dir ../../{out_path}/arkcompiler/ets_runtime:../../{out_path}/thirdparty/icu" \ 430 f":../../{out_path}/thirdparty/zlib:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib" \ 431 f" --ark-tool=../../{out_path}/arkcompiler/ets_runtime/ark_js_vm" \ 432 f" --ark-aot-tool=../../{out_path}/arkcompiler/ets_runtime/ark_aot_compiler" \ 433 f" --ark-frontend-binary=../../{out_path}/arkcompiler/ets_frontend/es2abc" \ 434 f" --merge-abc-binary=../../{out_path}/arkcompiler/ets_frontend/merge_abc" \ 435 " --ark-aot" \ 436 " --ark-frontend=es2panda" \ 437 f" {run_pgo_arg}" 438 if enable_litecg: 439 test262_cmd = test262_cmd + " --enable-litecg" 440 return test262_cmd 441 442 @staticmethod 443 def get_jit_cmd(test_suite, test_script_name, test_script_path, gn_args, out_path, x64_out_path, args_to_cmd, 444 timeout): 445 print(f"running {test_suite} in JIT mode\n") 446 if any('target_cpu="arm64"' in arg for arg in gn_args): 447 cmd = f"cd {test_script_path} && python3 {test_script_name} {args_to_cmd} --timeout {timeout}" \ 448 f" --libs-dir ../../prebuilts/clang/ohos/linux-x86_64/llvm/lib:../../{out_path}/thirdparty/icu/" \ 449 f":../../{out_path}/thirdparty/bounds_checking_function" \ 450 f":../../{out_path}/arkcompiler/ets_runtime:" \ 451 " --ark-arch aarch64" \ 452 " --run-jit" \ 453 f" --ark-arch-root=../../{out_path}/common/common/libc/" \ 454 f" --ark-aot-tool=../../{x64_out_path}/arkcompiler/ets_runtime/ark_aot_compiler" \ 455 f" --ark-tool=../../{out_path}/arkcompiler/ets_runtime/ark_js_vm" \ 456 f" --ark-frontend-binary=../../{x64_out_path}/arkcompiler/ets_frontend/es2abc" \ 457 f" --merge-abc-binary=../../{x64_out_path}/arkcompiler/ets_frontend/merge_abc" \ 458 " --ark-frontend=es2panda" 459 else: 460 cmd = f"cd arkcompiler/ets_frontend && python3 {test_script_name} {args_to_cmd} --timeout {timeout}" \ 461 f" --libs-dir ../../{out_path}/arkcompiler/ets_runtime:../../{out_path}/thirdparty/icu" \ 462 f":../../{out_path}/thirdparty/zlib:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib" \ 463 " --run-jit" \ 464 f" --ark-tool=../../{out_path}/arkcompiler/ets_runtime/ark_js_vm" \ 465 f" --ark-frontend-binary=../../{out_path}/arkcompiler/ets_frontend/es2abc" \ 466 f" --merge-abc-binary=../../{out_path}/arkcompiler/ets_frontend/merge_abc" \ 467 " --ark-frontend=es2panda" 468 return cmd 469 470 @staticmethod 471 def get_baseline_jit_cmd(test_suite, test_script_name, test_script_path, gn_args, out_path, x64_out_path, 472 args_to_test262_cmd, timeout): 473 print(f"running {test_suite} in baseline JIT mode\n") 474 if any('target_cpu="arm64"' in arg for arg in gn_args): 475 cmd = f"cd {test_script_path} && python3 {test_script_name} {args_to_test262_cmd} --timeout {timeout}" \ 476 f" --libs-dir ../../prebuilts/clang/ohos/linux-x86_64/llvm/lib" \ 477 f":../../{out_path}/thirdparty/icu" \ 478 f":../../prebuilts/clang/ohos/linux-x86_64/llvm/lib/aarch64-linux-ohos" \ 479 f":../../{out_path}/thirdparty/bounds_checking_function" \ 480 f":../../{out_path}/arkcompiler/ets_runtime" \ 481 f":../../{out_path}/common/common/libc/lib" \ 482 " --ark-arch aarch64" \ 483 " --run-baseline-jit" \ 484 f" --ark-arch-root=../../{out_path}/common/common/libc/" \ 485 f" --ark-aot-tool=../../{x64_out_path}/arkcompiler/ets_runtime/ark_aot_compiler" \ 486 f" --ark-tool=../../{out_path}/arkcompiler/ets_runtime/ark_js_vm" \ 487 f" --ark-frontend-binary=../../{x64_out_path}/arkcompiler/ets_frontend/es2abc" \ 488 f" --merge-abc-binary=../../{x64_out_path}/arkcompiler/ets_frontend/merge_abc" \ 489 " --ark-frontend=es2panda" 490 else: 491 cmd = f"cd {test_script_path} && python3 {test_script_name} {args_to_test262_cmd} --timeout {timeout}" \ 492 f" --libs-dir ../../{out_path}/lib.unstripped/arkcompiler/ets_runtime" \ 493 f":../../{out_path}/thirdparty/icu" \ 494 ":../../prebuilts/clang/ohos/linux-x86_64/llvm/lib" \ 495 f":../../{out_path}/thirdparty/bounds_checking_function/" \ 496 " --run-baseline-jit" \ 497 f" --ark-tool=../../{out_path}/arkcompiler/ets_runtime/ark_js_vm" \ 498 f" --ark-frontend-binary=../../{out_path}/arkcompiler/ets_frontend/es2abc" \ 499 f" --merge-abc-binary=../../{out_path}/arkcompiler/ets_frontend/merge_abc" \ 500 " --ark-frontend=es2panda" 501 return cmd 502 503 @staticmethod 504 def build_args_to_test262_cmd(arg_list): 505 args_to_test262_cmd = [] 506 507 disable_force_gc_name = "--disable-force-gc" 508 disable_force_gc_value, arg_list = ArkPy.parse_bool_option( 509 arg_list, option_name=disable_force_gc_name, default_value=False 510 ) 511 if disable_force_gc_value: 512 args_to_test262_cmd.extend([disable_force_gc_name]) 513 514 threads_name = "--threads" 515 threads_value, arg_list = ArkPy.parse_option(arg_list, option_name=threads_name, default_value=None) 516 if threads_value: 517 args_to_test262_cmd.extend([threads_name, threads_value]) 518 519 test_list_name = "--test-list" 520 test_list_value, arg_list = ArkPy.parse_option(arg_list, option_name=test_list_name, default_value=None) 521 if test_list_value is not None: 522 args_to_test262_cmd.extend([test_list_name, test_list_value]) 523 524 enable_rm = [arg for arg in arg_list if "enable-rm" in arg] 525 if enable_rm: 526 args_to_test262_cmd.append("--enable-rm") 527 arg_list.remove(enable_rm[0]) 528 529 skip_list_name = "--skip-list" 530 skip_list_value, arg_list = ArkPy.parse_option(arg_list, option_name=skip_list_name, default_value=None) 531 if skip_list_value is not None: 532 args_to_test262_cmd.extend([skip_list_name, skip_list_value]) 533 534 if len(arg_list) == 0: 535 args_to_test262_cmd.append("--es2021 all") 536 elif len(arg_list) == 1: 537 arg = arg_list[0] 538 if arg == "sendable": 539 args_to_test262_cmd.append("--sendable sendable") 540 elif ".js" in arg: 541 args_to_test262_cmd.append("--file test262/data/test_es2021/{}".format(arg)) 542 elif "--abc2program" in arg: 543 args_to_test262_cmd.append("--abc2program --es2021 all") 544 else: 545 args_to_test262_cmd.append("--dir test262/data/test_es2021/{}".format(arg)) 546 else: 547 print("\033[92m\"test262\" not support multiple additional arguments.\033[0m\n".format()) 548 sys.exit(0) 549 550 return " ".join(args_to_test262_cmd) 551 552 @staticmethod 553 def build_args_to_regress_cmd(arg_list): 554 args_to_regress_cmd = [] 555 556 disable_force_gc_name = "--disable-force-gc" 557 disable_force_gc_value, arg_list = ArkPy.parse_bool_option( 558 arg_list, option_name=disable_force_gc_name, default_value=False 559 ) 560 if disable_force_gc_value: 561 args_to_regress_cmd.extend([disable_force_gc_name]) 562 563 processes_name = "--processes" 564 processes_value, arg_list = ArkPy.parse_option(arg_list, option_name=processes_name, default_value=1) 565 args_to_regress_cmd.extend([processes_name, processes_value]) 566 567 test_list_name = "--test-list" 568 test_list_value, arg_list = ArkPy.parse_option(arg_list, option_name=test_list_name, default_value=None) 569 if test_list_value is not None: 570 args_to_regress_cmd.extend([test_list_name, test_list_value]) 571 compiler_opt_track_field_name = "--compiler-opt-track-field" 572 compiler_opt_track_field_value, arg_list = ArkPy.parse_bool_option( 573 arg_list, option_name=compiler_opt_track_field_name, default_value=False 574 ) 575 if compiler_opt_track_field_value: 576 args_to_regress_cmd.append(f"{compiler_opt_track_field_name}={compiler_opt_track_field_value}") 577 if len(arg_list) == 1: 578 arg = arg_list[0] 579 if ".js" in arg: 580 args_to_regress_cmd.append(f"--test-file {arg}") 581 else: 582 args_to_regress_cmd.append(f"--test-dir {arg}") 583 elif len(arg_list) > 1: 584 print("\033[92m\"regresstest\" not support multiple additional arguments.\033[0m\n".format()) 585 sys.exit(0) 586 587 return " ".join([str(arg) for arg in args_to_regress_cmd]) 588 589 @staticmethod 590 def parse_option(arg_list: List[str], option_name: str, default_value: Optional[Union[str, int]]) \ 591 -> Tuple[Optional[Union[str, int]], List[str]]: 592 option_value, arg_list = ArkPy.__parse_option_with_space(arg_list, option_name) 593 if option_value is None: 594 option_value, arg_list = ArkPy.__parse_option_with_equal(arg_list, option_name) 595 if option_value is None and default_value is not None: 596 option_value = default_value 597 return option_value, arg_list 598 599 @staticmethod 600 def parse_bool_option(arg_list: List[str], option_name: str, default_value: bool) \ 601 -> Tuple[bool, List[str]]: 602 if option_name in arg_list: 603 option_index = arg_list.index(option_name) 604 option_value = not default_value 605 arg_list = arg_list[:option_index] + arg_list[option_index + 1:] 606 else: 607 option_value = default_value 608 609 return option_value, arg_list 610 611 @staticmethod 612 def __is_option_value_int(value: Optional[Union[str, int]]) -> Tuple[bool, Optional[int]]: 613 if isinstance(value, int): 614 return True, int(value) 615 else: 616 return False, None 617 618 @staticmethod 619 def __is_option_value_str(value: Optional[Union[str, int]]) -> Tuple[bool, Optional[str]]: 620 if isinstance(value, str): 621 return True, str(value) 622 else: 623 return False, None 624 625 @staticmethod 626 def __get_option_value(option_name: str, value: Optional[Union[str, int]]) -> Union[str, int]: 627 result, res_value = ArkPy.__is_option_value_int(value) 628 if result: 629 return res_value 630 result, res_value = ArkPy.__is_option_value_str(value) 631 if result: 632 return res_value 633 print(f"Invalid '{option_name}' value.") 634 sys.exit(1) 635 636 @staticmethod 637 def __parse_option_with_space(arg_list: List[str], option_name: str) \ 638 -> Tuple[Optional[Union[str, int]], List[str]]: 639 if option_name in arg_list: 640 option_index = arg_list.index(option_name) 641 if len(arg_list) > option_index + 1: 642 option_value = ArkPy.__get_option_value(option_name, arg_list[option_index + 1]) 643 arg_list = arg_list[:option_index] + arg_list[option_index + 2:] 644 else: 645 print(f"Missing {option_name} value.") 646 sys.exit(1) 647 648 return option_value, arg_list 649 return None, arg_list 650 651 @staticmethod 652 def __parse_option_with_equal(arg_list: List[str], option_name: str) \ 653 -> Tuple[Optional[Union[str, int]], List[str]]: 654 for index, arg in enumerate(arg_list): 655 local_option_name = f"{option_name}=" 656 if arg.startswith(local_option_name): 657 option_value = arg[len(local_option_name):] 658 if option_value: 659 option_value = ArkPy.__get_option_value(option_name, option_value) 660 arg_list = arg_list[:index] + arg_list[index + 1:] 661 return option_value, arg_list 662 else: 663 print(f"Missing {option_name} value.") 664 sys.exit(1) 665 return None, arg_list 666 667 @staticmethod 668 def __get_x64_out_path(out_path) -> str: 669 if 'release' in out_path: 670 return 'out/x64.release' 671 if 'debug' in out_path: 672 return 'out/x64.debug' 673 if 'fastverify' in out_path: 674 return 'out/x64.fastverify' 675 return "" 676 677 def get_binaries(self): 678 host_os = sys.platform 679 host_cpu = platform.machine() 680 try: 681 with open(self.PREBUILTS_DOWNLOAD_CONFIG_FILE_PATH) as file_prebuilts_download_config: 682 prebuilts_download_config_dict = json.load(file_prebuilts_download_config) 683 file_prebuilts_download_config.close() 684 for element in prebuilts_download_config_dict[host_os][host_cpu]["copy_config"]: 685 if element["unzip_filename"] == "gn": 686 self.gn_binary_path = os.path.join(element["unzip_dir"], element["unzip_filename"]) 687 elif element["unzip_filename"] == "ninja": 688 self.ninja_binary_path = os.path.join(element["unzip_dir"], element["unzip_filename"]) 689 except Exception as error: 690 print("\nLogic of getting gn binary or ninja binary does not match logic of prebuilts_download." \ 691 "\nCheck func \033[92m{0} of class {1} in file {2}\033[0m against file {3} if the name of this " \ 692 "file had not changed!\n".format( 693 sys._getframe().f_code.co_name, self.__class__.__name__, CURRENT_FILENAME, 694 self.PREBUILTS_DOWNLOAD_CONFIG_FILE_PATH)) 695 raise error 696 if self.gn_binary_path == "" or self.ninja_binary_path == "": 697 print("\nLogic of prebuilts_download may be wrong." \ 698 "\nCheck \033[92mdata in file {0}\033[0m against func {1} of class {2} in file {3}!\n".format( 699 self.PREBUILTS_DOWNLOAD_CONFIG_FILE_PATH, sys._getframe().f_code.co_name, self.__class__.__name__, 700 CURRENT_FILENAME)) 701 sys.exit(0) 702 if not os.path.isfile(self.gn_binary_path) or not os.path.isfile(self.ninja_binary_path): 703 print("\nStep for prebuilts_download may be ommited. (\033[92m./prebuilts_download.sh\033[0m)" \ 704 "\nCheck \033[92mwhether gn binary and ninja binary are under directory prebuilts\033[0m!\n".format()) 705 sys.exit(0) 706 return 707 708 def which_dict_flags_match_arg(self, dict_including_dicts_to_match: dict, arg_to_match: str) -> str: 709 for key in dict_including_dicts_to_match.keys(): 710 if self.is_dict_flags_match_arg(dict_including_dicts_to_match[key], arg_to_match): 711 return key 712 return "" 713 714 def dict_in_os_cpu_mode_match_arg(self, arg: str) -> [bool, str, str]: 715 os_cpu_part = "" 716 mode_part = "" 717 match_success = True 718 key_to_dict_in_os_cpu_matched_arg = "" 719 key_to_dict_in_mode_matched_arg = "" 720 arg_to_list = arg.split(self.DELIMITER_BETWEEN_OS_CPU_MODE_FOR_COMMAND) 721 if len(arg_to_list) == 1: 722 os_cpu_part = arg_to_list[0] 723 mode_part = "release" 724 key_to_dict_in_os_cpu_matched_arg = self.which_dict_flags_match_arg(self.ARG_DICT.get("os_cpu"), os_cpu_part) 725 key_to_dict_in_mode_matched_arg = self.which_dict_flags_match_arg(self.ARG_DICT.get("mode"), mode_part) 726 elif len(arg_to_list) == 2: 727 os_cpu_part = arg_to_list[0] 728 mode_part = arg_to_list[1] 729 key_to_dict_in_os_cpu_matched_arg = self.which_dict_flags_match_arg(self.ARG_DICT.get("os_cpu"), os_cpu_part) 730 key_to_dict_in_mode_matched_arg = self.which_dict_flags_match_arg(self.ARG_DICT.get("mode"), mode_part) 731 else: 732 print("\"\033[92m{0}\033[0m\" combined with more than 2 flags is not supported.".format(arg)) 733 if (key_to_dict_in_os_cpu_matched_arg == "") | (key_to_dict_in_mode_matched_arg == ""): 734 match_success = False 735 return [match_success, key_to_dict_in_os_cpu_matched_arg, key_to_dict_in_mode_matched_arg] 736 737 def get_help_msg_of_dict(self, dict_in: dict, indentation_str_current: str, indentation_str_per_level: str) -> str: 738 help_msg = "".format() 739 for key in dict_in.keys(): 740 if isinstance(dict_in[key], dict): 741 help_msg += "{0}{1}:\n".format(indentation_str_current, key) 742 help_msg += self.get_help_msg_of_dict( 743 dict_in[key], indentation_str_current + indentation_str_per_level, indentation_str_per_level) 744 elif key == "flags": 745 help_msg += "{0}{1}: \033[92m{2}\033[0m\n".format(indentation_str_current, key, " ".join(dict_in[key])) 746 elif key == "description": 747 help_msg += "{0}{1}: {2}\n".format(indentation_str_current, key, dict_in[key]) 748 return help_msg 749 750 def get_help_msg_of_all(self) -> str: 751 help_msg = "".format() 752 # Command template 753 help_msg += "\033[32mCommand template:\033[0m\n{}\n\n".format( 754 " python3 ark.py \033[92m[os_cpu].[mode] [gn_target] [option]\033[0m\n" 755 " python3 ark.py \033[92m[os_cpu].[mode] [test262] [none or --aot] " \ 756 "[none or --pgo] [none or --litecg] [none, file or dir] [none or --threads=X] [option]\033[0m\n" 757 " python3 ark.py \033[92m[os_cpu].[mode] [test262] [none or --jit] [none or --threads=X]\033[0m\n" 758 " python3 ark.py \033[92m[os_cpu].[mode] [test262] [none or --baseline-jit] [none or --enable-rm] " \ 759 "[none or --threads=X and/or --test-list TEST_LIST_NAME]\033[0m\n" 760 " python3 ark.py \033[92m[os_cpu].[mode] [unittest] [option]\033[0m\n" 761 " python3 ark.py \033[92m[os_cpu].[mode] [runtime_core_unittest] [option]\033[0m\n" 762 " python3 ark.py \033[92m[os_cpu].[mode] [regresstest] [none, file or dir] " \ 763 "[none or --processes X and/or --test-list TEST_LIST_NAME]\033[0m\n") 764 # Command examples 765 help_msg += "\033[32mCommand examples:\033[0m\n{}\n\n".format( 766 " python3 ark.py \033[92mx64.release\033[0m\n" 767 " python3 ark.py \033[92mx64.release ets_runtime\033[0m\n" 768 " python3 ark.py \033[92mx64.release ark_js_vm es2panda\033[0m\n" 769 " python3 ark.py \033[92mx64.release ark_js_vm es2panda --clean\033[0m\n" 770 " python3 ark.py \033[92mx64.release test262\033[0m\n" 771 " python3 ark.py \033[92mx64.release test262 --threads=16\033[0m\n" 772 " python3 ark.py \033[92mx64.release test262 --aot --pgo --litecg\033[0m\n" 773 " python3 ark.py \033[92mx64.release test262 --aot --pgo --litecg --threads=8\033[0m\n" 774 " python3 ark.py \033[92mx64.release test262 --jit --enable-rm\033[0m\n" 775 " python3 ark.py \033[92mx64.release test262 --baseline-jit\033[0m\n" 776 " python3 ark.py \033[92mx64.release test262 built-ins/Array\033[0m\n" 777 " python3 ark.py \033[92mx64.release test262 built-ins/Array/name.js\033[0m\n" 778 " python3 ark.py \033[92mx64.release unittest\033[0m\n" 779 " python3 ark.py \033[92mx64.release runtime_core_unittest\033[0m\n" 780 " python3 ark.py \033[92mx64.release regresstest\033[0m\n" 781 " python3 ark.py \033[92mx64.release regresstest --processes=4\033[0m\n" 782 " python3 ark.py \033[92mx64.release workload\033[0m\n" 783 " python3 ark.py \033[92mx64.release workload report\033[0m\n" 784 " python3 ark.py \033[92mx64.release workload report dev\033[0m\n" 785 " python3 ark.py \033[92mx64.release workload report dev -20\033[0m\n" 786 " python3 ark.py \033[92mx64.release workload report dev -20 10\033[0m\n" 787 " python3 ark.py \033[92mx64.release workload report dev -20 10 weekly_workload\033[0m\n") 788 # Arguments 789 help_msg += "\033[32mArguments:\033[0m\n{}".format( 790 self.get_help_msg_of_dict( 791 self.ARG_DICT, self.INDENTATION_STRING_PER_LEVEL, self.INDENTATION_STRING_PER_LEVEL)) 792 return help_msg 793 794 def clean(self, out_path: str): 795 if not os.path.exists(out_path): 796 print("Path \"{}\" does not exist! No need to clean it.".format(out_path)) 797 else: 798 print("=== clean start ===") 799 code = _call("{0} clean {1}".format(self.gn_binary_path, out_path)) 800 if code != 0: 801 print("=== clean failed! ===\n") 802 sys.exit(code) 803 print("=== clean success! ===\n") 804 return 805 806 def build_for_gn_target(self, out_path: str, gn_args: list, arg_list: list, log_file_name: str): 807 # prepare log file 808 build_log_path = os.path.join(out_path, log_file_name) 809 backup(build_log_path, "w") 810 if arg_list is not None: 811 build_target = " ".join([str(arg).strip() for arg in arg_list 812 if arg is not None or len(str(arg).strip()) > 0]) 813 else: 814 build_target = "" 815 str_to_build_log = "================================\nbuild_time: {0}\nbuild_target: {1}\n\n".format( 816 str_of_time_now(), build_target) 817 _write(build_log_path, str_to_build_log, "a") 818 # gn command 819 print("=== gn gen start ===") 820 code = call_with_output( 821 "{0} gen {1} --args=\"{2}\" --export-compile-commands".format( 822 self.gn_binary_path, out_path, " ".join(gn_args).replace("\"", "\\\"")), 823 build_log_path) 824 if code != 0: 825 print("=== gn gen failed! ===\n") 826 sys.exit(code) 827 else: 828 print("=== gn gen success! ===\n") 829 # ninja command 830 # Always add " -d keeprsp" to ninja command to keep response file("*.rsp"), thus we could get shared libraries 831 # of an excutable from its response file. 832 ninja_cmd = \ 833 self.ninja_binary_path + \ 834 (" -v" if self.enable_verbose else "") + \ 835 (" -d keepdepfile" if self.enable_keepdepfile else "") + \ 836 " -d keeprsp" + \ 837 " -C {}".format(out_path) + \ 838 " {}".format(" ".join(arg_list if arg_list else [])) + \ 839 " -k {}".format(self.ignore_errors) 840 print(ninja_cmd) 841 code = call_with_output(ninja_cmd, build_log_path) 842 if code != 0: 843 print("=== ninja failed! ===\n") 844 sys.exit(code) 845 else: 846 print("=== ninja success! ===\n") 847 return 848 849 def call_build_gn_target(self, gn_args, out_path, x64_out_path, test_suite, log_file_name): 850 if any('target_cpu="arm64"' in arg for arg in gn_args): 851 gn_args.append("so_dir_for_qemu=\"../../{0}/common/common/libc/\"".format(out_path)) 852 gn_args.append("run_with_qemu=true".format(out_path)) 853 if not os.path.exists(x64_out_path): 854 os.makedirs(x64_out_path) 855 self.build_for_gn_target( 856 x64_out_path, 857 ['target_os="linux"', 'target_cpu="x64"', 'is_debug=false'], 858 self.ARG_DICT.get("target").get(test_suite).get("gn_targets_depend_on"), 859 log_file_name) 860 self.build_for_gn_target( 861 out_path, 862 gn_args, 863 self.ARG_DICT.get("target").get(test_suite).get("arm64_gn_targets_depend_on"), 864 log_file_name) 865 else: 866 self.build_for_gn_target( 867 out_path, 868 gn_args, 869 self.ARG_DICT.get("target").get(test_suite).get("gn_targets_depend_on"), 870 log_file_name) 871 872 def get_build_cmd(self, *, test_suite, test_script_name, test_script_path, 873 out_path, x64_out_path, gn_args: list, args_to_cmd: str, timeout, 874 run_jit: bool = False, run_baseline_jit: bool = False, aot_mode: bool = False, 875 run_pgo: bool = False, enable_litecg: bool = False, ignore_list: Optional[str] = None) -> str: 876 if run_jit: 877 cmd = self.get_jit_cmd(test_suite, test_script_name, test_script_path, 878 gn_args, out_path, x64_out_path, args_to_cmd, timeout) 879 elif run_baseline_jit: 880 cmd = self.get_baseline_jit_cmd(test_suite, test_script_name, test_script_path, 881 gn_args, out_path, x64_out_path, args_to_cmd, timeout) 882 elif aot_mode and test_suite == "test262": 883 cmd = self.get_test262_aot_cmd(gn_args, out_path, x64_out_path, run_pgo, 884 enable_litecg, args_to_cmd, timeout) 885 else: 886 cmd = self.get_cmd(test_suite, test_script_name, test_script_path, 887 gn_args, out_path, x64_out_path, aot_mode, run_pgo, 888 enable_litecg, args_to_cmd, timeout, ignore_list) 889 return cmd 890 891 def build_for_suite(self, *, test_suite, test_script_name, test_script_path, 892 out_path, gn_args: list, log_file_name, args_to_cmd: str, timeout, 893 run_jit: bool = False, run_baseline_jit: bool = False, aot_mode: bool = False, 894 run_pgo: bool = False, enable_litecg: bool = False, ignore_list: Optional[str] = None, 895 skip_compiler: bool = False): 896 x64_out_path = self.__get_x64_out_path(out_path) 897 if not skip_compiler: 898 self.call_build_gn_target(gn_args, out_path, x64_out_path, test_suite, log_file_name) 899 cmd = self.get_build_cmd( 900 test_suite=test_suite, 901 test_script_name=test_script_name, 902 test_script_path=test_script_path, 903 out_path=out_path, 904 x64_out_path=x64_out_path, 905 gn_args=gn_args, 906 args_to_cmd=args_to_cmd, 907 timeout=timeout, 908 run_jit=run_jit, 909 run_baseline_jit=run_baseline_jit, 910 aot_mode=aot_mode, run_pgo=run_pgo, enable_litecg=enable_litecg, ignore_list=ignore_list) 911 log_path = str(os.path.join(out_path, log_file_name)) 912 str_to_log = "================================\n{2}_time: {0}\n{2}_target: {1}\n\n".format( 913 str_of_time_now(), args_to_cmd, test_suite) 914 _write(log_path, str_to_log, "a") 915 print(f"=== {test_suite} start ===") 916 code = call_with_output(cmd, log_path) 917 if code != 0: 918 print(f"=== {test_suite} fail! ===\n") 919 sys.exit(code) 920 print(f"=== {test_suite} success! ===\n") 921 922 def build_for_test262(self, out_path, gn_args: list, arg_list: list): 923 timeout, arg_list = self.parse_timeout(arg_list) 924 arg_list = arg_list[1:] 925 926 is_aot_mode, arg_list = self.__purge_arg_list("--aot", arg_list) 927 is_pgo, arg_list = self.__purge_arg_list("--pgo", arg_list) 928 is_litecg, arg_list = self.__purge_arg_list("--litecg", arg_list) 929 is_jit, arg_list = self.__purge_arg_list("--jit", arg_list) 930 is_baseline_jit, arg_list = self.__purge_arg_list("--baseline-jit", arg_list) 931 is_skip_compiler, arg_list = self.__purge_arg_list("--skip-compiler", arg_list) 932 print(f"Test262: arg_list = {arg_list}") 933 934 args_to_test262_cmd = self.build_args_to_test262_cmd(arg_list) 935 self.build_for_suite( 936 test_suite="test262", 937 test_script_name="test262/run_test262.py", 938 test_script_path="arkcompiler/ets_frontend", 939 out_path=out_path, 940 gn_args=gn_args, 941 log_file_name=self.TEST262_LOG_FILE_NAME, 942 args_to_cmd=args_to_test262_cmd, 943 timeout=timeout, 944 run_jit=is_jit, 945 run_pgo=is_pgo, 946 run_baseline_jit=is_baseline_jit, 947 aot_mode=is_aot_mode, 948 enable_litecg=is_litecg, 949 skip_compiler=is_skip_compiler 950 ) 951 952 def build_for_unittest(self, out_path: str, gn_args: list, log_file_name: str): 953 self.build_for_gn_target( 954 out_path, gn_args, self.ARG_DICT.get("target").get("unittest").get("gn_targets_depend_on"), 955 log_file_name) 956 return 957 958 def build_for_runtime_core_unittest(self, out_path: str, gn_args: list, log_file_name: str): 959 runtime_core_ut_depend = self.ARG_DICT.get("target").get("runtime_core_unittest").get("gn_targets_depend_on") 960 self.build_for_gn_target(out_path, gn_args, runtime_core_ut_depend, log_file_name) 961 return 962 963 def build_for_regress_test(self, out_path, gn_args: list, arg_list: list): 964 timeout, arg_list = self.parse_option(arg_list, option_name="--timeout", default_value=200) 965 ignore_list, arg_list = self.parse_option(arg_list, option_name="--ignore-list", default_value=None) 966 967 arg_list = arg_list[1:] 968 969 is_aot, arg_list = self.__purge_arg_list("--aot", arg_list) 970 is_pgo, arg_list = self.__purge_arg_list("--pgo", arg_list) 971 is_litecg, arg_list = self.__purge_arg_list("--litecg", arg_list) 972 is_jit, arg_list = self.__purge_arg_list("--jit", arg_list) 973 is_baseline_jit, arg_list = self.__purge_arg_list("--baseline-jit", arg_list) 974 is_skip_compiler, arg_list = self.__purge_arg_list("--skip-compiler", arg_list) 975 print(f"Regress: arg_list = {arg_list}") 976 977 args_to_regress_test_cmd = self.build_args_to_regress_cmd(arg_list) 978 self.build_for_suite( 979 test_suite="regresstest", 980 test_script_name="test/regresstest/run_regress_test.py", 981 test_script_path="arkcompiler/ets_runtime", 982 out_path=out_path, 983 gn_args=gn_args, 984 log_file_name=self.REGRESS_TEST_LOG_FILE_NAME, 985 args_to_cmd=args_to_regress_test_cmd, 986 timeout=timeout, 987 run_jit=is_jit, 988 run_pgo=is_pgo, 989 run_baseline_jit=is_baseline_jit, 990 aot_mode=is_aot, 991 enable_litecg=is_litecg, 992 ignore_list=ignore_list, 993 skip_compiler=is_skip_compiler 994 ) 995 996 def build(self, out_path: str, gn_args: list, arg_list: list): 997 if not os.path.exists(out_path): 998 print("# mkdir -p {}".format(out_path)) 999 os.makedirs(out_path) 1000 if len(arg_list) == 0: 1001 self.build_for_gn_target(out_path, gn_args, ["default"], self.GN_TARGET_LOG_FILE_NAME) 1002 elif self.is_dict_flags_match_arg(self.ARG_DICT.get("target").get("workload"), arg_list[0]): 1003 self.build_for_workload(arg_list, out_path, gn_args, 'workload.log') 1004 elif self.is_dict_flags_match_arg(self.ARG_DICT.get("target").get("test262"), arg_list[0]): 1005 self.build_for_test262(out_path, gn_args, arg_list) 1006 elif self.is_dict_flags_match_arg(self.ARG_DICT.get("target").get("unittest"), arg_list[0]): 1007 if len(arg_list) > 1: 1008 print("\033[92m\"unittest\" not support additional arguments.\033[0m\n".format()) 1009 sys.exit(0) 1010 self.build_for_unittest(out_path, gn_args, self.UNITTEST_LOG_FILE_NAME) 1011 elif self.is_dict_flags_match_arg(self.ARG_DICT.get("target").get("runtime_core_unittest"), arg_list[0]): 1012 if len(arg_list) > 1: 1013 print("\033[92m\"runtime_core_unittest\" not support additional arguments.\033[0m\n".format()) 1014 sys.exit(0) 1015 self.build_for_runtime_core_unittest(out_path, gn_args, self.RUNTIME_CORE_UNITTEST_LOG_FILE_NAME) 1016 elif self.is_dict_flags_match_arg(self.ARG_DICT.get("target").get("regresstest"), arg_list[0]): 1017 self.build_for_regress_test(out_path, gn_args, arg_list) 1018 else: 1019 self.build_for_gn_target(out_path, gn_args, arg_list, self.GN_TARGET_LOG_FILE_NAME) 1020 return 1021 1022 def parse_timeout(self, arg_list) -> Tuple[Optional[Union[str, int]], List[str]]: 1023 return self.parse_option(arg_list, option_name="--timeout", default_value=400000) 1024 1025 def match_options(self, arg_list: list, out_path: str) -> [list, list]: 1026 arg_list_ret = [] 1027 gn_args_ret = [] 1028 for arg in arg_list: 1029 # match [option][clean] flag 1030 if self.is_dict_flags_match_arg(self.ARG_DICT.get("option").get("clean"), arg): 1031 self.clean(out_path) 1032 sys.exit(0) 1033 # match [option][clean-continue] flag 1034 elif self.is_dict_flags_match_arg(self.ARG_DICT.get("option").get("clean-continue"), arg): 1035 if not self.has_cleaned: 1036 self.clean(out_path) 1037 self.has_cleaned = True 1038 # match [option][gn-args] flag 1039 elif self.is_dict_flags_match_arg(self.ARG_DICT.get("option").get("gn-args"), arg): 1040 gn_args_ret.append(arg[(arg.find("=") + 1):]) 1041 # match [option][keepdepfile] flag 1042 elif self.is_dict_flags_match_arg(self.ARG_DICT.get("option").get("keepdepfile"), arg): 1043 if not self.enable_keepdepfile: 1044 self.enable_keepdepfile = True 1045 # match [option][verbose] flag 1046 elif self.is_dict_flags_match_arg(self.ARG_DICT.get("option").get("verbose"), arg): 1047 if not self.enable_verbose: 1048 self.enable_verbose = True 1049 # match [option][keep-going] flag 1050 elif self.is_dict_flags_match_arg(self.ARG_DICT.get("option").get("keep-going"), arg): 1051 if self.ignore_errors == 1: 1052 input_value = arg[(arg.find("=") + 1):] 1053 try: 1054 self.ignore_errors = int(input_value) 1055 except Exception as _: 1056 print("\033[92mIllegal value \"{}\" for \"--keep-going\" argument.\033[0m\n".format( 1057 input_value 1058 )) 1059 sys.exit(0) 1060 # make a new list with flag that do not match any flag in [option] 1061 else: 1062 arg_list_ret.append(arg) 1063 return [arg_list_ret, gn_args_ret] 1064 1065 def build_for_workload(self, arg_list, out_path, gn_args, log_file_name): 1066 root_dir = os.path.dirname(os.path.abspath(__file__)) 1067 report = False 1068 tools = 'dev' 1069 boundary_value = '-10' 1070 run_count = '10' 1071 code_v = '' 1072 run_interpreter = False 1073 if len(arg_list) >= 2 and arg_list[1] == 'report': 1074 report = True 1075 if len(arg_list) >= 3 and arg_list[2]: 1076 tools = arg_list[2] 1077 if len(arg_list) >= 4 and arg_list[3]: 1078 boundary_value = arg_list[3] 1079 if len(arg_list) >= 5 and arg_list[4]: 1080 run_count = arg_list[4] 1081 if len(arg_list) >= 6 and arg_list[5]: 1082 code_v = arg_list[5] 1083 if len(arg_list) >= 7 and arg_list[6] == '--run-interpreter': 1084 run_interpreter = True 1085 self.build_for_gn_target(out_path, gn_args, ["default"], self.GN_TARGET_LOG_FILE_NAME) 1086 workload_cmd = "cd arkcompiler/ets_runtime/test/workloadtest/ && python3 work_load.py" \ 1087 " --code-path {0}" \ 1088 " --report {1}" \ 1089 " --tools-type {2}" \ 1090 " --boundary-value {3}" \ 1091 " --run-count {4}" \ 1092 " --code-v {5}" \ 1093 .format(root_dir, report, tools, boundary_value, run_count, code_v) 1094 if run_interpreter: 1095 workload_cmd += " --run-interpreter true" 1096 workload_log_path = os.path.join(out_path, log_file_name) 1097 str_to_workload_log = "================================\nwokload_time: {0}\nwokload_target: {1}\n\n".format( 1098 str_of_time_now(), 'file') 1099 _write(workload_log_path, str_to_workload_log, "a") 1100 print("=== workload start ===") 1101 code = call_with_output(workload_cmd, workload_log_path) 1102 if code != 0: 1103 print("=== workload fail! ===\n") 1104 sys.exit(code) 1105 print("=== workload success! ===\n") 1106 return 1107 1108 def start_for_matched_os_cpu_mode(self, os_cpu_key: str, mode_key: str, arg_list: list): 1109 # get binary gn and ninja 1110 self.get_binaries() 1111 # get out_path 1112 name_of_out_dir_of_second_level = \ 1113 self.ARG_DICT.get("os_cpu").get(os_cpu_key).get("prefix_of_name_of_out_dir_of_second_level") + \ 1114 self.DELIMITER_FOR_SECOND_OUT_DIR_NAME + \ 1115 self.ARG_DICT.get("mode").get(mode_key).get("suffix_of_name_of_out_dir_of_second_level") 1116 out_path = os.path.join(self.NAME_OF_OUT_DIR_OF_FIRST_LEVEL, name_of_out_dir_of_second_level) 1117 # match [option] flag 1118 [arg_list, gn_args] = self.match_options(arg_list, out_path) 1119 # get expression which would be written to args.gn file 1120 gn_args.extend(self.ARG_DICT.get("os_cpu").get(os_cpu_key).get("gn_args")) 1121 gn_args.extend(self.ARG_DICT.get("mode").get(mode_key).get("gn_args")) 1122 # start to build 1123 self.build(out_path, gn_args, arg_list) 1124 return 1125 1126 def __purge_arg_list(self, option_name: str, arg_list: List[Any]) -> Tuple[bool, List[Any]]: 1127 if option_name in arg_list: 1128 arg_list.remove(option_name) 1129 return True, arg_list 1130 return False, arg_list 1131 1132 1133if __name__ == "__main__": 1134 ark_py = ArkPy() 1135 ark_py.__main__(sys.argv[1:]) 1136