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