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