1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# Copyright (c) 2024 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 argparse 17import json 18import os 19import shutil 20import stat 21import utils 22import subprocess 23 24 25def _get_args(): 26 parser = argparse.ArgumentParser(add_help=True) 27 parser.add_argument( 28 "-sp", 29 "--source_code_path", 30 default=r".", 31 type=str, 32 help="Path of source code", 33 ) 34 parser.add_argument( 35 "-hp", 36 "--hpmcache_path", 37 default=r".", 38 type=str, 39 help="Path of .hpmcache", 40 ) 41 parser.add_argument( 42 "-v", 43 "--variants", 44 default=r".", 45 type=str, 46 help="variants of build target", 47 ) 48 parser.add_argument( 49 "-rp", 50 "--root_path", 51 default=r".", 52 type=str, 53 help="Path of root", 54 ) 55 parser.add_argument( 56 "-t", "--test", 57 default=1, type=int, 58 help="whether the target contains test type. default 0 , choices: 0 or 1 2", 59 ) 60 args = parser.parse_args() 61 return args 62 63 64def _get_dependence_json(_path) -> dict: 65 dependences_path = os.path.join(_path, 'dependences.json') 66 _json = utils.get_json(dependences_path) 67 return _json 68 69 70def _get_bundle_path(hpm_cache_path, dependences_json, part_name): 71 bundle_path = (hpm_cache_path + 72 dependences_json[part_name]['installPath'] + os.sep + 'bundle.json') 73 return bundle_path 74 75 76def _get_src_bundle_path(source_code_path): 77 bundle_paths = list() 78 for root, dirs, files in os.walk(source_code_path): 79 for file in files: 80 if file.endswith("bundle.json"): 81 bundle_paths.append(os.path.join(root, file)) 82 return bundle_paths 83 84 85def _symlink_src2dest(src_dir, dest_dir): 86 if os.path.exists(dest_dir) and os.path.islink(dest_dir): 87 os.unlink(dest_dir) 88 if os.path.exists(dest_dir) and dest_dir != src_dir: 89 if os.path.isdir(dest_dir): 90 shutil.rmtree(dest_dir) 91 else: 92 os.remove(dest_dir) 93 os.symlink(src_dir, dest_dir) 94 95 96def _symlink_binarys(hpm_cache_path, bundle_json, dependences_json, part_name): 97 path = bundle_json["segment"]["destPath"] 98 link_path = os.path.join("binarys", path) 99 if not os.path.isdir(link_path): 100 try: 101 os.remove(link_path) 102 except FileNotFoundError: 103 pass 104 os.makedirs(link_path, exist_ok=True) 105 real_path = hpm_cache_path + dependences_json[part_name]['installPath'] 106 _symlink_src2dest(real_path, link_path) 107 108 109def _get_target_cpu(code_path, variants): 110 target_cpu_str = "" 111 config_path = os.path.join(code_path, "binarys", "variants", "variants_" + variants, "config", "build_config.json") 112 target_cpu = utils.get_json(config_path).get("target_cpu") 113 if target_cpu == "arm": 114 target_cpu_str = "arm" 115 elif target_cpu == "arm64": 116 target_cpu_str = "aarch64" 117 return target_cpu_str 118 119 120def _link_kernel_binarys(variants, hpm_cache_path, dependences_json, target_cpu): 121 target_path = target_cpu + "-linux-ohos" 122 musl_real_path = hpm_cache_path + dependences_json["musl"]['installPath'] 123 musl_include_link_path = os.path.join("out", variants, "obj/binarys/third_party/musl/usr/include", target_path) 124 musl_lib_link_path = os.path.join("out", variants, "obj/binarys/third_party/musl/usr/lib", target_path) 125 os.makedirs(musl_include_link_path, exist_ok=True) 126 os.makedirs(musl_lib_link_path, exist_ok=True) 127 _symlink_src2dest(os.path.join(musl_real_path, 'innerapis', 'includes'), musl_include_link_path) 128 _symlink_src2dest(os.path.join(musl_real_path, 'innerapis', 'libs'), musl_lib_link_path) 129 130 kernel_real_path = hpm_cache_path + dependences_json["linux"]['installPath'] 131 kernel_link_path = os.path.join("kernel", "linux") 132 if not os.path.isdir(kernel_link_path): 133 try: 134 os.remove(kernel_link_path) 135 except FileNotFoundError: 136 pass 137 os.makedirs(kernel_link_path, exist_ok=True) 138 os.makedirs(kernel_link_path, exist_ok=True) 139 _symlink_src2dest(os.path.join(kernel_real_path, "innerapis"), kernel_link_path) 140 141 142def _copy_test_binarys(test_check, variants, hpm_cache_path, dependences_json): 143 if test_check != 0: 144 googletest_real_path = hpm_cache_path + dependences_json["googletest"]['installPath'] 145 googletest_link_path = os.path.join("out", variants, "obj/binarys/third_party/googletest") 146 os.makedirs(googletest_link_path, exist_ok=True) 147 shutil.copytree(os.path.join(googletest_real_path, 'innerapis'), 148 os.path.join(googletest_link_path, 'innerapis')) 149 150 151def _gen_components_info(components_json, bundle_json, part_name, src_build_name_list, _part_toolchain_map_dict): 152 subsystem = bundle_json["component"]["subsystem"] 153 path = bundle_json["segment"]["destPath"] 154 try: 155 component = bundle_json["component"]["build"]["inner_kits"] 156 except KeyError: 157 if not bundle_json["component"]["build"]: 158 bundle_json["component"]["build"] = {} 159 if "inner_api" not in bundle_json["component"]["build"].keys(): 160 bundle_json["component"]["build"]["inner_api"] = [] 161 component = bundle_json["component"]["build"]["inner_api"] 162 innerapi_value_list = list() 163 for i in component: 164 innerapi_name = i["name"].split(':')[-1] 165 if part_name == 'musl': 166 innerapi_label = "{}:{}".format(os.path.join("//binarys", path), innerapi_name) 167 elif part_name in src_build_name_list: 168 innerapi_label = i['name'] 169 else: 170 innerapi_label = "{}:{}".format(os.path.join("//binarys", path, "innerapis", innerapi_name), innerapi_name) 171 innerapi_value_list.append({"name": innerapi_name, "label": innerapi_label}) 172 if innerapi_name in _part_toolchain_map_dict.keys(): 173 _name = innerapi_name 174 innerapi_name = f"{innerapi_name}({_part_toolchain_map_dict[_name]['toolchain_value']})" 175 innerapi_label = "{}:{}".format(os.path.join("//binarys", path, "innerapis", 176 _name, 177 _part_toolchain_map_dict[_name]['toolchain_key']), 178 innerapi_name) 179 innerapi_value_list.append({"name": innerapi_name, "label": innerapi_label}) 180 if part_name == 'cjson': 181 part_name = 'cJSON' 182 if part_name == 'freebsd': 183 part_name = 'FreeBSD' 184 spe_component_names = ['astc_encoder', 'llvm_project', 'alsa_lib', 'alsa_utils', 'abseil_cpp', 'cups_filters', 185 'libnfc_nci', 'vulkan_loader', 'libjpeg_turbo', 'opencl_headers', 'f2fs_tools', 'noto_cjk', 186 'fsverity_utils', 'vk_gl_cts', 187 'spirv_tools', 'spirv_headers', 'vulkan_headers', 'u_boot', 'weex_loader', 'ntfs_3g', 188 'css_what'] 189 if part_name in spe_component_names: 190 part_name = part_name.replace('_', '-') 191 one_component_dict = {part_name: { 192 "innerapis": innerapi_value_list, 193 "path": path, 194 "subsystem": subsystem 195 }} 196 components_json.update(one_component_dict) 197 198 return components_json 199 200 201def _get_src_part_name(src_bundle_paths): 202 _name = '' 203 _path = '' 204 for src_bundle_path in src_bundle_paths: 205 src_bundle_json = utils.get_json(src_bundle_path) 206 part_name = "" 207 try: 208 part_name = src_bundle_json['component']['name'] 209 except KeyError: 210 print(f'--get bundle json component name error--') 211 if part_name.endswith('_lite'): 212 pass 213 else: 214 _name = part_name 215 _path = src_bundle_path 216 return _name, _path 217 218 219def _binarys_permissions_handler(): 220 binarys_path = "binarys" 221 cmd = ["chmod", "755", "-R", binarys_path] 222 subprocess.Popen(cmd) 223 224 225def _components_info_handler(part_name_list, source_code_path, hpm_cache_path, root_path, dependences_json, 226 _part_toolchain_map_dict): 227 components_json = dict() 228 src_bundle_paths = _get_src_bundle_path(source_code_path) 229 src_part_name, src_bundle_path = _get_src_part_name(src_bundle_paths) 230 src_build_name_list = [src_part_name, 'build_framework'] 231 components_json = _gen_components_info(components_json, utils.get_json(src_bundle_path), src_part_name, 232 src_build_name_list, _part_toolchain_map_dict) 233 components_json = _gen_components_info(components_json, 234 utils.get_json(os.path.join(root_path, "build", "bundle.json")), 235 "build_framework", src_build_name_list, _part_toolchain_map_dict) 236 for part_name in part_name_list: 237 if part_name and part_name != src_part_name: 238 bundle_path = _get_bundle_path(hpm_cache_path, dependences_json, part_name) 239 bundle_json = utils.get_json(bundle_path) 240 components_json = _gen_components_info(components_json, bundle_json, part_name, src_build_name_list, 241 _part_toolchain_map_dict) 242 _symlink_binarys(hpm_cache_path, bundle_json, dependences_json, part_name) 243 244 return components_json 245 246 247def _out_components_json(components_json, output_path): 248 file_name = os.path.join(output_path, "components.json") 249 flags = os.O_WRONLY | os.O_CREAT 250 modes = stat.S_IWUSR | stat.S_IRUSR 251 with os.fdopen(os.open(file_name, flags, modes), 'w') as f: 252 json.dump(components_json, f, indent=4) 253 254 255def _generate_platforms_list(output_path): 256 platforms_list_gni_file = os.path.join(output_path, "platforms_list.gni") 257 platforms_list = ['phone'] 258 platforms_list_strings = ' "," '.join(platforms_list) 259 gni_file_content = [f'target_platform_list = [ "{platforms_list_strings}" ]', 260 f'kits_platform_list = [ "{platforms_list_strings}" ]'] 261 flags = os.O_WRONLY | os.O_CREAT 262 modes = stat.S_IWUSR | stat.S_IRUSR 263 with os.fdopen(os.open(platforms_list_gni_file, flags, modes), 'w') as f: 264 f.write('\n'.join(gni_file_content)) 265 266 267def _get_toolchain_json(_path): 268 toolchain_json = os.path.join(_path, 'build', 'indep_configs', 'variants', 'common', 'toolchain.json') 269 _json = utils.get_json(toolchain_json) 270 return _json 271 272 273def _get_all_have_toolchain_component(toolchain_json, hpm_cache_path): 274 _toolchain_list = toolchain_json.keys() 275 binarys_path = os.path.join(hpm_cache_path, 'binarys') 276 _part_toolchain_map_dict = dict() 277 for toolchain in _toolchain_list: 278 for root, dirs, files in os.walk(binarys_path, topdown=False, followlinks=True): 279 if toolchain in dirs: 280 _part_name = root.split(os.sep)[-1] 281 _part_toolchain_map_dict.update({ 282 _part_name: { 283 'toolchain_key': toolchain, 284 'toolchain_value': toolchain_json[toolchain] 285 } 286 }) 287 return _part_toolchain_map_dict 288 289 290def main(): 291 args = _get_args() 292 source_code_path = args.source_code_path 293 hpm_cache_path = args.hpmcache_path 294 variants = args.variants 295 root_path = args.root_path 296 test_check = args.test 297 project_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) 298 output_part_path = os.path.join(project_path, 'out', variants, 'build_configs', 'parts_info') 299 output_config_path = os.path.join(project_path, 'out', variants, 'build_configs') 300 dependences_json = _get_dependence_json(hpm_cache_path) 301 toolchain_json = _get_toolchain_json(root_path) 302 part_name_list = dependences_json.keys() 303 304 _part_toolchain_map_dict = _get_all_have_toolchain_component(toolchain_json, hpm_cache_path) 305 components_json = _components_info_handler(part_name_list, source_code_path, 306 hpm_cache_path, root_path, dependences_json, _part_toolchain_map_dict) 307 _binarys_permissions_handler() 308 _out_components_json(components_json, output_part_path) 309 _generate_platforms_list(output_config_path) 310 _link_kernel_binarys(variants, hpm_cache_path, dependences_json, _get_target_cpu(root_path, variants)) 311 _copy_test_binarys(test_check, variants, hpm_cache_path, dependences_json) 312 313 314if __name__ == '__main__': 315 main() 316