1bae44755Sopenharmony_ci#!/usr/bin/env python3 2bae44755Sopenharmony_ci# -*- coding: utf-8 -*- 3bae44755Sopenharmony_ci# Copyright (c) 2023 Huawei Device Co., Ltd. 4bae44755Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 5bae44755Sopenharmony_ci# you may not use this file except in compliance with the License. 6bae44755Sopenharmony_ci# You may obtain a copy of the License at 7bae44755Sopenharmony_ci# 8bae44755Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 9bae44755Sopenharmony_ci# 10bae44755Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 11bae44755Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 12bae44755Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bae44755Sopenharmony_ci# See the License for the specific language governing permissions and 14bae44755Sopenharmony_ci# limitations under the License. 15bae44755Sopenharmony_ciimport logging 16bae44755Sopenharmony_ciimport os 17bae44755Sopenharmony_ciimport json 18bae44755Sopenharmony_ciimport argparse 19bae44755Sopenharmony_ciimport stat 20bae44755Sopenharmony_cifrom collections import Counter 21bae44755Sopenharmony_ci 22bae44755Sopenharmony_ci 23bae44755Sopenharmony_cidef get_args(): 24bae44755Sopenharmony_ci parser = argparse.ArgumentParser(add_help=True) 25bae44755Sopenharmony_ci parser.add_argument( 26bae44755Sopenharmony_ci "-p", 27bae44755Sopenharmony_ci "--project_path", 28bae44755Sopenharmony_ci default=r"", 29bae44755Sopenharmony_ci type=str, 30bae44755Sopenharmony_ci help="root path of project. default: ./", 31bae44755Sopenharmony_ci ) 32bae44755Sopenharmony_ci args = parser.parse_args() 33bae44755Sopenharmony_ci return args 34bae44755Sopenharmony_ci 35bae44755Sopenharmony_ci 36bae44755Sopenharmony_cidef dict_to_json(output_path: str, syscaps_dict: dict): 37bae44755Sopenharmony_ci """ 38bae44755Sopenharmony_ci output diff product syscaps json to output path 39bae44755Sopenharmony_ci :param output_path: 40bae44755Sopenharmony_ci :param syscaps_dict: 41bae44755Sopenharmony_ci :return: 42bae44755Sopenharmony_ci """ 43bae44755Sopenharmony_ci print("start generate syscap json...") 44bae44755Sopenharmony_ci flags = os.O_WRONLY | os.O_CREAT 45bae44755Sopenharmony_ci modes = stat.S_IWUSR | stat.S_IRUSR 46bae44755Sopenharmony_ci for product_name, syscaps_list in syscaps_dict.items(): 47bae44755Sopenharmony_ci counts = Counter(syscaps_list) 48bae44755Sopenharmony_ci duplicates = [elem for elem, count in counts.items() if count > 1] 49bae44755Sopenharmony_ci if len(duplicates) > 0: 50bae44755Sopenharmony_ci print("[Warning] repeated syscap: {}".format(",".join(duplicates))) 51bae44755Sopenharmony_ci syscaps_list = list(set(syscaps_list)) 52bae44755Sopenharmony_ci filename = os.path.join(output_path, f'{product_name}.json') 53bae44755Sopenharmony_ci with os.fdopen(os.open(filename, flags, modes), 'w') as f: 54bae44755Sopenharmony_ci json.dump({'SysCaps': syscaps_list}, f, indent=4) 55bae44755Sopenharmony_ci print("end...") 56bae44755Sopenharmony_ci 57bae44755Sopenharmony_ci 58bae44755Sopenharmony_cidef check_syscap(syscap_str: str): 59bae44755Sopenharmony_ci syscap = syscap_str.split(' = ') 60bae44755Sopenharmony_ci if syscap[-1].lower() == 'false': 61bae44755Sopenharmony_ci return False 62bae44755Sopenharmony_ci else: 63bae44755Sopenharmony_ci return syscap[0] 64bae44755Sopenharmony_ci 65bae44755Sopenharmony_ci 66bae44755Sopenharmony_cidef bundle_syscap_list_handler(bundle_syscap_list: list, component_syscaps_list: list): 67bae44755Sopenharmony_ci """ 68bae44755Sopenharmony_ci check syscap 69bae44755Sopenharmony_ci :param bundle_syscap_list: 70bae44755Sopenharmony_ci :param component_syscaps_list: 71bae44755Sopenharmony_ci :return: 72bae44755Sopenharmony_ci """ 73bae44755Sopenharmony_ci for component_syscap in component_syscaps_list: 74bae44755Sopenharmony_ci component_syscap = check_syscap(component_syscap) 75bae44755Sopenharmony_ci if component_syscap: 76bae44755Sopenharmony_ci bundle_syscap_list.append(component_syscap) 77bae44755Sopenharmony_ci return bundle_syscap_list 78bae44755Sopenharmony_ci 79bae44755Sopenharmony_ci 80bae44755Sopenharmony_cidef read_json_file(bundle_json_path: str): 81bae44755Sopenharmony_ci bundle_syscap_list = list() 82bae44755Sopenharmony_ci error_list = dict() 83bae44755Sopenharmony_ci try: 84bae44755Sopenharmony_ci with open(bundle_json_path, 'r', encoding='utf-8') as f: 85bae44755Sopenharmony_ci bundle_data = json.load(f) 86bae44755Sopenharmony_ci component_data = bundle_data.get("component") 87bae44755Sopenharmony_ci component_syscaps_list = component_data.get("syscap") 88bae44755Sopenharmony_ci if component_syscaps_list: 89bae44755Sopenharmony_ci bundle_syscap_list = bundle_syscap_list_handler(bundle_syscap_list, component_syscaps_list) 90bae44755Sopenharmony_ci except FileNotFoundError as e: 91bae44755Sopenharmony_ci error_list[bundle_json_path] = str(e) 92bae44755Sopenharmony_ci except Exception as e: 93bae44755Sopenharmony_ci error_list[bundle_json_path] = str(e) 94bae44755Sopenharmony_ci return bundle_syscap_list, error_list 95bae44755Sopenharmony_ci 96bae44755Sopenharmony_ci 97bae44755Sopenharmony_cidef get_all_components_path(components_file_path: str): 98bae44755Sopenharmony_ci try: 99bae44755Sopenharmony_ci with open(components_file_path, 'r', encoding='utf-8') as f: 100bae44755Sopenharmony_ci path_dict = json.load(f) 101bae44755Sopenharmony_ci return path_dict 102bae44755Sopenharmony_ci except FileNotFoundError: 103bae44755Sopenharmony_ci logging.error(r"PATH ERROR") 104bae44755Sopenharmony_ci return {} 105bae44755Sopenharmony_ci 106bae44755Sopenharmony_ci 107bae44755Sopenharmony_cidef path_component_to_bundle(path: str) -> str: 108bae44755Sopenharmony_ci bundle_json_path = os.path.join(path, 'bundle.json') 109bae44755Sopenharmony_ci return bundle_json_path 110bae44755Sopenharmony_ci 111bae44755Sopenharmony_ci 112bae44755Sopenharmony_cidef find_false_syscap(syscap_l: list): 113bae44755Sopenharmony_ci res = [] 114bae44755Sopenharmony_ci for syscap in syscap_l: 115bae44755Sopenharmony_ci if not check_syscap(syscap): 116bae44755Sopenharmony_ci res.append(syscap.split('=')[0].strip()) 117bae44755Sopenharmony_ci return res 118bae44755Sopenharmony_ci 119bae44755Sopenharmony_ci 120bae44755Sopenharmony_cidef handle_bundle_json_file(component_path_dict: dict, product_define_dict: dict): 121bae44755Sopenharmony_ci """ 122bae44755Sopenharmony_ci from product required part bundle.json to all products parts list 123bae44755Sopenharmony_ci :param component_path_dict: 124bae44755Sopenharmony_ci :return: all products parts list 125bae44755Sopenharmony_ci """ 126bae44755Sopenharmony_ci print("start collect syscap path...") 127bae44755Sopenharmony_ci syscap_dict = dict() 128bae44755Sopenharmony_ci errors_list = list() 129bae44755Sopenharmony_ci for product_name, path_dict in component_path_dict.items(): 130bae44755Sopenharmony_ci bundles_list = list() 131bae44755Sopenharmony_ci for component in path_dict.keys(): 132bae44755Sopenharmony_ci path = path_dict.get(component) 133bae44755Sopenharmony_ci bundle_json_path = path_component_to_bundle(path) 134bae44755Sopenharmony_ci bundle_syscap_list, error_list = read_json_file(bundle_json_path) 135bae44755Sopenharmony_ci if product_define_dict.get(product_name).get(component): 136bae44755Sopenharmony_ci false_syscap = find_false_syscap(product_define_dict.get(product_name).get(component)) 137bae44755Sopenharmony_ci bundle_syscap_l = [sc for sc in bundle_syscap_list if sc not in false_syscap] 138bae44755Sopenharmony_ci bundles_list.extend(bundle_syscap_l) 139bae44755Sopenharmony_ci else: 140bae44755Sopenharmony_ci bundles_list.extend(bundle_syscap_list) 141bae44755Sopenharmony_ci errors_list.extend(error_list) 142bae44755Sopenharmony_ci syscap_dict.update({product_name: bundles_list}) 143bae44755Sopenharmony_ci return syscap_dict, errors_list 144bae44755Sopenharmony_ci 145bae44755Sopenharmony_ci 146bae44755Sopenharmony_cidef format_component_path(component_path: str): 147bae44755Sopenharmony_ci sep_list = ['\\', '/'] 148bae44755Sopenharmony_ci sep_list.remove(os.sep) 149bae44755Sopenharmony_ci component_path = component_path.replace(sep_list[0], os.sep) 150bae44755Sopenharmony_ci return component_path 151bae44755Sopenharmony_ci 152bae44755Sopenharmony_ci 153bae44755Sopenharmony_cidef traversal_path(parts_path_info: dict, project_path: str, product_define_dict): 154bae44755Sopenharmony_ci component_path_dict = dict() 155bae44755Sopenharmony_ci for product_name, component_name_list in product_define_dict.items(): 156bae44755Sopenharmony_ci component_paths = dict() 157bae44755Sopenharmony_ci for component_name in component_name_list.keys(): 158bae44755Sopenharmony_ci component_relpath = parts_path_info.get(component_name) 159bae44755Sopenharmony_ci if component_relpath: 160bae44755Sopenharmony_ci component_path = os.path.join(project_path, component_relpath) 161bae44755Sopenharmony_ci component_path = format_component_path(component_path) 162bae44755Sopenharmony_ci component_paths[component_name] = component_path 163bae44755Sopenharmony_ci else: 164bae44755Sopenharmony_ci logging.error(f'can\'t find component_name : {component_name}') 165bae44755Sopenharmony_ci component_path_dict.update({product_name: component_paths}) 166bae44755Sopenharmony_ci return component_path_dict 167bae44755Sopenharmony_ci 168bae44755Sopenharmony_ci 169bae44755Sopenharmony_cidef collect_all_product_component_syscap_dict(parts_path_info: dict, project_path: str, product_define_dict): 170bae44755Sopenharmony_ci """ 171bae44755Sopenharmony_ci get all syscap to dict 172bae44755Sopenharmony_ci :param parts_path_info: 173bae44755Sopenharmony_ci :param project_path: 174bae44755Sopenharmony_ci :param product_define_dict: 175bae44755Sopenharmony_ci :return: 176bae44755Sopenharmony_ci """ 177bae44755Sopenharmony_ci if parts_path_info: 178bae44755Sopenharmony_ci print("start collect component path...") 179bae44755Sopenharmony_ci component_path_dict = traversal_path(parts_path_info, project_path, product_define_dict) 180bae44755Sopenharmony_ci syscap_dict, errors_list = handle_bundle_json_file(component_path_dict, product_define_dict) 181bae44755Sopenharmony_ci return syscap_dict, errors_list 182bae44755Sopenharmony_ci else: 183bae44755Sopenharmony_ci return 0, 0 184bae44755Sopenharmony_ci 185bae44755Sopenharmony_ci 186bae44755Sopenharmony_cidef get_subsystem_info(subsystem_config_file, source_root_dir): 187bae44755Sopenharmony_ci """ 188bae44755Sopenharmony_ci get subsystem name and subsystem path from oh/build/subsystem_config.json 189bae44755Sopenharmony_ci :param subsystem_config_file: subsystem_config_file path 190bae44755Sopenharmony_ci :param source_root_dir: oh project path 191bae44755Sopenharmony_ci :return: subsystem name and subsystem path 192bae44755Sopenharmony_ci """ 193bae44755Sopenharmony_ci subsystem_configs = scan(subsystem_config_file, source_root_dir) 194bae44755Sopenharmony_ci _all_components_path = [] 195bae44755Sopenharmony_ci for _, value in subsystem_configs.get('subsystem').items(): 196bae44755Sopenharmony_ci for i in value.get('build_files'): 197bae44755Sopenharmony_ci _all_components_path.append(i) 198bae44755Sopenharmony_ci return subsystem_configs.get('subsystem') 199bae44755Sopenharmony_ci 200bae44755Sopenharmony_ci 201bae44755Sopenharmony_cidef _check_path_prefix(paths): 202bae44755Sopenharmony_ci allow_path_prefix = ['vendor', 'device'] 203bae44755Sopenharmony_ci result = list( 204bae44755Sopenharmony_ci filter(lambda x: x is False, 205bae44755Sopenharmony_ci map(lambda p: p.split('/')[0] in allow_path_prefix, paths))) 206bae44755Sopenharmony_ci return len(result) <= 1 207bae44755Sopenharmony_ci 208bae44755Sopenharmony_ci 209bae44755Sopenharmony_cidef traversal_files(subsystem_path, _files): 210bae44755Sopenharmony_ci for item in os.scandir(subsystem_path): 211bae44755Sopenharmony_ci if is_symlink(item.path): 212bae44755Sopenharmony_ci continue 213bae44755Sopenharmony_ci elif item.is_file() and item.name == 'ohos.build': 214bae44755Sopenharmony_ci _files.append(item.path) 215bae44755Sopenharmony_ci elif item.is_file() and item.name == 'bundle.json': 216bae44755Sopenharmony_ci _files.append(item.path) 217bae44755Sopenharmony_ci elif item.is_dir(): 218bae44755Sopenharmony_ci traversal_files(item, _files) 219bae44755Sopenharmony_ci return _files 220bae44755Sopenharmony_ci 221bae44755Sopenharmony_ci 222bae44755Sopenharmony_cidef get_file_type(file_path): 223bae44755Sopenharmony_ci if os.path.islink(file_path): 224bae44755Sopenharmony_ci return 'symlink' 225bae44755Sopenharmony_ci elif os.path.isfile(file_path): 226bae44755Sopenharmony_ci return 'file' 227bae44755Sopenharmony_ci elif os.path.isdir(file_path): 228bae44755Sopenharmony_ci return 'directory' 229bae44755Sopenharmony_ci else: 230bae44755Sopenharmony_ci return 'unknown' 231bae44755Sopenharmony_ci 232bae44755Sopenharmony_ci 233bae44755Sopenharmony_cidef is_symlink(file_path): 234bae44755Sopenharmony_ci file_type = get_file_type(file_path) 235bae44755Sopenharmony_ci if file_type == 'symlink': 236bae44755Sopenharmony_ci link_target = os.readlink(file_path) 237bae44755Sopenharmony_ci return link_target != file_type 238bae44755Sopenharmony_ci return False 239bae44755Sopenharmony_ci 240bae44755Sopenharmony_ci 241bae44755Sopenharmony_cidef _scan_build_file(subsystem_path): 242bae44755Sopenharmony_ci _files = [] 243bae44755Sopenharmony_ci _bundle_files = [] 244bae44755Sopenharmony_ci try: 245bae44755Sopenharmony_ci _files = traversal_files(subsystem_path, _files) 246bae44755Sopenharmony_ci except FileNotFoundError: 247bae44755Sopenharmony_ci print(f"read file {subsystem_path} failed.") 248bae44755Sopenharmony_ci return _files 249bae44755Sopenharmony_ci 250bae44755Sopenharmony_ci 251bae44755Sopenharmony_cidef scan(subsystem_config_file, source_root_dir): 252bae44755Sopenharmony_ci subsystem_infos = _read_config(subsystem_config_file) 253bae44755Sopenharmony_ci _default_subsystem = {"build": "build"} 254bae44755Sopenharmony_ci subsystem_infos.update(_default_subsystem) 255bae44755Sopenharmony_ci no_src_subsystem = {} 256bae44755Sopenharmony_ci _build_configs = {} 257bae44755Sopenharmony_ci for key, val in subsystem_infos.items(): 258bae44755Sopenharmony_ci _all_build_config_files = [] 259bae44755Sopenharmony_ci if not isinstance(val, list): 260bae44755Sopenharmony_ci val = [val] 261bae44755Sopenharmony_ci else: 262bae44755Sopenharmony_ci if not _check_path_prefix(val): 263bae44755Sopenharmony_ci raise Exception("subsystem '{}' path configuration is incorrect.".format(key), "2013") 264bae44755Sopenharmony_ci _info = {'path': val} 265bae44755Sopenharmony_ci for _path in val: 266bae44755Sopenharmony_ci _subsystem_path = os.path.join(source_root_dir, _path) 267bae44755Sopenharmony_ci _build_config_files = _scan_build_file(_subsystem_path) 268bae44755Sopenharmony_ci _all_build_config_files.extend(_build_config_files) 269bae44755Sopenharmony_ci if _all_build_config_files: 270bae44755Sopenharmony_ci _info['build_files'] = _all_build_config_files 271bae44755Sopenharmony_ci _build_configs[key] = _info 272bae44755Sopenharmony_ci else: 273bae44755Sopenharmony_ci no_src_subsystem[key] = val 274bae44755Sopenharmony_ci 275bae44755Sopenharmony_ci scan_result = { 276bae44755Sopenharmony_ci 'source_path': source_root_dir, 277bae44755Sopenharmony_ci 'subsystem': _build_configs, 278bae44755Sopenharmony_ci } 279bae44755Sopenharmony_ci print('subsystem config scan completed') 280bae44755Sopenharmony_ci return scan_result 281bae44755Sopenharmony_ci 282bae44755Sopenharmony_ci 283bae44755Sopenharmony_cidef _read_config(subsystem_config_file): 284bae44755Sopenharmony_ci if not os.path.exists(subsystem_config_file): 285bae44755Sopenharmony_ci raise Exception("config file '{}' doesn't exist.".format(subsystem_config_file), "2013") 286bae44755Sopenharmony_ci subsystem_config = _read_json_file(subsystem_config_file) 287bae44755Sopenharmony_ci if subsystem_config is None: 288bae44755Sopenharmony_ci raise Exception("read file '{}' failed.".format(subsystem_config_file), "2013") 289bae44755Sopenharmony_ci 290bae44755Sopenharmony_ci subsystem_info = {} 291bae44755Sopenharmony_ci for key, val in subsystem_config.items(): 292bae44755Sopenharmony_ci if 'path' not in val: 293bae44755Sopenharmony_ci raise Exception("subsystem '{}' not config path.".format(key), "2013") 294bae44755Sopenharmony_ci subsystem_info[key] = val.get('path') 295bae44755Sopenharmony_ci return subsystem_info 296bae44755Sopenharmony_ci 297bae44755Sopenharmony_ci 298bae44755Sopenharmony_cidef read_build_file(ohos_build_file): 299bae44755Sopenharmony_ci if not os.path.exists(ohos_build_file): 300bae44755Sopenharmony_ci raise Exception("config file '{}' doesn't exist.".format(ohos_build_file), "2014") 301bae44755Sopenharmony_ci subsystem_config = _read_json_file(ohos_build_file) 302bae44755Sopenharmony_ci if not subsystem_config: 303bae44755Sopenharmony_ci raise Exception("read file '{}' failed.".format(ohos_build_file), "2014") 304bae44755Sopenharmony_ci return subsystem_config 305bae44755Sopenharmony_ci 306bae44755Sopenharmony_ci 307bae44755Sopenharmony_ciclass BundlePartObj(object): 308bae44755Sopenharmony_ci def __init__(self, bundle_config_file): 309bae44755Sopenharmony_ci self._build_config_file = bundle_config_file 310bae44755Sopenharmony_ci self._loading_config() 311bae44755Sopenharmony_ci 312bae44755Sopenharmony_ci def to_ohos_build(self): 313bae44755Sopenharmony_ci _component_info = self.bundle_info.get('component') 314bae44755Sopenharmony_ci _subsystem_name = _component_info.get('subsystem') 315bae44755Sopenharmony_ci _part_name = _component_info.get('name') 316bae44755Sopenharmony_ci _bundle_build = _component_info.get('build') 317bae44755Sopenharmony_ci _ohos_build_info = dict() 318bae44755Sopenharmony_ci _ohos_build_info['subsystem'] = _subsystem_name 319bae44755Sopenharmony_ci _part_info = {} 320bae44755Sopenharmony_ci module_list = [] 321bae44755Sopenharmony_ci if _component_info.get('build').__contains__('sub_component'): 322bae44755Sopenharmony_ci _part_info['module_list'] = _component_info.get('build').get( 323bae44755Sopenharmony_ci 'sub_component') 324bae44755Sopenharmony_ci elif _component_info.get('build').__contains__('modules'): 325bae44755Sopenharmony_ci _part_info['module_list'] = _component_info.get( 326bae44755Sopenharmony_ci 'build').get('modules') 327bae44755Sopenharmony_ci elif _component_info.get('build').__contains__('group_type'): 328bae44755Sopenharmony_ci _module_groups = _component_info.get('build').get('group_type') 329bae44755Sopenharmony_ci for _group_type, _module_list in _module_groups.items(): 330bae44755Sopenharmony_ci _key = '{}:{}'.format(_subsystem_name, _part_name) 331bae44755Sopenharmony_ci _part_info['module_list'] = module_list 332bae44755Sopenharmony_ci if 'inner_kits' in _bundle_build: 333bae44755Sopenharmony_ci _part_info['inner_kits'] = _bundle_build.get('inner_kits') 334bae44755Sopenharmony_ci elif 'inner_api' in _bundle_build: 335bae44755Sopenharmony_ci _part_info['inner_kits'] = _bundle_build.get('inner_api') 336bae44755Sopenharmony_ci if 'features' in _component_info: 337bae44755Sopenharmony_ci _part_info['feature_list'] = _component_info.get('features') 338bae44755Sopenharmony_ci if 'syscap' in _component_info: 339bae44755Sopenharmony_ci _part_info['system_capabilities'] = _component_info.get('syscap') 340bae44755Sopenharmony_ci if 'hisysevent_config' in _component_info: 341bae44755Sopenharmony_ci _part_info['hisysevent_config'] = _component_info.get( 342bae44755Sopenharmony_ci 'hisysevent_config') 343bae44755Sopenharmony_ci _part_info['part_deps'] = _component_info.get('deps', {}) 344bae44755Sopenharmony_ci _part_info['part_deps']['build_config_file'] = self._build_config_file 345bae44755Sopenharmony_ci _ohos_build_info['parts'] = {_part_name: _part_info} 346bae44755Sopenharmony_ci return _ohos_build_info 347bae44755Sopenharmony_ci 348bae44755Sopenharmony_ci def _loading_config(self): 349bae44755Sopenharmony_ci if not os.path.exists(self._build_config_file): 350bae44755Sopenharmony_ci raise Exception("file '{}' doesn't exist.".format( 351bae44755Sopenharmony_ci self._build_config_file), "2011") 352bae44755Sopenharmony_ci self.bundle_info = _read_json_file(self._build_config_file) 353bae44755Sopenharmony_ci if not self.bundle_info: 354bae44755Sopenharmony_ci raise Exception("read file '{}' failed.".format( 355bae44755Sopenharmony_ci self._build_config_file), "2011") 356bae44755Sopenharmony_ci 357bae44755Sopenharmony_ci 358bae44755Sopenharmony_ciclass LoadBuildConfig(object): 359bae44755Sopenharmony_ci """load build config file and parse configuration info.""" 360bae44755Sopenharmony_ci 361bae44755Sopenharmony_ci def __init__(self, source_root_dir, subsystem_build_info, subsystem_name): 362bae44755Sopenharmony_ci self._source_root_dir = source_root_dir 363bae44755Sopenharmony_ci self._build_info = subsystem_build_info 364bae44755Sopenharmony_ci self._is_load = False 365bae44755Sopenharmony_ci self._parts_variants = {} 366bae44755Sopenharmony_ci self._part_list = {} 367bae44755Sopenharmony_ci self._part_targets_label = {} 368bae44755Sopenharmony_ci self._subsystem_name = subsystem_name 369bae44755Sopenharmony_ci self._parts_info_dict = {} 370bae44755Sopenharmony_ci self._phony_targets = {} 371bae44755Sopenharmony_ci self._parts_path_dict = {} 372bae44755Sopenharmony_ci self._part_hisysevent_config = {} 373bae44755Sopenharmony_ci self._parts_module_list = {} 374bae44755Sopenharmony_ci self._parts_deps = {} 375bae44755Sopenharmony_ci 376bae44755Sopenharmony_ci def parse(self): 377bae44755Sopenharmony_ci """parse part info from build config file.""" 378bae44755Sopenharmony_ci if self._is_load: 379bae44755Sopenharmony_ci return 380bae44755Sopenharmony_ci subsystem_config, parts_path_dict = self._merge_build_config() 381bae44755Sopenharmony_ci parts_config = subsystem_config.get('parts') 382bae44755Sopenharmony_ci self._parts_module_list.update(parts_config) 383bae44755Sopenharmony_ci self._parts_path_dict = parts_path_dict 384bae44755Sopenharmony_ci self._is_load = True 385bae44755Sopenharmony_ci 386bae44755Sopenharmony_ci def parts_path_info(self): 387bae44755Sopenharmony_ci """parts to path info.""" 388bae44755Sopenharmony_ci self.parse() 389bae44755Sopenharmony_ci return self._parts_path_dict 390bae44755Sopenharmony_ci 391bae44755Sopenharmony_ci def parts_info_filter(self, save_part): 392bae44755Sopenharmony_ci if save_part is None: 393bae44755Sopenharmony_ci raise Exception 394bae44755Sopenharmony_ci self._parts_info_dict = { 395bae44755Sopenharmony_ci key: value for key, value in self._parts_info_dict.items() if key in save_part} 396bae44755Sopenharmony_ci 397bae44755Sopenharmony_ci def _merge_build_config(self): 398bae44755Sopenharmony_ci _build_files = self._build_info.get('build_files') 399bae44755Sopenharmony_ci is_thirdparty_subsystem = False 400bae44755Sopenharmony_ci if _build_files[0].startswith(self._source_root_dir + 'third_party'): 401bae44755Sopenharmony_ci is_thirdparty_subsystem = True 402bae44755Sopenharmony_ci subsystem_name = None 403bae44755Sopenharmony_ci parts_info = {} 404bae44755Sopenharmony_ci parts_path_dict = {} 405bae44755Sopenharmony_ci for _build_file in _build_files: 406bae44755Sopenharmony_ci if _build_file.endswith('bundle.json'): 407bae44755Sopenharmony_ci bundle_part_obj = BundlePartObj(_build_file) 408bae44755Sopenharmony_ci _parts_config = bundle_part_obj.to_ohos_build() 409bae44755Sopenharmony_ci else: 410bae44755Sopenharmony_ci _parts_config = read_build_file(_build_file) 411bae44755Sopenharmony_ci _subsystem_name = _parts_config.get('subsystem') 412bae44755Sopenharmony_ci if not is_thirdparty_subsystem and subsystem_name and _subsystem_name != subsystem_name: 413bae44755Sopenharmony_ci raise Exception( 414bae44755Sopenharmony_ci "subsystem name config incorrect in '{}'.".format( 415bae44755Sopenharmony_ci _build_file), "2014") 416bae44755Sopenharmony_ci subsystem_name = _subsystem_name 417bae44755Sopenharmony_ci _curr_parts_info = _parts_config.get('parts') 418bae44755Sopenharmony_ci for _pname in _curr_parts_info.keys(): 419bae44755Sopenharmony_ci parts_path_dict[_pname] = os.path.relpath( 420bae44755Sopenharmony_ci os.path.dirname(_build_file), self._source_root_dir) 421bae44755Sopenharmony_ci parts_info.update(_curr_parts_info) 422bae44755Sopenharmony_ci subsystem_config = dict() 423bae44755Sopenharmony_ci subsystem_config['subsystem'] = subsystem_name 424bae44755Sopenharmony_ci subsystem_config['parts'] = parts_info 425bae44755Sopenharmony_ci return subsystem_config, parts_path_dict 426bae44755Sopenharmony_ci 427bae44755Sopenharmony_ci 428bae44755Sopenharmony_cidef get_parts_info(source_root_dir, subsystem_info, build_xts=False): 429bae44755Sopenharmony_ci """ 430bae44755Sopenharmony_ci get parts path info from subsystem info 431bae44755Sopenharmony_ci :param source_root_dir: oh project path 432bae44755Sopenharmony_ci :param subsystem_info: 433bae44755Sopenharmony_ci :param build_xts: 434bae44755Sopenharmony_ci :return: parts path info 435bae44755Sopenharmony_ci """ 436bae44755Sopenharmony_ci _phony_target = {} 437bae44755Sopenharmony_ci _parts_path_info = {} 438bae44755Sopenharmony_ci _parts_hisysevent_config = {} 439bae44755Sopenharmony_ci _parts_modules_info = {} 440bae44755Sopenharmony_ci _parts_deps = {} 441bae44755Sopenharmony_ci for subsystem_name, build_config_info in subsystem_info.items(): 442bae44755Sopenharmony_ci if not len(build_config_info.get("build_files")): 443bae44755Sopenharmony_ci continue 444bae44755Sopenharmony_ci build_loader = LoadBuildConfig(source_root_dir, build_config_info, subsystem_name) 445bae44755Sopenharmony_ci if subsystem_name == 'xts' and build_xts is False: 446bae44755Sopenharmony_ci xts_device_attest_name = ['device_attest_lite', 'device_attest'] 447bae44755Sopenharmony_ci build_loader.parse() 448bae44755Sopenharmony_ci build_loader.parts_info_filter(xts_device_attest_name) 449bae44755Sopenharmony_ci _parts_path_info.update(build_loader.parts_path_info()) 450bae44755Sopenharmony_ci return _parts_path_info 451bae44755Sopenharmony_ci 452bae44755Sopenharmony_ci 453bae44755Sopenharmony_cidef _read_json_file(input_file): 454bae44755Sopenharmony_ci if not os.path.exists(input_file): 455bae44755Sopenharmony_ci print("file '{}' doesn't exist.".format(input_file)) 456bae44755Sopenharmony_ci return {} 457bae44755Sopenharmony_ci try: 458bae44755Sopenharmony_ci with open(input_file, 'r') as input_f: 459bae44755Sopenharmony_ci data = json.load(input_f) 460bae44755Sopenharmony_ci return data 461bae44755Sopenharmony_ci except json.decoder.JSONDecodeError: 462bae44755Sopenharmony_ci print("The file '{}' format is incorrect.".format(input_file)) 463bae44755Sopenharmony_ci raise 464bae44755Sopenharmony_ci except Exception: 465bae44755Sopenharmony_ci print("read file '{}' failed.".format(input_file)) 466bae44755Sopenharmony_ci raise 467bae44755Sopenharmony_ci 468bae44755Sopenharmony_ci 469bae44755Sopenharmony_cidef get_product_define_path(source_root_dir): 470bae44755Sopenharmony_ci return os.path.join(source_root_dir, 'productdefine', 'common', 'inherit') 471bae44755Sopenharmony_ci 472bae44755Sopenharmony_ci 473bae44755Sopenharmony_cidef components_list_handler(product_file_json): 474bae44755Sopenharmony_ci components_dict = dict() 475bae44755Sopenharmony_ci for subsystems in product_file_json.get('subsystems'): 476bae44755Sopenharmony_ci for components in subsystems.get('components'): 477bae44755Sopenharmony_ci components_dict[components.get('component')] = components.get('syscap') 478bae44755Sopenharmony_ci 479bae44755Sopenharmony_ci return components_dict 480bae44755Sopenharmony_ci 481bae44755Sopenharmony_ci 482bae44755Sopenharmony_cidef product_component_handler(product_file, product_file_path): 483bae44755Sopenharmony_ci all_components_dict = dict() 484bae44755Sopenharmony_ci components_dict = dict() 485bae44755Sopenharmony_ci try: 486bae44755Sopenharmony_ci with open(product_file_path, 'r', encoding='utf-8') as f: 487bae44755Sopenharmony_ci product_file_json = json.load(f) 488bae44755Sopenharmony_ci components_dict = components_list_handler(product_file_json) 489bae44755Sopenharmony_ci except FileNotFoundError: 490bae44755Sopenharmony_ci print(f"read file {product_file_path} failed.") 491bae44755Sopenharmony_ci all_components_dict.update({product_file.split('.')[0]: components_dict}) 492bae44755Sopenharmony_ci return all_components_dict 493bae44755Sopenharmony_ci 494bae44755Sopenharmony_ci 495bae44755Sopenharmony_cidef collect_all_product_component(product_file_dict: dict): 496bae44755Sopenharmony_ci all_components_dict = dict() 497bae44755Sopenharmony_ci for product_file, product_file_path in product_file_dict.items(): 498bae44755Sopenharmony_ci product_components_dict = product_component_handler(product_file, product_file_path) 499bae44755Sopenharmony_ci all_components_dict.update(product_components_dict) 500bae44755Sopenharmony_ci return all_components_dict 501bae44755Sopenharmony_ci 502bae44755Sopenharmony_ci 503bae44755Sopenharmony_cidef get_product_define_dict(source_root_dir): 504bae44755Sopenharmony_ci product_define_path = get_product_define_path(source_root_dir) 505bae44755Sopenharmony_ci product_file_dict = dict() 506bae44755Sopenharmony_ci for file in os.scandir(product_define_path): 507bae44755Sopenharmony_ci if file.name.split('.')[-1] == 'json': 508bae44755Sopenharmony_ci product_file_dict.update({file.name: os.path.join(product_define_path, file.name)}) 509bae44755Sopenharmony_ci product_define_dict = collect_all_product_component(product_file_dict) 510bae44755Sopenharmony_ci return product_define_dict 511bae44755Sopenharmony_ci 512bae44755Sopenharmony_ci 513bae44755Sopenharmony_cidef output_path_handler(project_path): 514bae44755Sopenharmony_ci output_path = os.path.join(project_path, 'interface', 'sdk-js', 'api', 'device-define-common') 515bae44755Sopenharmony_ci folder = os.path.exists(output_path) 516bae44755Sopenharmony_ci # 多线程创建文件夹问题 517bae44755Sopenharmony_ci if not folder: 518bae44755Sopenharmony_ci os.makedirs(output_path, exist_ok=True) 519bae44755Sopenharmony_ci return output_path 520bae44755Sopenharmony_ci 521bae44755Sopenharmony_ci 522bae44755Sopenharmony_cidef project_path_handler(project_path): 523bae44755Sopenharmony_ci if not project_path: 524bae44755Sopenharmony_ci project_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) 525bae44755Sopenharmony_ci return project_path 526bae44755Sopenharmony_ci 527bae44755Sopenharmony_ci 528bae44755Sopenharmony_cidef main(): 529bae44755Sopenharmony_ci logging.basicConfig(level=logging.INFO) 530bae44755Sopenharmony_ci args = get_args() 531bae44755Sopenharmony_ci project_path = args.project_path 532bae44755Sopenharmony_ci project_path = project_path_handler(project_path) 533bae44755Sopenharmony_ci output_path = output_path_handler(project_path) 534bae44755Sopenharmony_ci subsystem_config_file = os.path.join(project_path, 'build', 'subsystem_config.json') 535bae44755Sopenharmony_ci product_define_dict = get_product_define_dict(project_path) 536bae44755Sopenharmony_ci _subsystem_info = get_subsystem_info(subsystem_config_file, project_path) 537bae44755Sopenharmony_ci _parts_path_info = get_parts_info(project_path, _subsystem_info) 538bae44755Sopenharmony_ci syscap_dict, errors_list = collect_all_product_component_syscap_dict(_parts_path_info, project_path, 539bae44755Sopenharmony_ci product_define_dict) 540bae44755Sopenharmony_ci if syscap_dict: 541bae44755Sopenharmony_ci dict_to_json(output_path, syscap_dict) 542bae44755Sopenharmony_ci 543bae44755Sopenharmony_ci 544bae44755Sopenharmony_ciif __name__ == "__main__": 545bae44755Sopenharmony_ci main()