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