1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# 4# Copyright (c) 2022 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 27 28CURRENT_FILENAME = os.path.basename(__file__) 29 30 31def str_of_time_now() -> str: 32 return datetime.now().strftime("%Y-%m-%d-%H-%M-%S-%f")[:-3] 33 34 35def _call(cmd: str): 36 print("# %s" % cmd) 37 return subprocess.call(cmd, shell=True) 38 39 40def _write(filename: str, content: str, mode: str): 41 with open(filename, mode) as f: 42 f.write(content) 43 44 45def call_with_output(cmd: str, file: str): 46 print("# %s" % cmd) 47 host = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) 48 while True: 49 try: 50 build_data = host.stdout.readline().decode('utf-8') 51 sys.stdout.flush() 52 print(build_data) 53 _write(file, build_data, "a") 54 except OSError as error: 55 if error == errno.ENOENT: 56 print("no such file") 57 elif error == errno.EPERM: 58 print("permission denied") 59 break 60 if not build_data: 61 break 62 host.wait() 63 return host.returncode 64 65 66class ArkPy: 67 # constants determined by designer of this class 68 NAME_OF_OUT_DIR_OF_FIRST_LEVEL = "out" 69 DELIMITER_BETWEEN_OS_CPU_MODE_FOR_COMMAND = "." 70 DELIMITER_FOR_SECOND_OUT_DIR_NAME = "." 71 GN_TARGET_LOG_FILE_NAME = "build.log" 72 UNITTEST_LOG_FILE_NAME = "unittest.log" 73 TEST262_LOG_FILE_NAME = "test262.log" 74 REGRESS_TEST_LOG_FILE_NAME = "regresstest.log" 75 PREBUILTS_DOWNLOAD_CONFIG_FILE_PATH = \ 76 "./arkcompiler/toolchain/build/prebuilts_download/prebuilts_download_config.json" 77 INDENTATION_STRING_PER_LEVEL = " " # for help message 78 # In ARG_DICT, "flags" and "description" are must-keys for the leaf-dicts in it. 79 # (Future designer need know.) 80 ARG_DICT = { 81 "os_cpu": { 82 "linux_x64": { 83 "flags": ["linux_x64", "x64"], 84 "description": 85 "Build for arkcompiler target of target-operating-system linux and " 86 "target-central-processing-unit x64.", 87 "gn_args": ["target_os=\"linux\"", "target_cpu=\"x64\""], 88 "prefix_of_name_of_out_dir_of_second_level": "x64", 89 }, 90 "linux_x86": { 91 "flags": ["linux_x86", "x86"], 92 "description": 93 "Build for arkcompiler target of target-operating-system linux and " 94 "target-central-processing-unit x86.", 95 "gn_args": ["target_os=\"linux\"", "target_cpu=\"x86\""], 96 "prefix_of_name_of_out_dir_of_second_level": "x86", 97 }, 98 "ohos_arm": { 99 "flags": ["ohos_arm", "arm"], 100 "description": 101 "Build for arkcompiler target of target-operating-system ohos and " 102 "target-central-processing-unit arm.", 103 "gn_args": ["target_os=\"ohos\"", "target_cpu=\"arm\""], 104 "prefix_of_name_of_out_dir_of_second_level": "arm", 105 }, 106 "ohos_arm64": { 107 "flags": ["ohos_arm64", "arm64"], 108 "description": 109 "Build for arkcompiler target of target-operating-system ohos and " 110 "target-central-processing-unit arm64.", 111 "gn_args": ["target_os=\"ohos\"", "target_cpu=\"arm64\""], 112 "prefix_of_name_of_out_dir_of_second_level": "arm64", 113 }, 114 "android_arm64": { 115 "flags": ["android_arm64"], 116 "description": 117 "Build for arkcompiler target of target-operating-system android and " 118 "target-central-processing-unit arm64.", 119 "gn_args": ["target_os=\"android\"", "target_cpu=\"arm64\""], 120 "prefix_of_name_of_out_dir_of_second_level": "android_arm64", 121 }, 122 "mingw_x86_64": { 123 "flags": ["mingw_x86_64"], 124 "description": 125 "Build for arkcompiler target of target-operating-system MinGW(Minimalist GNU on Windows) and " 126 "target-central-processing-unit x86_64.", 127 "gn_args": ["target_os=\"mingw\"", "target_cpu=\"x86_64\""], 128 "prefix_of_name_of_out_dir_of_second_level": "mingw_x86_64", 129 }, 130 "ohos_mipsel": { 131 "flags": ["ohos_mipsel", "mipsel"], 132 "description": 133 "Build for arkcompiler target of target-operating-system ohos and " 134 "target-central-processing-unit mipsel(32-bit little-endian mips).", 135 "gn_args": ["target_os=\"ohos\"", "target_cpu=\"mipsel\""], 136 "prefix_of_name_of_out_dir_of_second_level": "mipsel", 137 }, 138 }, 139 "mode": { 140 "release": { 141 "flags": ["release", "r"], 142 "description": "Build for arkcompiler target(executables and libraries) for distribution.", 143 "gn_args": ["is_debug=false"], 144 "suffix_of_name_of_out_dir_of_second_level": "release", 145 }, 146 "debug": { 147 "flags": ["debug", "d"], 148 "description": "Build for arkcompiler target(executables and libraries) for debugging.", 149 "gn_args": ["is_debug=true"], 150 "suffix_of_name_of_out_dir_of_second_level": "debug", 151 }, 152 }, 153 "target": { 154 "test262": { 155 "flags": ["test262", "test-262", "test_262", "262test", "262-test", "262_test", "262"], 156 "description": "Compile arkcompiler target and run test262 with arkcompiler target.", 157 "gn_targets_depend_on": ["default"], 158 }, 159 "unittest": { 160 "flags": ["unittest", "ut"], 161 "description": 162 "Compile and run unittest of arkcompiler target. " 163 "Add --gn-args=\"run_with_qemu=true\" to command when running unittest of non-host type with qemu.", 164 "gn_targets_depend_on": ["unittest_packages"], 165 }, 166 "workload": { 167 "flags": ["workload", "work-load", "work_load"], 168 "description": "Compile arkcompiler target and run workload with arkcompiler target.", 169 "gn_targets_depend_on": ["default"], 170 }, 171 "regresstest": { 172 "flags": ["regresstest", "regress_test", "regress", "testregress", "test_regress"], 173 "description": "Compile arkcompiler target and run regresstest with arkcompiler target.", 174 "gn_targets_depend_on": ["default"], 175 }, 176 "gn_target": { 177 "flags": ["<name of target in \"*.gn*\" file>"], # any other flags 178 "description": 179 "Build for arkcompiler target assigned by user. Targets include group(ets_runtime), " 180 "ohos_executable(ark_js_vm), ohos_shared_library(libark_jsruntime), " 181 "ohos_static_library(static_icuuc), ohos_source_set(libark_jsruntime_set), " 182 "ohos_unittest(EcmaVm_001_Test), action(EcmaVm_001_TestAction) and other target of user-defined " 183 "template type in \"*.gn*\" file.", 184 "gn_targets_depend_on": [], # not need, depend on deps of itself in "*.gn*" file 185 }, 186 }, 187 "option": { 188 "clean": { 189 "flags": ["--clean", "-clean"], 190 "description": 191 "Clean the root-out-dir(x64.release-->out/x64.release) execept for file args.gn. " 192 "Then exit.", 193 }, 194 "clean-continue": { 195 "flags": ["--clean-continue", "-clean-continue"], 196 "description": 197 "Clean the root-out-dir(x64.release-->out/x64.release) execept for file args.gn. " 198 "Then continue to build.", 199 }, 200 "gn-args": { 201 "flags": ["--gn-args=*", "-gn-args=*"], 202 "description": 203 "Pass args(*) to gn command. Example: python3 ark.py x64.release " 204 "--gn-args=\"bool_declared_in_src_gn=true string_declared_in_src_gn=\\\"abcd\\\" " 205 "list_declared_in_src_gn=[ \\\"element0\\\", \\\"element1\\\" ] print(list_declared_in_src_gn) " 206 "exec_script(\\\"script_in_src\\\", [ \\\"arg_to_script\\\" ])\" .", 207 }, 208 "keepdepfile": { 209 "flags": ["--keepdepfile", "-keepdepfile"], 210 "description": 211 "Keep depfile(\"*.o.d\") generated by commands(CXX, CC ...) called by ninja during compilation.", 212 }, 213 "verbose": { 214 "flags": ["--verbose", "-verbose"], 215 "description": "Print full commands(CXX, CC, LINK ...) called by ninja during compilation.", 216 }, 217 }, 218 "help": { 219 "flags": ["help", "--help", "--h", "-help", "-h"], 220 "description": "Show the usage of ark.py.", 221 }, 222 } 223 224 # variables which would change with the change of host_os or host_cpu 225 gn_binary_path = "" 226 ninja_binary_path = "" 227 228 # variables which would change with the change of ark.py command 229 has_cleaned = False 230 enable_verbose = False 231 enable_keepdepfile = False 232 233 def get_binaries(self): 234 host_os = sys.platform 235 host_cpu = platform.machine() 236 try: 237 with open(self.PREBUILTS_DOWNLOAD_CONFIG_FILE_PATH) as file_prebuilts_download_config: 238 prebuilts_download_config_dict = json.load(file_prebuilts_download_config) 239 file_prebuilts_download_config.close() 240 for element in prebuilts_download_config_dict[host_os][host_cpu]["copy_config"]: 241 if element["unzip_filename"] == "gn": 242 self.gn_binary_path = os.path.join(element["unzip_dir"], element["unzip_filename"]) 243 elif element["unzip_filename"] == "ninja": 244 self.ninja_binary_path = os.path.join(element["unzip_dir"], element["unzip_filename"]) 245 except Exception as error: 246 print("\nLogic of getting gn binary or ninja binary does not match logic of prebuilts_download." \ 247 "\nCheck func \033[92m{0} of class {1} in file {2}\033[0m against file {3} if the name of this " \ 248 "file had not changed!\n".format( 249 sys._getframe().f_code.co_name, self.__class__.__name__, CURRENT_FILENAME, 250 self.PREBUILTS_DOWNLOAD_CONFIG_FILE_PATH)) 251 raise error 252 if self.gn_binary_path == "" or self.ninja_binary_path == "": 253 print("\nLogic of prebuilts_download may be wrong." \ 254 "\nCheck \033[92mdata in file {0}\033[0m against func {1} of class {2} in file {3}!\n".format( 255 self.PREBUILTS_DOWNLOAD_CONFIG_FILE_PATH, sys._getframe().f_code.co_name, self.__class__.__name__, 256 CURRENT_FILENAME)) 257 sys.exit(0) 258 if not os.path.isfile(self.gn_binary_path) or not os.path.isfile(self.ninja_binary_path): 259 print("\nStep for prebuilts_download may be ommited. (\033[92m./prebuilts_download.sh\033[0m)" \ 260 "\nCheck \033[92mwhether gn binary and ninja binary are under directory prebuilts\033[0m!\n".format()) 261 sys.exit(0) 262 return 263 264 @staticmethod 265 def is_dict_flags_match_arg(dict_to_match: dict, arg_to_match: str) -> bool: 266 for flag in dict_to_match["flags"]: 267 if fnmatch(arg_to_match, flag): 268 return True 269 return False 270 271 def which_dict_flags_match_arg(self, dict_including_dicts_to_match: dict, arg_to_match: str) -> str: 272 for key in dict_including_dicts_to_match.keys(): 273 if self.is_dict_flags_match_arg(dict_including_dicts_to_match[key], arg_to_match): 274 return key 275 return "" 276 277 def dict_in_os_cpu_mode_match_arg(self, arg: str) -> [bool, str, str]: 278 os_cpu_part = "" 279 mode_part = "" 280 match_success = True 281 key_to_dict_in_os_cpu_matched_arg = "" 282 key_to_dict_in_mode_matched_arg = "" 283 arg_to_list = arg.split(self.DELIMITER_BETWEEN_OS_CPU_MODE_FOR_COMMAND) 284 if len(arg_to_list) == 1: 285 os_cpu_part = arg_to_list[0] 286 mode_part = "release" 287 key_to_dict_in_os_cpu_matched_arg = self.which_dict_flags_match_arg(self.ARG_DICT["os_cpu"], os_cpu_part) 288 key_to_dict_in_mode_matched_arg = self.which_dict_flags_match_arg(self.ARG_DICT["mode"], mode_part) 289 elif len(arg_to_list) == 2: 290 os_cpu_part = arg_to_list[0] 291 mode_part = arg_to_list[1] 292 key_to_dict_in_os_cpu_matched_arg = self.which_dict_flags_match_arg(self.ARG_DICT["os_cpu"], os_cpu_part) 293 key_to_dict_in_mode_matched_arg = self.which_dict_flags_match_arg(self.ARG_DICT["mode"], mode_part) 294 else: 295 print("\"\033[92m{0}\033[0m\" combined with more than 2 flags is not supported.".format(arg)) 296 if (key_to_dict_in_os_cpu_matched_arg == "") | (key_to_dict_in_mode_matched_arg == ""): 297 match_success = False 298 return [match_success, key_to_dict_in_os_cpu_matched_arg, key_to_dict_in_mode_matched_arg] 299 300 def get_help_msg_of_dict(self, dict_in: dict, indentation_str_current: str, indentation_str_per_level: str) -> str: 301 help_msg = "".format() 302 for key in dict_in.keys(): 303 if isinstance(dict_in[key], dict): 304 help_msg += "{0}{1}:\n".format(indentation_str_current, key) 305 help_msg += self.get_help_msg_of_dict( 306 dict_in[key], indentation_str_current + indentation_str_per_level, indentation_str_per_level) 307 elif key == "flags": 308 help_msg += "{0}{1}: \033[92m{2}\033[0m\n".format(indentation_str_current, key, " ".join(dict_in[key])) 309 elif key == "description": 310 help_msg += "{0}{1}: {2}\n".format(indentation_str_current, key, dict_in[key]) 311 return help_msg 312 313 def get_help_msg_of_all(self) -> str: 314 help_msg = "".format() 315 # Command template 316 help_msg += "\033[32mCommand template:\033[0m\n{}\n\n".format( 317 " python3 ark.py \033[92m[os_cpu].[mode] [gn_target] [option]\033[0m\n" 318 " python3 ark.py \033[92m[os_cpu].[mode] [test262] [none or --aot] " \ 319 "[none or --pgo] [none, file or dir] [option]\033[0m\n" 320 " python3 ark.py \033[92m[os_cpu].[mode] [unittest] [option]\033[0m\n" 321 " python3 ark.py \033[92m[os_cpu].[mode] [regresstest] [none, file or dir] [option]\033[0m\n") 322 # Command examples 323 help_msg += "\033[32mCommand examples:\033[0m\n{}\n\n".format( 324 " python3 ark.py \033[92mx64.release\033[0m\n" 325 " python3 ark.py \033[92mx64.release ets_runtime\033[0m\n" 326 " python3 ark.py \033[92mx64.release ark_js_vm es2panda\033[0m\n" 327 " python3 ark.py \033[92mx64.release ark_js_vm es2panda --clean\033[0m\n" 328 " python3 ark.py \033[92mx64.release test262\033[0m\n" 329 " python3 ark.py \033[92mx64.release test262 --aot --pgo\033[0m\n" 330 " python3 ark.py \033[92mx64.release test262 built-ins/Array\033[0m\n" 331 " python3 ark.py \033[92mx64.release test262 built-ins/Array/name.js\033[0m\n" 332 " python3 ark.py \033[92mx64.release unittest\033[0m\n" 333 " python3 ark.py \033[92mx64.release regresstest\033[0m\n" 334 " python3 ark.py \033[92mx64.release workload\033[0m\n" 335 " python3 ark.py \033[92mx64.release workload report\033[0m\n" 336 " python3 ark.py \033[92mx64.release workload report dev\033[0m\n" 337 " python3 ark.py \033[92mx64.release workload report dev -20\033[0m\n") 338 # Arguments 339 help_msg += "\033[32mArguments:\033[0m\n{}".format( 340 self.get_help_msg_of_dict( 341 self.ARG_DICT, self.INDENTATION_STRING_PER_LEVEL, self.INDENTATION_STRING_PER_LEVEL)) 342 return help_msg 343 344 def clean(self, out_path: str): 345 if not os.path.exists(out_path): 346 print("Path \"{}\" does not exist! No need to clean it.".format(out_path)) 347 else: 348 print("=== clean start ===") 349 code = _call("{0} clean {1}".format(self.gn_binary_path, out_path)) 350 if code != 0: 351 print("=== clean failed! ===\n") 352 sys.exit(code) 353 print("=== clean success! ===\n") 354 return 355 356 def build_for_gn_target(self, out_path: str, gn_args: list, arg_list: list, log_file_name: str): 357 # prepare log file 358 build_log_path = os.path.join(out_path, log_file_name) 359 str_to_build_log = "================================\nbuild_time: {0}\nbuild_target: {1}\n\n".format( 360 str_of_time_now(), " ".join(arg_list)) 361 _write(build_log_path, str_to_build_log, "a") 362 # gn command 363 print("=== gn gen start ===") 364 code = call_with_output( 365 "{0} gen {1} --args=\"{2}\"".format( 366 self.gn_binary_path, out_path, " ".join(gn_args).replace("\"", "\\\"")), 367 build_log_path) 368 if code != 0: 369 print("=== gn gen failed! ===\n") 370 sys.exit(code) 371 else: 372 print("=== gn gen success! ===\n") 373 # ninja command 374 # Always add " -d keeprsp" to ninja command to keep response file("*.rsp"), thus we could get shared libraries 375 # of an excutable from its response file. 376 ninja_cmd = \ 377 self.ninja_binary_path + \ 378 (" -v" if self.enable_verbose else "") + \ 379 (" -d keepdepfile" if self.enable_keepdepfile else "") + \ 380 " -d keeprsp" + \ 381 " -C {}".format(out_path) + \ 382 " {}".format(" ".join(arg_list)) 383 code = call_with_output(ninja_cmd, build_log_path) 384 if code != 0: 385 print("=== ninja failed! ===\n") 386 sys.exit(code) 387 else: 388 print("=== ninja success! ===\n") 389 return 390 391 def build_for_test262(self, out_path, gn_args: list, arg_list: list, log_file_name: str, 392 aot_mode: bool, run_pgo=False): 393 args_to_test262_cmd = "" 394 if len(arg_list) == 0: 395 args_to_test262_cmd = "--es2021 all" 396 elif len(arg_list) == 1: 397 if ".js" in arg_list[0]: 398 args_to_test262_cmd = "--file test262/data/test_es2021/{}".format(arg_list[0]) 399 else: 400 args_to_test262_cmd = "--dir test262/data/test_es2021/{}".format(arg_list[0]) 401 else: 402 print("\033[92m\"test262\" not support multiple additional arguments.\033[0m\n".format()) 403 sys.exit(0) 404 x64_out_path = "" 405 if any('target_cpu="arm64"' in arg for arg in gn_args): 406 if 'release' in out_path: 407 x64_out_path = 'out/x64.release' 408 if 'debug' in out_path: 409 x64_out_path = 'out/x64.debug' 410 gn_args.append("so_dir_for_qemu=\"../../{0}/common/common/libc/\"".format(out_path)) 411 gn_args.append("run_with_qemu=true".format(out_path)) 412 if not os.path.exists(x64_out_path): 413 os.makedirs(x64_out_path) 414 self.build_for_gn_target( 415 x64_out_path, ['target_os="linux"', 'target_cpu="x64"', 'is_debug=false'], 416 self.ARG_DICT["target"]["test262"]["gn_targets_depend_on"], log_file_name) 417 418 self.build_for_gn_target( 419 out_path, gn_args, self.ARG_DICT["target"]["test262"]["gn_targets_depend_on"], log_file_name) 420 test262_cmd = self.get_test262_cmd(gn_args, out_path, x64_out_path, aot_mode, run_pgo, args_to_test262_cmd) 421 test262_log_path = os.path.join(out_path, log_file_name) 422 str_to_test262_log = "================================\ntest262_time: {0}\ntest262_target: {1}\n\n".format( 423 str_of_time_now(), args_to_test262_cmd) 424 _write(test262_log_path, str_to_test262_log, "a") 425 if aot_mode: 426 self.generate_lib_ark_builtins_abc(run_pgo, gn_args, out_path, x64_out_path, test262_log_path) 427 print("=== test262 start ===") 428 code = call_with_output(test262_cmd, test262_log_path) 429 if code != 0: 430 print("=== test262 fail! ===\n") 431 sys.exit(code) 432 print("=== test262 success! ===\n") 433 return 434 435 @staticmethod 436 def generate_lib_ark_builtins_abc(run_pgo, gn_args, out_path, x64_out_path, test262_log_path): 437 generate_abc_cmd = "" 438 root_dir = os.path.dirname(os.path.abspath(__file__)) 439 if run_pgo: 440 generate_abc_cmd = "{root_dir}/{out_path}/arkcompiler/ets_frontend/es2abc" \ 441 " {root_dir}/arkcompiler/ets_runtime/ecmascript/ts_types/lib_ark_builtins.d.ts" \ 442 " --type-extractor" \ 443 " --type-dts-builtin" \ 444 " --module" \ 445 " --merge-abc" \ 446 " --extension=ts" \ 447 " --output" \ 448 " {root_dir}/arkcompiler/ets_runtime/ecmascript/ts_types/lib_ark_builtins.d.abc" 449 if any('target_cpu="arm64"' in arg for arg in gn_args): 450 generate_abc_cmd = generate_abc_cmd.format(root_dir=root_dir, out_path=x64_out_path) 451 else: 452 generate_abc_cmd = generate_abc_cmd.format(root_dir=root_dir, out_path=out_path) 453 call_with_output(generate_abc_cmd, test262_log_path) 454 455 @staticmethod 456 def get_test262_cmd(gn_args, out_path, x64_out_path, aot_mode, run_pgo, args_to_test262_cmd): 457 if aot_mode: 458 print("running test262 in AotMode\n") 459 if any('target_cpu="arm64"' in arg for arg in gn_args): 460 if run_pgo: 461 test262_cmd = "cd arkcompiler/ets_frontend && python3 test262/run_test262.py {0} --timeout 180000" \ 462 " --libs-dir ../../{1}/arkcompiler/ets_runtime:../../{1}/thirdparty/icu:" \ 463 "../../{1}/thirdparty/zlib:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib" \ 464 " --ark-arch aarch64" \ 465 " --ark-arch-root=../../{1}/common/common/libc/" \ 466 " --ark-tool=../../{1}/arkcompiler/ets_runtime/ark_js_vm" \ 467 " --ark-aot-tool=../../{1}/arkcompiler/ets_runtime/ark_aot_compiler" \ 468 " --ark-frontend-binary=../../{2}/arkcompiler/ets_frontend/es2abc" \ 469 " --merge-abc-binary=../../{2}/arkcompiler/ets_frontend/merge_abc" \ 470 " --ark-aot" \ 471 " --ark-frontend=es2panda"\ 472 "{3}".format(args_to_test262_cmd, out_path, x64_out_path, " --run-pgo") 473 else: 474 test262_cmd = "cd arkcompiler/ets_frontend && python3 test262/run_test262.py {0} --timeout 180000" \ 475 " --libs-dir ../../prebuilts/clang/ohos/linux-x86_64/llvm/lib:../../{2}/thirdparty/icu/" \ 476 " --ark-arch aarch64" \ 477 " --ark-arch-root=../../{1}/common/common/libc/" \ 478 " --ark-aot" \ 479 " --ark-aot-tool=../../{2}/arkcompiler/ets_runtime/ark_aot_compiler" \ 480 " --ark-tool=../../{1}/arkcompiler/ets_runtime/ark_js_vm" \ 481 " --ark-frontend-binary=../../{2}/arkcompiler/ets_frontend/es2abc" \ 482 " --merge-abc-binary=../../{2}/arkcompiler/ets_frontend/merge_abc" \ 483 " --ark-frontend=es2panda".format(args_to_test262_cmd, out_path, x64_out_path) 484 else: 485 test262_cmd = "cd arkcompiler/ets_frontend && python3 test262/run_test262.py {0} --timeout 180000" \ 486 " --libs-dir ../../{1}/arkcompiler/ets_runtime:../../{1}/thirdparty/icu" \ 487 ":../../{1}/thirdparty/zlib:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib" \ 488 " --ark-tool=../../{1}/arkcompiler/ets_runtime/ark_js_vm" \ 489 " --ark-aot-tool=../../{1}/arkcompiler/ets_runtime/ark_aot_compiler" \ 490 " --ark-frontend-binary=../../{1}/arkcompiler/ets_frontend/es2abc" \ 491 " --merge-abc-binary=../../{1}/arkcompiler/ets_frontend/merge_abc" \ 492 " --ark-aot" \ 493 " --ark-frontend=es2panda"\ 494 "{2}".format(args_to_test262_cmd, out_path, " --run-pgo" if run_pgo else "") 495 else: 496 print("running test262 in AsmMode\n") 497 test262_cmd = "cd arkcompiler/ets_frontend && python3 test262/run_test262.py {0} --timeout 180000" \ 498 " --libs-dir ../../prebuilts/clang/ohos/linux-x86_64/llvm/lib" \ 499 " --ark-tool=../../{1}/arkcompiler/ets_runtime/ark_js_vm" \ 500 " --ark-frontend-binary=../../{1}/arkcompiler/ets_frontend/es2abc" \ 501 " --merge-abc-binary=../../{1}/arkcompiler/ets_frontend/merge_abc" \ 502 " --ark-frontend=es2panda".format(args_to_test262_cmd, out_path) 503 return test262_cmd 504 505 def build_for_unittest(self, out_path: str, gn_args: list, log_file_name:str): 506 self.build_for_gn_target( 507 out_path, gn_args, self.ARG_DICT["target"]["unittest"]["gn_targets_depend_on"], 508 log_file_name) 509 return 510 511 def build_for_regress_test(self, out_path, gn_args: list, arg_list: list, log_file_name: str): 512 args_to_regress_test_cmd = "" 513 if len(arg_list) == 0: 514 args_to_regress_test_cmd = "" 515 elif len(arg_list) == 1: 516 if ".js" in arg_list[0]: 517 args_to_regress_test_cmd = "--test-file {}".format(arg_list[0]) 518 else: 519 args_to_regress_test_cmd = "--test-dir {}".format(arg_list[0]) 520 else: 521 print("\033[92m\"regresstest\" not support multiple additional arguments.\033[0m\n".format()) 522 sys.exit(0) 523 self.build_for_gn_target( 524 out_path, gn_args, self.ARG_DICT["target"]["regresstest"]["gn_targets_depend_on"], log_file_name) 525 regress_test_cmd = "python3 arkcompiler/ets_runtime/test/regresstest/run_regress_test.py" \ 526 " --ark-tool ./{0}/arkcompiler/ets_runtime/ark_js_vm" \ 527 " --ark-frontend-binary ./{0}/arkcompiler/ets_frontend/es2abc" \ 528 " --LD_LIBRARY_PATH ./{0}/arkcompiler/ets_runtime:./{0}/thirdparty/icu:" \ 529 "./prebuilts/clang/ohos/linux-x86_64/llvm/lib" \ 530 " --out-dir ./{0}/ {1}".format(out_path, args_to_regress_test_cmd) 531 regress_test_log_path = os.path.join(out_path, log_file_name) 532 str_to_test_log = "============\n regresstest_time: {0}\nregresstest_target: {1}\n\n".format( 533 str_of_time_now(), regress_test_cmd) 534 _write(regress_test_log_path, str_to_test_log, "a") 535 print("=== regresstest start ===") 536 code = call_with_output(regress_test_cmd, regress_test_log_path) 537 if code != 0: 538 print("=== regresstest fail! ===\n") 539 sys.exit(code) 540 print("=== regresstest success! ===\n") 541 return 542 543 def build(self, out_path: str, gn_args: list, arg_list: list): 544 if not os.path.exists(out_path): 545 print("# mkdir -p {}".format(out_path)) 546 os.makedirs(out_path) 547 if len(arg_list) == 0: 548 self.build_for_gn_target(out_path, gn_args, ["default"], self.GN_TARGET_LOG_FILE_NAME) 549 elif self.is_dict_flags_match_arg(self.ARG_DICT["target"]["workload"], arg_list[0]): 550 self.build_for_workload(arg_list, out_path, gn_args, 'workload.log') 551 elif self.is_dict_flags_match_arg(self.ARG_DICT["target"]["test262"], arg_list[0]): 552 if len(arg_list) >= 2 and arg_list[1] == "--aot": 553 if len(arg_list) >= 3 and arg_list[2] == "--pgo": 554 self.build_for_test262(out_path, gn_args, arg_list[3:], self.TEST262_LOG_FILE_NAME, True, True) 555 else: 556 self.build_for_test262(out_path, gn_args, arg_list[2:], self.TEST262_LOG_FILE_NAME, True) 557 else: 558 self.build_for_test262(out_path, gn_args, arg_list[1:], self.TEST262_LOG_FILE_NAME, False) 559 elif self.is_dict_flags_match_arg(self.ARG_DICT["target"]["unittest"], arg_list[0]): 560 if len(arg_list) > 1: 561 print("\033[92m\"unittest\" not support additional arguments.\033[0m\n".format()) 562 sys.exit(0) 563 self.build_for_unittest(out_path, gn_args, self.UNITTEST_LOG_FILE_NAME) 564 elif self.is_dict_flags_match_arg(self.ARG_DICT["target"]["regresstest"], arg_list[0]): 565 self.build_for_regress_test(out_path, gn_args, arg_list[1:], self.REGRESS_TEST_LOG_FILE_NAME) 566 else: 567 self.build_for_gn_target(out_path, gn_args, arg_list, self.GN_TARGET_LOG_FILE_NAME) 568 return 569 570 def match_options(self, arg_list: list, out_path: str) -> [list, list]: 571 arg_list_ret = [] 572 gn_args_ret = [] 573 for arg in arg_list: 574 # match [option][clean] flag 575 if self.is_dict_flags_match_arg(self.ARG_DICT["option"]["clean"], arg): 576 self.clean(out_path) 577 sys.exit(0) 578 # match [option][clean-continue] flag 579 elif self.is_dict_flags_match_arg(self.ARG_DICT["option"]["clean-continue"], arg): 580 if not self.has_cleaned: 581 self.clean(out_path) 582 self.has_cleaned = True 583 # match [option][gn-args] flag 584 elif self.is_dict_flags_match_arg(self.ARG_DICT["option"]["gn-args"], arg): 585 gn_args_ret.append(arg[(arg.find("=") + 1):]) 586 # match [option][keepdepfile] flag 587 elif self.is_dict_flags_match_arg(self.ARG_DICT["option"]["keepdepfile"], arg): 588 if not self.enable_keepdepfile: 589 self.enable_keepdepfile = True 590 # match [option][verbose] flag 591 elif self.is_dict_flags_match_arg(self.ARG_DICT["option"]["verbose"], arg): 592 if not self.enable_verbose: 593 self.enable_verbose = True 594 # make a new list with flag that do not match any flag in [option] 595 else: 596 arg_list_ret.append(arg) 597 return [arg_list_ret, gn_args_ret] 598 599 def build_for_workload(self, arg_list, out_path, gn_args, log_file_name): 600 root_dir = os.path.dirname(os.path.abspath(__file__)) 601 report = False 602 tools = 'dev' 603 boundary_value = '-10' 604 if len(arg_list) >= 2 and arg_list[1] == 'report': 605 report = True 606 if len(arg_list) >= 3 and arg_list[2]: 607 tools = arg_list[2] 608 if len(arg_list) >= 4 and arg_list[3]: 609 boundary_value = arg_list[3] 610 self.build_for_gn_target(out_path, gn_args, ["default"], self.GN_TARGET_LOG_FILE_NAME) 611 workload_cmd = "cd arkcompiler/ets_runtime/test/workloadtest/ && python3 work_load.py" \ 612 " --code-path {0}" \ 613 " --report {1}" \ 614 " --tools-type {2}" \ 615 " --boundary-value {3}" \ 616 .format(root_dir, report, tools, boundary_value) 617 workload_log_path = os.path.join(out_path, log_file_name) 618 str_to_workload_log = "================================\nwokload_time: {0}\nwokload_target: {1}\n\n".format( 619 str_of_time_now(), 'file') 620 _write(workload_log_path, str_to_workload_log, "a") 621 print("=== workload start ===") 622 code = call_with_output(workload_cmd, workload_log_path) 623 if code != 0: 624 print("=== workload fail! ===\n") 625 sys.exit(code) 626 print("=== workload success! ===\n") 627 return 628 629 def start_for_matched_os_cpu_mode(self, os_cpu_key: str, mode_key: str, arg_list: list): 630 # get binary gn and ninja 631 self.get_binaries() 632 # get out_path 633 name_of_out_dir_of_second_level = \ 634 self.ARG_DICT["os_cpu"][os_cpu_key]["prefix_of_name_of_out_dir_of_second_level"] + \ 635 self.DELIMITER_FOR_SECOND_OUT_DIR_NAME + \ 636 self.ARG_DICT["mode"][mode_key]["suffix_of_name_of_out_dir_of_second_level"] 637 out_path = os.path.join(self.NAME_OF_OUT_DIR_OF_FIRST_LEVEL, name_of_out_dir_of_second_level) 638 # match [option] flag 639 [arg_list, gn_args] = self.match_options(arg_list, out_path) 640 # get expression which would be written to args.gn file 641 gn_args.extend(self.ARG_DICT["os_cpu"][os_cpu_key]["gn_args"]) 642 gn_args.extend(self.ARG_DICT["mode"][mode_key]["gn_args"]) 643 # start to build 644 self.build(out_path, gn_args, arg_list) 645 return 646 647 def __main__(self, arg_list: list): 648 # delete duplicate arg in arg_list 649 arg_list = list(dict.fromkeys(arg_list)) 650 # match [help] flag 651 if len(arg_list) == 0 or ( 652 True in [self.is_dict_flags_match_arg(self.ARG_DICT["help"], arg) for arg in arg_list]): 653 print(self.get_help_msg_of_all()) 654 return 655 # match [[os_cpu].[mode]] flag 656 [match_success, key_to_dict_in_os_cpu, key_to_dict_in_mode] = self.dict_in_os_cpu_mode_match_arg(arg_list[0]) 657 if match_success: 658 self.start_for_matched_os_cpu_mode(key_to_dict_in_os_cpu, key_to_dict_in_mode, arg_list[1:]) 659 else: 660 print("\033[92mThe command is not supported! Help message shows below.\033[0m\n{}".format( 661 self.get_help_msg_of_all())) 662 return 663 664 665if __name__ == "__main__": 666 ark_py = ArkPy() 667 ark_py.__main__(sys.argv[1:]) 668