• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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    parser.add_argument(
61        "-out",
62        "--out_dir",
63        default="src",
64        type=str,
65        help="the independent build out storage dir. default src , choices: src src_test or test",
66    )
67    args = parser.parse_args()
68    return args
69
70
71def _get_dependence_json(_path) -> dict:
72    dependences_path = os.path.join(_path, 'dependences.json')
73    _json = utils.get_json(dependences_path)
74    return _json
75
76
77def _get_bundle_path(hpm_cache_path, dependences_json, part_name):
78    bundle_path = (hpm_cache_path +
79                   dependences_json[part_name]['installPath'] + os.sep + 'bundle.json')
80    return bundle_path
81
82
83def _get_src_bundle_path(source_code_path):
84    bundle_paths = list()
85    for root, dirs, files in os.walk(source_code_path):
86        for file in files:
87            if file == "bundle.json":
88                bundle_paths.append(os.path.join(root, file))
89    return bundle_paths
90
91
92def _symlink_src2dest(src_dir, dest_dir):
93    if os.path.exists(dest_dir) and os.path.islink(dest_dir):
94        os.unlink(dest_dir)
95    if os.path.exists(dest_dir) and dest_dir != src_dir:
96        if os.path.isdir(dest_dir):
97            shutil.rmtree(dest_dir)
98        else:
99            os.remove(dest_dir)
100    os.symlink(src_dir, dest_dir)
101
102
103def _symlink_binarys(hpm_cache_path, bundle_json, dependences_json, part_name):
104    path = bundle_json["segment"]["destPath"]
105    link_path = os.path.join("binarys", path)
106    if not os.path.isdir(link_path):
107        try:
108            os.remove(link_path)
109        except FileNotFoundError:
110            pass
111        os.makedirs(link_path, exist_ok=True)
112    real_path = hpm_cache_path + dependences_json[part_name]['installPath']
113    _symlink_src2dest(real_path, link_path)
114
115
116def _get_target_cpu(code_path, variants):
117    target_cpu_str = ""
118    config_path = os.path.join(code_path, "binarys", "variants", "variants_" + variants, "config", "build_config.json")
119    target_cpu = utils.get_json(config_path).get("target_cpu")
120    if target_cpu == "arm":
121        target_cpu_str = "arm"
122    elif target_cpu == "arm64":
123        target_cpu_str = "aarch64"
124    return target_cpu_str
125
126
127def _link_kernel_binarys(variants, hpm_cache_path, dependences_json, target_cpu):
128    target_path = target_cpu + "-linux-ohos"
129    musl_real_path = hpm_cache_path + dependences_json["musl"]['installPath']
130    musl_include_link_path = os.path.join("out", variants, "obj/binarys/third_party/musl/usr/include", target_path)
131    musl_lib_link_path = os.path.join("out", variants, "obj/binarys/third_party/musl/usr/lib", target_path)
132    os.makedirs(musl_include_link_path, exist_ok=True)
133    os.makedirs(musl_lib_link_path, exist_ok=True)
134
135    _symlink_src2dest(os.path.join(musl_real_path, 'innerapis', 'includes'), musl_include_link_path)
136    _symlink_src2dest(os.path.join(musl_real_path, 'innerapis', 'libs'), musl_lib_link_path)
137
138    kernel_real_path = hpm_cache_path + dependences_json["linux"]['installPath']
139    kernel_link_path = os.path.join("kernel", "linux")
140    if not os.path.exists(kernel_link_path):
141        os.makedirs(kernel_link_path)
142        _symlink_src2dest(os.path.join(kernel_real_path, "innerapis"), kernel_link_path)
143
144
145def is_directory_empty(path):
146    return len([f for f in os.listdir(path) if os.path.isdir(os.path.join(path, f))]) == 0
147
148
149def _copy_test_binarys(test_check, variants, hpm_cache_path, dependences_json):
150    if test_check != 0:
151        googletest_real_path = hpm_cache_path + dependences_json["googletest"]['installPath']
152        googletest_link_path = os.path.join("out", variants, "obj/binarys/third_party/googletest")
153        os.makedirs(googletest_link_path, exist_ok=True)
154        if is_directory_empty(googletest_link_path):
155            shutil.copytree(os.path.join(googletest_real_path, 'innerapis'),
156                            os.path.join(googletest_link_path, 'innerapis'))
157        else:
158            shutil.rmtree(googletest_link_path, True)
159            os.makedirs(googletest_link_path, exist_ok=True)
160            shutil.copytree(os.path.join(googletest_real_path, 'innerapis'),
161                            os.path.join(googletest_link_path, 'innerapis'))
162
163
164def _gen_components_info(components_json, bundle_json, part_name, src_build_name_list, _part_toolchain_map_dict):
165    subsystem = bundle_json["component"]["subsystem"]
166    path = bundle_json["segment"]["destPath"]
167    try:
168        component = bundle_json["component"]["build"]["inner_kits"]
169    except KeyError:
170        if not bundle_json["component"]["build"]:
171            bundle_json["component"]["build"] = {}
172        if "inner_api" not in bundle_json["component"]["build"].keys():
173            bundle_json["component"]["build"]["inner_api"] = []
174        component = bundle_json["component"]["build"]["inner_api"]
175    innerapi_value_list = list()
176    for i in component:
177        innerapi_name = i["name"].split(':')[-1]
178        if part_name == 'musl':
179            innerapi_label = "{}:{}".format(os.path.join("//binarys", path), innerapi_name)
180        elif part_name in src_build_name_list:
181            innerapi_label = i['name']
182        else:
183            innerapi_label = "{}:{}".format(os.path.join("//binarys", path, "innerapis", innerapi_name), innerapi_name)
184        innerapi_value_list.append({"name": innerapi_name, "label": innerapi_label})
185        if innerapi_name in _part_toolchain_map_dict.keys() and part_name not in src_build_name_list:
186            _name = innerapi_name
187            innerapi_name = f"{innerapi_name}({_part_toolchain_map_dict[_name]['toolchain_value']})"
188            innerapi_label = "{}:{}".format(os.path.join("//binarys", path, "innerapis",
189                                          _name,
190                                          _part_toolchain_map_dict[_name]['toolchain_key']), innerapi_name)
191            innerapi_value_list.append({"name": innerapi_name, "label": innerapi_label})
192    if part_name == 'cjson':
193        part_name = 'cJSON'
194    if part_name == 'freebsd':
195        part_name = 'FreeBSD'
196    spe_component_names = ['astc_encoder', 'llvm_project', 'alsa_lib', 'alsa_utils', 'abseil_cpp', 'cups_filters',
197                           'libnfc_nci', 'vulkan_loader', 'libjpeg_turbo', 'opencl_headers', 'f2fs_tools', 'noto_cjk',
198                           'fsverity_utils', 'vk_gl_cts',
199                           'spirv_tools', 'spirv_headers', 'vulkan_headers', 'u_boot', 'weex_loader', 'ntfs_3g',
200                           'css_what']
201    if part_name in spe_component_names:
202        part_name = part_name.replace('_', '-')
203    one_component_dict = {part_name: {
204        "innerapis": innerapi_value_list,
205        "path": path,
206        "subsystem": subsystem
207    }}
208    components_json.update(one_component_dict)
209
210    return components_json
211
212
213def _get_src_part_name(src_bundle_paths):
214    _name = ''
215    _path = ''
216    for src_bundle_path in src_bundle_paths:
217        src_bundle_json = utils.get_json(src_bundle_path)
218        part_name = ""
219        try:
220            part_name = src_bundle_json['component']['name']
221        except KeyError:
222            print(f'--get bundle json component name error--')
223        if part_name.endswith('_lite'):
224            pass
225        else:
226            _name = part_name
227            _path = src_bundle_path
228    return [_name, _path]
229
230
231def _binarys_permissions_handler():
232    binarys_path = "binarys"
233    cmd = ["chmod", "755", "-R", binarys_path]
234    subprocess.Popen(cmd)
235
236
237def _components_info_handler(part_name_list, source_code_path: str, hpm_cache_path, root_path, dependences_json,
238                             _part_toolchain_map_dict):
239    source_code_path_list = source_code_path.split(",")
240    components_json = dict()
241    src_build_name_list = ['build_framework']
242
243    # 获取源代码路径和组件名称的映射
244    src_bundle_path_dict = {
245        _get_src_part_name(_get_src_bundle_path(src_path))[0]: _get_src_part_name(_get_src_bundle_path(src_path))[1]
246        for src_path in source_code_path_list
247    }
248    # 更新构建名称列表并生成组件信息
249    src_build_name_list.extend(src_bundle_path_dict.keys())
250    for src_part_name, src_bundle_path in src_bundle_path_dict.items():
251        components_json = _gen_components_info(components_json, utils.get_json(src_bundle_path), src_part_name,
252                                               src_build_name_list, _part_toolchain_map_dict)
253
254    # 处理构建框架
255    build_framework_bundle_path = os.path.join(root_path, "build", "bundle.json")
256    components_json = _gen_components_info(components_json, utils.get_json(build_framework_bundle_path),
257                                           "build_framework", src_build_name_list, _part_toolchain_map_dict)
258
259    # 处理其他组件
260    for part_name in part_name_list:
261        if part_name and part_name not in src_bundle_path_dict:
262            bundle_path = _get_bundle_path(hpm_cache_path, dependences_json, part_name)
263            bundle_json = utils.get_json(bundle_path)
264            _symlink_binarys(hpm_cache_path, bundle_json, dependences_json, part_name)
265            if part_name == 'developer_test':
266                continue
267            components_json = _gen_components_info(components_json, bundle_json, part_name, src_build_name_list,
268                                                   _part_toolchain_map_dict)
269
270    return components_json
271
272
273def _out_components_json(components_json, output_path):
274    file_name = os.path.join(output_path, "components.json")
275    flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
276    modes = stat.S_IWUSR | stat.S_IRUSR
277    with os.fdopen(os.open(file_name, flags, modes), 'w') as f:
278        json.dump(components_json, f, indent=4)
279
280
281def _generate_platforms_list(output_path):
282    platforms_list_gni_file = os.path.join(output_path, "platforms_list.gni")
283    platforms_list = ['phone']
284    platforms_list_strings = ' "," '.join(platforms_list)
285    gni_file_content = [f'target_platform_list = [ "{platforms_list_strings}" ]',
286                        f'kits_platform_list  = [ "{platforms_list_strings}" ]']
287    flags = os.O_WRONLY | os.O_CREAT
288    modes = stat.S_IWUSR | stat.S_IRUSR
289    with os.fdopen(os.open(platforms_list_gni_file, flags, modes), 'w') as f:
290        f.write('\n'.join(gni_file_content))
291
292
293def _get_toolchain_json(_path):
294    toolchain_json = os.path.join(_path, 'build', 'indep_configs', 'variants', 'common', 'toolchain.json')
295    _json = utils.get_json(toolchain_json)
296    return _json
297
298
299def _get_all_have_toolchain_component(toolchain_json, hpm_cache_path):
300    _toolchain_list = toolchain_json.keys()
301    binarys_path = os.path.join(hpm_cache_path, 'binarys')
302    _part_toolchain_map_dict = dict()
303    for toolchain in _toolchain_list:
304        for root, dirs, files in os.walk(binarys_path, topdown=False, followlinks=True):
305            if toolchain in dirs:
306                _part_name = os.path.basename(root)
307                _part_toolchain_map_dict.update({
308                    _part_name: {
309                        'toolchain_key': toolchain,
310                        'toolchain_value': toolchain_json[toolchain]
311                    }
312                })
313    return _part_toolchain_map_dict
314
315
316def main():
317    args = _get_args()
318    source_code_path = args.source_code_path
319    hpm_cache_path = args.hpmcache_path
320    variants = args.variants
321    root_path = args.root_path
322    test_check = args.test
323    out_dir = args.out_dir
324    project_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
325    output_part_path = os.path.join(project_path, 'out', variants, out_dir, 'build_configs', 'parts_info')
326    output_config_path = os.path.join(project_path, 'out', variants, out_dir, 'build_configs')
327    dependences_json = _get_dependence_json(hpm_cache_path)
328    toolchain_json = _get_toolchain_json(root_path)
329    part_name_list = dependences_json.keys()
330
331    _part_toolchain_map_dict = _get_all_have_toolchain_component(toolchain_json, hpm_cache_path)
332    components_json = _components_info_handler(part_name_list, source_code_path,
333                                               hpm_cache_path, root_path, dependences_json, _part_toolchain_map_dict)
334    _binarys_permissions_handler()
335    _out_components_json(components_json, output_part_path)
336    _generate_platforms_list(output_config_path)
337    _link_kernel_binarys(variants + os.sep + out_dir, hpm_cache_path, dependences_json, _get_target_cpu(root_path, variants))
338    _copy_test_binarys(test_check, variants + os.sep + out_dir, hpm_cache_path, dependences_json)
339
340
341if __name__ == '__main__':
342    main()
343