15f9996aaSopenharmony_ci#!/usr/bin/env python
25f9996aaSopenharmony_ci# -*- coding: utf-8 -*-
35f9996aaSopenharmony_ci# Copyright (c) 2024 Huawei Device Co., Ltd.
45f9996aaSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
55f9996aaSopenharmony_ci# you may not use this file except in compliance with the License.
65f9996aaSopenharmony_ci# You may obtain a copy of the License at
75f9996aaSopenharmony_ci#
85f9996aaSopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
95f9996aaSopenharmony_ci#
105f9996aaSopenharmony_ci# Unless required by applicable law or agreed to in writing, software
115f9996aaSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
125f9996aaSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135f9996aaSopenharmony_ci# See the License for the specific language governing permissions and
145f9996aaSopenharmony_ci# limitations under the License.
155f9996aaSopenharmony_ci
165f9996aaSopenharmony_ciimport argparse
175f9996aaSopenharmony_ciimport json
185f9996aaSopenharmony_ciimport os
195f9996aaSopenharmony_ciimport shutil
205f9996aaSopenharmony_ciimport stat
215f9996aaSopenharmony_ciimport utils
225f9996aaSopenharmony_ciimport subprocess
235f9996aaSopenharmony_ci
245f9996aaSopenharmony_ci
255f9996aaSopenharmony_cidef _get_args():
265f9996aaSopenharmony_ci    parser = argparse.ArgumentParser(add_help=True)
275f9996aaSopenharmony_ci    parser.add_argument(
285f9996aaSopenharmony_ci        "-sp",
295f9996aaSopenharmony_ci        "--source_code_path",
305f9996aaSopenharmony_ci        default=r".",
315f9996aaSopenharmony_ci        type=str,
325f9996aaSopenharmony_ci        help="Path of source code",
335f9996aaSopenharmony_ci    )
345f9996aaSopenharmony_ci    parser.add_argument(
355f9996aaSopenharmony_ci        "-hp",
365f9996aaSopenharmony_ci        "--hpmcache_path",
375f9996aaSopenharmony_ci        default=r".",
385f9996aaSopenharmony_ci        type=str,
395f9996aaSopenharmony_ci        help="Path of .hpmcache",
405f9996aaSopenharmony_ci    )
415f9996aaSopenharmony_ci    parser.add_argument(
425f9996aaSopenharmony_ci        "-v",
435f9996aaSopenharmony_ci        "--variants",
445f9996aaSopenharmony_ci        default=r".",
455f9996aaSopenharmony_ci        type=str,
465f9996aaSopenharmony_ci        help="variants of build target",
475f9996aaSopenharmony_ci    )
485f9996aaSopenharmony_ci    parser.add_argument(
495f9996aaSopenharmony_ci        "-rp",
505f9996aaSopenharmony_ci        "--root_path",
515f9996aaSopenharmony_ci        default=r".",
525f9996aaSopenharmony_ci        type=str,
535f9996aaSopenharmony_ci        help="Path of root",
545f9996aaSopenharmony_ci    )
555f9996aaSopenharmony_ci    parser.add_argument(
565f9996aaSopenharmony_ci        "-t", "--test",
575f9996aaSopenharmony_ci        default=1, type=int,
585f9996aaSopenharmony_ci        help="whether the target contains test type. default 0 , choices: 0 or 1 2",
595f9996aaSopenharmony_ci    )
605f9996aaSopenharmony_ci    args = parser.parse_args()
615f9996aaSopenharmony_ci    return args
625f9996aaSopenharmony_ci
635f9996aaSopenharmony_ci
645f9996aaSopenharmony_cidef _get_dependence_json(_path) -> dict:
655f9996aaSopenharmony_ci    dependences_path = os.path.join(_path, 'dependences.json')
665f9996aaSopenharmony_ci    _json = utils.get_json(dependences_path)
675f9996aaSopenharmony_ci    return _json
685f9996aaSopenharmony_ci
695f9996aaSopenharmony_ci
705f9996aaSopenharmony_cidef _get_bundle_path(hpm_cache_path, dependences_json, part_name):
715f9996aaSopenharmony_ci    bundle_path = (hpm_cache_path +
725f9996aaSopenharmony_ci                   dependences_json[part_name]['installPath'] + os.sep + 'bundle.json')
735f9996aaSopenharmony_ci    return bundle_path
745f9996aaSopenharmony_ci
755f9996aaSopenharmony_ci
765f9996aaSopenharmony_cidef _get_src_bundle_path(source_code_path):
775f9996aaSopenharmony_ci    bundle_paths = list()
785f9996aaSopenharmony_ci    for root, dirs, files in os.walk(source_code_path):
795f9996aaSopenharmony_ci        for file in files:
805f9996aaSopenharmony_ci            if file.endswith("bundle.json"):
815f9996aaSopenharmony_ci                bundle_paths.append(os.path.join(root, file))
825f9996aaSopenharmony_ci    return bundle_paths
835f9996aaSopenharmony_ci
845f9996aaSopenharmony_ci
855f9996aaSopenharmony_cidef _symlink_src2dest(src_dir, dest_dir):
865f9996aaSopenharmony_ci    if os.path.exists(dest_dir) and os.path.islink(dest_dir):
875f9996aaSopenharmony_ci        os.unlink(dest_dir)
885f9996aaSopenharmony_ci    if os.path.exists(dest_dir) and dest_dir != src_dir:
895f9996aaSopenharmony_ci        if os.path.isdir(dest_dir):
905f9996aaSopenharmony_ci            shutil.rmtree(dest_dir)
915f9996aaSopenharmony_ci        else:
925f9996aaSopenharmony_ci            os.remove(dest_dir)
935f9996aaSopenharmony_ci    os.symlink(src_dir, dest_dir)
945f9996aaSopenharmony_ci
955f9996aaSopenharmony_ci
965f9996aaSopenharmony_cidef _symlink_binarys(hpm_cache_path, bundle_json, dependences_json, part_name):
975f9996aaSopenharmony_ci    path = bundle_json["segment"]["destPath"]
985f9996aaSopenharmony_ci    link_path = os.path.join("binarys", path)
995f9996aaSopenharmony_ci    if not os.path.isdir(link_path):
1005f9996aaSopenharmony_ci        try:
1015f9996aaSopenharmony_ci            os.remove(link_path)
1025f9996aaSopenharmony_ci        except FileNotFoundError:
1035f9996aaSopenharmony_ci            pass
1045f9996aaSopenharmony_ci        os.makedirs(link_path, exist_ok=True)
1055f9996aaSopenharmony_ci    real_path = hpm_cache_path + dependences_json[part_name]['installPath']
1065f9996aaSopenharmony_ci    _symlink_src2dest(real_path, link_path)
1075f9996aaSopenharmony_ci
1085f9996aaSopenharmony_ci
1095f9996aaSopenharmony_cidef _get_target_cpu(code_path, variants):
1105f9996aaSopenharmony_ci    target_cpu_str = ""
1115f9996aaSopenharmony_ci    config_path = os.path.join(code_path, "binarys", "variants", "variants_" + variants, "config", "build_config.json")
1125f9996aaSopenharmony_ci    target_cpu = utils.get_json(config_path).get("target_cpu")
1135f9996aaSopenharmony_ci    if target_cpu == "arm":
1145f9996aaSopenharmony_ci        target_cpu_str = "arm"
1155f9996aaSopenharmony_ci    elif target_cpu == "arm64":
1165f9996aaSopenharmony_ci        target_cpu_str = "aarch64"
1175f9996aaSopenharmony_ci    return target_cpu_str
1185f9996aaSopenharmony_ci
1195f9996aaSopenharmony_ci
1205f9996aaSopenharmony_cidef _link_kernel_binarys(variants, hpm_cache_path, dependences_json, target_cpu):
1215f9996aaSopenharmony_ci    target_path = target_cpu + "-linux-ohos"
1225f9996aaSopenharmony_ci    musl_real_path = hpm_cache_path + dependences_json["musl"]['installPath']
1235f9996aaSopenharmony_ci    musl_include_link_path = os.path.join("out", variants, "obj/binarys/third_party/musl/usr/include", target_path)
1245f9996aaSopenharmony_ci    musl_lib_link_path = os.path.join("out", variants, "obj/binarys/third_party/musl/usr/lib", target_path)
1255f9996aaSopenharmony_ci    os.makedirs(musl_include_link_path, exist_ok=True)
1265f9996aaSopenharmony_ci    os.makedirs(musl_lib_link_path, exist_ok=True)
1275f9996aaSopenharmony_ci    _symlink_src2dest(os.path.join(musl_real_path, 'innerapis', 'includes'), musl_include_link_path)
1285f9996aaSopenharmony_ci    _symlink_src2dest(os.path.join(musl_real_path, 'innerapis', 'libs'), musl_lib_link_path)
1295f9996aaSopenharmony_ci
1305f9996aaSopenharmony_ci    kernel_real_path = hpm_cache_path + dependences_json["linux"]['installPath']
1315f9996aaSopenharmony_ci    kernel_link_path = os.path.join("kernel", "linux")
1325f9996aaSopenharmony_ci    if not os.path.isdir(kernel_link_path):
1335f9996aaSopenharmony_ci        try:
1345f9996aaSopenharmony_ci            os.remove(kernel_link_path)
1355f9996aaSopenharmony_ci        except FileNotFoundError:
1365f9996aaSopenharmony_ci            pass
1375f9996aaSopenharmony_ci        os.makedirs(kernel_link_path, exist_ok=True)
1385f9996aaSopenharmony_ci    os.makedirs(kernel_link_path, exist_ok=True)
1395f9996aaSopenharmony_ci    _symlink_src2dest(os.path.join(kernel_real_path, "innerapis"), kernel_link_path)
1405f9996aaSopenharmony_ci
1415f9996aaSopenharmony_ci
1425f9996aaSopenharmony_cidef _copy_test_binarys(test_check, variants, hpm_cache_path, dependences_json):
1435f9996aaSopenharmony_ci    if test_check != 0:
1445f9996aaSopenharmony_ci        googletest_real_path = hpm_cache_path + dependences_json["googletest"]['installPath']
1455f9996aaSopenharmony_ci        googletest_link_path = os.path.join("out", variants, "obj/binarys/third_party/googletest")
1465f9996aaSopenharmony_ci        os.makedirs(googletest_link_path, exist_ok=True)
1475f9996aaSopenharmony_ci        shutil.copytree(os.path.join(googletest_real_path, 'innerapis'),
1485f9996aaSopenharmony_ci            os.path.join(googletest_link_path, 'innerapis'))
1495f9996aaSopenharmony_ci
1505f9996aaSopenharmony_ci
1515f9996aaSopenharmony_cidef _gen_components_info(components_json, bundle_json, part_name, src_build_name_list, _part_toolchain_map_dict):
1525f9996aaSopenharmony_ci    subsystem = bundle_json["component"]["subsystem"]
1535f9996aaSopenharmony_ci    path = bundle_json["segment"]["destPath"]
1545f9996aaSopenharmony_ci    try:
1555f9996aaSopenharmony_ci        component = bundle_json["component"]["build"]["inner_kits"]
1565f9996aaSopenharmony_ci    except KeyError:
1575f9996aaSopenharmony_ci        if not bundle_json["component"]["build"]:
1585f9996aaSopenharmony_ci            bundle_json["component"]["build"] = {}
1595f9996aaSopenharmony_ci        if "inner_api" not in bundle_json["component"]["build"].keys():
1605f9996aaSopenharmony_ci            bundle_json["component"]["build"]["inner_api"] = []
1615f9996aaSopenharmony_ci        component = bundle_json["component"]["build"]["inner_api"]
1625f9996aaSopenharmony_ci    innerapi_value_list = list()
1635f9996aaSopenharmony_ci    for i in component:
1645f9996aaSopenharmony_ci        innerapi_name = i["name"].split(':')[-1]
1655f9996aaSopenharmony_ci        if part_name == 'musl':
1665f9996aaSopenharmony_ci            innerapi_label = "{}:{}".format(os.path.join("//binarys", path), innerapi_name)
1675f9996aaSopenharmony_ci        elif part_name in src_build_name_list:
1685f9996aaSopenharmony_ci            innerapi_label = i['name']
1695f9996aaSopenharmony_ci        else:
1705f9996aaSopenharmony_ci            innerapi_label = "{}:{}".format(os.path.join("//binarys", path, "innerapis", innerapi_name), innerapi_name)
1715f9996aaSopenharmony_ci        innerapi_value_list.append({"name": innerapi_name, "label": innerapi_label})
1725f9996aaSopenharmony_ci        if innerapi_name in _part_toolchain_map_dict.keys():
1735f9996aaSopenharmony_ci            _name = innerapi_name
1745f9996aaSopenharmony_ci            innerapi_name = f"{innerapi_name}({_part_toolchain_map_dict[_name]['toolchain_value']})"
1755f9996aaSopenharmony_ci            innerapi_label = "{}:{}".format(os.path.join("//binarys", path, "innerapis",
1765f9996aaSopenharmony_ci                                                         _name,
1775f9996aaSopenharmony_ci                                                         _part_toolchain_map_dict[_name]['toolchain_key']),
1785f9996aaSopenharmony_ci                                            innerapi_name)
1795f9996aaSopenharmony_ci            innerapi_value_list.append({"name": innerapi_name, "label": innerapi_label})
1805f9996aaSopenharmony_ci    if part_name == 'cjson':
1815f9996aaSopenharmony_ci        part_name = 'cJSON'
1825f9996aaSopenharmony_ci    if part_name == 'freebsd':
1835f9996aaSopenharmony_ci        part_name = 'FreeBSD'
1845f9996aaSopenharmony_ci    spe_component_names = ['astc_encoder', 'llvm_project', 'alsa_lib', 'alsa_utils', 'abseil_cpp', 'cups_filters',
1855f9996aaSopenharmony_ci                           'libnfc_nci', 'vulkan_loader', 'libjpeg_turbo', 'opencl_headers', 'f2fs_tools', 'noto_cjk',
1865f9996aaSopenharmony_ci                           'fsverity_utils', 'vk_gl_cts',
1875f9996aaSopenharmony_ci                           'spirv_tools', 'spirv_headers', 'vulkan_headers', 'u_boot', 'weex_loader', 'ntfs_3g',
1885f9996aaSopenharmony_ci                           'css_what']
1895f9996aaSopenharmony_ci    if part_name in spe_component_names:
1905f9996aaSopenharmony_ci        part_name = part_name.replace('_', '-')
1915f9996aaSopenharmony_ci    one_component_dict = {part_name: {
1925f9996aaSopenharmony_ci        "innerapis": innerapi_value_list,
1935f9996aaSopenharmony_ci        "path": path,
1945f9996aaSopenharmony_ci        "subsystem": subsystem
1955f9996aaSopenharmony_ci    }}
1965f9996aaSopenharmony_ci    components_json.update(one_component_dict)
1975f9996aaSopenharmony_ci
1985f9996aaSopenharmony_ci    return components_json
1995f9996aaSopenharmony_ci
2005f9996aaSopenharmony_ci
2015f9996aaSopenharmony_cidef _get_src_part_name(src_bundle_paths):
2025f9996aaSopenharmony_ci    _name = ''
2035f9996aaSopenharmony_ci    _path = ''
2045f9996aaSopenharmony_ci    for src_bundle_path in src_bundle_paths:
2055f9996aaSopenharmony_ci        src_bundle_json = utils.get_json(src_bundle_path)
2065f9996aaSopenharmony_ci        part_name = ""
2075f9996aaSopenharmony_ci        try:
2085f9996aaSopenharmony_ci            part_name = src_bundle_json['component']['name']
2095f9996aaSopenharmony_ci        except KeyError:
2105f9996aaSopenharmony_ci            print(f'--get bundle json component name error--')
2115f9996aaSopenharmony_ci        if part_name.endswith('_lite'):
2125f9996aaSopenharmony_ci            pass
2135f9996aaSopenharmony_ci        else:
2145f9996aaSopenharmony_ci            _name = part_name
2155f9996aaSopenharmony_ci            _path = src_bundle_path
2165f9996aaSopenharmony_ci    return _name, _path
2175f9996aaSopenharmony_ci
2185f9996aaSopenharmony_ci
2195f9996aaSopenharmony_cidef _binarys_permissions_handler():
2205f9996aaSopenharmony_ci    binarys_path = "binarys"
2215f9996aaSopenharmony_ci    cmd = ["chmod", "755", "-R", binarys_path]
2225f9996aaSopenharmony_ci    subprocess.Popen(cmd)
2235f9996aaSopenharmony_ci
2245f9996aaSopenharmony_ci
2255f9996aaSopenharmony_cidef _components_info_handler(part_name_list, source_code_path, hpm_cache_path, root_path, dependences_json,
2265f9996aaSopenharmony_ci                             _part_toolchain_map_dict):
2275f9996aaSopenharmony_ci    components_json = dict()
2285f9996aaSopenharmony_ci    src_bundle_paths = _get_src_bundle_path(source_code_path)
2295f9996aaSopenharmony_ci    src_part_name, src_bundle_path = _get_src_part_name(src_bundle_paths)
2305f9996aaSopenharmony_ci    src_build_name_list = [src_part_name, 'build_framework']
2315f9996aaSopenharmony_ci    components_json = _gen_components_info(components_json, utils.get_json(src_bundle_path), src_part_name,
2325f9996aaSopenharmony_ci                                           src_build_name_list, _part_toolchain_map_dict)
2335f9996aaSopenharmony_ci    components_json = _gen_components_info(components_json,
2345f9996aaSopenharmony_ci                                           utils.get_json(os.path.join(root_path, "build", "bundle.json")),
2355f9996aaSopenharmony_ci                                           "build_framework", src_build_name_list, _part_toolchain_map_dict)
2365f9996aaSopenharmony_ci    for part_name in part_name_list:
2375f9996aaSopenharmony_ci        if part_name and part_name != src_part_name:
2385f9996aaSopenharmony_ci            bundle_path = _get_bundle_path(hpm_cache_path, dependences_json, part_name)
2395f9996aaSopenharmony_ci            bundle_json = utils.get_json(bundle_path)
2405f9996aaSopenharmony_ci            components_json = _gen_components_info(components_json, bundle_json, part_name, src_build_name_list,
2415f9996aaSopenharmony_ci                                                   _part_toolchain_map_dict)
2425f9996aaSopenharmony_ci            _symlink_binarys(hpm_cache_path, bundle_json, dependences_json, part_name)
2435f9996aaSopenharmony_ci
2445f9996aaSopenharmony_ci    return components_json
2455f9996aaSopenharmony_ci
2465f9996aaSopenharmony_ci
2475f9996aaSopenharmony_cidef _out_components_json(components_json, output_path):
2485f9996aaSopenharmony_ci    file_name = os.path.join(output_path, "components.json")
2495f9996aaSopenharmony_ci    flags = os.O_WRONLY | os.O_CREAT
2505f9996aaSopenharmony_ci    modes = stat.S_IWUSR | stat.S_IRUSR
2515f9996aaSopenharmony_ci    with os.fdopen(os.open(file_name, flags, modes), 'w') as f:
2525f9996aaSopenharmony_ci        json.dump(components_json, f, indent=4)
2535f9996aaSopenharmony_ci
2545f9996aaSopenharmony_ci
2555f9996aaSopenharmony_cidef _generate_platforms_list(output_path):
2565f9996aaSopenharmony_ci    platforms_list_gni_file = os.path.join(output_path, "platforms_list.gni")
2575f9996aaSopenharmony_ci    platforms_list = ['phone']
2585f9996aaSopenharmony_ci    platforms_list_strings = ' "," '.join(platforms_list)
2595f9996aaSopenharmony_ci    gni_file_content = [f'target_platform_list = [ "{platforms_list_strings}" ]',
2605f9996aaSopenharmony_ci                        f'kits_platform_list  = [ "{platforms_list_strings}" ]']
2615f9996aaSopenharmony_ci    flags = os.O_WRONLY | os.O_CREAT
2625f9996aaSopenharmony_ci    modes = stat.S_IWUSR | stat.S_IRUSR
2635f9996aaSopenharmony_ci    with os.fdopen(os.open(platforms_list_gni_file, flags, modes), 'w') as f:
2645f9996aaSopenharmony_ci        f.write('\n'.join(gni_file_content))
2655f9996aaSopenharmony_ci
2665f9996aaSopenharmony_ci
2675f9996aaSopenharmony_cidef _get_toolchain_json(_path):
2685f9996aaSopenharmony_ci    toolchain_json = os.path.join(_path, 'build', 'indep_configs', 'variants', 'common', 'toolchain.json')
2695f9996aaSopenharmony_ci    _json = utils.get_json(toolchain_json)
2705f9996aaSopenharmony_ci    return _json
2715f9996aaSopenharmony_ci
2725f9996aaSopenharmony_ci
2735f9996aaSopenharmony_cidef _get_all_have_toolchain_component(toolchain_json, hpm_cache_path):
2745f9996aaSopenharmony_ci    _toolchain_list = toolchain_json.keys()
2755f9996aaSopenharmony_ci    binarys_path = os.path.join(hpm_cache_path, 'binarys')
2765f9996aaSopenharmony_ci    _part_toolchain_map_dict = dict()
2775f9996aaSopenharmony_ci    for toolchain in _toolchain_list:
2785f9996aaSopenharmony_ci        for root, dirs, files in os.walk(binarys_path, topdown=False, followlinks=True):
2795f9996aaSopenharmony_ci            if toolchain in dirs:
2805f9996aaSopenharmony_ci                _part_name = root.split(os.sep)[-1]
2815f9996aaSopenharmony_ci                _part_toolchain_map_dict.update({
2825f9996aaSopenharmony_ci                    _part_name: {
2835f9996aaSopenharmony_ci                        'toolchain_key': toolchain,
2845f9996aaSopenharmony_ci                        'toolchain_value': toolchain_json[toolchain]
2855f9996aaSopenharmony_ci                    }
2865f9996aaSopenharmony_ci                })
2875f9996aaSopenharmony_ci    return _part_toolchain_map_dict
2885f9996aaSopenharmony_ci
2895f9996aaSopenharmony_ci
2905f9996aaSopenharmony_cidef main():
2915f9996aaSopenharmony_ci    args = _get_args()
2925f9996aaSopenharmony_ci    source_code_path = args.source_code_path
2935f9996aaSopenharmony_ci    hpm_cache_path = args.hpmcache_path
2945f9996aaSopenharmony_ci    variants = args.variants
2955f9996aaSopenharmony_ci    root_path = args.root_path
2965f9996aaSopenharmony_ci    test_check = args.test
2975f9996aaSopenharmony_ci    project_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
2985f9996aaSopenharmony_ci    output_part_path = os.path.join(project_path, 'out', variants, 'build_configs', 'parts_info')
2995f9996aaSopenharmony_ci    output_config_path = os.path.join(project_path, 'out', variants, 'build_configs')
3005f9996aaSopenharmony_ci    dependences_json = _get_dependence_json(hpm_cache_path)
3015f9996aaSopenharmony_ci    toolchain_json = _get_toolchain_json(root_path)
3025f9996aaSopenharmony_ci    part_name_list = dependences_json.keys()
3035f9996aaSopenharmony_ci
3045f9996aaSopenharmony_ci    _part_toolchain_map_dict = _get_all_have_toolchain_component(toolchain_json, hpm_cache_path)
3055f9996aaSopenharmony_ci    components_json = _components_info_handler(part_name_list, source_code_path,
3065f9996aaSopenharmony_ci                                               hpm_cache_path, root_path, dependences_json, _part_toolchain_map_dict)
3075f9996aaSopenharmony_ci    _binarys_permissions_handler()
3085f9996aaSopenharmony_ci    _out_components_json(components_json, output_part_path)
3095f9996aaSopenharmony_ci    _generate_platforms_list(output_config_path)
3105f9996aaSopenharmony_ci    _link_kernel_binarys(variants, hpm_cache_path, dependences_json, _get_target_cpu(root_path, variants))
3115f9996aaSopenharmony_ci    _copy_test_binarys(test_check, variants, hpm_cache_path, dependences_json)
3125f9996aaSopenharmony_ci
3135f9996aaSopenharmony_ci
3145f9996aaSopenharmony_ciif __name__ == '__main__':
3155f9996aaSopenharmony_ci    main()
316