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