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