• 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.
15import subprocess
16import sys
17import stat
18import os
19import argparse
20import shutil
21import json
22import time
23import re
24import urllib.request
25
26
27def _get_args():
28    parser = argparse.ArgumentParser(add_help=True)
29    parser.add_argument("-op", "--out_path", default=r"./", type=str,
30                        help="path of out.", )
31    parser.add_argument("-rp", "--root_path", default=r"./", type=str,
32                        help="path of root. default: ./", )
33    parser.add_argument("-cl", "--components_list", default="", type=str,
34                        help="components_list , "
35                             "pass in the components' name, separated by commas , "
36                             "example: A,B,C . "
37                             "default: none", )
38    parser.add_argument("-bt", "--build_type", default=0, type=int,
39                        help="build_type ,default: 0", )
40    parser.add_argument("-on", "--organization_name", default='ohos', type=str,
41                        help="organization_name ,default: '' ", )
42    parser.add_argument("-os", "--os_arg", default=r"linux", type=str,
43                        help="path of output file. default: linux", )
44    parser.add_argument("-ba", "--build_arch", default=r"x86", type=str,
45                        help="build_arch_arg. default: x86", )
46    parser.add_argument("-lt", "--local_test", default=0, type=int,
47                        help="local test ,default: not local , 0", )
48    args = parser.parse_args()
49    return args
50
51
52def create_directories(paths):
53    for path in paths:
54        os.makedirs(path, exist_ok=True)
55
56
57def copy_files(src_dst_pairs):
58    for src, dst in src_dst_pairs:
59        shutil.copy2(src, dst)
60
61
62def generate_common_configs():
63    return """import("//build/ohos.gni")
64
65
66config("musl_common_configs") {
67  visibility = [ ":*" ]
68  include_dirs = [
69    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include",
70    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1",
71    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__algorithm",
72    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__bit",
73    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__charconv",
74    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__chrono",
75    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__compare",
76    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__concepts",
77    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__debug_utils",
78    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__concepts",
79    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__filesystem",
80    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__format",
81    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__functional",
82    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__fwd",
83    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__ios",
84    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__iterator",
85    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__memory",
86    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__numeric",
87    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__random",
88    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__ranges",
89    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__string",
90    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__support",
91    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__thread",
92    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__type_traits",
93    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__utility",
94    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/__variant",
95    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/experimental",
96    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/c++/v1/ext",
97    "//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/include/arm-linux-ohos/c++/v1",
98  ]
99
100   cflags_c = [
101      "-Wno-error=bitwise-op-parentheses",
102      "-Wno-error=shift-op-parentheses",
103    ]
104}
105    """
106
107
108def generate_soft_libc_musl_shared_configs():
109    return """
110config("soft_libc_musl_shared_configs") {
111  visibility = [ ":*" ]
112  include_dirs = [
113    "innerapis/includes",
114  ]
115}
116
117ohos_prebuilt_shared_library("soft_libc_musl_shared") {
118  public_configs = [":soft_libc_musl_shared_configs",":musl_common_configs"]
119  public_external_deps = [
120  ]
121  source = "innerapis/libs/libc.so"
122  part_name = "musl"
123  subsystem_name = "thirdparty"
124}
125    """
126
127
128def generate_soft_libcrypt_configs():
129    return """
130config("soft_libcrypt_configs") {
131  visibility = [ ":*" ]
132  include_dirs = [
133    "innerapis/includes",
134  ]
135}
136
137ohos_prebuilt_static_library("soft_libcrypt") {
138  public_configs = [":soft_libcrypt_configs",":musl_common_configs"]
139  public_external_deps = [
140  ]
141  source = "innerapis/libs/libcrypt.a"
142  part_name = "musl"
143  subsystem_name = "thirdparty"
144}
145    """
146
147
148def generate_soft_libdl_configs():
149    return """
150config("soft_libdl_configs") {
151  visibility = [ ":*" ]
152  include_dirs = [
153    "innerapis/includes",
154  ]
155}
156
157ohos_prebuilt_static_library("soft_libdl") {
158  public_configs = [":soft_libdl_configs",":musl_common_configs"]
159  public_external_deps = [
160  ]
161  source = "innerapis/libs/libdl.a"
162  part_name = "musl"
163  subsystem_name = "thirdparty"
164}
165    """
166
167
168def generate_soft_libm_configs():
169    return """
170config("soft_libm_configs") {
171  visibility = [ ":*" ]
172  include_dirs = [
173    "innerapis/includes",
174  ]
175}
176
177ohos_prebuilt_static_library("soft_libm") {
178  public_configs = [":soft_libm_configs",":musl_common_configs"]
179  public_external_deps = [
180  ]
181  source = "innerapis/libs/libm.a"
182  part_name = "musl"
183  subsystem_name = "thirdparty"
184}
185    """
186
187
188def generate_soft_libpthread_configs():
189    return """
190config("soft_libpthread_configs") {
191  visibility = [ ":*" ]
192  include_dirs = [
193    "innerapis/includes",
194  ]
195}
196
197ohos_prebuilt_static_library("soft_libpthread") {
198  public_configs = [":soft_libpthread_configs",":musl_common_configs"]
199  public_external_deps = [
200  ]
201  source = "innerapis/libs/libpthread.a"
202  part_name = "musl"
203  subsystem_name = "thirdparty"
204}
205    """
206
207
208def generate_soft_libresolv_configs():
209    return """
210config("soft_libresolv_configs") {
211  visibility = [ ":*" ]
212  include_dirs = [
213    "innerapis/includes",
214  ]
215}
216
217ohos_prebuilt_static_library("soft_libresolv") {
218  public_configs = [":soft_libresolv_configs",":musl_common_configs"]
219  public_external_deps = [
220  ]
221  source = "innerapis/libs/libresolv.a"
222  part_name = "musl"
223  subsystem_name = "thirdparty"
224}
225    """
226
227
228def generate_soft_librt_configs():
229    return """
230config("soft_librt_configs") {
231  visibility = [ ":*" ]
232  include_dirs = [
233    "innerapis/includes",
234  ]
235}
236
237ohos_prebuilt_static_library("soft_librt") {
238  public_configs = [":soft_librt_configs",":musl_common_configs"]
239  public_external_deps = [
240  ]
241  source = "innerapis/libs/librt.a"
242  part_name = "musl"
243  subsystem_name = "thirdparty"
244}
245    """
246
247
248def generate_soft_libutil_configs():
249    return """
250config("soft_libutil_configs") {
251  visibility = [ ":*" ]
252  include_dirs = [
253    "innerapis/includes",
254  ]
255}
256
257ohos_prebuilt_static_library("soft_libutil") {
258  public_configs = [":soft_libutil_configs",":musl_common_configs"]
259  public_external_deps = [
260  ]
261  source = "innerapis/libs/libutil.a"
262  part_name = "musl"
263  subsystem_name = "thirdparty"
264}
265    """
266
267
268def generate_soft_libxnet_configs():
269    return """
270config("soft_libxnet_configs") {
271  visibility = [ ":*" ]
272  include_dirs = [
273    "innerapis/includes",
274  ]
275}
276
277ohos_prebuilt_static_library("soft_libxnet") {
278  public_configs = [":soft_libxnet_configs",":musl_common_configs"]
279  public_external_deps = [
280  ]
281  source = "innerapis/libs/libxnet.a"
282  part_name = "musl"
283  subsystem_name = "thirdparty"
284}
285    """
286
287
288def generate_group_copy_libs_block():
289    return """
290group("copy_libs") {
291    lib_files = [
292      "libc.a",
293      "libc.so",
294      "libcrypt.a",
295      "libdl.a",
296      "libm.a",
297      "libpthread.a",
298      "libresolv.a",
299      "librt.a",
300      "libutil.a",
301      "libxnet.a",
302      "crtn.o",
303      "crti.o",
304      "crt1.o",
305      "rcrt1.o",
306      "Scrt1.o",
307    ]
308    sources = []
309    outputs = []
310    deps = []
311    foreach(file, lib_files) {
312      copy("copy_${file}") {
313        sources += [ "innerapis/libs/${file}" ]
314        outputs += [ "${target_out_dir}/usr/lib/arm-linux-ohos/${file}" ]
315      }
316      deps += [ ":copy_${file}" ]
317    }
318}
319group("soft_shared_libs") {
320  public_configs = [":musl_common_configs", ":soft_libxnet_configs"]
321  deps = [
322    ":soft_libc_musl_shared",
323    ":soft_libcrypt",
324    ":soft_libdl",
325    ":soft_libm",
326    ":soft_libpthread",
327    ":soft_libresolv",
328    ":soft_librt",
329    ":soft_libutil",
330    ":soft_libxnet",
331  ]
332}
333    """
334
335
336def generate_group_musl_headers_block():
337    return """
338group("musl_headers") {
339  public_configs = [
340    ":musl_common_configs",
341    ":soft_libxnet_configs",
342  ]
343}
344    """
345
346
347def generate_gn_file_content(part_data):
348    gn_content = []
349    gn_content.append(generate_common_configs())
350    gn_content.append(generate_soft_libc_musl_shared_configs())
351    gn_content.append(generate_soft_libcrypt_configs())
352    gn_content.append(generate_soft_libdl_configs())
353    gn_content.append(generate_soft_libm_configs())
354    gn_content.append(generate_soft_libpthread_configs())
355    gn_content.append(generate_soft_libresolv_configs())
356    gn_content.append(generate_soft_librt_configs())
357    gn_content.append(generate_soft_libutil_configs())
358    gn_content.append(generate_soft_libxnet_configs())
359    gn_content.append(generate_group_copy_libs_block())
360    gn_content.append(generate_group_musl_headers_block())
361    return '\n'.join(gn_content)
362
363
364def write_gn_file(gn_path, content):
365    with open(gn_path, 'w') as gn_file:
366        gn_file.write(content)
367
368
369def copy_musl_libs_includes(musl_obj_path, innerapi_target_path):
370    for folder_name in ['include', 'lib']:
371        src_folder_path = os.path.join(musl_obj_path, folder_name, 'arm-linux-ohos')
372        dst_folder_path = os.path.join(innerapi_target_path, folder_name + 's')
373        dst_folder_path_1 = os.path.join(innerapi_target_path, 'musl_headers', folder_name + 's')
374        dst_folder_path_2 = os.path.join(innerapi_target_path, 'soft_libc_musl_static', folder_name + 's')
375        dst_folder_path_3 = os.path.join(innerapi_target_path, 'soft_shared_libs', folder_name + 's')
376        if os.path.exists(src_folder_path):
377            shutil.copytree(src_folder_path, dst_folder_path, dirs_exist_ok=True)
378            shutil.copytree(src_folder_path, dst_folder_path_1, dirs_exist_ok=True)
379            shutil.copytree(src_folder_path, dst_folder_path_2, dirs_exist_ok=True)
380            shutil.copytree(src_folder_path, dst_folder_path_3, dirs_exist_ok=True)
381
382
383def write_musl_bundle(musl_bundle_path):
384    # 向musl的bundle.json文件里写入下面的接口
385    additional_innerkits = [{"name": "//third_party/musl:soft_shared_libs"},
386                            {"name": "//third_party/musl:musl_headers"}]
387    with open(musl_bundle_path, "r") as file:
388        musl_bundle_content = json.load(file)
389    musl_innerkits = musl_bundle_content["component"]["build"]["inner_kits"]
390    musl_innerkits.extend(additional_innerkits)
391    with open(musl_bundle_path, "w", encoding='utf-8') as file:
392        json.dump(musl_bundle_content, file, ensure_ascii=False, indent=2)
393
394
395def process_musl(part_data, parts_path_info, part_name, subsystem_name, components_json):
396    musl_obj_path = os.path.join(part_data.get('out_path'), 'obj', 'third_party', 'musl', 'usr')
397    musl_dst_path = os.path.join(part_data.get('out_path'), 'component_package', 'third_party', 'musl')
398    musl_src_path = os.path.join(part_data.get('root_path'), 'third_party', 'musl')
399    create_directories([musl_dst_path])
400
401    # Copy necessary files to the musl destination path
402    files_to_copy = [
403        'configure',
404        'dynamic.list',
405        'libc.map.txt',
406        'musl_config.gni'
407    ]
408    copy_files([(os.path.join(musl_src_path, file_name), os.path.join(musl_dst_path, file_name)) for file_name in
409                files_to_copy])
410
411    # Generate and write the GN file
412    gn_path = os.path.join(musl_dst_path, 'BUILD.gn')
413    gn_content = generate_gn_file_content(part_data)
414    write_gn_file(gn_path, gn_content)
415    innerapi_target_path = os.path.join(musl_dst_path, 'innerapis')
416    copy_musl_libs_includes(musl_obj_path, innerapi_target_path)
417    modules = _parse_module_list(part_data)
418    print('modules', modules)
419    if len(modules) == 0:
420        return
421    _public_deps_list = []
422    # ... Additional logic for processing modules, copying docs, and finishing the component build ...
423    _copy_required_docs(part_data, _public_deps_list)
424    musl_bundle_path = os.path.join(musl_dst_path, "bundle.json")
425    write_musl_bundle(musl_bundle_path)
426    _finish_component_build(part_data)
427
428
429def _create_bundle_json(bundle_path, bundle_content):
430    bundle = {}
431    with open(bundle_path, "w", encoding="utf-8") as f1:
432        json.dump(bundle_content, f1, indent=2)
433
434
435def _generate_rust_bundle_content():
436    bundle_content = {
437        "name": "@ohos/rust",
438        "description": "third party rust tools, provide multiply functions about compiler",
439        "version": "3.1.0-snapshot",
440        "license": "Apache License 2.0",
441        "publishAs": "binary",
442        "segment": {"destPath": "third_party/rust/crates"},
443        "dirs": {"./": ["*"]},
444        "scripts": {},
445        "component": {
446            "name": "rust",
447            "subsystem": "thirdparty",
448            "syscap": [],
449            "features": [],
450            "adapted_system_type": ["standard"],
451            "rom": "",
452            "ram": "",
453            "hisysevent_config": [],
454            "deps": {
455                "components": [],
456                "third_party": []
457            },
458            "build": {
459                "sub_component": [],
460                "inner_api": [],
461                "test": []
462            }
463        },
464        "os": "linux",
465        "buildArch": "x86"
466    }
467    return bundle_content
468
469
470def process_rust(part_data, parts_path_info, part_name, subsystem_name, components_json):
471    rust_src_path = os.path.join(part_data.get('root_path'), 'third_party', 'rust', 'crates')
472    dst_path = os.path.join(part_data.get("out_path"), "component_package", part_data.get("part_path"))
473    copy_directory_contents(rust_src_path, dst_path)
474
475    gn_path = os.path.join(dst_path, "bundle.json")
476    bundle_content = _generate_rust_bundle_content()
477    _create_bundle_json(gn_path, bundle_content)
478
479    _copy_license(part_data)
480    _copy_readme(part_data)
481
482
483def copy_directory_contents(src_path, dst_path):
484    if not os.path.exists(dst_path):
485        os.makedirs(dst_path)
486    for item in os.listdir(src_path):
487        src = os.path.join(src_path, item)
488        dst = os.path.join(dst_path, item)
489        if os.path.isdir(src):
490            if os.path.exists(dst):
491                shutil.rmtree(dst)
492            shutil.copytree(src, dst)
493        elif os.path.isfile(src):
494            shutil.copy2(src, dst)
495
496
497def generate_developer_test_bundle_base_info():
498    return {
499        "name": "@ohos/developer_test",
500        "description": "developer_test",
501        "version": "3.1.0-snapshot",
502        "license": "Apache License 2.0",
503        "publishAs": "binary",
504        "segment": {"destPath": "test/testfwk/developer_test"},
505        "repository": "",
506        "dirs": {"./": ["*"]},
507        "scripts": {},
508        "os": "linux",
509        "buildArch": "x86"
510    }
511
512
513def generate_developer_test_component_info():
514    return {
515        "name": "developer_test",
516        "subsystem": "testfwk",
517        "syscap": [],
518        "features": [],
519        "adapted_system_type": ["mini", "small", "standard"],
520        "rom": "0KB",
521        "ram": "0KB",
522        "deps": {}
523    }
524
525
526def generate_developer_test_build_info():
527    return {
528        "sub_component": [
529            "//test/testfwk/developer_test/examples/app_info:app_info",
530            "//test/testfwk/developer_test/examples/detector:detector",
531            "//test/testfwk/developer_test/examples/calculator:calculator",
532            "//test/testfwk/developer_test/examples/calculator:calculator_static"
533        ],
534        "inner_kits": [
535            {
536                "name": "//test/testfwk/developer_test/aw/cxx/distributed:distributedtest_lib",
537                "header": {
538                    "header_base": [
539                        "//test/testfwk/developer_test/aw/cxx/distributed/utils",
540                        "//test/testfwk/developer_test/aw/cxx/distributed"
541                    ],
542                    "header_files": [
543                        "csv_transform_xml.h",
544                        "distributed.h",
545                        "distributed_agent.h",
546                        "distributed_cfg.h",
547                        "distributed_major.h"
548                    ]
549                }
550            },
551            {
552                "name": "//test/testfwk/developer_test/aw/cxx/hwext:performance_test_static",
553                "header": {
554                    "header_base": "//test/testfwk/developer_test/aw/cxx/hwext",
555                    "header_files": "perf.h"
556                }
557            }
558        ],
559        "test": [
560            "//test/testfwk/developer_test/examples/app_info/test:unittest",
561            "//test/testfwk/developer_test/examples/calculator/test:unittest",
562            "//test/testfwk/developer_test/examples/calculator/test:fuzztest",
563            "//test/testfwk/developer_test/examples/calculator/test:benchmarktest",
564            "//test/testfwk/developer_test/examples/detector/test:unittest",
565            "//test/testfwk/developer_test/examples/sleep/test:performance",
566            "//test/testfwk/developer_test/examples/distributedb/test:distributedtest",
567            "//test/testfwk/developer_test/examples/stagetest/actsbundlemanagerstagetest:unittest"
568        ]
569    }
570
571
572def _generate_developer_test_bundle_content():
573    bundle_content = generate_developer_test_bundle_base_info()
574    component_info = generate_developer_test_component_info()
575    build_info = generate_developer_test_build_info()
576
577    bundle_content["component"] = component_info
578    component_info["build"] = build_info
579
580    return bundle_content
581
582
583def process_developer_test(part_data, parts_path_info, part_name, subsystem_name, components_json):
584    developer_test_src_path = os.path.join(part_data.get('root_path'), 'test', 'testfwk', 'developer_test')
585    dst_path = os.path.join(part_data.get("out_path"), "component_package", part_data.get("part_path"))
586
587    copy_directory_contents(developer_test_src_path, dst_path)
588
589    gn_path = os.path.join(dst_path, "bundle.json")
590
591    bundle_content = _generate_developer_test_bundle_content()
592    _create_bundle_json(gn_path, bundle_content)
593
594    _copy_license(part_data)
595    _copy_readme(part_data)
596    _finish_component_build(part_data)
597
598
599def process_skia(part_data, parts_path_info, part_name, subsystem_name, components_json):
600    skia_piex_path = os.path.join(part_data.get('root_path'), 'third_party', 'skia', 'third_party', 'externals', 'piex')
601    skia_libjpeg_path = os.path.join(part_data.get('root_path'), 'third_party', 'skia', 'third_party', 'externals', 'libjpeg-turbo')
602    skia_component_piex_path = os.path.join(part_data.get("out_path"), "component_package", part_data.get("part_path"), 'innerapis', 'piex', 'includes')
603    skia_component_libjpeg_path = os.path.join(part_data.get("out_path"), "component_package", part_data.get("part_path"), 'innerapis', 'libjpeg', 'includes')
604    copy_directory_contents(skia_piex_path, skia_component_piex_path)
605    copy_directory_contents(skia_libjpeg_path, skia_component_libjpeg_path)
606
607    part_path = _get_parts_path(parts_path_info, part_name)
608    if part_path is None:
609        return
610    part_data.update({"subsystem_name": subsystem_name, "part_name": part_name,
611                      "part_path": part_path})
612    modules = _parse_module_list(part_data)
613    if len(modules) == 0:
614        return
615    is_component_build = False
616    _public_deps_list = []
617    for module in modules:
618        module_deps_list = _handle_module(part_data, components_json, module)
619        if module_deps_list:
620            _public_deps_list.extend(module_deps_list)
621            is_component_build = True
622    _copy_required_docs(part_data, _public_deps_list)
623    _finish_component_build(part_data)
624
625
626def process_variants_default(part_data, parts_path_info, part_name, subsystem_name, components_json):
627    # 减少代码重复调用
628    preloader_path = os.path.join(part_data.get('root_path'), 'out', 'preloader', 'rk3568')
629    variants_default_source_files = [
630        os.path.join(preloader_path, 'build_config.json'),
631        os.path.join(part_data.get('root_path'), 'build', 'indep_configs', 'variants', 'common', 'default_deps.json'),
632        os.path.join(preloader_path, 'features.json'),
633        os.path.join(preloader_path, 'parts_config.json'),
634        os.path.join(preloader_path, 'system', 'etc', 'syscap.json'),
635        os.path.join(preloader_path, 'system', 'etc', 'param', 'syscap.para'),
636        os.path.join(preloader_path, 'system', 'etc', 'SystemCapability.json')
637    ]
638
639    variants_root = os.path.join(part_data.get('out_path'), 'component_package', 'variants', 'variants_default')
640    variants_component_path = os.path.join(variants_root, 'config')
641    try:
642        os.makedirs(variants_component_path, exist_ok=True)
643        for source_file in variants_default_source_files:
644            if not os.path.exists(source_file):
645                raise FileNotFoundError(f"Source file not found: {source_file}")
646            shutil.copy2(source_file, variants_component_path)
647        print("All confiauration files copied successfully")
648
649        # 处理bundle.json文件和license文件,readme文件
650        bundle_content = generate_variants_default_bundle_info()
651        bundle_path = os.path.join(variants_root, 'bundle.json')
652        _create_bundle_json(bundle_path, bundle_content)
653
654        # 创建LICENSE文件、readme.md
655        variants_default_license_path = os.path.join(variants_root, 'LICENSE')
656        variants_default_readme_path = os.path.join(variants_root, 'README.md')
657        with open(variants_default_license_path, 'w') as file:
658            file.write("license")
659        with open(variants_default_readme_path, 'w') as file:
660            file.write("readme")
661
662        _finish_component_build(part_data)
663    except Exception as e:
664        print(f"Error processing variants_default: {str(e)}")
665        raise
666
667
668def generate_variants_default_bundle_info():
669    return {
670        "name": "@ohos/variants_default",
671        "description": "",
672        "version": "3.1.0-snapshot",
673        "license": "Apache License 2.0",
674        "publishAs": "binary",
675        "segment": {
676            "destPath": "variants/variants_default"
677        },
678        "dirs": {
679            "config": [
680                "config/*"
681            ]
682        },
683        "scripts": {},
684        "component": {
685            "name": "variants_default",
686            "subsystem": "build",
687            "syscap": [],
688            "features": [],
689            "adapted_system_type": [],
690            "rom": "",
691            "ram": "",
692            "deps": {
693                "components": [
694                    "musl",
695                    "linux",
696                    "googletest"
697                ],
698                "third_party": []
699            },
700            "build": {
701                "sub_component": [],
702                "inner_kits": [],
703                "test": []
704            }
705        },
706        "os": "linux",
707        "buildArch": "x86",
708        "dependencies": {}
709    }
710
711
712def write_hilog_gn(part_data, module):
713    gn_path = os.path.join(part_data.get("out_path"), "component_package", part_data.get("part_path"),
714                           "innerapis", module, "BUILD.gn")
715    if os.path.exists(gn_path):
716        os.remove(gn_path)
717    fd = os.open(gn_path, os.O_WRONLY | os.O_CREAT, mode=0o640)
718    fp = os.fdopen(fd, 'w')
719    fp.write("""import("//build/ohos.gni")
720
721    config("hilog_rust_configs") {
722      visibility = [ ":*" ]
723      include_dirs = [
724        "includes",
725      ]
726      }
727
728
729    ohos_rust_shared_library("hilog_rust") {
730      sources = [ "src/lib.rs" ]
731
732      deps = [ "../libhilog:libhilog" ]
733      crate_name = "hilog_rust"
734      crate_type = "dylib"
735      rustflags = [ "-Zstack-protector=all" ]
736
737      subsystem_name = "hiviewdfx"
738      part_name = "hilog"
739    }""")
740    print("_generate_build_gn has done ")
741    fp.close()
742
743
744def _hilog_rust_handle(part_data, module, components_json):
745    public_deps_list = []
746    if not _is_innerkit(components_json, part_data.get("part_name"), module):
747        return public_deps_list
748    json_data = _get_json_data(part_data, module)
749    _lib_special_handler(part_data.get("part_name"), module, part_data)
750    lib_exists, _ = _copy_lib(part_data, json_data, module)
751    if lib_exists is False:
752        return public_deps_list
753    includes = _handle_includes_data(json_data)
754    deps = _handle_deps_data(json_data)
755    _copy_includes(part_data, module, includes)
756    _list = _generate_build_gn(part_data, module, json_data, deps, components_json, public_deps_list)
757    write_hilog_gn(part_data, module)
758    _toolchain_gn_copy(part_data, module, json_data['out_name'])
759    hilog_rust_out = os.path.join(part_data.get("out_path"), "component_package", part_data.get("part_path"),
760                                  "innerapis", module)
761    hilog_rust_dir = os.path.join(part_data.get("root_path"), part_data.get("part_path"), "interfaces", "rust")
762    folder_to_copy = os.path.join(hilog_rust_dir, "src")  # 替换为实际的文件夹名称
763    file_to_copy = os.path.join(hilog_rust_dir, "Cargo.toml")  # 替换为实际的文件名称
764    # 检查文件夹和文件是否存在
765    if os.path.exists(folder_to_copy) and os.path.exists(file_to_copy):
766        # 复制文件夹
767        shutil.copytree(folder_to_copy, os.path.join(hilog_rust_out, os.path.basename(folder_to_copy)))
768        # 复制文件
769        shutil.copy(file_to_copy, os.path.join(hilog_rust_out, os.path.basename(file_to_copy)))
770    else:
771        print("文件夹或文件不存在,无法复制。")
772
773    return _list
774
775
776def process_hilog(part_data, parts_path_info, part_name, subsystem_name, components_json):
777    # 只处理一个模块
778    # 处理分类B的逻辑
779    part_path = _get_parts_path(parts_path_info, part_name)
780    if part_path is None:
781        return
782    part_data.update({"subsystem_name": subsystem_name, "part_name": part_name,
783                      "part_path": part_path})
784    modules = _parse_module_list(part_data)
785    print('modules', modules)
786    if len(modules) == 0:
787        return
788    is_component_build = False
789    _public_deps_list = []
790    for module in modules:
791        module_deps_list = _handle_module(part_data, components_json, module)
792        if module == 'hilog_rust':
793            _hilog_rust_handle(part_data, module, components_json)
794        if module_deps_list:
795            _public_deps_list.extend(module_deps_list)
796        is_component_build = True
797    if is_component_build:
798        _copy_required_docs(part_data, _public_deps_list)
799        _finish_component_build(part_data)
800
801
802def generate_hisysevent_gn(part_data, module):
803    gn_path = os.path.join(part_data.get("out_path"), "component_package", part_data.get("part_path"),
804                           "innerapis", module, "BUILD.gn")
805    if os.path.exists(gn_path):
806        os.remove(gn_path)
807    fd = os.open(gn_path, os.O_WRONLY | os.O_CREAT, mode=0o640)
808    fp = os.fdopen(fd, 'w')
809    fp.write("""import("//build/ohos.gni")
810
811    ohos_rust_shared_library("hisysevent_rust") {
812      sources = [
813        "src/lib.rs",
814        "src/macros.rs",
815        "src/sys_event.rs",
816        "src/sys_event_manager.rs",
817        "src/utils.rs",
818      ]
819
820      external_deps = [
821        "hisysevent:hisysevent_c_wrapper",
822        "hisysevent:libhisysevent",
823        "hisysevent:libhisyseventmanager",
824      ]
825
826      crate_name = "hisysevent"
827      crate_type = "dylib"
828      rustflags = [ "-Zstack-protector=all" ]
829
830      part_name = "hisysevent"
831      subsystem_name = "hiviewdfx"
832    }
833    """)
834    print("_generate_build_gn has done ")
835    fp.close()
836
837
838def _hisysevent_rust_handle(part_data, module, components_json):
839    public_deps_list = []
840    if not _is_innerkit(components_json, part_data.get("part_name"), module):
841        return public_deps_list
842    json_data = _get_json_data(part_data, module)
843    _lib_special_handler(part_data.get("part_name"), module, part_data)
844    lib_exists, _ = _copy_lib(part_data, json_data, module)
845    if lib_exists is False:
846        return public_deps_list
847    includes = _handle_includes_data(json_data)
848    deps = _handle_deps_data(json_data)
849    _copy_includes(part_data, module, includes)
850    _list = _generate_build_gn(part_data, module, json_data, deps, components_json, public_deps_list)
851    generate_hisysevent_gn(part_data, module)
852    _toolchain_gn_copy(part_data, module, json_data['out_name'])
853    hisysevent_rust_out = os.path.join(part_data.get("out_path"), "component_package", part_data.get("part_path"),
854                                       "innerapis", module)
855    hisysevent_rust_dir = os.path.join(part_data.get("root_path"), part_data.get("part_path"), "interfaces",
856                                       "innerkits", "rust")
857    folder_to_copy = os.path.join(hisysevent_rust_dir, "src")  # 替换为实际的文件夹名称
858    file_to_copy = os.path.join(hisysevent_rust_dir, "Cargo.toml")  # 替换为实际的文件名称
859    # 检查文件夹和文件是否存在
860    if os.path.exists(folder_to_copy) and os.path.exists(file_to_copy):
861        # 复制文件夹
862        shutil.copytree(folder_to_copy, os.path.join(hisysevent_rust_out, os.path.basename(folder_to_copy)))
863        # 复制文件
864        shutil.copy(file_to_copy, os.path.join(hisysevent_rust_out, os.path.basename(file_to_copy)))
865    else:
866        print("文件夹或文件不存在,无法复制。")
867
868    return _list
869
870
871def process_hisysevent(part_data, parts_path_info, part_name, subsystem_name, components_json):
872    # 只处理一个模块
873    part_path = _get_parts_path(parts_path_info, part_name)
874    if part_path is None:
875        return
876    part_data.update({"subsystem_name": subsystem_name, "part_name": part_name,
877                      "part_path": part_path})
878    modules = _parse_module_list(part_data)
879    print('modules', modules)
880    if len(modules) == 0:
881        return
882    is_component_build = False
883    _public_deps_list = []
884    for module in modules:
885        module_deps_list = _handle_module(part_data, components_json, module)
886        if module == 'hisysevent_rust':
887            _hisysevent_rust_handle(part_data, module, components_json)
888        if module_deps_list:
889            _public_deps_list.extend(module_deps_list)
890        is_component_build = True
891    if is_component_build:
892        _copy_required_docs(part_data, _public_deps_list)
893        _finish_component_build(part_data)
894
895
896def _generate_runtime_core_build_gn():
897    gn_path = os.path.join(args.get("out_path"), "component_package", args.get("part_path"),
898                           "innerapis", module, "BUILD.gn")
899    fd = os.open(gn_path, os.O_WRONLY | os.O_CREAT, mode=0o640)
900    fp = os.fdopen(fd, 'w')
901    _generate_import(fp)
902    _generate_configs(fp, module)
903    _generate_prebuilt_shared_library(fp, json_data.get('type'), module)
904    _generate_public_configs(fp, module)
905    _list = _generate_public_external_deps(fp, module, deps, components_json, public_deps_list)
906    _generate_other(fp, args, json_data, module)
907    _generate_end(fp)
908    print("_generate_build_gn has done ")
909    fp.close()
910    return _list
911
912
913def _handle_module_runtime_core(args, components_json, module):
914    public_deps_list = []
915    if _is_innerkit(components_json, args.get("part_name"), module) == False:
916        return public_deps_list
917    json_data = _get_json_data(args, module)
918    _lib_special_handler(args.get("part_name"), module, args)
919    lib_exists, is_ohos_ets_copy = _copy_lib(args, json_data, module)
920    if lib_exists is False:
921        return public_deps_list
922    includes = _handle_includes_data(json_data)
923    deps = _handle_deps_data(json_data)
924    _copy_includes(args, module, includes)
925    _list = _generate_build_gn(args, module, json_data, deps, components_json, public_deps_list, is_ohos_ets_copy)
926    _toolchain_gn_copy(args, module, json_data['out_name'])
927    return _list
928
929
930def process_runtime_core(part_data, parts_path_info, part_name, subsystem_name, components_json):
931    # 处理分类runtime_core的逻辑
932    part_path = _get_parts_path(parts_path_info, part_name)
933    if part_path is None:
934        return
935    part_data.update({"subsystem_name": subsystem_name, "part_name": part_name,
936                      "part_path": part_path})
937    modules = _parse_module_list(part_data)
938    print('modules', modules)
939    if len(modules) == 0:
940        return
941    is_component_build = False
942    _public_deps_list = []
943    for module in modules:
944        module_deps_list = _handle_module_runtime_core(part_data, components_json, module)
945        if module_deps_list:
946            _public_deps_list.extend(module_deps_list)
947            is_component_build = True
948    if is_component_build:
949        _copy_required_docs(part_data, _public_deps_list)
950        _finish_component_build(part_data)
951
952
953def process_drivers_interface_display(part_data, parts_path_info, part_name, subsystem_name, components_json):
954    part_path = _get_parts_path(parts_path_info, part_name)
955    if part_path is None:
956        return
957    part_data.update({"subsystem_name": subsystem_name, "part_name": part_name,
958                      "part_path": part_path})
959    modules = _parse_module_list(part_data)
960    print('modules', modules)
961    if len(modules) == 0:
962        return
963    is_component_build = False
964    _public_deps_list = []
965    for module in modules:
966        module_deps_list = _handle_module(part_data, components_json, module)
967        if module_deps_list:
968            _public_deps_list.extend(module_deps_list)
969            is_component_build = True
970    lib_out_dir = os.path.join(part_data.get("out_path"), "component_package",
971                               part_data.get("part_path"), "innerapis", "display_commontype_idl_headers", "libs")
972    if not os.path.exists(lib_out_dir):
973        os.makedirs(lib_out_dir)
974    file_path = os.path.join(lib_out_dir, 'libdisplay_commontype_idl_headers')
975    with open(file_path, 'wb') as file:
976        pass
977    if is_component_build:
978        _copy_required_docs(part_data, _public_deps_list)
979        _finish_component_build(part_data)
980
981
982def process_drivers_interface_usb(part_data, parts_path_info, part_name, subsystem_name, components_json):
983    part_path = _get_parts_path(parts_path_info, part_name)
984    if part_path is None:
985        return
986    part_data.update({"subsystem_name": subsystem_name, "part_name": part_name,
987                      "part_path": part_path})
988    modules = _parse_module_list(part_data)
989    print('modules', modules)
990    if len(modules) == 0:
991        return
992    is_component_build = False
993    _public_deps_list = []
994    for module in modules:
995        module_deps_list = _handle_module(part_data, components_json, module)
996        if module_deps_list:
997            _public_deps_list.extend(module_deps_list)
998            is_component_build = True
999    lib_out_dir = os.path.join(part_data.get("out_path"), "component_package",
1000                               part_data.get("part_path"), "innerapis", "usb_idl_headers_1.1", "libs")
1001    if not os.path.exists(lib_out_dir):
1002        os.makedirs(lib_out_dir)
1003    file_path = os.path.join(lib_out_dir, 'libusb_idl_headers_1.1')
1004    with open(file_path, 'wb') as file:
1005        pass
1006    if is_component_build:
1007        _copy_required_docs(part_data, _public_deps_list)
1008        _finish_component_build(part_data)
1009
1010
1011def process_drivers_interface_ril(part_data, parts_path_info, part_name, subsystem_name, components_json):
1012    part_path = _get_parts_path(parts_path_info, part_name)
1013    if part_path is None:
1014        return
1015    part_data.update({"subsystem_name": subsystem_name, "part_name": part_name,
1016                      "part_path": part_path})
1017    modules = _parse_module_list(part_data)
1018    print('modules', modules)
1019    if len(modules) == 0:
1020        return
1021    is_component_build = False
1022    _public_deps_list = []
1023    for module in modules:
1024        module_deps_list = _handle_module(part_data, components_json, module)
1025        if module_deps_list:
1026            _public_deps_list.extend(module_deps_list)
1027            is_component_build = True
1028    lib_out_dir = os.path.join(part_data.get("out_path"), "component_package",
1029                               part_data.get("part_path"), "innerapis", "ril_idl_headers", "libs")
1030    if not os.path.exists(lib_out_dir):
1031        os.makedirs(lib_out_dir)
1032    file_path = os.path.join(lib_out_dir, 'libril_idl_headers')
1033    with open(file_path, 'wb') as file:
1034        pass
1035    if is_component_build:
1036        _copy_required_docs(part_data, _public_deps_list)
1037        _finish_component_build(part_data)
1038
1039
1040# 函数映射字典
1041function_map = {
1042    'musl': process_musl,
1043    "developer_test": process_developer_test,  # 同rust
1044    "drivers_interface_display": process_drivers_interface_display,  # 驱动的, 新建一个libs目录/ innerapi同名文件
1045    "runtime_core": process_runtime_core,  # 编译参数, 所有下面的innerapi的cflags都不
1046    "drivers_interface_usb": process_drivers_interface_usb,  # 同驱动
1047    "drivers_interface_ril": process_drivers_interface_ril,  # 同驱动
1048    "skia": process_skia,
1049    "variants_default": process_variants_default,
1050}
1051
1052
1053def _process_part(args, parts_path_info, part_name, subsystem_name, components_json):
1054    # 使用映射字典来调用对应的函数
1055    if part_name in function_map.keys():
1056        function_map[part_name](args, parts_path_info, part_name, subsystem_name, components_json)
1057    else:
1058        print(f"没有找到处理分类{part_name}的函数。")
1059
1060
1061def _check_label(public_deps, value):
1062    innerapis = value["innerapis"]
1063    for _innerapi in innerapis:
1064        if _innerapi:
1065            label = _innerapi.get("label")
1066            if public_deps == label:
1067                return label.split(':')[-1]
1068            continue
1069    return ""
1070
1071
1072def _get_public_external_deps(data, public_deps):
1073    if not isinstance(data, dict):
1074        return ""
1075    for key, value in data.items():
1076        if not isinstance(value, dict):
1077            continue
1078        _data = _check_label(public_deps, value)
1079        if _data:
1080            return f"{key}:{_data}"
1081        continue
1082    return ""
1083
1084
1085def _is_innerkit(data, part, module):
1086    if not isinstance(data, dict):
1087        return False
1088
1089    part_data = data.get(part)
1090    if not isinstance(part_data, dict):
1091        return False
1092    module_list = []
1093    for i in part_data["innerapis"]:
1094        if i:
1095            module_list.append(i["name"])
1096    if module in module_list:
1097        return True
1098    return False
1099
1100
1101def _get_components_json(out_path):
1102    jsondata = ""
1103    json_path = os.path.join(out_path + "/build_configs/parts_info/components.json")
1104    with os.fdopen(os.open(json_path, os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR),
1105                   'r', encoding='utf-8') as f:
1106        try:
1107            jsondata = json.load(f)
1108        except Exception as e:
1109            print('--_get_components_json parse json error--')
1110    return jsondata
1111
1112
1113def _handle_one_layer_json(json_key, json_data, desc_list):
1114    data_list = json_data.get(json_key)
1115    if isinstance(data_list, list) and len(json_data.get(json_key)) >= 1:
1116        desc_list.extend(data_list)
1117    else:
1118        desc_list.append(json_data.get(json_key))
1119
1120
1121def _get_external_public_config(_path, _config_name):
1122    py_args = _get_args()
1123    out_path = py_args.out_path
1124    _json_path = os.path.join(out_path, 'external_public_configs', _path, f'{_config_name}.json')
1125    try:
1126        with os.fdopen(os.open(_json_path, os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR),
1127                       'r', encoding='utf-8') as f:
1128            jsondata = json.load(f)
1129    except Exception as e:
1130        print('_json_path: ', _json_path)
1131        print('--_get_external_public_config parse json error--')
1132        return []
1133
1134    include_dirs = jsondata.get('include_dirs')
1135    return include_dirs
1136
1137
1138def _handle_two_layer_json(json_key, json_data, desc_list):
1139    value_depth = len(json_data.get(json_key))
1140    for i in range(value_depth):
1141        _label = json_data.get(json_key)[i].get('label')
1142        _include_dirs = json_data.get(json_key)[i].get('include_dirs')
1143        if _include_dirs:
1144            desc_list.extend(_include_dirs)
1145        else:
1146            full_path = _label.split('//')[-1]
1147            _path = full_path.split(':')[0]
1148            _config_name = full_path.split(':')[-1]
1149            _include_dirs = _get_external_public_config(_path, _config_name)
1150            if _include_dirs:
1151                desc_list.extend(_include_dirs)
1152
1153
1154def _get_json_data(args, module):
1155    json_path = os.path.join(args.get("out_path"),
1156                             args.get("subsystem_name"), args.get("part_name"), "publicinfo", module + ".json")
1157    with os.fdopen(os.open(json_path, os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR),
1158                   'r', encoding='utf-8') as f:
1159        try:
1160            file_content = f.read()
1161            jsondata = json.loads(file_content)
1162        except Exception as e:
1163            print(json_path)
1164            print('--_get_json_data parse json error--', e)
1165    return jsondata
1166
1167
1168def _handle_deps_data(json_data):
1169    dep_list = []
1170    if json_data.get('public_deps'):
1171        _handle_one_layer_json('public_deps', json_data, dep_list)
1172    return dep_list
1173
1174
1175def _handle_includes_data(json_data):
1176    include_list = []
1177    if json_data.get('public_configs'):
1178        _handle_two_layer_json('public_configs', json_data, include_list)
1179    if json_data.get('all_dependent_configs'):
1180        _handle_two_layer_json('all_dependent_configs', json_data, include_list)
1181    return include_list
1182
1183
1184def _get_static_lib_path(args, json_data):
1185    label = json_data.get('label')
1186    split_label = label.split("//")[1].split(":")[0]
1187    real_static_lib_path = os.path.join(args.get("out_path"), "obj",
1188                                        split_label, json_data.get('out_name'))
1189    return real_static_lib_path
1190
1191
1192def _copy_dir(src_path, target_path):
1193    if not os.path.isdir(src_path):
1194        return False
1195    for file in os.listdir(src_path):
1196        path = os.path.join(src_path, file)
1197        if os.path.isdir(path):
1198            if file.startswith("."):
1199                continue
1200            path1 = os.path.join(target_path, file)
1201            _copy_dir(path, path1)
1202        else:
1203            _, file_extension = os.path.splitext(file)
1204            if file_extension not in [".h", ".hpp", ".in", ".inc", ".inl"]:
1205                continue
1206            if not os.path.exists(target_path):
1207                os.makedirs(target_path)
1208            # 打包时存在同名头文件时,使用先遍历到的
1209            if not os.path.exists(os.path.join(target_path, file)):
1210                shutil.copy2(path, os.path.join(target_path, file))
1211    return True
1212
1213
1214def _get_target_include(part_name, include):
1215    # 需要多层提取include头文件的白名单路径
1216    multilayer_include_config_path = os.path.join('build', 'indep_configs', 'config', 'multilayer_include_config.json')
1217    with open(multilayer_include_config_path, "r") as f:
1218        part_whitch_use_multilayer_include = json.load(f)
1219        if part_name in part_whitch_use_multilayer_include:
1220            target_include = include.replace("//", "")
1221            if target_include.endswith("/"):
1222                target_include = target_include[:-1]
1223            return target_include
1224        else:
1225            return ""
1226
1227
1228def _copy_includes(args, module, includes: list):
1229    if module == 'ipc_single':
1230        includes = [
1231            "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include",
1232            "//foundation/communication/ipc/ipc/native/src/core/include",
1233            "//foundation/communication/ipc/ipc/native/src/mock/include",
1234        ]
1235    includes_out_dir = os.path.join(args.get("out_path"), "component_package",
1236                                    args.get("part_path"), "innerapis", module, "includes")
1237    for i in args.get("toolchain_info").keys():
1238        toolchain_includes_out_dir = os.path.join(args.get("out_path"), "component_package",
1239                                                  args.get("part_path"), "innerapis", module, i, "includes")
1240        toolchain_lib_out_dir = os.path.join(args.get("out_path"), "component_package",
1241                                             args.get("part_path"), "innerapis", module, i, "libs")
1242        if not os.path.exists(toolchain_includes_out_dir) and os.path.exists(toolchain_lib_out_dir):
1243            os.makedirs(toolchain_includes_out_dir)
1244        else:
1245            continue
1246        for include in includes:
1247            relative_target_include = _get_target_include(args.get("part_name"), include)
1248            toolchain_real_include_out_dir = os.path.join(toolchain_includes_out_dir, relative_target_include)
1249            if not os.path.exists(toolchain_real_include_out_dir):
1250                os.makedirs(toolchain_real_include_out_dir)
1251            part_path = args.get("part_path")
1252            _sub_include = include.split(f"{part_path}/")[-1]
1253            split_include = include.split("//")[1]
1254            real_include_path = os.path.join(args.get("root_path"), split_include)
1255            _copy_dir(real_include_path, toolchain_real_include_out_dir)
1256    if not os.path.exists(includes_out_dir):
1257        os.makedirs(includes_out_dir)
1258    for include in includes:
1259        relative_target_include = _get_target_include(args.get("part_name"), include)
1260        includes_real_out_dir = os.path.join(includes_out_dir, relative_target_include)
1261        if not os.path.exists(includes_real_out_dir):
1262            os.makedirs(includes_real_out_dir)
1263        part_path = args.get("part_path")
1264        _sub_include = include.split(f"{part_path}/")[-1]
1265        split_include = include.split("//")[1]
1266        real_include_path = os.path.join(args.get("root_path"), split_include)
1267        _copy_dir(real_include_path, includes_real_out_dir)
1268    print("_copy_includes has done ")
1269
1270
1271def _copy_toolchain_lib(file_name, root, _name, lib_out_dir):
1272    if not file_name.startswith('.') and file_name.startswith(_name):
1273        if not os.path.exists(lib_out_dir):
1274            os.makedirs(lib_out_dir)
1275        file = os.path.join(root, file_name)
1276        shutil.copy(file, lib_out_dir)
1277
1278
1279def _toolchain_lib_handler(args, toolchain_path, _name, module, toolchain_name):
1280    lib_out_dir = os.path.join(args.get("out_path"), "component_package",
1281                                       args.get("part_path"), "innerapis", module, toolchain_name, "libs")
1282    if os.path.isfile(toolchain_path):
1283        if not os.path.exists(lib_out_dir):
1284            os.makedirs(lib_out_dir)
1285        shutil.copy(toolchain_path, lib_out_dir)
1286    else:
1287        for root, dirs, files in os.walk(toolchain_path):
1288            for file_name in files:
1289                _copy_toolchain_lib(file_name, root, _name, lib_out_dir)
1290
1291
1292def _toolchain_static_file_path_mapping(subsystem_name, args, i):
1293    if subsystem_name == "thirdparty":
1294        subsystem_name = "third_party"
1295    toolchain_path = os.path.join(args.get("out_path"), i, 'obj', subsystem_name,
1296                                  args.get("part_name"))
1297    return toolchain_path
1298
1299
1300def replace_default_toolchains_in_output(path, default_toolchain="ohos_clang_arm64/"):
1301    return path.replace(default_toolchain, "")
1302
1303
1304def _copy_lib(args, json_data, module):
1305    so_path = ""
1306    lib_status = True
1307    _target_type = json_data.get('type')
1308    subsystem_name = args.get("subsystem_name")
1309    is_ohos_ets_copy = False
1310    ets_outputs = []
1311
1312    # 根据 type 字段和 module 选择正确的 so_path
1313    if _target_type == 'copy' and module == 'ipc_core':
1314        so_path = os.path.join(subsystem_name, args.get("part_name"), 'libipc_single.z.so')
1315    elif _target_type == "rust_library" or _target_type == "rust_proc_macro":
1316        # 选择包含 'lib.unstripped' 的路径
1317        outputs = json_data.get('outputs', [])
1318        for output in outputs:
1319            if 'lib.unstripped' in output:
1320                output = replace_default_toolchains_in_output(output)
1321                so_path = output
1322                break
1323        # 如果没有找到包含 'lib.unstripped' 的路径,则选择最后一个路径
1324        if not so_path and outputs:
1325            so_path = outputs[-1]
1326    else:
1327        # 对于非 rust_library 类型,选择不包含 'lib.unstripped' 的路径
1328        outputs = json_data.get('outputs', [])
1329        for output in outputs:
1330            if 'ohos_ets' in output:
1331                is_ohos_ets_copy = True
1332                ets_outputs.append(output)
1333            elif '.unstripped' not in output:
1334                output = replace_default_toolchains_in_output(output)
1335                so_path = output
1336                break
1337        # 如果所有路径都包含 'lib.unstripped' 或者没有 outputs,则使用 out_name
1338        if not so_path:
1339            so_path = json_data.get('out_name')
1340    if is_ohos_ets_copy:
1341        for output in ets_outputs:
1342            if not copy_so_file(args, module, output, _target_type):
1343                lib_status = False
1344    elif so_path:
1345        lib_status = copy_so_file(args, module, so_path, _target_type)
1346    if lib_status and _target_type == 'static_library':
1347        copy_static_deps_file(args, json_data.get('label'), module, so_path)
1348    return lib_status, is_ohos_ets_copy
1349
1350
1351def _do_copy_static_deps_file(args, out_path, lib_path, toolchain):
1352    lib_status = False
1353    static_lib_path = os.path.join(out_path, lib_path)
1354    lib_out_dir = os.path.join(out_path, "component_package",
1355                                   args.get("part_path"), "common", toolchain, "deps")
1356    lib_status = _copy_file(static_lib_path, lib_out_dir) or lib_status
1357    return lib_status
1358
1359
1360def is_not_basic_lib(lib_path):
1361    if "obj/third_party/musl" in lib_path or "prebuilts/clang" in lib_path:
1362        return False
1363    else:
1364        return True
1365
1366
1367def read_deps_from_ninja_file(ninja_file, prefix):
1368    print("ninja file: ", ninja_file)
1369    with open(ninja_file, 'r') as f:
1370        for line in f:
1371            if line.strip().startswith(prefix):
1372                deps_libs = line.strip().split(' ')
1373                return deps_libs
1374    return []
1375
1376
1377def copy_static_deps_file(args, label, module, so_path):
1378    toolchains = set(args.get("toolchain_info").keys())
1379    toolchains.add("")
1380    lib_status = False
1381    out_path = args.get("out_path")
1382    for toolchain in toolchains:
1383        ninja_file = os.path.join(out_path, toolchain, "obj", (label.split(':')[0]).split('//')[1], label.split(':')[1] + ".ninja")
1384        if not os.path.exists(ninja_file):
1385            continue
1386        prefix = "build " + os.path.join(toolchain, so_path)
1387        deps_libs = read_deps_from_ninja_file(ninja_file, prefix)
1388        static_deps = []
1389        toolchain_module = toolchain + "_" + module
1390        for lib in deps_libs:
1391            lib_name = os.path.basename(lib)
1392            if lib_name in static_deps:
1393                print("lib_name: {} already in static_deps".format(lib_name))
1394                continue
1395            if lib.endswith(".a") and lib != so_path and is_not_basic_lib(lib):
1396                static_deps.append(lib_name)
1397                lib_status = _do_copy_static_deps_file(args, out_path, lib, toolchain) or lib_status
1398        args.get("static_deps")[toolchain_module] = static_deps
1399        print("copy static deps: ", static_deps)
1400    return lib_status
1401
1402
1403def copy_so_file(args, module, so_path, target_type):
1404    lib_status = False
1405    out_path = args.get("out_path")
1406    so_path_with_out_path = os.path.join(out_path, so_path)
1407    lib_out_dir = os.path.join(out_path, "component_package",
1408                                   args.get("part_path"), "innerapis", module, "libs")
1409    if args.get("toolchain_info").keys():
1410        for toolchain_name in args.get("toolchain_info").keys():
1411            lib_out_dir_with_toolchain = os.path.join(args.get("out_path"), "component_package",
1412                                       args.get("part_path"), "innerapis", module, toolchain_name, "libs")
1413            so_path_with_toolchain = os.path.join(args.get("out_path"), toolchain_name, so_path)
1414            unzipped_so_path_with_toolchain = so_path_with_toolchain.replace(".z.", ".")
1415            if toolchain_name in so_path:
1416                lib_status = _copy_file(so_path_with_out_path, lib_out_dir_with_toolchain, target_type) or lib_status
1417            elif os.path.isfile(so_path_with_toolchain):
1418                lib_status = _copy_file(so_path_with_toolchain, lib_out_dir_with_toolchain, target_type) or lib_status
1419            elif os.path.isfile(unzipped_so_path_with_toolchain):
1420                lib_status = _copy_file(unzipped_so_path_with_toolchain, lib_out_dir_with_toolchain, target_type) or lib_status
1421    lib_status = _copy_file(so_path_with_out_path, lib_out_dir, target_type) or lib_status
1422    return lib_status
1423
1424
1425def _copy_file(so_path, lib_out_dir, target_type=""):
1426    # 处理静态库依赖
1427    if lib_out_dir.endswith("deps") or lib_out_dir.endswith("deps/"):
1428        if not os.path.isfile(so_path):
1429            print("WARNING: {} is not a file!".format(so_path))
1430            return False
1431        if not os.path.exists(lib_out_dir):
1432            os.makedirs(lib_out_dir)
1433        shutil.copy(so_path, lib_out_dir)
1434        return True
1435    if target_type != 'copy' and not os.path.isfile(so_path):
1436        print("WARNING: {} is not a file!".format(so_path))
1437        return False
1438    if os.path.exists(lib_out_dir):
1439        shutil.rmtree(lib_out_dir)
1440    if os.path.isfile(so_path):
1441        if not os.path.exists(lib_out_dir):
1442            os.makedirs(lib_out_dir)
1443            shutil.copy(so_path, lib_out_dir)
1444    elif os.path.exists(so_path):
1445        dir_name = os.path.basename(so_path)
1446        new_lib_out_dir = os.path.join(lib_out_dir, dir_name)
1447        shutil.copytree(so_path, new_lib_out_dir)
1448    return True
1449
1450
1451def _dirs_handler(bundlejson_out):
1452    dirs = dict()
1453    dirs['./'] = []
1454    directory = bundlejson_out
1455    for filename in os.listdir(directory):
1456        filepath = os.path.join(directory, filename)
1457        if os.path.isfile(filepath):
1458            dirs['./'].append(filename)
1459        else:
1460            dirs[filename] = [f"{filename}/*"]
1461    delete_list = ['LICENSE', 'README.md', 'README_zh.md', 'README_en.md', 'bundle.json']
1462    for delete_txt in delete_list:
1463        if delete_txt in dirs['./']:
1464            dirs['./'].remove(delete_txt)
1465    if dirs['./'] == []:
1466        del dirs['./']
1467    return dirs
1468
1469
1470def _copy_bundlejson(args, public_deps_list):
1471    bundlejson_out = os.path.join(args.get("out_path"), "component_package", args.get("part_path"))
1472    print("bundlejson_out : ", bundlejson_out)
1473    if not os.path.exists(bundlejson_out):
1474        os.makedirs(bundlejson_out)
1475    bundlejson = os.path.join(args.get("root_path"), args.get("part_path"), "bundle.json")
1476    dependencies_dict = {}
1477    sorted_dict = {}
1478    for public_deps in public_deps_list:
1479        _public_dep_part_name = public_deps.split(':')[0]
1480        if _public_dep_part_name != args.get("part_name"):
1481            _public_dep = f"@{args.get('organization_name')}/{_public_dep_part_name}"
1482            dependencies_dict.update({_public_dep: "*"})
1483            sorted_dict = dict(sorted(dependencies_dict.items()))
1484    if os.path.isfile(bundlejson):
1485        with open(bundlejson, 'r') as f:
1486            bundle_data = json.load(f)
1487            bundle_data['publishAs'] = 'binary'
1488            bundle_data.update({'os': args.get('os')})
1489            bundle_data.update({'buildArch': args.get('buildArch')})
1490            dirs = _dirs_handler(bundlejson_out)
1491            bundle_data['dirs'] = dirs
1492            bundle_data['version'] = str(bundle_data['version'])
1493            if bundle_data['version'] == '':
1494                bundle_data['version'] = '1.0.0'
1495            pattern = r'^(\d+)\.(\d+)(-[a-zA-Z]+)?$'  # 正则表达式匹配a.b[-后缀]格式的字符串
1496            match = re.match(pattern, bundle_data['version'])
1497            if match:
1498                a = match.group(1)
1499                b = match.group(2)
1500                suffix = match.group(3) if match.group(3) else ""
1501                bundle_data['version'] = f"{a}.{b}.0{suffix}"
1502            if args.get('build_type') in [0, 1]:
1503                bundle_data['version'] += '-snapshot'
1504            if args.get('organization_name'):
1505                _name_pattern = r'@(.*.)/'
1506                bundle_data['name'] = re.sub(_name_pattern, '@' + args.get('organization_name') + '/',
1507                                             bundle_data['name'])
1508            if bundle_data.get('scripts'):
1509                bundle_data.update({'scripts': {}})
1510            if bundle_data.get('licensePath'):
1511                del bundle_data['licensePath']
1512            if bundle_data.get('readmePath'):
1513                del bundle_data['readmePath']
1514            bundle_data['dependencies'] = sorted_dict
1515            if os.path.isfile(os.path.join(bundlejson_out, "bundle.json")):
1516                os.remove(os.path.join(bundlejson_out, "bundle.json"))
1517            with os.fdopen(os.open(os.path.join(bundlejson_out, "bundle.json"), os.O_WRONLY | os.O_CREAT, mode=0o640),
1518                           "w",
1519                           encoding='utf-8') as fd:
1520                json.dump(bundle_data, fd, indent=4, ensure_ascii=False)
1521
1522
1523def _copy_license(args):
1524    license_out = os.path.join(args.get("out_path"), "component_package", args.get("part_path"))
1525    print("license_out : ", license_out)
1526    if not os.path.exists(license_out):
1527        os.makedirs(license_out)
1528    license_file = os.path.join(args.get("root_path"), args.get("part_path"), "LICENSE")
1529    if os.path.isfile(license_file):
1530        shutil.copy(license_file, license_out)
1531    else:
1532        license_default = os.path.join(args.get("root_path"), "build", "LICENSE")
1533        shutil.copy(license_default, license_out)
1534        bundlejson_out = os.path.join(args.get("out_path"), "component_package", args.get("part_path"), 'bundle.json')
1535        with open(bundlejson_out, 'r') as f:
1536            bundle_data = json.load(f)
1537            bundle_data.update({"license": "Apache License 2.0"})
1538        if os.path.isfile(bundlejson_out):
1539            os.remove(bundlejson_out)
1540        with os.fdopen(os.open(bundlejson_out, os.O_WRONLY | os.O_CREAT, mode=0o640), "w",
1541                       encoding='utf-8') as fd:
1542            json.dump(bundle_data, fd, indent=4, ensure_ascii=False)
1543
1544
1545def _copy_readme(args):
1546    readme_out = os.path.join(args.get("out_path"), "component_package", args.get("part_path"))
1547    print("readme_out : ", readme_out)
1548    if not os.path.exists(readme_out):
1549        os.makedirs(readme_out)
1550    readme = os.path.join(args.get("root_path"), args.get("part_path"), "README.md")
1551    readme_zh = os.path.join(args.get("root_path"), args.get("part_path"), "README_zh.md")
1552    readme_en = os.path.join(args.get("root_path"), args.get("part_path"), "README_en.md")
1553    readme_out_file = os.path.join(readme_out, "README.md")
1554    if os.path.isfile(readme):
1555        shutil.copy(readme, readme_out)
1556    elif os.path.isfile(readme_zh):
1557        shutil.copy(readme_zh, readme_out_file)
1558    elif os.path.isfile(readme_en):
1559        shutil.copy(readme_en, readme_out_file)
1560    else:
1561        try:
1562            with os.fdopen(os.open(readme_out_file, os.O_WRONLY | os.O_CREAT, mode=0o640), 'w') as fp:
1563                fp.write('READ.ME')
1564        except FileExistsError:
1565            pass
1566
1567
1568def _generate_import(fp, is_ohos_ets_copy=False):
1569    fp.write('import("//build/ohos.gni")\n')
1570    if is_ohos_ets_copy:
1571        fp.write('import("//build/templates/common/copy.gni")\n')
1572
1573
1574def _gcc_flags_info_handle(json_data):
1575    def should_process_key(k):
1576        return k not in ["label", "include_dirs"]
1577
1578    def process_config(config):
1579        result = {}
1580        for k, v in config.items():
1581            if should_process_key(k):
1582                result.setdefault(k, []).extend(v)
1583        return result
1584
1585    _flags_info = {}
1586    _public_configs = json_data.get('public_configs')
1587    if _public_configs:
1588        for config in _public_configs:
1589            config_info = process_config(config)
1590            for k, v in config_info.items():
1591                _flags_info.setdefault(k, []).extend(v)
1592    return _flags_info
1593
1594
1595def _generate_configs(fp, module, json_data, _part_name):
1596    includes = _handle_includes_data(json_data)
1597    target_includes = []
1598
1599    fp.write('\nconfig("' + module + '_configs") {\n')
1600    fp.write('  visibility = [ ":*" ]\n')
1601    fp.write('  include_dirs = [\n')
1602    for include in includes:
1603        target_include = _get_target_include(_part_name, include)
1604        if target_include not in target_includes:
1605            target_includes.append(target_include)
1606    for include_dir in target_includes:
1607        include_dir = os.path.join('includes', include_dir)
1608        fp.write('    "{}",\n'.format(include_dir))
1609    if module == 'ability_runtime':
1610        fp.write('    "includes/context",\n')
1611        fp.write('    "includes/app",\n')
1612    fp.write('  ]\n')
1613    if _part_name == 'runtime_core':
1614        fp.write('  }\n')
1615        return
1616    _flags_info = _gcc_flags_info_handle(json_data)
1617    if _flags_info:
1618        for k, _list in _flags_info.items():
1619            fp.write(f'  {k} = [\n')
1620            for j in _list:
1621                # 保留所有 \ 转义符号
1622                j_escaped = j.replace('"', '\\"')
1623                fp.write(f'  "{j_escaped}",\n')
1624            fp.write('  ]\n')
1625    fp.write('  }\n')
1626
1627
1628def _generate_prebuilt_target(fp, target_type, module, is_ohos_ets_copy=False):
1629    if target_type == 'static_library':
1630        fp.write('ohos_prebuilt_static_library("' + module + '") {\n')
1631    elif target_type == 'executable':
1632        fp.write('ohos_prebuilt_executable("' + module + '") {\n')
1633    elif module != 'ipc_core' and (target_type == 'etc' or target_type == 'copy'):
1634        if is_ohos_ets_copy:
1635            fp.write('ohos_copy("' + module + '") {\n')
1636        else:
1637            fp.write('ohos_prebuilt_etc("' + module + '") {\n')
1638    elif target_type == 'rust_library' or target_type == 'rust_proc_macro':
1639        fp.write('ohos_prebuilt_rust_library("' + module + '") {\n')
1640    else:
1641        fp.write('ohos_prebuilt_shared_library("' + module + '") {\n')
1642
1643
1644def _generate_public_configs(fp, module):
1645    fp.write(f'  public_configs = [":{module}_configs"]\n')
1646
1647
1648# 目前特殊处理的依赖关系映射
1649_DEPENDENCIES_MAP = {
1650    ('samgr', 'samgr_proxy'): ["ipc:ipc_core"],
1651    ('ets_runtime', 'libark_jsruntime'): ["runtime_core:libarkfile_static"],
1652}
1653
1654
1655def _public_deps_special_handler(module, args):
1656    _part_name = args.get('part_name')
1657    # 使用映射字典来获取依赖列表
1658    return _DEPENDENCIES_MAP.get((_part_name, module), [])
1659
1660
1661def _generate_public_external_deps(fp, module, deps: list, components_json, public_deps_list: list, args):
1662    fp.write('  public_external_deps = [\n')
1663    for dep in deps:
1664        public_external_deps = _get_public_external_deps(components_json, dep)
1665        if len(public_external_deps) > 0:
1666            fp.write(f"""    "{public_external_deps}",\n""")
1667            public_deps_list.append(public_external_deps)
1668    for _public_external_deps in _public_deps_special_handler(module, args):
1669        fp.write(f"""    "{_public_external_deps}",\n""")
1670        public_deps_list.append(_public_external_deps)
1671    fp.write('  ]\n')
1672
1673    return public_deps_list
1674
1675
1676def _find_ohos_ets_dir(outputs):
1677    for path in outputs:
1678        parts = path.split('/')
1679        for part in parts:
1680            if "ohos_ets" in part:
1681                return '/'.join(parts[:-1])
1682    return None
1683
1684
1685def _generate_other(fp, args, json_data, module, is_ohos_ets_copy=False):
1686    outputs = json_data.get('outputs', [])
1687    ohos_ets_dir = _find_ohos_ets_dir(outputs)
1688    if is_ohos_ets_copy:
1689        sources_arr = [f"libs/{path.split('/')[-1]}" for path in outputs]
1690        sources_str = str(sources_arr).replace("'", '"')
1691        fp.write(f'  sources = {sources_str}\n')
1692        fp.write('  outputs = [ "$root_out_dir/' + ohos_ets_dir + '/{{source_file_part}}" ]\n')
1693        fp.write('  part_name = "' + args.get("part_name") + '"\n')
1694        fp.write('  subsystem_name = "' + args.get("subsystem_name") + '"\n')
1695    else:
1696        if json_data.get('type') == 'copy' and module == 'ipc_core':
1697            so_name = 'libipc_single.z.so'
1698        else:
1699            so_name = json_data.get('out_name')
1700            for output in outputs:
1701                so_name = output.split('/')[-1]
1702        if json_data.get('type') == 'copy' and module != 'ipc_core':
1703            fp.write('  copy_linkable_file = true \n')
1704        fp.write('  source = "libs/' + so_name + '"\n')
1705        fp.write('  part_name = "' + args.get("part_name") + '"\n')
1706        fp.write('  subsystem_name = "' + args.get("subsystem_name") + '"\n')
1707
1708
1709def _generate_end(fp):
1710    fp.write('}')
1711
1712
1713def convert_rustdeps_to_innerapi(dep, components_json):
1714    # 分割路径和模块名
1715    dep_parts = dep.split(':', 1)
1716    if len(dep_parts) != 2:
1717        return False, "" # 格式不正确,不是 innerapi
1718
1719    path, module = dep_parts
1720    path = path.lstrip('//')
1721
1722    # 遍历 components.json 中的每个部件
1723    for component, info in components_json.items():
1724        if path.startswith(info['path']) and _check_dep_in_innerapi(info.get('innerapis', []), dep):
1725            return True, f"{component}:{module}"
1726    return False, ""
1727
1728
1729def _check_dep_in_innerapi(innerapis, dep):
1730    for innerapi in innerapis:
1731        if innerapi['label'] == (dep.split('(')[0] if ('(' in dep) else dep):
1732            return True
1733    return False
1734
1735
1736def _generate_rust_deps(fp, json_data, components_json):
1737    rust_deps = json_data.get("rust_deps")
1738    external_deps = []
1739    for _dep in rust_deps:
1740        has_innerapi, innerapi = convert_rustdeps_to_innerapi(_dep, components_json)
1741        if has_innerapi:
1742            external_deps.append(innerapi)
1743    fp.write('  external_deps = [\n')
1744    for external_dep in external_deps:
1745        fp.write(f"""    "{external_dep}",\n""")
1746    fp.write('  ]\n')
1747
1748
1749def _copy_rust_crate_info(fp, json_data):
1750    fp.write(f'  rust_crate_name = \"{json_data.get("rust_crate_name")}\"\n')
1751    fp.write(f'  rust_crate_type = \"{json_data.get("rust_crate_type")}\"\n')
1752
1753
1754def _get_static_deps(args, module, toolchain):
1755    default_toolchain_module = toolchain + "_" + module
1756    return args.get("static_deps").get(default_toolchain_module, [])
1757
1758
1759def _generate_static_public_deps_string(args, deps: list, toolchain: str):
1760    public_deps_str = ""
1761    if not deps:
1762        return ""
1763    public_deps_str += '  public_deps = [\n'
1764    for dep in deps:
1765        public_deps_str += f"""    ":{dep}", \n"""
1766    public_deps_str += '  ]\n'
1767    return public_deps_str
1768
1769
1770def _generate_static_deps_target_string(args, deps: list, toolchain: str):
1771    # target_path: part_name/innerapis/${innerapi_name}/${toolchain}/BUILD.gn
1772    # static_lib_path: part_name/common/${toolchain}/deps
1773    if toolchain:
1774        source_prefix = os.path.join("../../../common", toolchain, "deps/")
1775    else:
1776        source_prefix = os.path.join("../../common", toolchain, "deps/")
1777    output_prefix = os.path.join("common", toolchain, "deps/")
1778    target_string = ""
1779    for dep in deps:
1780        target_string += '\n'
1781        target_string += 'ohos_prebuilt_static_library("' + dep + '") {\n'
1782        target_string += '  source = "' + source_prefix + dep + '"\n'
1783        target_string += '  output = "' + output_prefix + dep + '"\n'
1784        target_string += '  part_name = "' + args.get("part_name") + '"\n'
1785        target_string += '  subsystem_name = "' + args.get("subsystem_name") + '"\n'
1786        target_string += '}'
1787    return target_string
1788
1789
1790def _generate_static_deps_target(fp, args, deps: list, toolchain):
1791    target_string = _generate_static_deps_target_string(args, deps, toolchain)
1792    fp.write(target_string)
1793
1794
1795def _generate_static_public_deps(fp, args, deps: list, toolchain):
1796    public_deps_string = _generate_static_public_deps_string(args, deps, toolchain)
1797    fp.write(public_deps_string)
1798
1799
1800def _generate_build_gn(args, module, json_data, deps: list, components_json, public_deps_list, is_ohos_ets_copy=False):
1801    gn_path = os.path.join(args.get("out_path"), "component_package", args.get("part_path"),
1802                           "innerapis", module, "BUILD.gn")
1803    static_deps_files = _get_static_deps(args, module, "") # 处理静态库依赖
1804    fd = os.open(gn_path, os.O_WRONLY | os.O_CREAT, mode=0o640)
1805    fp = os.fdopen(fd, 'w')
1806    _generate_import(fp, is_ohos_ets_copy)
1807    _generate_configs(fp, module, json_data, args.get('part_name'))
1808    _target_type = json_data.get('type')
1809    _generate_prebuilt_target(fp, _target_type, module, is_ohos_ets_copy)
1810    _generate_public_configs(fp, module)
1811    _list = _generate_public_external_deps(fp, module, deps, components_json, public_deps_list, args)
1812    _generate_static_public_deps(fp, args, static_deps_files, "") # 处理静态库依赖
1813    if _target_type == "rust_library" or _target_type == "rust_proc_macro":
1814        _copy_rust_crate_info(fp, json_data)
1815        _generate_rust_deps(fp, json_data, components_json)
1816    _generate_other(fp, args, json_data, module, is_ohos_ets_copy)
1817    _generate_end(fp)
1818    _generate_static_deps_target(fp, args, static_deps_files, "") # 处理静态库依赖
1819    print(f"{module}_generate_build_gn has done ")
1820    fp.close()
1821    return _list
1822
1823
1824def _toolchain_gn_modify(args, module, toolchain_name, gn_path, so_name, toolchain_gn_file):
1825    if os.path.isfile(gn_path) and so_name:
1826        with open(gn_path, 'r') as f:
1827            _gn = f.read()
1828            pattern = r"libs/(.*.)"
1829            toolchain_gn = re.sub(pattern, 'libs/' + so_name + '\"', _gn)
1830            # 处理静态库依赖传递
1831            static_deps = _get_static_deps(args, module, toolchain_name)
1832            public_deps_str = _generate_static_public_deps_string(args, static_deps, toolchain_name)
1833            static_deps_target_str = _generate_static_deps_target_string(args, static_deps, toolchain_name)
1834            public_deps_pattern = r"  public_deps\s*=\s*\[\s*([^]]*)\s*\]"
1835            toolchain_gn = re.sub(public_deps_pattern, public_deps_str, toolchain_gn, re.DOTALL)
1836            static_deps_target_pattern = re.compile(r'ohos_prebuilt_static_library\("([^"]+\.a)"\)\s*\{[^}]*\}', re.DOTALL)
1837            toolchain_gn = static_deps_target_pattern.sub("", toolchain_gn)
1838            # toolchain_gn = re.sub(r"[\n]{2,}", "\n", toolchain_gn, re.DOTALL) # 删除多余换行符
1839            toolchain_gn += "\n"
1840            toolchain_gn += static_deps_target_str
1841        fd = os.open(toolchain_gn_file, os.O_WRONLY | os.O_CREAT, mode=0o640)
1842        fp = os.fdopen(fd, 'w')
1843        fp.write(toolchain_gn)
1844        fp.close()
1845
1846
1847def _get_toolchain_gn_file(lib_out_dir, out_name):
1848    unzipped_out_name = out_name.replace(".z.", ".")
1849    if os.path.exists(os.path.join(lib_out_dir, out_name)):
1850        return out_name
1851    elif os.path.exists(os.path.join(lib_out_dir, unzipped_out_name)):
1852        return unzipped_out_name
1853    else:
1854        print('Output file not found in toolchain dir.')
1855        return ''
1856
1857
1858def _toolchain_gn_copy(args, module, out_name):
1859    gn_path = os.path.join(args.get("out_path"), "component_package", args.get("part_path"),
1860                           "innerapis", module, "BUILD.gn")
1861    for i in args.get("toolchain_info").keys():
1862        lib_out_dir = os.path.join(args.get("out_path"), "component_package",
1863                                   args.get("part_path"), "innerapis", module, i, "libs")
1864        so_name = _get_toolchain_gn_file(lib_out_dir, out_name)
1865        if not so_name:
1866            continue
1867        toolchain_gn_file = os.path.join(args.get("out_path"), "component_package",
1868                                         args.get("part_path"), "innerapis", module, i, "BUILD.gn")
1869        if not os.path.exists(toolchain_gn_file):
1870            os.mknod(toolchain_gn_file)
1871        _toolchain_gn_modify(args, module, i, gn_path, so_name, toolchain_gn_file)
1872
1873
1874def _parse_module_list(args):
1875    module_list = []
1876    publicinfo_path = os.path.join(args.get("out_path"),
1877                                   args.get("subsystem_name"), args.get("part_name"), "publicinfo")
1878    print('publicinfo_path', publicinfo_path)
1879    if os.path.exists(publicinfo_path) is False:
1880        return module_list
1881    publicinfo_dir = os.listdir(publicinfo_path)
1882    for filename in publicinfo_dir:
1883        if filename.endswith(".json"):
1884            module_name = filename.split(".json")[0]
1885            module_list.append(module_name)
1886            print('filename', filename)
1887    print('module_list', module_list)
1888    return module_list
1889
1890
1891def _lib_special_handler(part_name, module, args):
1892    if part_name == 'mksh':
1893        mksh_file_path = os.path.join(args.get('out_path'), 'startup', 'init', 'sh')
1894        sh_out = os.path.join(args.get("out_path"), "thirdparty", "mksh")
1895        if os.path.isfile(mksh_file_path):
1896            shutil.copy(mksh_file_path, sh_out)
1897    if module == 'blkid':
1898        blkid_file_path = os.path.join(args.get('out_path'), 'filemanagement', 'storage_service', 'blkid')
1899        blkid_out = os.path.join(args.get("out_path"), "thirdparty", "e2fsprogs")
1900        if os.path.isfile(blkid_file_path):
1901            shutil.copy(blkid_file_path, blkid_out)
1902    if module == 'grpc_cpp_plugin':
1903        blkid_file_path = os.path.join(args.get('out_path'), 'clang_x64', 'thirdparty', 'grpc', 'grpc_cpp_plugin')
1904        blkid_out = os.path.join(args.get("out_path"), "thirdparty", "grpc")
1905        if os.path.isfile(blkid_file_path):
1906            shutil.copy(blkid_file_path, blkid_out)
1907
1908
1909def _handle_module(args, components_json, module):
1910    public_deps_list = []
1911    if _is_innerkit(components_json, args.get("part_name"), module) == False:
1912        return public_deps_list
1913    json_data = _get_json_data(args, module)
1914    _lib_special_handler(args.get("part_name"), module, args)
1915    libstatus, is_ohos_ets_copy = _copy_lib(args, json_data, module)
1916    includes = _handle_includes_data(json_data)
1917    deps = _handle_deps_data(json_data)
1918    _copy_includes(args, module, includes)
1919    _list = _generate_build_gn(args, module, json_data, deps, components_json, public_deps_list, is_ohos_ets_copy)
1920    _toolchain_gn_copy(args, module, json_data['out_name'])
1921    return _list
1922
1923
1924def _copy_required_docs(args, public_deps_list):
1925    _copy_bundlejson(args, public_deps_list)
1926    _copy_license(args)
1927    _copy_readme(args)
1928
1929
1930def _finish_component_build(args):
1931    if args.get("build_type") in [0, 1]:
1932        _hpm_status = _hpm_pack(args)
1933        if _hpm_status:
1934            _copy_hpm_pack(args)
1935
1936
1937def _generate_component_package(args, components_json):
1938    modules = _parse_module_list(args)
1939    print('modules', modules)
1940    if len(modules) == 0:
1941        return
1942    is_component_build = False
1943    _public_deps_list = []
1944    for module in modules:
1945        module_deps_list = _handle_module(args, components_json, module)
1946        if module_deps_list:
1947            _public_deps_list.extend(module_deps_list)
1948        is_component_build = True
1949    if is_component_build:
1950        _copy_required_docs(args, _public_deps_list)
1951        _finish_component_build(args)
1952
1953
1954def _get_part_subsystem(components_json: dict):
1955    jsondata = dict()
1956    try:
1957        for component, v in components_json.items():
1958            jsondata[component] = v.get('subsystem')
1959    except Exception as e:
1960        print('--_get_part_subsystem parse json error--')
1961    return jsondata
1962
1963
1964def _get_parts_path_info(components_json):
1965    jsondata = dict()
1966    try:
1967        for component, v in components_json.items():
1968            jsondata[component] = v.get('path')
1969    except Exception as e:
1970        print('--_get_part_subsystem parse json error--')
1971    return jsondata
1972
1973
1974def _get_toolchain_info(root_path):
1975    jsondata = ""
1976    json_path = os.path.join(root_path + "/build/indep_configs/variants/common/toolchain.json")
1977    with os.fdopen(os.open(json_path, os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR),
1978                   'r', encoding='utf-8') as f:
1979        try:
1980            jsondata = json.load(f)
1981        except Exception as e:
1982            print('--_get_toolchain_info parse json error--')
1983    return jsondata
1984
1985
1986def _get_parts_path(json_data, part_name):
1987    parts_path = None
1988    if json_data.get(part_name) is not None:
1989        parts_path = json_data[part_name]
1990    return parts_path
1991
1992
1993def _hpm_pack(args):
1994    part_path = os.path.join(args.get("out_path"), "component_package", args.get("part_path"))
1995    cmd = ['hpm', 'pack']
1996    try:
1997        subprocess.run(cmd, shell=False, cwd=part_path)
1998    except Exception as e:
1999        print("{} pack fail".format(args.get("part_name")))
2000        return 0
2001    print("{} pack succ".format(args.get("part_name")))
2002    return 1
2003
2004
2005def _copy_hpm_pack(args):
2006    hpm_packages_path = args.get('hpm_packages_path')
2007    part_path = os.path.join(args.get("out_path"), "component_package", args.get("part_path"))
2008    dirs = os.listdir(part_path)
2009    tgz_file_name = ''
2010    for file in dirs:
2011        if file.endswith(".tgz"):
2012            tgz_file_name = file
2013    tgz_file_out = os.path.join(part_path, tgz_file_name)
2014    if tgz_file_name:
2015        shutil.copy(tgz_file_out, hpm_packages_path)
2016
2017
2018def _make_hpm_packages_dir(root_path):
2019    _out_path = os.path.join(root_path, 'out')
2020    hpm_packages_path = os.path.join(_out_path, 'hpm_packages')
2021    os.makedirs(hpm_packages_path, exist_ok=True)
2022    return hpm_packages_path
2023
2024
2025def _del_exist_component_package(out_path):
2026    _component_package_path = os.path.join(out_path, 'component_package')
2027    if os.path.isdir(_component_package_path):
2028        try:
2029            print('del dir component_package start..')
2030            shutil.rmtree(_component_package_path)
2031            print('del dir component_package end..')
2032        except Exception as e:
2033            print('del dir component_package FAILED')
2034
2035
2036def _get_component_check(local_test) -> list:
2037    check_list = []
2038    if local_test == 0:
2039        contents = urllib.request.urlopen(
2040            "https://ci.openharmony.cn/api/daily_build/component/check/list").read().decode(
2041            encoding="utf-8")
2042        _check_json = json.loads(contents)
2043        try:
2044            check_list.extend(_check_json["data"]["dep_list"])
2045            check_list.extend(_check_json["data"]["indep_list"])
2046        except Exception as e:
2047            print("Call the component check API something wrong, plz check the API return..")
2048    check_list = list(set(check_list))
2049    check_list = sorted(check_list)
2050    return check_list
2051
2052
2053def _package_interface(args, parts_path_info, part_name, subsystem_name, components_json):
2054    part_path = _get_parts_path(parts_path_info, part_name)
2055    if part_path is None:
2056        return
2057    args.update({"subsystem_name": subsystem_name, "part_name": part_name,
2058                 "part_path": part_path})
2059    if part_name in [
2060        "musl",  # 从obj/third_party/musl/usr 下提取到includes和libs
2061        "developer_test",  # 同rust
2062        "drivers_interface_display",  # 驱动的, 新建一个libs目录/ innerapi同名文件
2063        "runtime_core",  # 编译参数, 所有下面的innerapi的cflags都不
2064        "drivers_interface_usb",  # 同驱动
2065        "drivers_interface_ril",  # 同驱动
2066        "skia",
2067        "variants_default",
2068    ]:
2069        _process_part(args, parts_path_info, part_name, subsystem_name, components_json)
2070    else:
2071        _generate_component_package(args, components_json)
2072
2073
2074def _get_exclusion_list(root_path):
2075    part_black_list_path = os.path.join(root_path, "build", "indep_configs", "config",
2076                                        "binary_package_exclusion_list.json")
2077    data = []
2078    try:
2079        with open(part_black_list_path, 'r') as f:
2080            data = json.load(f)
2081    except FileNotFoundError:
2082        print(f"can not find file: {part_black_list_path}.")
2083    except Exception as e:
2084        print(f"{part_black_list_path}: \n {e}")
2085    return data
2086
2087
2088def additional_comoponents_json():
2089    return {"rust": {
2090        "innerapis": [],
2091        "path": "third_party/rust",
2092        "subsystem": "thirdparty",
2093        "variants": []
2094    },
2095        "developer_test": {
2096            "innerapis": [],
2097            "path": "test/testfwk/developer_test",
2098            "subsystem": "testfwk",
2099            "variants": []
2100        },
2101        "variants_default": {
2102        "innerapis": [],
2103        "path": "variants/variants_default",
2104        "subsystem": "build",
2105        "variants": []
2106        },
2107    }
2108
2109
2110def generate_component_package(out_path, root_path, components_list=None, build_type=0, organization_name='ohos',
2111                               os_arg='linux', build_arch_arg='x86', local_test=0):
2112    """
2113
2114    Args:
2115        out_path: output path of code default : out/rk3568
2116        root_path: root path of code default : oh/
2117        components_list: list of all components that need to be built
2118        build_type: build type
2119            0: default pack,do not change organization_name
2120            1: pack ,change organization_name
2121            2: do not pack,do not change organization_name
2122        organization_name: default ohos, if diff then change
2123        os_arg: default : linux
2124        build_arch_arg:  default : x86
2125        local_test: 1 to open local test , default 0 to close
2126    Returns:
2127
2128    """
2129    start_time = time.time()
2130    components_json = _get_components_json(out_path)
2131    additional_comoponents_json_data = additional_comoponents_json()
2132    components_json.update(additional_comoponents_json_data)
2133    part_subsystem = _get_part_subsystem(components_json)
2134    parts_path_info = _get_parts_path_info(components_json)
2135    hpm_packages_path = _make_hpm_packages_dir(root_path)
2136    toolchain_info = _get_toolchain_info(root_path)
2137
2138    ### add
2139    exclusion_list = _get_exclusion_list(root_path)  # 黑名单列表
2140    # 如果没有提供 components_list,则默认为所有非黑名单组件
2141    all_components = components_json.keys()
2142    if local_test == 1:
2143        components_list = components_list.split(",") if components_list else all_components
2144    elif local_test == 0:
2145        if components_list:
2146            components_list = [component for component in components_list.split(",") if component not in exclusion_list]
2147        else:
2148            components_list = [component for component in all_components if component not in exclusion_list]
2149        # 如果 components_list 为空,则退出程序
2150        if not components_list:
2151            sys.exit("stop for no target to pack..")
2152    print('components_list', components_list)
2153
2154    # del component_package
2155    _del_exist_component_package(out_path)
2156    args = {"out_path": out_path, "root_path": root_path,
2157            "os": os_arg, "buildArch": build_arch_arg, "hpm_packages_path": hpm_packages_path,
2158            "build_type": build_type, "organization_name": organization_name,
2159            "toolchain_info": toolchain_info,
2160            "static_deps": {}
2161            }
2162    for key, value in part_subsystem.items():
2163        part_name = key
2164        subsystem_name = value
2165        if not components_list or part_name in components_list:
2166            _package_interface(args, parts_path_info, part_name, subsystem_name, components_json)
2167    end_time = time.time()
2168    run_time = end_time - start_time
2169    print("generate_component_package out_path", out_path)
2170    print(f"Generating binary product package takes time:{run_time}")
2171
2172
2173def main():
2174    py_args = _get_args()
2175    generate_component_package(py_args.out_path,
2176                               py_args.root_path,
2177                               components_list=py_args.components_list,
2178                               build_type=py_args.build_type,
2179                               organization_name=py_args.organization_name,
2180                               os_arg=py_args.os_arg,
2181                               build_arch_arg=py_args.build_arch,
2182                               local_test=py_args.local_test)
2183
2184
2185if __name__ == '__main__':
2186    main()
2187