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/ohos/copy_ex.gni") 15import("//build/config/python.gni") 16import("//build/ohos/build_var.gni") 17import("//build/ohos/notice/notice.gni") 18import("//build/ohos_var.gni") 19 20declare_args() { 21 sdk_native = "sdk-native" 22 version_script_suffix = ".map.txt" 23 ndk_signature_save_dir = "//interface/sdk-native" 24 ndk_zip_prefix = "native" 25 enable_ndk_doxygen = true 26} 27 28if (use_current_sdk) { 29 # native_dir is native current-sdk release dir, all things redefine base the value. 30 native_dir = "base-current-sdk/linux/${api_version}/native" 31 32 ndk_os_irrelevant_out_dir = "$root_out_dir/${native_dir}" 33 ndk_os_specific_out_dir = "$root_out_dir/${native_dir}" 34 ndk_signature_out_dir = "$root_out_dir/${native_dir}/.others/signature" 35} else { 36 ndk_os_irrelevant_out_dir = "$root_out_dir/${sdk_native}/os-irrelevant" 37 ndk_os_specific_out_dir = "$root_out_dir/${sdk_native}/os-specific" 38 ndk_signature_out_dir = "$root_out_dir/${sdk_native}/signature" 39} 40 41ndk_headers_out_dir = "$ndk_os_irrelevant_out_dir/sysroot/usr/include" 42ndk_libraries_out_dir = "$ndk_os_irrelevant_out_dir/sysroot/usr/lib" 43ndk_docs_out_dir = "$ndk_os_irrelevant_out_dir/docs" 44 45windows_system = "windows" 46linux_system = "linux" 47darwin_system = "darwin" 48ohos_system = "ohos" 49 50if (use_current_sdk) { 51 ndk_windows_specific_out_dir = 52 "${ndk_os_specific_out_dir}/.others/${windows_system}" 53 ndk_darwin_specific_out_dir = 54 "${ndk_os_specific_out_dir}/.others/${darwin_system}" 55 ndk_linux_specific_out_dir = "${ndk_os_specific_out_dir}" 56 ndk_ohos_specific_out_dir = 57 "${ndk_os_specific_out_dir}/.others/${ohos_system}" 58} else { 59 ndk_windows_specific_out_dir = "${ndk_os_specific_out_dir}/${windows_system}" 60 ndk_darwin_specific_out_dir = "${ndk_os_specific_out_dir}/${darwin_system}" 61 ndk_linux_specific_out_dir = "${ndk_os_specific_out_dir}/${linux_system}" 62 ndk_ohos_specific_out_dir = "${ndk_os_specific_out_dir}/${ohos_system}" 63} 64 65ndk_windows_toolchains_out_dir = "${ndk_windows_specific_out_dir}/llvm" 66ndk_windows_tools_out_dir = "${ndk_windows_specific_out_dir}/build-tools" 67 68ndk_darwin_toolchains_out_dir = "${ndk_darwin_specific_out_dir}/llvm" 69ndk_darwin_tools_out_dir = "${ndk_darwin_specific_out_dir}/build-tools" 70 71ndk_linux_toolchains_out_dir = "${ndk_linux_specific_out_dir}/llvm" 72ndk_linux_tools_out_dir = "${ndk_linux_specific_out_dir}/build-tools" 73 74ndk_ohos_toolchains_out_dir = "${ndk_ohos_specific_out_dir}/llvm" 75ndk_ohos_tools_out_dir = "${ndk_ohos_specific_out_dir}/build-tools" 76 77# Generate NDK library from NDK description file. 78# 79# Variables: 80# ndk_description_file: 81# min_compact_version: string specifies the minimal compactible version of NDK. 82# set to major_version in default. 83# 84template("ohos_ndk_library") { 85 forward_variables_from(invoker, [ "testonly" ]) 86 assert(defined(invoker.ndk_description_file), 87 "ndk description file is necessary ") 88 89 _ndk_description_file = invoker.ndk_description_file 90 91 _system_capability = "" 92 if (defined(invoker.system_capability)) { 93 _system_capability = invoker.system_capability 94 } 95 96 _system_capability_headers = "" 97 if (defined(invoker.system_capability_headers)) { 98 _system_capability_headers = invoker.system_capability_headers 99 } 100 101 _deps = [] 102 if (defined(invoker.deps)) { 103 _deps += invoker.deps 104 } 105 106 _ndk_config_output = "$target_gen_dir/$target_name.build_config" 107 _sdk_version = exec_script("//build/ohos/version.py", 108 [ 109 "--version", 110 sdk_version, 111 ], 112 "list lines") 113 _min_compact_version = _sdk_version[0] 114 if (defined(invoker.min_compact_version)) { 115 _min_compact_version = invoker.min_compact_version 116 } 117 assert(_min_compact_version != "0") # mark as used 118 119 _output_name = target_name 120 if (defined(invoker.output_name)) { 121 _output_name = invoker.output_name 122 } 123 124 _output_extension = "z.so" 125 if (defined(invoker.output_extension)) { 126 _output_extension = invoker.output_extension 127 } 128 129 _ndk_stub_target = "${target_name}__ndk_stub" 130 _generated_ndk_stub_file = target_gen_dir + "/${target_name}.ndk/" + 131 get_path_info(_ndk_description_file, "name") + ".c" 132 _current_label = get_label_info(":${target_name}", "label_with_toolchain") 133 action_with_pydeps(_ndk_stub_target) { 134 deps = _deps 135 script = "//build/ohos/ndk/generate_ndk_stub_file.py" 136 depfile = "${target_gen_dir}/${target_name}.d" 137 args = [ 138 "--output", 139 rebase_path(_generated_ndk_stub_file, root_build_dir), 140 "--ndk-description-file", 141 rebase_path(_ndk_description_file, root_build_dir), 142 "--depfile", 143 rebase_path(depfile, root_build_dir), 144 ] 145 inputs = [ _ndk_description_file ] 146 outputs = [ _generated_ndk_stub_file ] 147 148 _ndk_config_info = { 149 label = _current_label 150 lib_name = _output_name 151 system_capability = _system_capability 152 system_capability_headers = _system_capability_headers 153 } 154 metadata = { 155 ndk_config = [ _ndk_config_info ] 156 } 157 } 158 159 _ndk_config_target = "${target_name}__ndk_config" 160 generated_file(_ndk_config_target) { 161 deps = [ ":$_ndk_stub_target" ] 162 output_conversion = "json" 163 outputs = [ _ndk_config_output ] 164 165 data_keys = [ "ndk_config" ] 166 } 167 168 ndk_toolchains = [] 169 if (build_ohos_ndk || use_current_sdk) { 170 ndk_toolchains = [ 171 "//build/toolchain/ohos:ohos_clang_arm", 172 "//build/toolchain/ohos:ohos_clang_arm64", 173 "//build/toolchain/ohos:ohos_clang_x86_64", 174 ] 175 } else if (!is_arkui_x) { 176 # Don't enable cross compile if build_ohos_ndk is false. 177 # Cross compiling in this case may cause build failure in some scenario, 178 # such as build for ASAN. 179 ndk_toolchains = [ "//build/toolchain/ohos:ohos_clang_${target_cpu}" ] 180 } 181 182 if (ndk_toolchains == []) { 183 not_needed([ "_output_extension" ]) 184 } 185 186 _accumulated_deps = [] 187 188 foreach(_toolchain, ndk_toolchains) { 189 if (_toolchain == "//build/toolchain/ohos:ohos_clang_arm") { 190 _ndk_shlib_directory = "arm-linux-ohos" 191 } else if (_toolchain == "//build/toolchain/ohos:ohos_clang_arm64") { 192 _ndk_shlib_directory = "aarch64-linux-ohos" 193 } else if (_toolchain == "//build/toolchain/ohos:ohos_clang_x86_64") { 194 _ndk_shlib_directory = "x86_64-linux-ohos" 195 } 196 197 assert(defined(_ndk_shlib_directory)) 198 _output_dir = "$ndk_libraries_out_dir/$_ndk_shlib_directory" 199 if (defined(invoker.current_ndk_outpath) && 200 invoker.current_ndk_outpath != "" && use_current_sdk) { 201 _output_dir = "${invoker.current_ndk_outpath}/${_ndk_shlib_directory}" 202 } 203 _output_ndk_shlib = "${_output_dir}/lib${_output_name}.${_output_extension}" 204 205 _toolchain_name = get_label_info(_toolchain, "name") 206 207 _ndk_shlib_target = "${target_name}_${_toolchain_name}__ndk_shlib" 208 209 shared_library(_ndk_shlib_target) { 210 forward_variables_from(invoker, 211 [ 212 "cflags", 213 "ldflags", 214 "configs", 215 "libs", 216 "include_dirs", 217 ]) 218 deps = [ ":$_ndk_stub_target" ] 219 sources = [ _generated_ndk_stub_file ] 220 output_dir = target_out_dir + "/$_toolchain_name" 221 output_name = _output_name 222 output_extension = _output_extension 223 } 224 225 _ndk_shlib_copy_target = "${target_name}_${_toolchain_name}__copy" 226 copy(_ndk_shlib_copy_target) { 227 deps = [ ":$_ndk_shlib_target($_toolchain)" ] 228 sources = [ get_label_info(":$_ndk_shlib_target($_toolchain)", 229 "target_out_dir") + 230 "/$_toolchain_name/lib$_output_name.$_output_extension" ] 231 outputs = [ _output_ndk_shlib ] 232 } 233 _accumulated_deps += [ ":$_ndk_shlib_copy_target" ] 234 _accumulated_deps += [ ":$_ndk_shlib_target" ] 235 } 236 237 _ndk_version_script_target = target_name 238 if (current_toolchain == default_toolchain) { 239 # Notice file for different toolchains are the same, it's enough to 240 # collect notice file for default toolchain. 241 _notice_target = "${target_name}__ndk_libraries_notice" 242 collect_notice(_notice_target) { 243 forward_variables_from(invoker, 244 [ 245 "testonly", 246 "license_as_sources", 247 "license_file", 248 ]) 249 module_source_dir = 250 get_label_info(":${_ndk_version_script_target}", "dir") 251 outputs = [ "$ndk_notice_dir/sysroot/usr/lib/lib$_output_name.$_output_extension.txt" ] 252 } 253 _accumulated_deps += [ ":$_notice_target" ] 254 } 255 if (defined(invoker.license_file)) { 256 not_needed(invoker, [ "license_file" ]) 257 } 258 if (defined(invoker.license_as_sources)) { 259 not_needed(invoker, [ "license_as_sources" ]) 260 } 261 262 _generated_version_script = 263 target_gen_dir + "/$target_name" + version_script_suffix 264 action_with_pydeps(_ndk_version_script_target) { 265 deps = _accumulated_deps 266 script = "//build/ohos/ndk/generate_version_script.py" 267 depfile = "${target_gen_dir}/${target_name}.d" 268 args = [ 269 "--output", 270 rebase_path(_generated_version_script, root_build_dir), 271 "--ndk-description-file", 272 rebase_path(_ndk_description_file, root_build_dir), 273 "--shlib-name", 274 _output_name, 275 "--depfile", 276 rebase_path(depfile, root_build_dir), 277 ] 278 outputs = [ _generated_version_script ] 279 } 280} 281 282# Specify an ndk copy target 283# NOTE: It's an internal template, not designed for everyone use. 284# 285# Input variables: 286# dest_dir: Root directory where sources are copied to. 287# sources: List of files and directories to copy to ${dest_dir}. 288# 289template("ohos_ndk_copy") { 290 assert(defined(invoker.sources) && defined(invoker.dest_dir), 291 "sources and dest_dir are necessary ") 292 293 _deps = [] 294 if (defined(invoker.deps)) { 295 _deps += invoker.deps 296 } 297 _dest = invoker.dest_dir 298 299 if (defined(invoker.current_ndk_outpath) && 300 invoker.current_ndk_outpath != "" && use_current_sdk) { 301 _dest = invoker.current_ndk_outpath 302 } 303 304 sources = filter_exclude([ _dest ], [ "*os-irrelevant*" ]) 305 if (sources == []) { 306 _notice_rel_dir = ndk_os_irrelevant_out_dir 307 } else { 308 _notice_rel_dir = ndk_os_specific_out_dir 309 } 310 sources = [] 311 312 _main_target_name = target_name 313 _notice_target = "${target_name}__notice" 314 collect_notice(_notice_target) { 315 forward_variables_from(invoker, 316 [ 317 "testonly", 318 "license_as_sources", 319 "license_file", 320 ]) 321 module_source_dir = get_label_info(":${_main_target_name}", "dir") 322 outputs = [] 323 324 foreach(s, invoker.sources) { 325 outputs += [ ndk_notice_dir + "/" + rebase_path(_dest, _notice_rel_dir) + 326 "/" + get_path_info(s, "file") + ".txt" ] 327 } 328 } 329 _deps += [ ":$_notice_target" ] 330 _clear_dest = true 331 if (defined(invoker.clear_dest) && !invoker.clear_dest) { 332 _clear_dest = false 333 } 334 335 copy_ex(target_name) { 336 forward_variables_from(invoker, 337 [ 338 "testonly", 339 "visibility", 340 ]) 341 forward_variables_from(invoker, [ "outputs" ]) 342 deps = _deps 343 sources = invoker.sources 344 345 if (!defined(outputs)) { 346 outputs = [] 347 foreach(src, invoker.sources) { 348 _all_files = [] 349 _all_files = 350 exec_script("//build/scripts/find.py", 351 [ 352 rebase_path(src, root_build_dir), 353 "--base-dir=" + rebase_path(src, root_build_dir), 354 "--return-relpath", 355 "--follow-symlinks", 356 ], 357 "list lines") 358 359 if (_all_files == [ "." ]) { 360 outputs += [ _dest + "/" + get_path_info(src, "file") ] 361 } else { 362 foreach(f, _all_files) { 363 outputs += [ _dest + "/" + get_path_info(src, "name") + "/$f" ] 364 } 365 } 366 } 367 } 368 369 dest = _dest 370 depfile = "$target_gen_dir/$target_name.d" 371 args = [ 372 "--clear", 373 "--follow-outside-symlinks", 374 "--depfile", 375 rebase_path(depfile, root_build_dir), 376 "--stamp", 377 rebase_path("$target_gen_dir/$target_name.stamp", root_build_dir), 378 ] 379 if (!_clear_dest) { 380 args -= [ "--clear" ] 381 } 382 if (defined(invoker.args)) { 383 args += invoker.args 384 } 385 } 386} 387 388# Specify ndk header files 389# 390# Input variables: 391# dest_dir: Root directory where sources are copied to. 392# sources: List of files and directories to copy to ${dest_dir}. 393# 394template("ohos_ndk_headers") { 395 assert(defined(invoker.sources), "sources are necessary ") 396 397 if (defined(invoker.dest_dir)) { 398 _dest_dir = invoker.dest_dir 399 } else { 400 _dest_dir = "$ndk_headers_out_dir" 401 } 402 403 if (defined(invoker.current_ndk_outpath) && 404 invoker.current_ndk_outpath != "" && use_current_sdk) { 405 _dest_dir = invoker.current_ndk_outpath 406 } 407 408 _ndk_header_signature_target = "${target_name}__ndk_signature_check" 409 _target_name = target_name 410 action_with_pydeps(_ndk_header_signature_target) { 411 if (defined(invoker.deps)) { 412 deps = invoker.deps 413 } 414 415 script = "//build/ohos/ndk/check_ndk_header_signature.py" 416 depfile = "${target_gen_dir}/${target_name}.d" 417 418 inputs = [] 419 foreach(src, invoker.sources) { 420 _all_files = [] 421 _all_files = exec_script("//build/scripts/find.py", 422 [ rebase_path(src) ], 423 "list lines") 424 425 inputs += _all_files 426 } 427 428 _output = "$target_gen_dir/$target_name.stamp" 429 430 args = [ 431 "--depfile", 432 rebase_path(depfile, root_build_dir), 433 "--generated-signature", 434 rebase_path("$ndk_signature_out_dir/$_target_name/signature.txt", 435 root_build_dir), 436 "--saved-signature", 437 rebase_path("$ndk_signature_save_dir/$_target_name/signature.txt", 438 root_build_dir), 439 "--output", 440 rebase_path(_output, root_build_dir), 441 ] 442 foreach(f, inputs) { 443 args += [ 444 "--headers", 445 rebase_path(f, root_build_dir), 446 "--root-build-dir", 447 rebase_path("//", root_build_dir), 448 ] 449 } 450 451 if (check_ndk_signature) { 452 args += [ "--check-signature" ] 453 } 454 455 outputs = [ _output ] 456 } 457 458 _ndk_header_check_target = "${target_name}__ndk_header_check" 459 action_with_pydeps(_ndk_header_check_target) { 460 script = "//build/ohos/ndk/check_ndk_header.py" 461 inputs = [] 462 foreach(src, invoker.sources) { 463 _all_files = [] 464 _all_files = exec_script("//build/scripts/find.py", 465 [ rebase_path(src) ], 466 "list lines") 467 468 inputs += _all_files 469 } 470 471 _output = "$target_gen_dir/$target_name.gch" 472 args = [ 473 "--output", 474 rebase_path(_output, root_build_dir), 475 ] 476 foreach(f, inputs) { 477 args += [ 478 "--headers", 479 rebase_path(f, root_build_dir), 480 ] 481 } 482 483 outputs = [ _output ] 484 } 485 ohos_ndk_copy(target_name) { 486 forward_variables_from(invoker, 487 "*", 488 [ 489 "deps", 490 "args", 491 "dest_dir", 492 ]) 493 deps = [ ":$_ndk_header_signature_target" ] 494 if (defined(ndk_check_header) && target_name != "libuv_uv_header") { 495 deps += [ ":$_ndk_header_check_target" ] 496 } 497 498 if (defined(invoker.deps)) { 499 deps += invoker.deps 500 } 501 dest_dir = _dest_dir 502 503 args = [ "--ignore-stale" ] 504 if (defined(invoker.args)) { 505 args += invoker.args 506 } 507 } 508} 509 510# Specify ndk toolchains 511# 512# Input variables: 513# dest_dir: Root directory where sources are copied to. 514# sources: List of files and directories to copy to ${dest_dir}. 515# 516template("ohos_ndk_toolchains") { 517 ohos_ndk_copy(target_name) { 518 forward_variables_from(invoker, "*") 519 } 520} 521 522# Specify ndk prebuilt library 523# 524# Input variables: 525# dest_dir: Root directory where sources are copied to. 526# sources: List of files and directories to copy to ${dest_dir}. 527# 528template("ohos_ndk_prebuilt_library") { 529 if (defined(invoker.dest_dir)) { 530 _dest_dir = invoker.dest_dir 531 } else { 532 _dest_dir = "$ndk_libraries_out_dir" 533 } 534 535 if (defined(invoker.current_ndk_outpath) && 536 invoker.current_ndk_outpath != "" && use_current_sdk) { 537 _dest_dir = invoker.current_ndk_outpath 538 } 539 540 ohos_ndk_copy(target_name) { 541 forward_variables_from(invoker, 542 "*", 543 [ 544 "args", 545 "dest_dir", 546 ]) 547 dest_dir = _dest_dir 548 549 args = [ "--ignore-stale" ] 550 if (defined(invoker.args)) { 551 args += invoker.args 552 } 553 } 554} 555 556template("current_ndk") { 557 forward_variables_from(invoker, 558 [ 559 "ndk_class", 560 "all_ndk_targets", 561 "ndk_out_dir", 562 ]) 563 564 package_info_name = "oh-uni-package" 565 if (ndk_class != "base") { 566 package_info_name = "uni-package" 567 } 568 package_info_file = "$ndk_out_dir/$package_info_name.json" 569 570 package_info = { 571 path = "native" 572 displayName = "Native" 573 version = current_ndk_version 574 if (release_type != "") { 575 releaseType = release_type 576 } 577 if (meta_version != "") { 578 meta = { 579 metaVersion = meta_version 580 } 581 } 582 if (defined(ext_ndk_config_file) && ext_ndk_config_file != "") { 583 platformVersion = platform_version 584 } 585 apiVersion = api_version 586 } 587 write_file(package_info_file, package_info, "json") 588 589 action_with_pydeps(target_name) { 590 deps = all_ndk_targets 591 script = "//build/ohos/ndk/collect_ndk_syscap.py" 592 depfile = "$target_gen_dir/$target_name.d" 593 _ndk_syscap_desc_file = "${ndk_out_dir}/ndk_system_capability.json" 594 _native_syscap_config_file = "${ndk_out_dir}/nativeapi_syscap_config.json" 595 outputs = [ _ndk_syscap_desc_file ] 596 args = [ 597 "--depfile", 598 rebase_path(depfile, root_build_dir), 599 "--system-capability-file", 600 rebase_path(_ndk_syscap_desc_file, root_build_dir), 601 "--system-capability-header-config", 602 rebase_path(_native_syscap_config_file, root_build_dir), 603 "--targets-build-config", 604 ] 605 foreach(_ndk_target, all_ndk_targets) { 606 _target_bc_file = get_label_info(_ndk_target, "target_gen_dir") + "/" + 607 get_label_info(_ndk_target, "name") + ".build_config" 608 args += [ rebase_path(_target_bc_file, root_build_dir) ] 609 } 610 } 611} 612