1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# Copyright (c) 2023 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import os 17import sys 18 19from containers.status import throw_exception 20from util.log_util import LogUtil 21from resources.config import Config 22from exceptions.ohos_exception import OHOSException 23from scripts.util.file_utils import read_json_file, write_json_file, \ 24 write_file # noqa: E402, E501 pylint: disable=C0413, E0611 25from . import load_bundle_file 26 27IMPORT_LIST = """ 28# import("//build/ohos.gni") 29# import("//build/ohos_var.gni") 30import("//build/ohos/ohos_part.gni") 31import("//build/ohos/ohos_kits.gni") 32import("//build/ohos/ohos_test.gni") 33""" 34 35PART_TEMPLATE = """ 36ohos_part("{}") {{ 37 subsystem_name = "{}" 38 module_list = [ 39 {} 40 ] 41 origin_name = "{}" 42 variant = "{}" 43}}""" 44 45INNER_KITS_TEMPLATE = """ 46ohos_inner_kits("{0}_inner_kits") {{ 47 sdk_libs = [ 48{1} 49 ] 50 part_name = "{2}" 51 origin_name = "{3}" 52 variant = "{4}" 53}}""" 54 55SYSTEM_KITS_TEMPLATE = """ 56ohos_system_kits("{0}_system_kits") {{ 57 sdk_libs = [ 58{1} 59 ] 60 part_name = "{0}" 61 origin_name = "{2}" 62 variant = "{3}" 63}}""" 64 65TEST_TEMPLATE = """ 66ohos_part_test("{0}_test") {{ 67 testonly = true 68 test_packages = [ 69 {1} 70 ] 71 deps = [":{0}"] 72 part_name = "{0}" 73 subsystem_name = "{2}" 74}}""" 75 76 77def _normalize(label, path): 78 if not label.startswith('//'): 79 label = '//{}/{}'.format(path, label) 80 return label 81 82 83@throw_exception 84def get_syscap_from_bundle(bundle_file): 85 if not os.path.exists(bundle_file): 86 raise OHOSException( 87 "config file '{}' doesn't exist.".format(bundle_file), "2014") 88 bundle_config = read_json_file(bundle_file) 89 if bundle_config is None: 90 raise OHOSException( 91 "read file '{}' failed.".format(bundle_file), "2014") 92 part_name = bundle_config.get('component').get('name') 93 part_syscap = bundle_config.get('component').get('syscap') 94 return part_name, part_syscap 95 96 97def read_build_file(ohos_build_file): 98 if not os.path.exists(ohos_build_file): 99 raise OHOSException( 100 "config file '{}' doesn't exist.".format(ohos_build_file), "2014") 101 subsystem_config = read_json_file(ohos_build_file) 102 if subsystem_config is None: 103 raise OHOSException( 104 "read file '{}' failed.".format(ohos_build_file), "2014") 105 return subsystem_config 106 107 108class PartObject(object): 109 """"part object info, description part variant.""" 110 111 def __init__(self, part_name, variant_name, part_config, toolchain, 112 subsystem_name, target_arch, overrided_components): 113 self._origin_name = part_name 114 if variant_name != 'phone': 115 _real_name = '{}_{}'.format(part_name, variant_name) 116 else: 117 _real_name = part_name 118 self._part_name = _real_name 119 self._variant_name = variant_name 120 self._subsystem_name = subsystem_name 121 self._feature_list = [] 122 self._toolchain = toolchain 123 self._inner_kits_info = {} 124 self._components_info = {} 125 self._kits = [] 126 self._target_arch = target_arch 127 self._system_capabilities = [] 128 self._overrided_components = overrided_components 129 self._parsing_config(self._part_name, part_config, subsystem_name) 130 131 @classmethod 132 def _parsing_kits_lib(cls, kit_lib, is_inner_kits=False): 133 lib_config = [] 134 lib_type = kit_lib.get('type') 135 if lib_type is None: 136 lib_type = 'so' if is_inner_kits else 'jar' 137 label = kit_lib.get('name') 138 if label is None: 139 raise Exception("kits lib config incorrect, required for name.") 140 lib_config.append(' type = "{}"'.format(lib_type)) 141 lib_config.append(' name = "{}"'.format(label)) 142 if lib_type == 'so' and 'header' in kit_lib: 143 header = kit_lib.get('header') 144 header_files = header.get('header_files') 145 lib_config.append(' header = {') 146 lib_config.append(' header_files = [') 147 for h_file in header_files: 148 lib_config.append(' "{}",'.format(h_file)) 149 lib_config.append(' ]') 150 header_base = header.get('header_base') 151 lib_config.append(' header_base = "{}"'.format(header_base)) 152 lib_config.append(' }') 153 if is_inner_kits is False and 'javadoc' in kit_lib: 154 javadoc_val = kit_lib.get('javadoc') 155 lib_config.append(' javadoc = {') 156 resource_dir = javadoc_val.get('resource_dir') 157 lib_config.append( 158 ' resource_dir = "{}"'.format(resource_dir)) 159 lib_config.append(' }') 160 return lib_config 161 162 def _overrided_part_name(self): 163 overrided_components = self._overrided_components 164 full_part_name = f"{self._subsystem_name}:{self._origin_name}" 165 overrided_map = overrided_components.get(full_part_name) 166 if overrided_map: 167 # origin_name is same as part_name in variant phone 168 overrided_origin_name = overrided_map.get("partName") 169 overrided_part_name = overrided_origin_name 170 else: 171 overrided_part_name = self._part_name 172 overrided_origin_name = self._origin_name 173 174 return overrided_part_name, overrided_origin_name 175 176 def _parsing_base_info(self, inner_kits_lib, part_name): 177 info = {'part_name': part_name} 178 label = inner_kits_lib.get('name') 179 lib_name = label.split(':')[1] 180 info['label'] = label 181 info['name'] = lib_name 182 if inner_kits_lib.get('visibility') is not None: 183 info['visibility'] = inner_kits_lib.get('visibility') 184 lib_type = inner_kits_lib.get('type') 185 if lib_type is None: 186 lib_type = 'so' 187 info['type'] = lib_type 188 prebuilt = inner_kits_lib.get('prebuilt_enable') 189 if prebuilt: 190 info['prebuilt_enable'] = prebuilt 191 prebuilt_source_libs = inner_kits_lib.get('prebuilt_source') 192 prebuilt_source = prebuilt_source_libs.get(target_arch) 193 info['prebuilt_source'] = prebuilt_source 194 else: 195 info['prebuilt_enable'] = False 196 return info, lib_name, lib_type 197 198 @throw_exception 199 def _parsing_inner_kits(self, part_name, inner_kits_info, build_gn_content, 200 target_arch): 201 inner_kits_libs_gn = [] 202 for inner_kits_lib in inner_kits_info: 203 header = inner_kits_lib.get('header') 204 if header is None: 205 continue 206 inner_kits_libs_gn.append(' {') 207 inner_kits_libs_gn.extend( 208 self._parsing_kits_lib(inner_kits_lib, True)) 209 inner_kits_libs_gn.append(' },') 210 211 overrided_part_name, overrided_origin_name = self._overrided_part_name() 212 213 inner_kits_libs_gn_line = '\n'.join(inner_kits_libs_gn) 214 inner_kits_def = INNER_KITS_TEMPLATE.format(part_name, 215 inner_kits_libs_gn_line, 216 overrided_part_name, 217 overrided_origin_name, 218 self._variant_name) 219 build_gn_content.append(inner_kits_def) 220 # output inner kits info to resolve external deps 221 _libs_info = {} 222 for inner_kits_lib in inner_kits_info: 223 info, lib_name, lib_type = self._parsing_base_info(inner_kits_lib, part_name) 224 self._components_info[lib_name] = info 225 # header files 226 header = inner_kits_lib.get('header') 227 if header is None: 228 continue 229 if lib_type == 'so': 230 header_base = header.get('header_base') 231 if header_base is None: 232 raise OHOSException( 233 "header base not configuration, part_name = '{}'". 234 format(part_name), "2014") 235 info['header_base'] = header_base 236 info['header_files'] = header.get('header_files') 237 _libs_info[lib_name] = info 238 self._inner_kits_info = _libs_info 239 240 def _parsing_system_kits(self, part_name, system_kits_info, 241 build_gn_content): 242 system_kits_libs_gn = [] 243 kits = [] 244 for _kits_lib in system_kits_info: 245 system_kits_libs_gn.append(' {') 246 system_kits_libs_gn.extend(self._parsing_kits_lib( 247 _kits_lib, False)) 248 kits.append('"{}"'.format(_kits_lib.get('name'))) 249 system_kits_libs_gn.append(' },') 250 _kits_libs_gn_line = '\n'.join(system_kits_libs_gn) 251 system_kits_def = SYSTEM_KITS_TEMPLATE.format(part_name, 252 _kits_libs_gn_line, 253 self._origin_name, 254 self._variant_name) 255 build_gn_content.append(system_kits_def) 256 self._kits = kits 257 258 def _parsing_config(self, part_name, part_config, subsystem_name): 259 self._part_target_list = [] 260 build_gn_content = [] 261 build_gn_content.append(IMPORT_LIST) 262 263 # ohos part 264 if 'module_list' not in part_config: 265 raise OHOSException( 266 "ohos.build incorrect, part name: '{}'".format(part_name), "2014") 267 module_list = part_config.get('module_list') 268 if len(module_list) == 0: 269 module_list_line = '' 270 else: 271 module_list_line = '"{}",'.format('",\n "'.join(module_list)) 272 parts_definition = PART_TEMPLATE.format(part_name, subsystem_name, 273 module_list_line, 274 self._origin_name, 275 self._variant_name) 276 build_gn_content.append(parts_definition) 277 278 # part inner kits 279 if part_config.get('inner_kits'): 280 self._part_target_list.append('inner_kits') 281 inner_kits_info = part_config.get('inner_kits') 282 self._parsing_inner_kits(part_name, inner_kits_info, 283 build_gn_content, self._target_arch) 284 # part system kits 285 if part_config.get('system_kits'): 286 self._part_target_list.append('system_kits') 287 system_kits_info = part_config.get('system_kits') 288 self._parsing_system_kits(part_name, system_kits_info, 289 build_gn_content) 290 # part test list 291 if part_config.get('test_list'): 292 self._part_target_list.append('test') 293 test_list = part_config.get('test_list') 294 test_list_line = '"{}",'.format('",\n "'.join(test_list)) 295 test_def = TEST_TEMPLATE.format(part_name, test_list_line, 296 subsystem_name) 297 build_gn_content.append(test_def) 298 self._build_gn_content = build_gn_content 299 # feature 300 if part_config.get('feature_list'): 301 self._feature_list = part_config.get('feature_list') 302 # check feature 303 for _feature_name in self._feature_list: 304 if not _feature_name.startswith('{}_'.format( 305 self._origin_name)): 306 raise OHOSException( 307 "part feature list config incorrect," 308 " part_name='{}', feature_name='{}'".format( 309 self._origin_name, _feature_name), "2014") 310 311 # system_capabilities is a list attribute of a part in ohos.build 312 if part_config.get('system_capabilities'): 313 self._system_capabilities = part_config.get('system_capabilities') 314 315 def part_name(self): 316 """part name.""" 317 return self._part_name 318 319 def part_variant(self): 320 """part variant.""" 321 return self._variant_name 322 323 def toolchain(self): 324 """current part variant toolchain.""" 325 return self._toolchain 326 327 def part_inner_kits(self): 328 """part inner kits.""" 329 return self._inner_kits_info 330 331 def part_component_info(self): 332 """part component info.""" 333 return self._components_info 334 335 def part_kits(self): 336 """part kits.""" 337 return self._kits 338 339 def write_build_gn(self, config_output_dir): 340 """output build gn.""" 341 part_gn_file = os.path.join(config_output_dir, self._part_name, 342 'BUILD.gn') 343 write_file(part_gn_file, '\n'.join(self._build_gn_content)) 344 345 def get_target_label(self, config_output_relpath): 346 """target label.""" 347 if config_output_relpath.startswith('/'): 348 raise OHOSException( 349 "args config output relative path is incorrect.", "2003") 350 if self._toolchain == '': 351 return "//{0}/{1}:{1}".format(config_output_relpath, 352 self._part_name) 353 else: 354 return "//{0}/{1}:{1}({2})".format(config_output_relpath, 355 self._part_name, 356 self._toolchain) 357 358 def part_group_targets(self, config_output_relpath): 359 """part group target.""" 360 if config_output_relpath.startswith('/'): 361 raise OHOSException( 362 "args config output relative path is incorrect.", "2003") 363 _labels = {} 364 _labels['part'] = self.get_target_label(config_output_relpath) 365 for group_label in self._part_target_list: 366 if group_label == 'phony': 367 _labels[group_label] = "//{0}/{1}:{1}_{2}".format( 368 config_output_relpath, self._part_name, group_label) 369 continue 370 if self._toolchain == '': 371 _labels[group_label] = "//{0}/{1}:{1}_{2}".format( 372 config_output_relpath, self._part_name, group_label) 373 else: 374 _labels[group_label] = "//{0}/{1}:{1}_{2}({3})".format( 375 config_output_relpath, self._part_name, group_label, 376 self._toolchain) 377 return _labels 378 379 def part_info(self): 380 """part info.""" 381 _info = {} 382 _info['part_name'] = self._part_name 383 _info['origin_part_name'] = self._origin_name 384 _info['toolchain_label'] = self._toolchain 385 _info['variant_name'] = self._variant_name 386 _info['subsystem_name'] = self._subsystem_name 387 _info['system_capabilities'] = self._system_capabilities 388 389 if self._feature_list: 390 _info['feature_list'] = self._feature_list 391 if self._variant_name != 'phone': 392 toolchain_name = self._toolchain.split(':')[1] 393 _build_out_dir = toolchain_name 394 else: 395 _build_out_dir = '.' 396 _info['build_out_dir'] = _build_out_dir 397 return _info 398 399 400class LoadBuildConfig(object): 401 """load build config file and parse configuration info.""" 402 403 def __init__(self, source_root_dir, subsystem_build_info, 404 config_output_dir, variant_toolchains, subsystem_name, 405 target_arch, ignored_subsystems, exclusion_modules_config_file, 406 load_test_config, overrided_components, bundle_subsystem_allow_list): 407 self._source_root_dir = source_root_dir 408 self._build_info = subsystem_build_info 409 self._config_output_relpath = config_output_dir 410 self._is_load = False 411 self._parts_variants = {} 412 self._part_list = {} 413 self._part_targets_label = {} 414 self._variant_toolchains = variant_toolchains 415 self._subsystem_name = subsystem_name 416 self._target_arch = target_arch 417 self._ignored_subsystems = ignored_subsystems 418 self._parts_info_dict = {} 419 self._phony_targets = {} 420 self._parts_path_dict = {} 421 self._part_hisysevent_config = {} 422 self._parts_module_list = {} 423 self._parts_deps = {} 424 self._exclusion_modules_config_file = exclusion_modules_config_file 425 self._load_test_config = load_test_config 426 self._overrided_components = overrided_components 427 self._bundle_subsystem_allow_list = bundle_subsystem_allow_list 428 429 @throw_exception 430 def _parsing_config(self, parts_config): 431 _parts_info_dict = {} 432 _parts_deps = {} 433 _variant_phony_targets = {} 434 for part_name, value in parts_config.items(): 435 if 'variants' in value: 436 variants = value.get('variants') 437 if len(variants) == 0: 438 variants = ['phone'] 439 else: 440 variants = ['phone'] 441 _build_target = {} 442 _targets_label = {} 443 _parts_info = [] 444 for variant in variants: 445 toolchain = self._variant_toolchains.get(variant) 446 if toolchain is None: 447 continue 448 part_obj = PartObject(part_name, variant, value, toolchain, 449 self._subsystem_name, self._target_arch, self._overrided_components) 450 real_part_name = part_obj.part_name() 451 self._part_list[real_part_name] = part_obj 452 453 subsystem_config_dir = os.path.join( 454 self._config_output_relpath, self._subsystem_name) 455 part_obj.write_build_gn( 456 os.path.join(self._source_root_dir, subsystem_config_dir)) 457 458 _target_label = part_obj.get_target_label(subsystem_config_dir) 459 _build_target[variant] = _target_label 460 _targets_label[real_part_name] = part_obj.part_group_targets( 461 subsystem_config_dir) 462 _parts_info.append(part_obj.part_info()) 463 if variant != 'phone': 464 _variant_phony_targets[real_part_name] = _target_label 465 self._part_targets_label.update(_targets_label) 466 self._parts_variants[part_name] = _build_target 467 if 'hisysevent_config' in value: 468 _config_files = value.get('hisysevent_config') 469 for _config_file in _config_files: 470 if not _config_file.startswith('//'): 471 raise OHOSException( 472 "part '{}' hisysevent config incorrest.".format( 473 part_name), "2014") 474 self._part_hisysevent_config[part_name] = _config_files 475 _parts_info_dict[part_name] = _parts_info 476 _parts_deps[part_name] = value.get('part_deps') 477 self._parts_info_dict = _parts_info_dict 478 self._phony_targets = _variant_phony_targets 479 self._parts_deps = _parts_deps 480 481 def _merge_build_config(self): 482 _build_files = self._build_info.get('build_files') 483 is_thirdparty_subsystem = False 484 if _build_files[0].startswith(self._source_root_dir + 'third_party'): 485 is_thirdparty_subsystem = True 486 subsystem_name = None 487 parts_info = {} 488 parts_path_dict = {} 489 for _build_file in _build_files: 490 if _build_file.endswith('bundle.json'): 491 bundle_part_obj = load_bundle_file.BundlePartObj( 492 _build_file, self._exclusion_modules_config_file, 493 self._load_test_config) 494 _parts_config = bundle_part_obj.to_ohos_build() 495 else: 496 _parts_config = read_build_file(_build_file) 497 498 _subsystem_name = _parts_config.get('subsystem') 499 if not is_thirdparty_subsystem and subsystem_name and _subsystem_name != subsystem_name: 500 raise OHOSException( 501 "subsystem name config incorrect in '{}'.".format( 502 _build_file), "2014") 503 if _subsystem_name != self._subsystem_name: 504 is_allow = False 505 for file_path in self._bundle_subsystem_allow_list: 506 if _build_file.endswith(file_path): 507 is_allow = True 508 break 509 if is_allow: 510 print("warning: subsystem name config incorrect in '{}', build file subsystem name is {}," 511 "configured subsystem name is {}.".format( 512 _build_file, _subsystem_name, self._subsystem_name)) 513 else: 514 raise OHOSException("subsystem name config incorrect in '{}', build file subsystem name is {}," 515 "configured subsystem name is {}.".format( 516 _build_file, _subsystem_name, self._subsystem_name), 2014) 517 518 subsystem_name = _subsystem_name 519 _curr_parts_info = _parts_config.get('parts') 520 for _pname in _curr_parts_info.keys(): 521 parts_path_dict[_pname] = os.path.relpath( 522 os.path.dirname(_build_file), self._source_root_dir) 523 parts_info.update(_curr_parts_info) 524 subsystem_config = {} 525 subsystem_config['subsystem'] = subsystem_name 526 subsystem_config['parts'] = parts_info 527 return subsystem_config, parts_path_dict 528 529 def parse_syscap_info(self): 530 _build_files = self._build_info.get('build_files') 531 subsystem_syscap = [] 532 for _build_file in _build_files: 533 if _build_file.endswith('bundle.json'): 534 part_name, part_syscap = get_syscap_from_bundle(_build_file) 535 subsystem_syscap.append( 536 {'component': part_name, 'syscap': part_syscap}) 537 return subsystem_syscap 538 539 def parse(self): 540 """parse part info from build config file.""" 541 if self._is_load: 542 return 543 subsystem_config, parts_path_dict = self._merge_build_config() 544 parts_config = subsystem_config.get('parts') 545 self._parts_module_list.update(parts_config) 546 self._parsing_config(parts_config) 547 self._parts_path_dict = parts_path_dict 548 self._is_load = True 549 550 def parts_variants(self): 551 """parts varinats info.""" 552 self.parse() 553 return self._parts_variants 554 555 def parts_inner_kits_info(self): 556 """parts inner kits info.""" 557 self.parse() 558 _parts_inner_kits = {} 559 for part_obj in self._part_list.values(): 560 _parts_inner_kits[ 561 part_obj.part_name()] = part_obj.part_inner_kits() 562 return _parts_inner_kits 563 564 def parts_component_info(self): 565 """parts component info.""" 566 self.parse() 567 _parts_component_info = {} 568 for part_obj in self._part_list.values(): 569 _parts_component_info[ 570 part_obj.part_name()] = part_obj.part_component_info() 571 return _parts_component_info 572 573 def parts_build_targets(self): 574 """parts build target label.""" 575 self.parse() 576 return self._part_targets_label 577 578 def parts_name_list(self): 579 """parts name list.""" 580 self.parse() 581 return list(self._part_list.keys()) 582 583 def parts_info(self): 584 """parts info.""" 585 self.parse() 586 return self._parts_info_dict 587 588 def parts_phony_target(self): 589 """parts phony target info""" 590 self.parse() 591 return self._phony_targets 592 593 def parts_kits_info(self): 594 """parts kits info.""" 595 self.parse() 596 _parts_kits = {} 597 for part_obj in self._part_list.values(): 598 _parts_kits[part_obj.part_name()] = part_obj.part_kits() 599 return _parts_kits 600 601 def parts_path_info(self): 602 """parts to path info.""" 603 self.parse() 604 return self._parts_path_dict 605 606 def parts_hisysevent_config(self): 607 self.parse() 608 return self._part_hisysevent_config 609 610 def parts_modules_info(self): 611 self.parse() 612 return self._parts_module_list 613 614 def parts_deps(self): 615 self.parse() 616 return self._parts_deps 617 618 def parts_info_filter(self, save_part): 619 if save_part is None: 620 raise Exception 621 self._parts_variants = { 622 key: value for key, value in self._parts_variants.items() if key in save_part} 623 self._part_list = { 624 key: value for key, value in self._part_list.items() if key in save_part} 625 self._part_targets_label = { 626 key: value for key, value in self._part_targets_label.items() if key in save_part} 627 self._parts_info_dict = { 628 key: value for key, value in self._parts_info_dict.items() if key in save_part} 629 self._phony_targets = { 630 key: value for key, value in self._phony_targets.items() if key in save_part} 631 self._parts_path_dict = { 632 key: value for key, value in self._parts_path_dict.items() if key in save_part} 633 self._part_hisysevent_config = { 634 key: value for key, value in self._part_hisysevent_config.items() if key in save_part} 635 self._parts_module_list = { 636 key: value for key, value in self._parts_module_list.items() if key in save_part} 637 self._parts_deps = { 638 key: value for key, value in self._parts_deps.items() if key in save_part} 639 640 641def compare_subsystem_and_component(subsystem_name, components_name, subsystem_compoents_whitelist_info, 642 part_subsystem_component_info, parts_config_path, subsystem_components_list): 643 name = "" 644 message = "" 645 if components_name in list(subsystem_compoents_whitelist_info.keys()): 646 return 647 overrided_components_name = '{}_{}'.format(components_name, 'override') 648 if components_name in list(part_subsystem_component_info.keys()) \ 649 or overrided_components_name in list(part_subsystem_component_info.keys()): 650 if subsystem_name in list(part_subsystem_component_info.values()): 651 return 652 if subsystem_name == components_name: 653 return 654 name = subsystem_name 655 message = "find subsystem {} failed, please check it in {}.".format(subsystem_name, parts_config_path) 656 else: 657 name = components_name 658 message = "find component {} failed, please check it in {}.".format(components_name, parts_config_path) 659 if name in subsystem_components_list: 660 print(f"Warning: {message}") 661 else: 662 raise Exception(message) 663 664 665def check_subsystem_and_component(parts_info_output_path, skip_partlist_check): 666 config = Config() 667 parts_config_path = os.path.join(config.root_path, "out/preloader", config.product, 668 "parts.json") 669 part_subsystem_file = os.path.join(parts_info_output_path, 670 "part_subsystem.json") 671 part_subsystem_component_info = read_json_file(part_subsystem_file) 672 673 subsystem_compoents_whitelist_file = os.path.join(config.root_path, 674 "build/subsystem_compoents_whitelist.json") 675 subsystem_compoents_whitelist_info = read_json_file(subsystem_compoents_whitelist_file) 676 677 compile_standard_whitelist_file = os.path.join(config.root_path, "out/preloader", config.product, 678 "compile_standard_whitelist.json") 679 compile_standard_whitelist_info = read_json_file(compile_standard_whitelist_file) 680 subsystem_components_list = compile_standard_whitelist_info.get("subsystem_components", []) 681 682 if os.path.isfile(parts_config_path): 683 parts_config_info = read_json_file(parts_config_path) 684 parts_info = parts_config_info.get("parts") 685 686 for subsystem_part in parts_info: 687 subsystem_part_list = subsystem_part.split(':') 688 subsystem_name = subsystem_part_list[0] 689 components_name = subsystem_part_list[1] 690 691 if subsystem_name is None or components_name is None: 692 print("Warning: subsystem_name or components_name is empty, please check it in {}.".format( 693 parts_config_path)) 694 continue 695 if not skip_partlist_check: 696 compare_subsystem_and_component(subsystem_name, components_name, subsystem_compoents_whitelist_info, 697 part_subsystem_component_info, parts_config_path, 698 subsystem_components_list) 699 700 701def _output_all_components_info(parts_config_dict, parts_info_output_path): 702 if 'parts_component_info' not in parts_config_dict: 703 return 704 parts_component_info = parts_config_dict.get('parts_component_info') 705 if 'parts_info' not in parts_config_dict: 706 return 707 parts_info = parts_config_dict.get('parts_info') 708 if 'parts_path_info' not in parts_config_dict: 709 return 710 parts_path_info = parts_config_dict.get('parts_path_info') 711 712 components = {} 713 714 for name, val in parts_component_info.items(): 715 component = {} 716 component["innerapis"] = [] 717 component["variants"] = [] 718 if name in parts_path_info: 719 component["path"] = parts_path_info[name] 720 else: 721 print("Warning: component %s has no path info." % name) 722 723 if name in parts_info: 724 for item in parts_info[name]: 725 component["subsystem"] = item.get("subsystem_name") 726 break 727 else: 728 print("Warning: component %s has no subsystem info." % name) 729 730 if val: 731 for k, v in val.items(): 732 innerapi = {"name": k, "label": v["label"]} 733 if "visibility" in v: 734 innerapi["visibility"] = v["visibility"] 735 component["innerapis"].append(innerapi) 736 737 components[name] = component 738 739 _component_file = os.path.join(parts_info_output_path, 740 "components.json") 741 write_json_file(_component_file, components) 742 743 744def _output_parts_info(parts_config_dict, 745 config_output_path, skip_partlist_check): 746 parts_info_output_path = os.path.join(config_output_path, "parts_info") 747 # parts_info.json 748 process_parts_info(parts_config_dict, parts_info_output_path, skip_partlist_check) 749 750 # subsystem_parts.json 751 process_subsystem_parts(config_output_path, parts_config_dict, parts_info_output_path) 752 753 # _parts_modules_info 754 process_parts_modules_info(parts_config_dict, parts_info_output_path) 755 756 # paths_path_info.json 757 process_parts_path_info(parts_config_dict, parts_info_output_path) 758 759 other_parts = ["parts_variants", "parts_inner_kits_info", "parts_targets", 760 "phony_target", "hisysevent_config", "parts_deps"] 761 762 for parts in other_parts: 763 process_other_parts(parts, parts_config_dict, parts_info_output_path) 764 765 check_subsystem_and_component(parts_info_output_path, skip_partlist_check) 766 767 _output_all_components_info(parts_config_dict, parts_info_output_path) 768 769 770def process_other_parts(part_name, parts_config_dict, parts_info_output_path): 771 if part_name in parts_config_dict: 772 parts_info = parts_config_dict.get(part_name) 773 parts_info_file = os.path.join(parts_info_output_path, 774 part_name + ".json") 775 if part_name == 'hisysevent_config': 776 parts_info_file = os.path.join(parts_info_output_path, 777 'hisysevent_configs' + ".json") 778 if part_name == 'parts_inner_kits_info': 779 parts_info_file = os.path.join(parts_info_output_path, 780 'inner_kits_info' + ".json") 781 write_json_file(parts_info_file, parts_info) 782 LogUtil.hb_info("generate '{}' info to '{}'".format(part_name, 783 parts_info_file), mode=Config.log_mode) 784 785 786def process_parts_modules_info(parts_config_dict, parts_info_output_path): 787 if 'parts_modules_info' in parts_config_dict: 788 parts_modules_info = parts_config_dict.get('parts_modules_info') 789 _output_info = {} 790 _all_p_info = [] 791 for key, value in parts_modules_info.items(): 792 _p_info = {} 793 _p_info['part_name'] = key 794 _module_list = value.get('module_list') 795 _p_info['module_list'] = _module_list 796 _all_p_info.append(_p_info) 797 _output_info['parts'] = _all_p_info 798 parts_modules_info_file = os.path.join(parts_info_output_path, 799 'parts_modules_info.json') 800 write_json_file(parts_modules_info_file, _output_info) 801 LogUtil.hb_info("generate parts modules info to '{}'".format( 802 parts_modules_info_file), mode=Config.log_mode) 803 804 805def process_parts_path_info(parts_config_dict, parts_info_output_path): 806 if 'parts_path_info' in parts_config_dict: 807 parts_path_info = parts_config_dict.get('parts_path_info') 808 parts_path_info_file = os.path.join(parts_info_output_path, 809 'parts_path_info.json') 810 write_json_file(parts_path_info_file, parts_path_info) 811 LogUtil.hb_info( 812 "generate parts path info to '{}'".format(parts_path_info_file), mode=Config.log_mode) 813 path_to_parts = {} 814 for _key, _val in parts_path_info.items(): 815 _p_list = path_to_parts.get(_val, []) 816 _p_list.append(_key) 817 path_to_parts[_val] = _p_list 818 path_to_parts_file = os.path.join(parts_info_output_path, 819 'path_to_parts.json') 820 write_json_file(path_to_parts_file, path_to_parts) 821 LogUtil.hb_info( 822 "generate path to parts to '{}'".format(path_to_parts_file), mode=Config.log_mode) 823 824 825def process_subsystem_parts(config_output_path, parts_config_dict, parts_info_output_path): 826 if 'subsystem_parts' in parts_config_dict: 827 subsystem_parts = parts_config_dict.get('subsystem_parts') 828 subsystem_parts_file = os.path.join(parts_info_output_path, 829 "subsystem_parts.json") 830 write_json_file(subsystem_parts_file, subsystem_parts) 831 LogUtil.hb_info( 832 "generate ubsystem-parts of parts-info to '{}'".format( 833 subsystem_parts_file), mode=Config.log_mode) 834 835 # adapter mini system 836 for _sub_name, _p_list in subsystem_parts.items(): 837 _output_info = {} 838 _output_info['parts'] = _p_list 839 _sub_info_output_file = os.path.join(config_output_path, 840 'mini_adapter', 841 '{}.json'.format(_sub_name)) 842 write_json_file(_sub_info_output_file, _output_info) 843 LogUtil.hb_info( 844 "generate mini adapter info to '{}/mini_adapter/'".format( 845 config_output_path), mode=Config.log_mode) 846 847 848def process_parts_info(parts_config_dict, parts_info_output_path, skip_partlist_check): 849 if 'parts_info' in parts_config_dict: 850 parts_info = parts_config_dict.get('parts_info') 851 parts_info_file = os.path.join(parts_info_output_path, 852 "parts_info.json") 853 write_json_file(parts_info_file, parts_info) 854 LogUtil.hb_info("generate parts info to '{}'".format(parts_info_file), mode=Config.log_mode) 855 _part_subsystem_dict = {} 856 for key, value in parts_info.items(): 857 for _info in value: 858 _sub_name = _info.get('subsystem_name') 859 _part_subsystem_dict[key] = _sub_name 860 break 861 _part_subsystem_file = os.path.join(parts_info_output_path, 862 "part_subsystem.json") 863 write_json_file(_part_subsystem_file, _part_subsystem_dict) 864 LogUtil.hb_info( 865 "generate part-subsystem of parts-info to '{}'".format( 866 _part_subsystem_file), mode=Config.log_mode) 867 868 869def get_parts_info(source_root_dir, 870 config_output_relpath, 871 subsystem_info, 872 variant_toolchains, 873 target_arch, 874 ignored_subsystems, 875 exclusion_modules_config_file, 876 load_test_config, 877 overrided_components, 878 bundle_subsystem_allow_list, 879 skip_partlist_check, 880 build_xts=False): 881 """parts info, 882 get info from build config file. 883 """ 884 parts_variants = {} 885 parts_inner_kits_info = {} 886 parts_component_info = {} 887 parts_kits_info = {} 888 parts_targets = {} 889 parts_info = {} 890 subsystem_parts = {} 891 _phony_target = {} 892 _parts_path_info = {} 893 _parts_hisysevent_config = {} 894 _parts_modules_info = {} 895 _parts_deps = {} 896 system_syscap = [] 897 for subsystem_name, build_config_info in subsystem_info.items(): 898 if not len(build_config_info.get("build_files")): 899 continue 900 build_loader = LoadBuildConfig(source_root_dir, build_config_info, 901 config_output_relpath, 902 variant_toolchains, subsystem_name, 903 target_arch, ignored_subsystems, 904 exclusion_modules_config_file, 905 load_test_config, overrided_components, 906 bundle_subsystem_allow_list) 907 # xts subsystem special handling, device_attest and 908 # device_attest_lite parts need to be compiled into the version image, other parts are not. 909 # parts_modules_info needs to be parse before filting. 910 if subsystem_name == 'xts' and build_xts is False: 911 xts_device_attest_name = ['device_attest_lite', 'device_attest'] 912 build_loader.parse() 913 build_loader.parts_info_filter(xts_device_attest_name) 914 _parts_variants = build_loader.parts_variants() 915 parts_variants.update(_parts_variants) 916 _inner_kits_info = build_loader.parts_inner_kits_info() 917 parts_inner_kits_info.update(_inner_kits_info) 918 _parts_component_info = build_loader.parts_component_info() 919 parts_component_info.update(_parts_component_info) 920 parts_kits_info.update(build_loader.parts_kits_info()) 921 _parts_targets = build_loader.parts_build_targets() 922 parts_targets.update(_parts_targets) 923 subsystem_parts[subsystem_name] = build_loader.parts_name_list() 924 parts_info.update(build_loader.parts_info()) 925 _phony_target.update(build_loader.parts_phony_target()) 926 _parts_path_info.update(build_loader.parts_path_info()) 927 _parts_hisysevent_config.update(build_loader.parts_hisysevent_config()) 928 _parts_modules_info.update(build_loader.parts_modules_info()) 929 _parts_deps.update(build_loader.parts_deps()) 930 system_syscap.extend(build_loader.parse_syscap_info()) 931 LogUtil.hb_info( 932 "generate all parts build gn file to '{}/{}'".format( 933 source_root_dir, config_output_relpath), mode=Config.log_mode) 934 parts_config_dict = {} 935 parts_config_dict['parts_info'] = parts_info 936 parts_config_dict['subsystem_parts'] = subsystem_parts 937 parts_config_dict['parts_variants'] = parts_variants 938 parts_config_dict['parts_inner_kits_info'] = parts_inner_kits_info 939 parts_config_dict['parts_component_info'] = parts_component_info 940 parts_config_dict['parts_kits_info'] = parts_kits_info 941 parts_config_dict['parts_targets'] = parts_targets 942 parts_config_dict['phony_target'] = _phony_target 943 parts_config_dict['parts_path_info'] = _parts_path_info 944 parts_config_dict['hisysevent_config'] = _parts_hisysevent_config 945 parts_config_dict['parts_modules_info'] = _parts_modules_info 946 parts_config_dict['parts_deps'] = _parts_deps 947 _output_parts_info(parts_config_dict, 948 os.path.join(source_root_dir, config_output_relpath), skip_partlist_check) 949 parts_config_dict['syscap_info'] = system_syscap 950 LogUtil.hb_info('all parts scan completed') 951 return parts_config_dict 952