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