1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3 4# 5# Copyright (c) 2023 Huawei Device Co., Ltd. 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18 19import os 20import re 21import sys 22import stat 23import subprocess 24 25from datetime import datetime 26from distutils.spawn import find_executable 27from containers.arg import Arg 28from containers.status import throw_exception 29from exceptions.ohos_exception import OHOSException 30from modules.interface.build_module_interface import BuildModuleInterface 31from resources.config import Config 32from resources.global_var import CURRENT_OHOS_ROOT, DEFAULT_BUILD_ARGS 33from resolver.interface.args_resolver_interface import ArgsResolverInterface 34from util.type_check_util import TypeCheckUtil 35from util.io_util import IoUtil 36from util.log_util import LogUtil 37from util.system_util import SystemUtil 38from util.type_check_util import TypeCheckUtil 39from util.component_util import ComponentUtil 40from util.product_util import ProductUtil 41from util.post_build.part_rom_statistics import output_part_rom_status 42 43 44class BuildArgsResolver(ArgsResolverInterface): 45 46 def __init__(self, args_dict: dict): 47 super().__init__(args_dict) 48 49 @staticmethod 50 def resolve_product(target_arg: Arg, build_module: BuildModuleInterface): 51 """resolve '--product-name' arg. 52 :param target_arg: arg object which is used to get arg value. 53 :param build_module [maybe unused]: build module object which is used to get other services. 54 :phase: prebuild. 55 """ 56 config = Config() 57 target_generator = build_module.target_generator 58 target_generator.regist_arg('product_name', config.product) 59 target_generator.regist_arg('product_path', config.product_path) 60 target_generator.regist_arg( 61 'product_config_path', config.product_config_path) 62 63 target_generator.regist_arg('device_name', config.board) 64 target_generator.regist_arg('device_path', config.device_path) 65 target_generator.regist_arg('device_company', config.device_company) 66 target_generator.regist_arg( 67 'device_config_path', config.device_config_path) 68 69 target_generator.regist_arg('target_cpu', config.target_cpu) 70 target_generator.regist_arg( 71 'is_{}_system'.format(config.os_level), True) 72 73 target_generator.regist_arg('ohos_kernel_type', config.kernel) 74 target_generator.regist_arg('ohos_build_compiler_specified', 75 ProductUtil.get_compiler(config.device_path)) 76 77 target_generator.regist_arg('ohos_build_time', 78 SystemUtil.get_current_time(time_type='timestamp')) 79 target_generator.regist_arg('ohos_build_datetime', 80 SystemUtil.get_current_time(time_type='datetime')) 81 82 features_dict = ProductUtil.get_features_dict(config.product_json) 83 for key, value in features_dict.items(): 84 target_generator.regist_arg(key, value) 85 86 if ProductUtil.get_compiler(config.device_path) == 'clang': 87 target_generator.regist_arg( 88 'ohos_build_compiler_dir', config.clang_path) 89 90 if target_arg.arg_value == 'ohos-sdk': 91 target_generator = build_module.target_generator 92 target_generator.regist_arg('build_ohos_sdk', True) 93 target_generator.regist_arg('build_ohos_ndk', True) 94 if len(build_module.args_dict['build_target'].arg_value) == 0: 95 build_module.args_dict['build_target'].arg_value = [ 96 'build_ohos_sdk'] 97 build_module.args_dict['target_cpu'].arg_value = 'arm64' 98 elif target_arg.arg_value == 'arkui-x': 99 target_generator = build_module.target_generator 100 target_generator.regist_arg('is_arkui_x', True) 101 target_generator.regist_arg('enable_ng_build', True) 102 target_generator.regist_arg('is_component_build', False) 103 target_generator.regist_arg('use_musl', False) 104 target_generator.regist_arg('is_use_check_deps', False) 105 if len(build_module.args_dict['build_target'].arg_value) == 0: 106 build_module.args_dict['build_target'].arg_value = [ 107 'arkui_targets'] 108 109 @staticmethod 110 def resolve_target_cpu(target_arg: Arg, build_module: BuildModuleInterface): 111 """resolve '--target-cpu' arg. 112 :param target_arg: arg object which is used to get arg value. 113 :param build_module [maybe unused]: build module object which is used to get other services. 114 :phase: prebuild. 115 """ 116 config = Config() 117 default_build_args = IoUtil.read_json_file(DEFAULT_BUILD_ARGS) 118 if config.target_cpu == "": 119 config.target_cpu = target_arg.arg_value 120 elif target_arg.arg_value != default_build_args.get("target_cpu").get("argDefault"): 121 config.target_cpu = target_arg.arg_value 122 123 @staticmethod 124 def resolve_target_os(target_arg: Arg, build_module: BuildModuleInterface): 125 """resolve '--target-os' arg. 126 :param target_arg: arg object which is used to get arg value. 127 :param build_module [maybe unused]: build module object which is used to get other services. 128 :phase: prebuild. 129 """ 130 config = Config() 131 default_build_args = IoUtil.read_json_file(DEFAULT_BUILD_ARGS) 132 if config.target_os == "": 133 config.target_os = target_arg.arg_value 134 elif target_arg.arg_value != default_build_args.get("target_os").get("argDefault"): 135 config.target_os = target_arg.arg_value 136 137 @staticmethod 138 @throw_exception 139 def resolve_build_target(target_arg: Arg, build_module: BuildModuleInterface): 140 """resolve '--build-target' arg. 141 :param target_arg: arg object which is used to get arg value. 142 :param build_module [maybe unused]: build module object which is used to get other services. 143 :phase: prebuild. 144 :raise OHOSException: when build target not exist in compiling product. 145 """ 146 config = Config() 147 build_executor = build_module.target_compiler 148 target_list = [] 149 if len(target_arg.arg_value): 150 target_list = target_arg.arg_value 151 else: 152 if os.getcwd() == CURRENT_OHOS_ROOT: 153 target_list = ['images'] 154 elif ComponentUtil.is_in_component_dir(os.getcwd()) and \ 155 ComponentUtil.is_component_in_product( 156 ComponentUtil.get_component_name(os.getcwd()), Config().product): 157 component_name = ComponentUtil.get_component_name(os.getcwd()) 158 LogUtil.write_log(Config().log_path, 'In the component "{}" directory,' 159 'this compilation will compile only this component'.format( 160 component_name), 161 'warning') 162 target_list.append(component_name) 163 target_list.append(component_name + '_test') 164 else: 165 component_name = ComponentUtil.get_component_name(os.getcwd()) 166 component_name = os.path.basename( 167 os.getcwd()) if component_name == '' else component_name 168 raise OHOSException('There is no target component "{}" for the current product "{}"' 169 .format(component_name, Config().product), "4001") 170 build_executor.regist_arg('build_target', target_list) 171 172 @staticmethod 173 def resolve_rename_last_log(target_arg: Arg, build_module: BuildModuleInterface): 174 """resolve '--rename-last-log' arg 175 :param target_arg: arg object which is used to get arg value. 176 :param build_module [maybe unused]: build module object which is used to get other services. 177 :phase: prebuild. 178 """ 179 if target_arg.arg_value: 180 config = Config() 181 out_path = config.out_path 182 logfile = os.path.join(out_path, 'build.log') 183 if os.path.exists(logfile): 184 mtime = os.stat(logfile).st_mtime 185 os.rename(logfile, '{}/build.{}.log'.format(out_path, mtime)) 186 187 @staticmethod 188 def resolve_ccache(target_arg: Arg, build_module: BuildModuleInterface): 189 """resolve '--ccache' arg 190 :param target_arg: arg object which is used to get arg value. 191 :param build_module [maybe unused]: build module object which is used to get other services. 192 :phase: prebuild. 193 """ 194 if target_arg.arg_value: 195 config = Config() 196 ccache_path = find_executable('ccache') 197 if ccache_path is None: 198 LogUtil.hb_warning('Failed to find ccache, ccache disabled.') 199 return 200 else: 201 target_generator = build_module.target_generator 202 target_generator.regist_arg( 203 'ohos_build_enable_ccache', target_arg.arg_value) 204 205 ccache_local_dir = os.environ.get('CCACHE_LOCAL_DIR') 206 ccache_base = os.environ.get('CCACHE_BASE') 207 if not ccache_local_dir: 208 ccache_local_dir = '.ccache' 209 if not ccache_base: 210 ccache_base = os.environ.get('HOME') 211 ccache_base = os.path.join(ccache_base, ccache_local_dir) 212 if not os.path.exists(ccache_base): 213 os.makedirs(ccache_base, exist_ok=True) 214 215 ccache_log_suffix = os.environ.get('CCACHE_LOG_SUFFIX') 216 if ccache_log_suffix: 217 logfile = os.path.join( 218 ccache_base, "ccache.{}.log".format(ccache_log_suffix)) 219 else: 220 logfile = os.path.join(ccache_base, "ccache.log") 221 if os.path.exists(logfile): 222 oldfile = os.path.join(ccache_base, '{}.old'.format(logfile)) 223 if os.path.exists(oldfile): 224 os.unlink(oldfile) 225 os.rename(logfile, oldfile) 226 227 os.environ['CCACHE_EXEC'] = ccache_path 228 os.environ['CCACHE_LOGFILE'] = logfile 229 os.environ['USE_CCACHE'] = '1' 230 os.environ['CCACHE_DIR'] = ccache_base 231 os.environ['CCACHE_UMASK'] = '002' 232 os.environ['CCACHE_BASEDIR'] = config.root_path 233 ccache_max_size = os.environ.get('CCACHE_MAXSIZE') 234 if not ccache_max_size: 235 ccache_max_size = '100G' 236 237 cmd = ['ccache', '-M', ccache_max_size] 238 239 SystemUtil.exec_command(cmd, log_path=config.log_path) 240 241 @staticmethod 242 def resolve_pycache(target_arg: Arg, build_module: BuildModuleInterface): 243 """resolve '--enable-pycache' arg 244 :param target_arg: arg object which is used to get arg value. 245 :param build_module [maybe unused]: build module object which is used to get other services. 246 :phase: prebuild. 247 """ 248 if target_arg.arg_value: 249 config = Config() 250 pycache_dir = os.environ.get('CCACHE_BASE') 251 # The default value is HOME for local users 252 if not pycache_dir: 253 pycache_dir = os.environ.get('HOME') 254 pycache_dir = os.path.join(pycache_dir, '.pycache') 255 os.environ['PYCACHE_DIR'] = pycache_dir 256 pyd_start_cmd = [ 257 'python3', 258 '{}/build/scripts/util/pyd.py'.format(config.root_path), 259 '--root', 260 pycache_dir, 261 '--start', 262 ] 263 cmd = ['/bin/bash', '-c', ' '.join(pyd_start_cmd), '&'] 264 subprocess.Popen(cmd) 265 266 @staticmethod 267 def resolve_full_compilation(target_arg: Arg, build_module: BuildModuleInterface): 268 """resolve '--full-compilation' arg 269 :param target_arg: arg object which is used to get arg value. 270 :param build_module [maybe unused]: build module object which is used to get other services. 271 :phase: prebuild. 272 """ 273 if target_arg.arg_value: 274 build_executor = build_module.target_compiler 275 target_list = build_executor.args_dict.get('build_target', None) 276 if isinstance(target_list, list): 277 target_list.append('make_all') 278 target_list.append('make_test') 279 else: 280 build_executor.regist_arg( 281 'build_target', ['make_all', 'make_test']) 282 283 @staticmethod 284 @throw_exception 285 def resolve_gn_args(target_arg: Arg, build_module: BuildModuleInterface): 286 """resolve '--gn-args' arg 287 :param target_arg: arg object which is used to get arg value. 288 :param build_module [maybe unused]: build module object which is used to get other services. 289 :phase: prebuild. 290 :raise OHOSException: when some gn_arg is not in 'key=value' format. 291 """ 292 target_generator = build_module.target_generator 293 target_generator.regist_arg( 294 'device_type', build_module.args_dict['device_type'].arg_value) 295 target_generator.regist_arg( 296 'build_variant', build_module.args_dict['build_variant'].arg_value) 297 for gn_args in target_arg.arg_value: 298 try: 299 gn_args_list = gn_args.split() 300 for gn_arg in gn_args_list: 301 variable, value = gn_arg.split('=') 302 if TypeCheckUtil.is_bool_type(value): 303 if str(value).lower() == 'false': 304 convert_value = False 305 elif str(value).lower() == 'true': 306 convert_value = True 307 elif TypeCheckUtil.is_int_type(value): 308 convert_value = int(value) 309 elif isinstance(value, list): 310 convert_value = list(value) 311 else: 312 convert_value = str(value).strip('"') 313 target_generator.regist_arg(variable, convert_value) 314 except ValueError: 315 raise OHOSException(f'Invalid gn args: {gn_arg}', "0001") 316 317 @staticmethod 318 @throw_exception 319 def resolve_gn_flags(target_arg: Arg, build_module: BuildModuleInterface): 320 """resolve '--gn-flags' arg 321 :param target_arg: arg object which is used to get arg value. 322 :param build_module [maybe unused]: build module object which is used to get other services. 323 :phase: targetGenerate. 324 :raise OHOSException: when some gn_arg is not in 'key=value' format. 325 """ 326 target_generator = build_module.target_generator 327 gn_flags_list = [] 328 for gn_flags in target_arg.arg_value: 329 gn_flags = re.sub("'", "", gn_flags) 330 gn_flags_list.append(gn_flags) 331 target_generator.regist_flag('gn_flags', gn_flags_list) 332 333 @staticmethod 334 @throw_exception 335 def resolve_ninja_args(target_arg: Arg, build_module: BuildModuleInterface): 336 """resolve '--ninja-args' arg 337 :param target_arg: arg object which is used to get arg value. 338 :param build_module [maybe unused]: build module object which is used to get other services. 339 :phase: prebuild. 340 :raise OHOSException: when the value of the ninja parameter does not use quotation marks. 341 """ 342 build_executor = build_module.target_compiler 343 ninja_args_list = [] 344 for ninja_arg in target_arg.arg_value: 345 ninja_arg = re.sub("'", "", ninja_arg) 346 ninja_args_list.append(ninja_arg) 347 build_executor.regist_arg('ninja_args', ninja_args_list) 348 349 @staticmethod 350 @throw_exception 351 def resolve_strict_mode(target_arg: Arg, build_module: BuildModuleInterface): 352 """resolve '--strict-mode' arg. 353 :param target_arg: arg object which is used to get arg value. 354 :param build_module [maybe unused]: build module object which is used to get other services. 355 :phase: load. 356 :raise OHOSException: when preloader or loader results not correct 357 """ 358 if target_arg.arg_value: 359 preloader = build_module.preloader 360 loader = build_module.loader 361 if not preloader.outputs.check_outputs(): 362 raise OHOSException('Preloader result not correct', "1001") 363 if not loader.outputs.check_outputs(): 364 raise OHOSException('Loader result not correct ', "2001") 365 366 @staticmethod 367 def resolve_scalable_build(target_arg: Arg, build_module: BuildModuleInterface): 368 """resolve '--scalable-build' arg. 369 :param target_arg: arg object which is used to get arg value. 370 :param build_module [maybe unused]: build module object which is used to get other services. 371 :phase: load. 372 """ 373 loader = build_module.loader 374 loader.regist_arg("scalable_build", target_arg.arg_value) 375 376 @staticmethod 377 def resolve_build_example(target_arg: Arg, build_module: BuildModuleInterface): 378 """resolve '--build-example' arg. 379 :param target_arg: arg object which is used to get arg value. 380 :param build_module [maybe unused]: build module object which is used to get other services. 381 :phase: load. 382 """ 383 loader = build_module.loader 384 loader.regist_arg("build_example", target_arg.arg_value) 385 386 @staticmethod 387 def resolve_build_platform_name(target_arg: Arg, build_module: BuildModuleInterface): 388 """resolve '---build-platform-name' arg 389 :param target_arg: arg object which is used to get arg value. 390 :param build_module [maybe unused]: build module object which is used to get other services. 391 :phase: load. 392 """ 393 loader = build_module.loader 394 loader.regist_arg("build_platform_name", target_arg.arg_value) 395 396 @staticmethod 397 def resolve_build_xts(target_arg: Arg, build_module: BuildModuleInterface): 398 """resolve '--build-xts' arg 399 :param target_arg: arg object which is used to get arg value. 400 :param build_module [maybe unused]: build module object which is used to get other services. 401 :phase: load. 402 """ 403 loader = build_module.loader 404 for gn_arg in build_module.args_dict['gn_args'].arg_value: 405 if 'build_xts' in gn_arg: 406 variable, value = gn_arg.split('=') 407 if str(value).lower() == 'false': 408 value = False 409 elif str(value).lower() == 'true': 410 value = True 411 loader.regist_arg(variable, value) 412 return 413 loader.regist_arg("build_xts", target_arg.arg_value) 414 415 @staticmethod 416 def resolve_ignore_api_check(target_arg: Arg, build_module: BuildModuleInterface): 417 """resolve '--ignore-api-check' arg 418 :param target_arg: arg object which is used to get arg value. 419 :param build_module [maybe unused]: build module object which is used to get other services. 420 :phase: load. 421 """ 422 loader = build_module.loader 423 if len(target_arg.arg_value): 424 loader.regist_arg("ignore_api_check", target_arg.arg_value) 425 else: 426 loader.regist_arg("ignore_api_check", [ 427 'xts', 'common', 'developertest']) 428 429 @staticmethod 430 def resolve_load_test_config(target_arg: Arg, build_module: BuildModuleInterface): 431 """resolve '--load-test-config' arg 432 :param target_arg: arg object which is used to get arg value. 433 :param build_module [maybe unused]: build module object which is used to get other services. 434 :phase: load. 435 """ 436 loader = build_module.loader 437 loader.regist_arg("load_test_config", target_arg.arg_value) 438 439 @staticmethod 440 @throw_exception 441 def resolve_export_para(target_arg: Arg, build_module: BuildModuleInterface): 442 """resolve '--export-para' arg 443 :param target_arg: arg object which is used to get arg value. 444 :param build_module [maybe unused]: build module object which is used to get other services. 445 :phase: targetGenerate. 446 """ 447 target_generator = build_module.target_generator 448 for gn_arg in target_arg.arg_value: 449 try: 450 variable, value = gn_arg.split(':') 451 if TypeCheckUtil.is_bool_type(value): 452 if str(value).lower() == 'false': 453 value = False 454 elif str(value).lower() == 'true': 455 value = True 456 elif TypeCheckUtil.is_int_type(value): 457 value = int(value) 458 else: 459 value = str(value) 460 target_generator.regist_arg(variable, value) 461 except ValueError: 462 raise OHOSException(f'Invalid gn args: {gn_arg}', "0001") 463 464 @staticmethod 465 def resolve_log_level(target_arg: Arg, build_module: BuildModuleInterface): 466 """resolve '--log-level' arg. 467 :param target_arg: arg object which is used to get arg value. 468 :param build_module [maybe unused]: build module object which is used to get other services. 469 :phase: targetGenerate. 470 """ 471 if target_arg.arg_value == 'debug': 472 target_generator = build_module.target_generator 473 target_compiler = build_module.target_compiler 474 target_generator.regist_flag('-v', ''), 475 target_generator.regist_flag( 476 '--tracelog', '{}/gn_trace.log'.format(Config().out_path)) 477 target_generator.regist_flag('--ide', 'json') 478 target_compiler.regist_arg('-v', '') 479 480 @staticmethod 481 @throw_exception 482 def resolve_test(target_arg: Arg, build_module: BuildModuleInterface): 483 """resolve '--test' arg 484 :param target_arg: arg object which is used to get arg value. 485 :param build_module [maybe unused]: build module object which is used to get other services. 486 :phase: targetGenerate. 487 """ 488 if len(target_arg.arg_value) > 1: 489 target_generator = build_module.target_generator 490 # TODO: Ask sternly why the xts subsystem passes parameters in this way? 491 if 'notest' in target_arg.arg_value: 492 target_generator.regist_arg('ohos_test_args', 'notest') 493 elif 'xts' in target_arg.arg_value: 494 test_target_index = 1 495 if target_arg.arg_value.index('xts') == 1: 496 test_target_index = 0 497 target_generator.regist_arg( 498 'ohos_xts_test_args', target_arg.arg_value[test_target_index]) 499 else: 500 raise OHOSException('Test type value "{}" is not support' 501 .format(target_arg.arg_value), "0002") 502 503 @staticmethod 504 def resolve_build_type(target_arg: Arg, build_module: BuildModuleInterface): 505 """resolve '--build-type' arg 506 :param target_arg: arg object which is used to get arg value. 507 :param build_module [maybe unused]: build module object which is used to get other services. 508 :phase: targetGenerate. 509 """ 510 target_generator = build_module.target_generator 511 if target_arg.arg_value == 'debug': 512 target_generator.regist_arg('is_debug', True) 513 elif target_arg.arg_value == 'profile': 514 target_generator.regist_arg('is_profile', True) 515 # For historical reasons, this value must be debug 516 target_generator.regist_arg('ohos_build_type', 'debug') 517 518 @staticmethod 519 def resolve_runtime_mode(target_arg: Arg, build_module: BuildModuleInterface): 520 """resolve '--runtime-mode' arg 521 :param target_arg: arg object which is used to get arg value. 522 :param build_module [maybe unused]: build module object which is used to get other services. 523 :phase: targetGenerate. 524 """ 525 target_generator = build_module.target_generator 526 target_generator.regist_arg('runtime_mode', target_arg.arg_value) 527 528 @staticmethod 529 def resolve_keep_ninja_going(target_arg: Arg, build_module: BuildModuleInterface): 530 """resolve '--keep-ninja-going' arg 531 :param target_arg: arg object which is used to get arg value. 532 :param build_module [maybe unused]: build module object which is used to get other services. 533 :phase: targetCompilation. 534 """ 535 if target_arg.arg_value: 536 target_compiler = build_module.target_compiler 537 target_compiler.regist_arg('-k1000000', '') 538 539 @staticmethod 540 def resolve_build_variant(target_arg: Arg, build_module: BuildModuleInterface): 541 """resolve '--build-variant' arg 542 :param target_arg: arg object which is used to get arg value. 543 :param build_module [maybe unused]: build module object which is used to get other services. 544 :phase: postTargetCompilation. 545 """ 546 config = Config() 547 ohos_para_data = [] 548 ohos_para_file_path = os.path.join( 549 config.out_path, 'packages/phone/system/etc/param/ohos.para') 550 if not os.path.exists(ohos_para_file_path): 551 return 552 with open(ohos_para_file_path, 'r', encoding='utf-8') as ohos_para_file: 553 for line in ohos_para_file: 554 ohos_para_data.append(line) 555 for i, line in enumerate(ohos_para_data): 556 if ohos_para_data[i].__contains__('const.secure'): 557 if target_arg.arg_value == 'user': 558 ohos_para_data[i] = 'const.secure=1\n' 559 else: 560 ohos_para_data[i] = 'const.secure=0\n' 561 if ohos_para_data[i].__contains__('const.debuggable'): 562 if target_arg.arg_value == 'user': 563 ohos_para_data[i] = 'const.debuggable=0\n' 564 else: 565 ohos_para_data[i] = 'const.debuggable=1\n' 566 data = '' 567 for line in ohos_para_data: 568 data += line 569 with os.fdopen(os.open(ohos_para_file_path, os.O_RDWR | os.O_CREAT), 'w', encoding='utf-8') as ohos_para_file: 570 ohos_para_file.write(data) 571 572 @staticmethod 573 def resolve_device_type(target_arg: Arg, build_module: BuildModuleInterface): 574 """resolve '--device-type' arg 575 :param target_arg: arg object which is used to get arg value. 576 :param build_module [maybe unused]: build module object which is used to get other services. 577 :phase: postTargetCompilation. 578 """ 579 config = Config() 580 ohos_para_data = [] 581 ohos_para_file_path = os.path.join( 582 config.out_path, 'packages/phone/system/etc/param/ohos.para') 583 if target_arg.arg_value != 'default': 584 with os.fdopen(os.open(ohos_para_file_path, 585 os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR), 586 'r', encoding='utf-8') as ohos_para_file: 587 for line in ohos_para_file: 588 ohos_para_data.append(line) 589 for i, line in enumerate(ohos_para_data): 590 if ohos_para_data[i].__contains__('const.build.characteristics'): 591 ohos_para_data[i] = 'const.build.characteristics=' + \ 592 target_arg.arg_value + '\n' 593 break 594 data = '' 595 for line in ohos_para_data: 596 data += line 597 with os.fdopen(os.open(ohos_para_file_path, 598 os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR), 599 'r', encoding='utf-8') as ohos_para_file: 600 ohos_para_file.write(data) 601 602 @staticmethod 603 def resolve_archive_image(target_arg: Arg, build_module: BuildModuleInterface): 604 """resolve '--archive-image' arg 605 :param target_arg: arg object which is used to get arg value. 606 :param build_module [maybe unused]: build module object which is used to get other services. 607 :phase: postTargetCompilation 608 """ 609 if target_arg.arg_value: 610 config = Config() 611 image_path = os.path.join( 612 config.out_path, 'packages', 'phone', 'images') 613 if os.path.exists(image_path): 614 packaged_file_path = os.path.join( 615 config.out_path, 'images.tar.gz') 616 cmd = ['tar', '-zcvf', packaged_file_path, image_path] 617 SystemUtil.exec_command(cmd, log_path=config.out_path) 618 else: 619 LogUtil.hb_info( 620 '"--archive-image" option not work, cause the currently compiled product is not a standard product') 621 622 @staticmethod 623 def resolve_rom_size_statistics(target_arg: Arg, build_module: BuildModuleInterface): 624 """resolve '--rom-size-statistics' arg 625 :param target_arg: arg object which is used to get arg value. 626 :param build_module [maybe unused]: build module object which is used to get other services. 627 :phase: postTargetCompilation 628 """ 629 if target_arg.arg_value: 630 output_part_rom_status(CURRENT_OHOS_ROOT) 631 632 @staticmethod 633 def resolve_stat_ccache(target_arg: Arg, build_module: BuildModuleInterface): 634 """resolve "--stat-ccache' arg 635 :param target_arg: arg object which is used to get arg value. 636 :param build_module [maybe unused]: build module object which is used to get other services. 637 :phase: postTargetCompilation 638 """ 639 if target_arg.arg_value: 640 config = Config() 641 ccache_path = find_executable('ccache') 642 if ccache_path is None: 643 LogUtil.hb_warning('Failed to find ccache, ccache disabled.') 644 return 645 ccache_log_suffix = os.environ.get('CCACHE_LOG_SUFFIX') 646 if ccache_log_suffix: 647 logfile = "ccache.{}.log".format(ccache_log_suffix) 648 else: 649 logfile = "ccache.log" 650 ccache_local_dir = os.environ.get('CCACHE_LOCAL_DIR') 651 if not ccache_local_dir: 652 ccache_local_dir = '.ccache' 653 ccache_base = os.environ.get('CCACHE_BASE') 654 655 # The default value is HOME for local users 656 if not ccache_base: 657 ccache_base = os.environ.get('HOME') 658 ccache_base = os.path.join(ccache_base, ccache_local_dir) 659 cmd = [ 660 'python3', '{}/build/scripts/summary_ccache_hitrate.py'.format( 661 config.root_path), '{}/{}'.format(ccache_base, logfile) 662 ] 663 SystemUtil.exec_command(cmd, log_path=config.log_path) 664 665 @staticmethod 666 def resolve_get_warning_list(target_arg: Arg, build_module: BuildModuleInterface): 667 """resolve "--get-warning-list' arg 668 :param target_arg: arg object which is used to get arg value. 669 :param build_module [maybe unused]: build module object which is used to get other services. 670 :phase: postTargetCompilation 671 """ 672 if target_arg.arg_value: 673 config = Config() 674 cmd = [ 675 'python3', 676 '{}/build/scripts/get_warnings.py'.format(config.root_path), 677 '--build-log-file', 678 '{}/build.log'.format(config.out_path), 679 '--warning-out-file', 680 '{}/packages/WarningList.txt'.format(config.out_path), 681 ] 682 SystemUtil.exec_command(cmd, log_path=config.log_path) 683 684 @staticmethod 685 def resolve_generate_ninja_trace(target_arg: Arg, build_module: BuildModuleInterface): 686 """resolve "--generate-ninja-trace' arg 687 :param target_arg: arg object which is used to get arg value. 688 :param build_module [maybe unused]: build module object which is used to get other services. 689 :phase: postTargetCompilation 690 """ 691 if target_arg.arg_value: 692 config = Config() 693 epoch = datetime.utcfromtimestamp(0) 694 unixtime = '%f' % ( 695 (build_module.target_compiler._start_time - epoch).total_seconds() * 10**9) 696 cmd = [ 697 'python3', 698 '{}/build/scripts/ninja2trace.py'.format(config.root_path), 699 '--ninja-log', 700 '{}/.ninja_log'.format(config.out_path), 701 "--trace-file", 702 "{}/build.trace".format(config.out_path), 703 "--ninja-start-time", 704 str(unixtime), 705 "--duration-file", 706 "{}/sorted_action_duration.txt".format(config.out_path), 707 ] 708 SystemUtil.exec_command(cmd, log_path=config.log_path) 709 710 @staticmethod 711 def resolve_compute_overlap_rate(target_arg: Arg, build_module: BuildModuleInterface): 712 """resolve "--compute-overlap-rate' arg 713 :param target_arg: arg object which is used to get arg value. 714 :param build_module [maybe unused]: build module object which is used to get other services. 715 :phase: postTargetCompilation 716 """ 717 if target_arg.arg_value: 718 config = Config() 719 subsystem_config_overlay_path = os.path.join(config.product_path, 720 'subsystem_config_overlay.json') 721 if os.path.isfile(subsystem_config_overlay_path): 722 cmd = [ 723 'python3', 724 '{}/build/ohos/statistics/build_overlap_statistics.py'.format( 725 config.root_path), "--build-out-dir", config.out_path, 726 "--subsystem-config-file", 727 "{}/build/subsystem_config.json".format(config.root_path), 728 "--subsystem-config-overlay-file", 729 "{}/subsystem_config_overlay.json".format( 730 config.product_path), 731 "--root-source-dir", config.root_path 732 ] 733 else: 734 cmd = [ 735 'python3', 736 '{}/build/ohos/statistics/build_overlap_statistics.py'.format( 737 config.root_path), "--build-out-dir", config.out_path, 738 "--subsystem-config-file", 739 "{}/build/subsystem_config.json".format(config.root_path), 740 "--root-source-dir", config.root_path 741 ] 742 SystemUtil.exec_command(cmd, log_path=config.log_path) 743 744 @staticmethod 745 def resolve_deps_guard(target_arg: Arg, build_module: BuildModuleInterface): 746 """resolve '--deps-guard' arg 747 :param target_arg: arg object which is used to get arg value. 748 :param build_module [maybe unused]: build module object which is used to get other services. 749 :phase: postbuild 750 """ 751 if target_arg.arg_value: 752 config = Config() 753 if config.os_level == "standard": 754 sys.path.append(os.path.join( 755 config.root_path, "developtools/integration_verification/tools/deps_guard")) 756 from deps_guard import deps_guard 757 deps_guard(config.out_path) 758 759 @staticmethod 760 def resolve_skip_partlist_check(target_arg: Arg, build_module: BuildModuleInterface): 761 """resolve '--skip-partlist-check' arg 762 :param target_arg: arg object which is used to get arg value. 763 :param build_module [maybe unused]: build module object which is used to get other services. 764 :phase: load. 765 """ 766 loader = build_module.loader 767 loader.regist_arg("skip_partlist_check", target_arg.arg_value) 768 769 @staticmethod 770 def resolve_clean_args(target_arg: Arg, build_module: BuildModuleInterface): 771 """resolve '--clean-args' arg 772 :param target_arg: arg object which is used to get arg value. 773 :param build_module [maybe unused]: build module object which is used to get other services. 774 :phase: postbuild 775 """ 776 if target_arg.arg_value: 777 Arg.clean_args_file() 778 779 # PlaceHolder 780 @staticmethod 781 def resolve_compiler(target_arg: Arg, build_module: BuildModuleInterface): 782 return 783 784 # PlaceHolder 785 @staticmethod 786 def resolve_jobs(target_arg: Arg, build_module: BuildModuleInterface): 787 return 788 789 # PlaceHolder 790 @staticmethod 791 def resolve_disable_part_of_post_build(target_arg: Arg, build_module: BuildModuleInterface): 792 return 793 794 # PlaceHolder 795 @staticmethod 796 def resolve_disable_package_image(target_arg: Arg, build_module: BuildModuleInterface): 797 return 798 799 # PlaceHolder 800 @staticmethod 801 def resolve_disable_post_build(target_arg: Arg, build_module: BuildModuleInterface): 802 return 803 804 # PlaceHolder 805 @staticmethod 806 def resolve_build_only_gn(target_arg: Arg, build_module: BuildModuleInterface): 807 return 808 809 # PlaceHolder 810 @staticmethod 811 def resolve_fast_rebuild(target_arg: Arg, build_module: BuildModuleInterface): 812 return 813