• 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
16
17import sys
18import os
19import argparse
20import shutil
21import json
22import time
23from hb.util.log_util import LogUtil
24import re
25
26
27def _get_public_external_deps(data, public_deps):
28    if not isinstance(data, dict):
29        return ""
30    for key, value in data.items():
31        if not isinstance(value, dict):
32            continue
33
34        for key_1, value_1 in value.items():
35            label = value_1.get("label")
36            if public_deps == label:
37                return key + ":" + key_1
38
39    return ""
40
41
42def _is_innerkit(data, part, module):
43    if not isinstance(data, dict):
44        return False
45
46    part_data = data.get(part)
47    if not isinstance(part_data, dict):
48        return False
49
50    if module in part_data:
51        return True
52
53    return False
54
55
56def _get_inner_kits_info(out_path):
57    jsondata = ""
58    json_path = os.path.join(
59        out_path + "/build_configs/parts_info/inner_kits_info.json"
60    )
61    with open(json_path, "r") as f:
62        try:
63            jsondata = json.load(f)
64        except Exception as e:
65            print("--_get_inner_kits_info parse json error--", e)
66    return jsondata
67
68
69def _get_module_name(json_data):
70    part_data = json_data.get(part_name)
71    if isinstance(data_list, list) and len(json_data.get(json_key)) >= 1:
72        desc_list.extend(data_list)
73    else:
74        desc_list.append(json_data.get(json_key))
75
76
77def _handle_one_layer_json(json_key, json_data, desc_list):
78    data_list = json_data.get(json_key)
79    if isinstance(data_list, list) and len(json_data.get(json_key)) >= 1:
80        desc_list.extend(data_list)
81    else:
82        desc_list.append(json_data.get(json_key))
83
84
85def _handle_two_layer_json(json_key, json_data, desc_list):
86    value_depth = len(json_data.get(json_key))
87    for i in range(value_depth):
88        _include_dirs = json_data.get(json_key)[i].get("include_dirs")
89        if _include_dirs:
90            desc_list.extend(_include_dirs)
91
92
93def _get_json_data(args, module):
94    json_path = os.path.join(
95        args.get("out_path"),
96        args.get("subsystem_name"),
97        args.get("part_name"),
98        "publicinfo",
99        module + ".json",
100    )
101    with open(json_path, "r") as f:
102        try:
103            jsondata = json.load(f)
104        except Exception as e:
105            print("--_get_json_data parse json error--", e)
106    return jsondata
107
108
109def _handle_deps_data(json_data):
110    dep_list = []
111    if json_data.get("public_deps"):
112        _handle_one_layer_json("public_deps", json_data, dep_list)
113    return dep_list
114
115
116def _handle_includes_data(json_data):
117    include_list = []
118    if json_data.get("public_configs"):
119        _handle_two_layer_json("public_configs", json_data, include_list)
120    if json_data.get("all_dependent_configs"):
121        _handle_two_layer_json("all_dependent_configs", json_data, include_list)
122    return include_list
123
124
125def _get_static_lib_path(args, json_data):
126    label = json_data.get("label")
127    split_label = label.split("//")[1].split(":")[0]
128    real_static_lib_path = os.path.join(
129        args.get("out_path"), "obj", split_label, json_data.get("out_name")
130    )
131    return real_static_lib_path
132
133
134def _copy_dir(src_path, target_path):
135    if not os.path.isdir(src_path):
136        return False
137    filelist_src = os.listdir(src_path)
138    for file in filelist_src:
139        path = os.path.join(os.path.abspath(src_path), file)
140        if os.path.isdir(path):
141            if file.startswith("."):
142                continue
143            path1 = os.path.join(target_path, file)
144            _copy_dir(path, path1)
145        else:
146            if not path.endswith(".h"):
147                continue
148            with open(path, "rb") as read_stream:
149                contents = read_stream.read()
150            if not os.path.exists(target_path):
151                os.makedirs(target_path)
152            path1 = os.path.join(target_path, file)
153            with os.fdopen(
154                os.open(path1, os.O_WRONLY | os.O_CREAT, mode=0o640), "wb"
155            ) as write_stream:
156                write_stream.write(contents)
157    return True
158
159
160def _copy_includes(args, module, includes: list):
161    includes_out_dir = os.path.join(
162        args.get("out_path"),
163        "component_package",
164        args.get("part_path"),
165        "innerapis",
166        module,
167        "includes",
168    )
169    if not os.path.exists(includes_out_dir):
170        os.makedirs(includes_out_dir)
171    for include in includes:
172        splitInclude = include.split("//")[1]
173        realIncludePath = os.path.join(args.get("root_path"), splitInclude)
174        _copy_dir(realIncludePath, includes_out_dir)
175    print("_copy_includes has done ")
176
177
178def _copy_lib(args, json_data, module):
179    so_path = ""
180    if json_data.get("type") == "static_library":
181        so_path = _get_static_lib_path(args, json_data)
182    else:
183        so_path = os.path.join(
184            args.get("out_path"),
185            args.get("subsystem_name"),
186            args.get("part_name"),
187            json_data.get("out_name"),
188        )
189    if os.path.isfile(so_path):
190        lib_out_dir = os.path.join(
191            args.get("out_path"),
192            "component_package",
193            args.get("part_path"),
194            "innerapis",
195            module,
196            "libs",
197        )
198        if not os.path.exists(lib_out_dir):
199            os.makedirs(lib_out_dir)
200        shutil.copy(so_path, lib_out_dir)
201        return True
202    else:
203        return False
204
205
206def _copy_bundlejson(args):
207    bundlejson_out = os.path.join(
208        args.get("out_path"), "component_package", args.get("part_path")
209    )
210    print("bundlejson_out : ", bundlejson_out)
211    if not os.path.exists(bundlejson_out):
212        os.makedirs(bundlejson_out)
213    bundlejson = os.path.join(
214        args.get("root_path"), args.get("part_path"), "bundle.json"
215    )
216    if os.path.isfile(bundlejson):
217        with open(bundlejson, "r") as f:
218            bundle_data = json.load(f)
219        bundle_data["publishAs"] = "binary"
220        bundle_data["os"] = "linux"
221        bundle_data["buildArch"] = "x86"
222        dirs = dict()
223        dirs["./"] = []
224        directory = bundlejson_out
225        for filename in os.listdir(directory):
226            filepath = os.path.join(directory, filename)
227            if os.path.isfile(filepath):
228                dirs["./"].append(filename)
229            else:
230                dirs[filename] = [filename + "/*"]
231        delete_list = [
232            "LICENSE",
233            "README.md",
234            "README_zh.md",
235            "README_en.md",
236            "bundle.json",
237        ]
238        for delete_txt in delete_list:
239            if delete_txt in dirs["./"]:
240                dirs["./"].remove(delete_txt)
241        if dirs["./"] == []:
242            del dirs["./"]
243        bundle_data["dirs"] = dirs
244        bundle_data["version"] = str(bundle_data["version"])
245        if bundle_data["version"] == "":
246            bundle_data["version"] = "1.0.0"
247        pattern = r"^(\d+)\.(\d+)(-[a-zA-Z]+)?$"  # 正则表达式匹配a.b[-后缀]格式的字符串
248        match = re.match(pattern, bundle_data["version"])
249        if match:
250            a = match.group(1)
251            b = match.group(2)
252            suffix = match.group(3) if match.group(3) else ""
253            bundle_data["version"] = f"{a}.{b}.0{suffix}"
254        with os.fdopen(
255            os.open(
256                os.path.join(bundlejson_out, "bundle.json"),
257                os.O_WRONLY | os.O_CREAT,
258                mode=0o640,
259            ),
260            "w",
261            encoding="utf-8",
262        ) as fd:
263            json.dump(bundle_data, fd, indent=4, ensure_ascii=False)
264
265
266def _copy_license(args):
267    license_out = os.path.join(
268        args.get("out_path"), "component_package", args.get("part_path")
269    )
270    print("license_out : ", license_out)
271    if not os.path.exists(license_out):
272        os.makedirs(license_out)
273    license = os.path.join(args.get("root_path"), args.get("part_path"), "LICENSE")
274    if os.path.isfile(license):
275        shutil.copy(license, license_out)
276
277
278def _copy_readme(args):
279    readme_out = os.path.join(
280        args.get("out_path"), "component_package", args.get("part_path")
281    )
282    print("readme_out : ", readme_out)
283    if not os.path.exists(readme_out):
284        os.makedirs(readme_out)
285    readme = os.path.join(args.get("root_path"), args.get("part_path"), "README.md")
286    if os.path.isfile(readme):
287        shutil.copy(readme, readme_out)
288    readme_zh = os.path.join(
289        args.get("root_path"), args.get("part_path"), "README_zh.md"
290    )
291    if os.path.isfile(readme_zh):
292        shutil.copy(readme_zh, readme_out)
293    readme_en = os.path.join(
294        args.get("root_path"), args.get("part_path"), "README_en.md"
295    )
296    if os.path.isfile(readme_en):
297        shutil.copy(readme_en, readme_out)
298
299
300def _generate_import(fp):
301    fp.write('import("//build/ohos.gni")\n')
302
303
304def _generate_configs(fp, module):
305    fp.write('\nconfig("' + module + '_configs") {\n')
306    fp.write('  visibility = [ ":*" ]\n')
307    fp.write("  include_dirs = [\n")
308    fp.write('    "includes"\n')
309    fp.write("  ]\n}\n")
310
311
312def _generate_prebuilt_shared_library(fp, type, module):
313    if type == "static_library":
314        fp.write('ohos_prebuilt_static_library("' + module + '") {\n')
315    else:
316        fp.write('ohos_prebuilt_shared_library("' + module + '") {\n')
317
318
319def _generate_public_configs(fp, module):
320    fp.write('  public_configs = [":' + module + '_configs"]\n')
321
322
323def _generate_public_deps(fp, deps: list, innerkit_json):
324    if not deps:
325        return
326    fp.write("  public_external_deps = [\n")
327    for dep in deps:
328        public_external_deps = _get_public_external_deps(innerkit_json, dep)
329        if len(public_external_deps) > 0:
330            fp.write('    "' + public_external_deps + '",\n')
331    fp.write("  ]\n")
332
333
334def _generate_other(fp, args, json_data, module):
335    so_name = json_data.get("out_name")
336    fp.write('  source = "libs/' + so_name + '"\n')
337    fp.write('  part_name = "' + args.get("part_name") + '"\n')
338    fp.write('  subsystem_name = "' + args.get("subsystem_name") + '"\n')
339
340
341def _generate_end(fp):
342    fp.write("}")
343
344
345def _generate_build_gn(args, module, json_data, deps: list, innerkit_json):
346    gn_path = os.path.join(
347        args.get("out_path"),
348        "component_package",
349        args.get("part_path"),
350        "innerapis",
351        module,
352        "BUILD.gn",
353    )
354    fd = os.open(gn_path, os.O_WRONLY | os.O_CREAT, mode=0o640)
355    fp = os.fdopen(fd, "w")
356    _generate_import(fp)
357    _generate_configs(fp, module)
358    _generate_prebuilt_shared_library(fp, json_data.get("type"), module)
359    _generate_public_configs(fp, module)
360    _generate_public_deps(fp, deps, innerkit_json)
361    _generate_other(fp, args, json_data, module)
362    _generate_end(fp)
363    print("_generate_build_gn has done ")
364    fp.close()
365
366
367def _parse_module_list(args):
368    module_list = []
369    publicinfoPath = os.path.join(
370        args.get("out_path"),
371        args.get("subsystem_name"),
372        args.get("part_name"),
373        "publicinfo",
374    )
375    print("publicinfoPath", publicinfoPath)
376    if os.path.exists(publicinfoPath) is False:
377        return module_list
378    publicinfoDir = os.listdir(publicinfoPath)
379    for filename in publicinfoDir:
380        if filename.endswith(".json"):
381            module_name = filename.split(".json")[0]
382            module_list.append(module_name)
383            print("filename", filename)
384    print("module_list", module_list)
385    return module_list
386
387
388def _generate_component_package(args, innerkit_json):
389    modules = _parse_module_list(args)
390    if len(modules) == 0:
391        return
392    is_component_build = False
393    for module in modules:
394        if _is_innerkit(innerkit_json, args.get("part_name"), module) == False:
395            continue
396        json_data = _get_json_data(args, module)
397        lib_exists = _copy_lib(args, json_data, module)
398        if lib_exists is False:
399            continue
400        is_component_build = True
401        includes = _handle_includes_data(json_data)
402        deps = _handle_deps_data(json_data)
403        _copy_includes(args, module, includes)
404        _generate_build_gn(args, module, json_data, deps, innerkit_json)
405    if is_component_build:
406        _copy_bundlejson(args)
407        _copy_license(args)
408        _copy_readme(args)
409
410
411def _get_part_subsystem(out_path):
412    jsondata = ""
413    json_path = os.path.join(out_path + "/build_configs/parts_info/part_subsystem.json")
414    with open(json_path, "r") as f:
415        try:
416            jsondata = json.load(f)
417        except Exception as e:
418            print("--_get_part_subsystem parse json error--", e)
419    return jsondata
420
421
422def _get_parts_path_info(out_path):
423    jsondata = ""
424    json_path = os.path.join(
425        out_path + "/build_configs/parts_info/parts_path_info.json"
426    )
427    with open(json_path, "r") as f:
428        try:
429            jsondata = json.load(f)
430        except Exception as e:
431            print("--_get_parts_path_info parse json error--", e)
432    return jsondata
433
434
435def _get_parts_path(json_data, part_name):
436    parts_path = None
437    if json_data.get(part_name) is not None:
438        parts_path = json_data[part_name]
439    return parts_path
440
441
442def generate_component_package(out_path, root_path):
443    start_time = time.time()
444    part_subsystem = _get_part_subsystem(out_path)
445    parts_path_info = _get_parts_path_info(out_path)
446    inner_kits_info = _get_inner_kits_info(out_path)
447    for key, value in part_subsystem.items():
448        part_name = key
449        subsystem_name = value
450        part_path = _get_parts_path(parts_path_info, part_name)
451        if part_path is None:
452            continue
453        args = {
454            "subsystem_name": subsystem_name,
455            "part_name": part_name,
456            "out_path": out_path,
457            "root_path": root_path,
458            "part_path": part_path,
459        }
460        _generate_component_package(args, inner_kits_info)
461    end_time = time.time()
462    run_time = end_time - start_time
463    print("generate_component_package out_path", out_path)
464    print(f"生成二进制产物包耗时:{run_time}秒")
465