1# Copyright (c) 2021 Huawei Device Co., Ltd. 2# Licensed under the Apache License, Version 2.0 (the "License"); 3# you may not use this file except in compliance with the License. 4# You may obtain a copy of the License at 5# 6# http://www.apache.org/licenses/LICENSE-2.0 7# 8# Unless required by applicable law or agreed to in writing, software 9# distributed under the License is distributed on an "AS IS" BASIS, 10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11# See the License for the specific language governing permissions and 12# limitations under the License. 13 14import("//build/config/python.gni") 15import("//build/ohos/app/app_internal.gni") 16import("//build/ohos/notice/notice.gni") 17import("//build/ohos_var.gni") 18import("//build/templates/common/collect_target.gni") 19import("//build/templates/metadata/module_info.gni") 20 21declare_args() { 22 app_need_publicity = false 23} 24 25# Declare an OHOS AppScope target 26# 27# Variables: 28# app_profile: common config of hap. 29# sources: list of asset files to be included in hap. 30# 31template("ohos_app_scope") { 32 forward_variables_from(invoker, [ "testonly" ]) 33 assert(defined(invoker.app_profile), 34 "app_profile must be defined for ohos_app_scope") 35 assert(defined(invoker.sources), "sources must be defined for ohos_app_scope") 36 37 _metadata = "$target_gen_dir/$target_name.metadata" 38 _metadata_target = "${target_name}__metadata" 39 write_meta_data(_metadata_target) { 40 forward_variables_from(invoker, [ "app_profile" ]) 41 type = "app_profile" 42 meta_data = _metadata 43 resources = invoker.sources 44 app_profile = invoker.app_profile 45 } 46 group(target_name) { 47 public_deps = [ ":$_metadata_target" ] 48 } 49} 50 51# Declare an OHOS assets target 52# 53# Variables: 54# deps: dependencies of this target. 55# sources: list of asset files to be included in hap. 56# 57template("ohos_assets") { 58 forward_variables_from(invoker, [ "testonly" ]) 59 assert(defined(invoker.sources), "sources must be defined for ohos_assets") 60 _metadata = "$target_gen_dir/$target_name.metadata" 61 62 _metadata_target = "${target_name}__metadata" 63 write_meta_data(_metadata_target) { 64 forward_variables_from(invoker, [ "deps" ]) 65 type = "assets" 66 meta_data = _metadata 67 raw_assets = invoker.sources 68 } 69 group(target_name) { 70 public_deps = [ ":$_metadata_target" ] 71 } 72} 73 74# Declare a js assets target 75# 76# Variables: 77# source_dir: js assets directory, only one directory supported, string not list. 78# js2abc: whether to transform js bundle to ark bytecode, default value 79# follows build_ark. 80# ets2abc: whether to transform ets bundle to ark bytecode, default value false 81# deps: dependencies of this target. 82# 83template("ohos_js_assets") { 84 forward_variables_from(invoker, [ "testonly" ]) 85 assert(defined(invoker.source_dir), 86 "source_dir must be defined for ohos_js_assets") 87 88 _metadata = "$target_gen_dir/$target_name.metadata" 89 _metadata_target = "${target_name}__metadata" 90 write_meta_data(_metadata_target) { 91 forward_variables_from(invoker, 92 [ 93 "source_dir", 94 "deps", 95 ]) 96 meta_data = _metadata 97 if (defined(invoker.ets2abc) && invoker.ets2abc) { 98 type = "ets_assets" 99 ets_assets = [ source_dir ] 100 } else if (defined(invoker.js2abc) && invoker.js2abc) { 101 type = "js_assets" 102 js_assets = [ source_dir ] 103 } else { 104 type = "unresolved_assets" 105 unresolved_assets = [ source_dir ] 106 } 107 if (defined(invoker.hap_profile)) { 108 hap_profile = invoker.hap_profile 109 } 110 } 111 group(target_name) { 112 public_deps = [ ":$_metadata_target" ] 113 } 114} 115 116# Declare an OHOS resource target 117# 118# Variables: 119# deps: dependencies of this target. 120# sources: list of resource files to be compiled. 121# hap_profile: hap_profile is used when building resources. 122# 123template("ohos_resources") { 124 forward_variables_from(invoker, [ "testonly" ]) 125 assert(defined(invoker.sources), "sources must be defined for ohos_resources") 126 _metadata = "$target_gen_dir/$target_name.metadata" 127 128 _deps = [] 129 if (defined(invoker.deps)) { 130 _deps += invoker.deps 131 } 132 133 module_config = "" 134 module_configs = string_split(invoker.hap_profile, "/") 135 foreach(_module_config, module_configs) { 136 module_config = _module_config 137 } 138 _generated_profile = "$target_gen_dir/${target_name}/${module_config}" 139 _metadata_target = "${target_name}__metadata" 140 write_meta_data(_metadata_target) { 141 forward_variables_from(invoker, [ "package_name" ]) 142 type = "resources" 143 meta_data = _metadata 144 resources = invoker.sources 145 hap_profile = _generated_profile 146 deps = _deps 147 possible_deps = _deps 148 } 149 150 _deps += [ ":$_metadata_target" ] 151 152 # compile_resources target here only used for concat app.json to module.json 153 _compile_profile_target = "${target_name}__compile_profile" 154 merge_profile(_compile_profile_target) { 155 forward_variables_from(invoker, 156 [ 157 "deps", 158 "hap_profile", 159 ]) 160 meta_data = _metadata 161 generated_profile = _generated_profile 162 if (defined(deps)) { 163 deps += _deps 164 } else { 165 deps = _deps 166 } 167 } 168 169 _deps += [ ":$_compile_profile_target" ] 170 171 # compile_resources target here only used for resources.h generation 172 _compile_resources_target = "${target_name}__compile_resources" 173 _generated_header_dir = "$target_gen_dir/$target_name" 174 compile_resources(_compile_resources_target) { 175 forward_variables_from(invoker, 176 [ 177 "deps", 178 "package_name", 179 ]) 180 hap_profile = _generated_profile 181 meta_data = _metadata 182 generated_header_dir = _generated_header_dir 183 if (defined(deps)) { 184 deps += _deps 185 } else { 186 deps = _deps 187 } 188 } 189 190 _resources_config = "${target_name}__resources_headers" 191 config(_resources_config) { 192 include_dirs = [ _generated_header_dir ] 193 } 194 195 group(target_name) { 196 public_deps = [ ":$_metadata_target" ] 197 deps = [ 198 ":$_compile_profile_target", 199 ":$_compile_resources_target", 200 ] 201 public_configs = [ ":$_resources_config" ] 202 } 203} 204 205if (app_need_publicity) { 206 template("_ohos_publicity") { 207 forward_variables_from(invoker, 208 [ 209 "_hap_name", 210 "module_install_dir", 211 "relative_install_dir", 212 ]) 213 214 action(target_name) { 215 script = "//build/scripts/collect_publicity.py" 216 module_type = "app" 217 if (defined(module_install_dir)) { 218 not_needed([ "relative_install_dir" ]) 219 install_dir = string_replace(module_install_dir, "${module_type}/", "") 220 } else if (defined(relative_install_dir)) { 221 install_dir = relative_install_dir 222 } else { 223 install_dir = "" 224 } 225 226 if (install_dir == "") { 227 print( 228 "${invoker.module_label} not set install dir, empty install dir is invalid.") 229 } 230 args = [] 231 if (defined(invoker.publicity_file)) { 232 inputs = [ invoker.publicity_file ] 233 source = inputs[0] 234 args += [ 235 "--source", 236 rebase_path(source, root_build_dir), 237 ] 238 } else { 239 print("${invoker.module_label} need to set publicity_file.") 240 } 241 outputs = [ "${root_build_dir}/app_publicity/${install_dir}/${_hap_name}_publicity.xml" ] 242 args += [ 243 "--output", 244 rebase_path(outputs[0], root_build_dir), 245 ] 246 } 247 } 248} 249 250template("ohos_app") { 251 forward_variables_from(invoker, 252 [ 253 "testonly", 254 "install_enable", 255 "install_images", 256 "module_install_dir", 257 "relative_install_dir", 258 ]) 259 260 _test_target = defined(testonly) && testonly 261 _unsigned_hap_path_list = 262 "${target_out_dir}/${target_name}/unsigned_hap_path_list.json" 263 264 _abs_path = get_path_info("./", "abspath") 265 _hap_out_dir = "${target_out_dir}/${target_name}" 266 if (defined(invoker.hap_out_dir)) { 267 _hap_out_dir = invoker.hap_out_dir 268 } 269 270 _hap_name = target_name 271 if (defined(invoker.hap_name)) { 272 _hap_name = invoker.hap_name 273 } 274 275 if (defined(invoker.build_profile)) { 276 build_profile = invoker.build_profile 277 } else { 278 build_profile = "./build-profile.json5" 279 } 280 281 _js_build_mode = "release" 282 if (defined(invoker.js_build_mode)) { 283 _js_build_mode = invoker.js_build_mode 284 } 285 286 if (defined(invoker.system_lib_deps)) { 287 _system_lib_deps = invoker.system_lib_deps 288 } 289 290 _main_target_name = target_name 291 292 if (defined(invoker.subsystem_name) && defined(invoker.part_name)) { 293 _subsystem_name = invoker.subsystem_name 294 _part_name = invoker.part_name 295 } else if (defined(invoker.part_name)) { 296 _part_name = invoker.part_name 297 _part_subsystem_info_file = 298 "$root_build_dir/build_configs/parts_info/part_subsystem.json" 299 _arguments = [ 300 "--part-name", 301 _part_name, 302 "--part-subsystem-info-file", 303 rebase_path(_part_subsystem_info_file, root_build_dir), 304 ] 305 _get_subsystem_script = "//build/templates/common/get_subsystem_name.py" 306 _subsystem_name = 307 exec_script(_get_subsystem_script, _arguments, "trim string") 308 } else if (defined(invoker.subsystem_name)) { 309 _subsystem_name = invoker.subsystem_name 310 _part_name = _subsystem_name 311 } else { 312 _subsystem_name = "build" 313 _part_name = "build_framework" 314 } 315 316 assert(_subsystem_name != "") # Mark as used 317 assert(_part_name != "") # Mark as used 318 319 module_label = get_label_info(":${target_name}", "label_with_toolchain") 320 _collect_target = "${target_name}__collect" 321 collect_module_target(_collect_target) { 322 forward_variables_from(invoker, [ "install_images" ]) 323 } 324 325 if (!defined(install_enable)) { 326 install_enable = true 327 } 328 329 if (!_test_target) { 330 if (defined(install_images)) { 331 app_allow_images = [ "system" ] 332 allow_image = filter_exclude(install_images, app_allow_images) 333 assert( 334 allow_image == [], 335 "${module_label} has invaild install_images: ${invoker.install_images}, allowed values: ${app_allow_images}") 336 } 337 338 if (defined(module_install_dir)) { 339 app_allow_path = [ "app/*" ] 340 if (filter_exclude([ module_install_dir ], app_allow_path) != [] || 341 module_install_dir == "app/") { 342 assert( 343 false, 344 "${module_label} has invaild module_install_dir: ${invoker.module_install_dir}, allowed values: app/{{app_name}}") 345 } 346 } 347 348 if (!defined(module_install_dir) && !defined(relative_install_dir)) { 349 print( 350 "Set module_install_dir or relative_install_dir field in the ${module_label}. Do not install the module to app.") 351 } 352 353 if (app_need_publicity) { 354 if (install_enable) { 355 _publicity_target = "${_main_target_name}_publicity" 356 _ohos_publicity(_publicity_target) { 357 forward_variables_from(invoker, [ "publicity_file" ]) 358 } 359 } 360 } 361 } 362 363 _module_info_target = "${_main_target_name}_info" 364 generate_module_info(_module_info_target) { 365 module_name = _main_target_name 366 module_type = "app" 367 module_source_dir = get_path_info(_hap_out_dir, "dir") 368 369 if (defined(invoker.install_images)) { 370 module_install_images = [] 371 module_install_images += invoker.install_images 372 } else { 373 module_install_images = [ "system" ] 374 } 375 376 if (defined(invoker.symlink_target_name)) { 377 symlink_target_name = invoker.symlink_target_name 378 } 379 380 notice = "$target_out_dir/$_main_target_name.notice.txt" 381 } 382 383 _notice_target = "${target_name}_notice" 384 collect_notice(_notice_target) { 385 forward_variables_from(invoker, 386 [ 387 "license_as_sources", 388 "license_file", 389 ]) 390 module_name = _main_target_name 391 module_type = "app" 392 module_source_dir = get_label_info(":${_main_target_name}", "dir") 393 } 394 395 _compile_app_target = "${target_name}_compile_app" 396 compile_app(_compile_app_target) { 397 build_mode = _js_build_mode 398 cwd = _abs_path 399 unsigned_hap_path_list = _unsigned_hap_path_list 400 deps = [ 401 ":${_collect_target}", 402 ":${_notice_target}", 403 ] 404 405 if (!_test_target && app_need_publicity) { 406 if (install_enable) { 407 deps += [ ":${_publicity_target}" ] 408 } else { 409 if (defined(invoker.publicity_file)) { 410 print( 411 "${module_label} is not install, please delete set publicity_file: ${invoker.publicity_file}.") 412 } 413 } 414 } else { 415 if (defined(invoker.publicity_file)) { 416 not_needed(invoker, [ "publicity_file" ]) 417 } 418 } 419 if (defined(invoker.deps)) { 420 deps += invoker.deps 421 } 422 if (defined(invoker.system_lib_deps)) { 423 system_lib_deps = _system_lib_deps 424 deps += _system_lib_deps 425 } 426 if (defined(invoker.test_hap)) { 427 test_hap = invoker.test_hap 428 } 429 if (defined(invoker.test_module)) { 430 test_module = invoker.test_module 431 } 432 if (defined(invoker.module_libs_dir)) { 433 module_libs_dir = invoker.module_libs_dir 434 } 435 if (defined(invoker.sdk_home)) { 436 sdk_home = invoker.sdk_home 437 } else { 438 sdk_home = "//prebuilts/ohos-sdk/linux" 439 } 440 if (defined(invoker.sdk_type_name)) { 441 sdk_type_name = invoker.sdk_type_name 442 } 443 if (defined(invoker.hvigor_home)) { 444 hvigor_home = invoker.hvigor_home 445 } 446 if (defined(invoker.build_modules)) { 447 build_modules = invoker.build_modules 448 } 449 if (defined(invoker.assemble_type)) { 450 assemble_type = invoker.assemble_type 451 } 452 if (defined(invoker.build_level)) { 453 build_level = invoker.build_level 454 } 455 } 456 _hap_list = "${target_out_dir}/${target_name}/hap_list.json" 457 if (defined(invoker.hap_list)) { 458 _hap_list_json = { 459 do_filter = true 460 hap_list = invoker.hap_list 461 } 462 write_file(_hap_list, _hap_list_json, "json") 463 } 464 app_sign(target_name) { 465 forward_variables_from(invoker, 466 [ 467 "private_key_path", 468 "signature_algorithm", 469 "certificate_profile", 470 "keystore_path", 471 "keystore_password", 472 "key_alias", 473 "certificate_file", 474 "compatible_version", 475 ]) 476 unsigned_hap_path_list = _unsigned_hap_path_list 477 deps = [ 478 ":$_compile_app_target", 479 ":$_module_info_target", 480 ] 481 hap_out_dir = _hap_out_dir 482 hap_name = _hap_name 483 hap_list = _hap_list 484 install_module_info = { 485 module_def = get_label_info(":$target_name", "label_with_toolchain") 486 module_info_file = 487 rebase_path(get_label_info(module_def, "target_out_dir"), 488 root_build_dir) + "/${target_name}_module_info.json" 489 toolchain = current_toolchain 490 toolchain_out_dir = rebase_path(root_out_dir, root_build_dir) 491 part_name = _part_name 492 subsystem_name = _subsystem_name 493 } 494 } 495} 496 497# Declare an OHOS hap target 498# 499# Variables: 500# deps: dependencies of this target. 501# hap_name: name of output hap file. 502# final_hap_path: full path of output hap file, final_hap_path overwrites hap_name. 503# js2abc: whether to transform js bundle to ark bytecode, default value 504# follows build_ark. 505# ets2abc: whether to transform js bundle to ark bytecode, default value false 506# 507# 508template("ohos_hap") { 509 forward_variables_from(invoker, 510 [ 511 "testonly", 512 "install_enable", 513 "install_images", 514 "module_install_dir", 515 "relative_install_dir", 516 ]) 517 assert(defined(invoker.hap_profile), 518 "hap_profile must be defined for ohos_hap") 519 520 _test_target = defined(testonly) && testonly 521 _deps = [] 522 if (defined(invoker.deps)) { 523 _deps = invoker.deps 524 } 525 526 _hap_profile = invoker.hap_profile 527 _hap_name = target_name 528 if (defined(invoker.hap_name)) { 529 _hap_name = invoker.hap_name 530 } 531 532 _hap_path = "$target_out_dir/$_hap_name.hap" 533 if (defined(invoker.final_hap_path)) { 534 _hap_path = invoker.final_hap_path 535 } 536 537 _js2abc = build_ark 538 if (defined(invoker.js2abc)) { 539 _js2abc = invoker.js2abc 540 } 541 542 _ets2abc = false 543 if (defined(invoker.ets2abc)) { 544 _ets2abc = invoker.ets2abc 545 } 546 547 if (_ets2abc) { 548 _js2abc = false 549 } 550 551 _js_build_mode = "release" 552 if (defined(invoker.js_build_mode)) { 553 _js_build_mode = invoker.js_build_mode 554 } 555 556 _main_target_name = target_name 557 558 if (defined(invoker.subsystem_name) && defined(invoker.part_name)) { 559 _subsystem_name = invoker.subsystem_name 560 _part_name = invoker.part_name 561 } else if (defined(invoker.part_name)) { 562 _part_name = invoker.part_name 563 _part_subsystem_info_file = 564 "$root_build_dir/build_configs/parts_info/part_subsystem.json" 565 _arguments = [ 566 "--part-name", 567 _part_name, 568 "--part-subsystem-info-file", 569 rebase_path(_part_subsystem_info_file, root_build_dir), 570 ] 571 _get_subsystem_script = "//build/templates/common/get_subsystem_name.py" 572 _subsystem_name = 573 exec_script(_get_subsystem_script, _arguments, "trim string") 574 } else if (defined(invoker.subsystem_name)) { 575 _subsystem_name = invoker.subsystem_name 576 _part_name = _subsystem_name 577 } else { 578 _subsystem_name = "build" 579 _part_name = "build_framework" 580 } 581 582 assert(_subsystem_name != "") # Mark as used 583 assert(_part_name != "") # Mark as used 584 585 # metadata is used to record all necessary data for hap. 586 _metadata_target = "${target_name}__metadata" 587 _meta_data = "$target_gen_dir/$target_name.metadata" 588 write_meta_data(_metadata_target) { 589 forward_variables_from(invoker, 590 [ 591 "raw_assets", 592 "resources", 593 "js_assets", 594 "ets_assets", 595 ]) 596 hap_profile = invoker.hap_profile 597 meta_data = _meta_data 598 possible_deps = _deps 599 type = "hap" 600 js2abc = _js2abc 601 hap_path = _hap_path 602 } 603 604 _js_assets_target = "${target_name}__js_assets" 605 _packaged_js_assets = "$target_out_dir/$target_name/js_assets.zip" 606 compile_js_assets(_js_assets_target) { 607 hap_profile = _hap_profile 608 packaged_js_assets = _packaged_js_assets 609 meta_data = _meta_data 610 deps = [ ":$_metadata_target" ] + _deps 611 build_mode = _js_build_mode 612 js2abc = _js2abc 613 ets2abc = _ets2abc 614 if (defined(testonly) && testonly == true) { 615 main_target_name = _main_target_name 616 } 617 } 618 619 _resources_target = "${target_name}__compile_resources" 620 _packaged_resources = "$target_out_dir/$target_name/resources.zip" 621 _generated_header_dir = "$target_out_dir/$target_name" 622 compile_resources(_resources_target) { 623 hap_profile = _hap_profile 624 packaged_resources = _packaged_resources 625 generated_header_dir = _generated_header_dir 626 meta_data = _meta_data 627 deps = [ ":$_metadata_target" ] + _deps 628 } 629 630 module_label = get_label_info(":${target_name}", "label_with_toolchain") 631 _collect_target = "${target_name}__collect" 632 collect_module_target(_collect_target) { 633 forward_variables_from(invoker, [ "install_images" ]) 634 } 635 636 _notice_target = "${target_name}__notice" 637 collect_notice(_notice_target) { 638 forward_variables_from(invoker, 639 [ 640 "license_as_sources", 641 "license_file", 642 ]) 643 module_type = "app" 644 module_name = _main_target_name 645 module_source_dir = get_label_info(":${_main_target_name}", "dir") 646 } 647 648 if (!defined(install_enable)) { 649 install_enable = true 650 } 651 652 if (!_test_target) { 653 if (defined(install_images)) { 654 app_allow_images = [ "system" ] 655 allow_image = filter_exclude(install_images, app_allow_images) 656 assert( 657 allow_image == [], 658 "${module_label} has invaild install_images: ${invoker.install_images}, allowed values: ${app_allow_images}") 659 } 660 661 if (defined(module_install_dir)) { 662 app_allow_path = [ "app/*" ] 663 if (filter_exclude([ module_install_dir ], app_allow_path) != [] || 664 module_install_dir == "app/") { 665 assert( 666 false, 667 "${module_label} has invaild module_install_dir: ${invoker.module_install_dir}, allowed values: app/{{app_name}}") 668 } 669 } 670 671 if (!defined(module_install_dir) && !defined(relative_install_dir)) { 672 print( 673 "Set module_install_dir or relative_install_dir field in the ${module_label}. Do not install the module to app.") 674 } 675 676 if (app_need_publicity) { 677 if (install_enable) { 678 _publicity_target = "${_main_target_name}_publicity" 679 _ohos_publicity(_publicity_target) { 680 forward_variables_from(invoker, [ "publicity_file" ]) 681 } 682 } 683 } 684 } 685 686 _module_info_target = "${_main_target_name}_info" 687 generate_module_info(_module_info_target) { 688 module_name = _main_target_name 689 module_type = "app" 690 691 module_source_dir = get_path_info(_hap_path, "dir") 692 module_install_name = get_path_info(_hap_path, "name") 693 if (defined(invoker.module_install_name)) { 694 module_install_name = invoker.module_install_name 695 } 696 697 module_install_images = [ "system" ] 698 if (defined(invoker.install_images)) { 699 module_install_images = [] 700 module_install_images += invoker.install_images 701 } 702 703 module_output_extension = ".hap" 704 705 if (defined(invoker.symlink_target_name)) { 706 symlink_target_name = invoker.symlink_target_name 707 } 708 notice = "$target_out_dir/$_main_target_name.notice.txt" 709 } 710 711 package_app(target_name) { 712 forward_variables_from(invoker, 713 [ 714 "shared_libraries", 715 "private_key_path", 716 "signature_algorithm", 717 "certificate_profile", 718 "keystore_path", 719 "keystore_password", 720 "key_alias", 721 "certificate_file", 722 "compatible_version", 723 ]) 724 deps = [ 725 ":$_js_assets_target", 726 ":$_metadata_target", 727 ":$_notice_target", 728 ":$_resources_target", 729 ":${_collect_target}", 730 "//developtools/packing_tool:packing_tool", 731 ] 732 if (!_test_target && app_need_publicity) { 733 if (install_enable) { 734 deps += [ ":${_publicity_target}" ] 735 } else { 736 if (defined(invoker.publicity_file)) { 737 print( 738 "${module_label} is not install, please delete set publicity_file: ${invoker.publicity_file}.") 739 } 740 } 741 } else { 742 if (defined(invoker.publicity_file)) { 743 not_needed(invoker, [ "publicity_file" ]) 744 } 745 } 746 if (!skip_gen_module_info) { 747 deps += [ ":$_module_info_target" ] 748 } 749 enable_ark = build_ark 750 if (defined(shared_libraries)) { 751 deps += shared_libraries 752 } 753 packaged_js_assets = _packaged_js_assets 754 packaged_resources = _packaged_resources 755 hap_profile = _hap_profile 756 meta_data = _meta_data 757 hap_path = _hap_path 758 build_mode = _js_build_mode 759 760 install_module_info = { 761 module_def = get_label_info(":$target_name", "label_with_toolchain") 762 module_info_file = 763 rebase_path(get_label_info(module_def, "target_out_dir"), 764 root_build_dir) + "/${target_name}_module_info.json" 765 subsystem_name = _subsystem_name 766 part_name = _part_name 767 toolchain = current_toolchain 768 toolchain_out_dir = rebase_path(root_out_dir, root_build_dir) 769 } 770 } 771} 772