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 if (host_os == "linux" && host_cpu == "arm64") { 171 ndk_toolchains = [ "//build/toolchain/ohos:ohos_clang_arm64" ] 172 } else { 173 ndk_toolchains = [ 174 "//build/toolchain/ohos:ohos_clang_arm", 175 "//build/toolchain/ohos:ohos_clang_arm64", 176 "//build/toolchain/ohos:ohos_clang_x86_64", 177 ] 178 } 179 } else if (!is_arkui_x) { 180 # Don't enable cross compile if build_ohos_ndk is false. 181 # Cross compiling in this case may cause build failure in some scenario, 182 # such as build for ASAN. 183 ndk_toolchains = [ "//build/toolchain/ohos:ohos_clang_${target_cpu}" ] 184 } 185 186 if (ndk_toolchains == []) { 187 not_needed([ "_output_extension" ]) 188 } 189 190 _accumulated_deps = [] 191 192 foreach(_toolchain, ndk_toolchains) { 193 if (_toolchain == "//build/toolchain/ohos:ohos_clang_arm") { 194 _ndk_shlib_directory = "arm-linux-ohos" 195 } else if (_toolchain == "//build/toolchain/ohos:ohos_clang_arm64") { 196 _ndk_shlib_directory = "aarch64-linux-ohos" 197 } else if (_toolchain == "//build/toolchain/ohos:ohos_clang_x86_64") { 198 _ndk_shlib_directory = "x86_64-linux-ohos" 199 } 200 201 assert(defined(_ndk_shlib_directory)) 202 _output_dir = "$ndk_libraries_out_dir/$_ndk_shlib_directory" 203 if (defined(invoker.current_ndk_outpath) && 204 invoker.current_ndk_outpath != "" && use_current_sdk) { 205 _output_dir = "${invoker.current_ndk_outpath}/${_ndk_shlib_directory}" 206 } 207 _output_ndk_shlib = "${_output_dir}/lib${_output_name}.${_output_extension}" 208 209 _toolchain_name = get_label_info(_toolchain, "name") 210 211 _ndk_shlib_target = "${target_name}_${_toolchain_name}__ndk_shlib" 212 213 shared_library(_ndk_shlib_target) { 214 forward_variables_from(invoker, 215 [ 216 "cflags", 217 "ldflags", 218 "configs", 219 "libs", 220 "include_dirs", 221 ]) 222 deps = [ ":$_ndk_stub_target" ] 223 sources = [ _generated_ndk_stub_file ] 224 output_dir = target_out_dir + "/$_toolchain_name" 225 output_name = _output_name 226 output_extension = _output_extension 227 } 228 229 _ndk_shlib_copy_target = "${target_name}_${_toolchain_name}__copy" 230 copy(_ndk_shlib_copy_target) { 231 deps = [ ":$_ndk_shlib_target($_toolchain)" ] 232 sources = [ get_label_info(":$_ndk_shlib_target($_toolchain)", 233 "target_out_dir") + 234 "/$_toolchain_name/lib$_output_name.$_output_extension" ] 235 outputs = [ _output_ndk_shlib ] 236 } 237 _accumulated_deps += [ ":$_ndk_shlib_copy_target" ] 238 _accumulated_deps += [ ":$_ndk_shlib_target" ] 239 } 240 241 _ndk_version_script_target = target_name 242 if (current_toolchain == default_toolchain) { 243 # Notice file for different toolchains are the same, it's enough to 244 # collect notice file for default toolchain. 245 _notice_target = "${target_name}__ndk_libraries_notice" 246 collect_notice(_notice_target) { 247 forward_variables_from(invoker, 248 [ 249 "testonly", 250 "license_as_sources", 251 "license_file", 252 ]) 253 module_source_dir = 254 get_label_info(":${_ndk_version_script_target}", "dir") 255 outputs = [ "$ndk_notice_dir/sysroot/usr/lib/lib$_output_name.$_output_extension.txt" ] 256 } 257 _accumulated_deps += [ ":$_notice_target" ] 258 } 259 if (defined(invoker.license_file)) { 260 not_needed(invoker, [ "license_file" ]) 261 } 262 if (defined(invoker.license_as_sources)) { 263 not_needed(invoker, [ "license_as_sources" ]) 264 } 265 266 _generated_version_script = 267 target_gen_dir + "/$target_name" + version_script_suffix 268 action_with_pydeps(_ndk_version_script_target) { 269 deps = _accumulated_deps 270 script = "//build/ohos/ndk/generate_version_script.py" 271 depfile = "${target_gen_dir}/${target_name}.d" 272 args = [ 273 "--output", 274 rebase_path(_generated_version_script, root_build_dir), 275 "--ndk-description-file", 276 rebase_path(_ndk_description_file, root_build_dir), 277 "--shlib-name", 278 _output_name, 279 "--depfile", 280 rebase_path(depfile, root_build_dir), 281 ] 282 outputs = [ _generated_version_script ] 283 } 284} 285 286# Specify an ndk copy target 287# NOTE: It's an internal template, not designed for everyone use. 288# 289# Input variables: 290# dest_dir: Root directory where sources are copied to. 291# sources: List of files and directories to copy to ${dest_dir}. 292# 293template("ohos_ndk_copy") { 294 assert(defined(invoker.sources) && defined(invoker.dest_dir), 295 "sources and dest_dir are necessary ") 296 297 _deps = [] 298 if (defined(invoker.deps)) { 299 _deps += invoker.deps 300 } 301 _dest = invoker.dest_dir 302 303 if (defined(invoker.current_ndk_outpath) && 304 invoker.current_ndk_outpath != "" && use_current_sdk) { 305 _dest = invoker.current_ndk_outpath 306 } 307 308 sources = filter_exclude([ _dest ], [ "*os-irrelevant*" ]) 309 if (sources == []) { 310 _notice_rel_dir = ndk_os_irrelevant_out_dir 311 } else { 312 _notice_rel_dir = ndk_os_specific_out_dir 313 } 314 sources = [] 315 316 _main_target_name = target_name 317 _notice_target = "${target_name}__notice" 318 collect_notice(_notice_target) { 319 forward_variables_from(invoker, 320 [ 321 "testonly", 322 "license_as_sources", 323 "license_file", 324 ]) 325 module_source_dir = get_label_info(":${_main_target_name}", "dir") 326 outputs = [] 327 328 foreach(s, invoker.sources) { 329 outputs += [ ndk_notice_dir + "/" + rebase_path(_dest, _notice_rel_dir) + 330 "/" + get_path_info(s, "file") + ".txt" ] 331 } 332 } 333 _deps += [ ":$_notice_target" ] 334 _clear_dest = true 335 if (defined(invoker.clear_dest) && !invoker.clear_dest) { 336 _clear_dest = false 337 } 338 339 copy_ex(target_name) { 340 forward_variables_from(invoker, 341 [ 342 "testonly", 343 "visibility", 344 ]) 345 forward_variables_from(invoker, [ "outputs" ]) 346 deps = _deps 347 sources = invoker.sources 348 349 if (!defined(outputs)) { 350 outputs = [] 351 foreach(src, invoker.sources) { 352 _all_files = [] 353 _all_files = 354 exec_script("//build/scripts/find.py", 355 [ 356 rebase_path(src, root_build_dir), 357 "--base-dir=" + rebase_path(src, root_build_dir), 358 "--return-relpath", 359 "--follow-symlinks", 360 ], 361 "list lines") 362 363 if (_all_files == [ "." ]) { 364 outputs += [ _dest + "/" + get_path_info(src, "file") ] 365 } else { 366 foreach(f, _all_files) { 367 outputs += [ _dest + "/" + get_path_info(src, "name") + "/$f" ] 368 } 369 } 370 } 371 } 372 373 dest = _dest 374 depfile = "$target_gen_dir/$target_name.d" 375 args = [ 376 "--clear", 377 "--follow-outside-symlinks", 378 "--depfile", 379 rebase_path(depfile, root_build_dir), 380 "--stamp", 381 rebase_path("$target_gen_dir/$target_name.stamp", root_build_dir), 382 ] 383 if (!_clear_dest) { 384 args -= [ "--clear" ] 385 } 386 if (defined(invoker.args)) { 387 args += invoker.args 388 } 389 } 390} 391 392# Specify ndk header files 393# 394# Input variables: 395# dest_dir: Root directory where sources are copied to. 396# sources: List of files and directories to copy to ${dest_dir}. 397# 398template("ohos_ndk_headers") { 399 assert(defined(invoker.sources), "sources are necessary ") 400 401 if (defined(invoker.dest_dir)) { 402 _dest_dir = invoker.dest_dir 403 } else { 404 _dest_dir = "$ndk_headers_out_dir" 405 } 406 407 if (defined(invoker.current_ndk_outpath) && 408 invoker.current_ndk_outpath != "" && use_current_sdk) { 409 _dest_dir = invoker.current_ndk_outpath 410 } 411 412 _ndk_header_signature_target = "${target_name}__ndk_signature_check" 413 _target_name = target_name 414 action_with_pydeps(_ndk_header_signature_target) { 415 if (defined(invoker.deps)) { 416 deps = invoker.deps 417 } 418 419 script = "//build/ohos/ndk/check_ndk_header_signature.py" 420 depfile = "${target_gen_dir}/${target_name}.d" 421 422 inputs = [] 423 foreach(src, invoker.sources) { 424 _all_files = [] 425 _all_files = exec_script("//build/scripts/find.py", 426 [ rebase_path(src) ], 427 "list lines") 428 429 inputs += _all_files 430 } 431 432 _output = "$target_gen_dir/$target_name.stamp" 433 434 args = [ 435 "--depfile", 436 rebase_path(depfile, root_build_dir), 437 "--generated-signature", 438 rebase_path("$ndk_signature_out_dir/$_target_name/signature.txt", 439 root_build_dir), 440 "--saved-signature", 441 rebase_path("$ndk_signature_save_dir/$_target_name/signature.txt", 442 root_build_dir), 443 "--output", 444 rebase_path(_output, root_build_dir), 445 ] 446 foreach(f, inputs) { 447 args += [ 448 "--headers", 449 rebase_path(f, root_build_dir), 450 "--root-build-dir", 451 rebase_path("//", root_build_dir), 452 ] 453 } 454 455 if (check_ndk_signature) { 456 args += [ "--check-signature" ] 457 } 458 459 outputs = [ _output ] 460 } 461 462 _ndk_header_check_target = "${target_name}__ndk_header_check" 463 action_with_pydeps(_ndk_header_check_target) { 464 script = "//build/ohos/ndk/check_ndk_header.py" 465 inputs = [] 466 foreach(src, invoker.sources) { 467 _all_files = [] 468 _all_files = exec_script("//build/scripts/find.py", 469 [ rebase_path(src) ], 470 "list lines") 471 472 inputs += _all_files 473 } 474 475 _output = "$target_gen_dir/$target_name.gch" 476 args = [ 477 "--output", 478 rebase_path(_output, root_build_dir), 479 ] 480 foreach(f, inputs) { 481 args += [ 482 "--headers", 483 rebase_path(f, root_build_dir), 484 ] 485 } 486 487 outputs = [ _output ] 488 } 489 ohos_ndk_copy(target_name) { 490 forward_variables_from(invoker, 491 "*", 492 [ 493 "deps", 494 "args", 495 "dest_dir", 496 ]) 497 deps = [ ":$_ndk_header_signature_target" ] 498 if (defined(ndk_check_header) && target_name != "libuv_uv_header") { 499 deps += [ ":$_ndk_header_check_target" ] 500 } 501 502 if (defined(invoker.deps)) { 503 deps += invoker.deps 504 } 505 dest_dir = _dest_dir 506 507 args = [ "--ignore-stale" ] 508 if (defined(invoker.args)) { 509 args += invoker.args 510 } 511 } 512} 513 514# Specify ndk toolchains 515# 516# Input variables: 517# dest_dir: Root directory where sources are copied to. 518# sources: List of files and directories to copy to ${dest_dir}. 519# 520template("ohos_ndk_toolchains") { 521 ohos_ndk_copy(target_name) { 522 forward_variables_from(invoker, "*") 523 } 524} 525 526# Specify ndk prebuilt library 527# 528# Input variables: 529# dest_dir: Root directory where sources are copied to. 530# sources: List of files and directories to copy to ${dest_dir}. 531# 532template("ohos_ndk_prebuilt_library") { 533 if (defined(invoker.dest_dir)) { 534 _dest_dir = invoker.dest_dir 535 } else { 536 _dest_dir = "$ndk_libraries_out_dir" 537 } 538 539 if (defined(invoker.current_ndk_outpath) && 540 invoker.current_ndk_outpath != "" && use_current_sdk) { 541 _dest_dir = invoker.current_ndk_outpath 542 } 543 544 ohos_ndk_copy(target_name) { 545 forward_variables_from(invoker, 546 "*", 547 [ 548 "args", 549 "dest_dir", 550 ]) 551 dest_dir = _dest_dir 552 553 args = [ "--ignore-stale" ] 554 if (defined(invoker.args)) { 555 args += invoker.args 556 } 557 } 558} 559 560template("current_ndk") { 561 forward_variables_from(invoker, 562 [ 563 "ndk_class", 564 "all_ndk_targets", 565 "ndk_out_dir", 566 ]) 567 568 package_info_name = "oh-uni-package" 569 if (ndk_class != "base") { 570 package_info_name = "uni-package" 571 } 572 package_info_file = "$ndk_out_dir/$package_info_name.json" 573 574 package_info = { 575 path = "native" 576 displayName = "Native" 577 version = current_ndk_version 578 if (release_type != "") { 579 releaseType = release_type 580 } 581 if (meta_version != "") { 582 meta = { 583 metaVersion = meta_version 584 } 585 } 586 if (defined(ext_ndk_config_file) && ext_ndk_config_file != "") { 587 platformVersion = platform_version 588 } 589 apiVersion = api_version 590 } 591 write_file(package_info_file, package_info, "json") 592 593 action_with_pydeps(target_name) { 594 deps = all_ndk_targets 595 script = "//build/ohos/ndk/collect_ndk_syscap.py" 596 depfile = "$target_gen_dir/$target_name.d" 597 _ndk_syscap_desc_file = "${ndk_out_dir}/ndk_system_capability.json" 598 _native_syscap_config_file = "${ndk_out_dir}/nativeapi_syscap_config.json" 599 outputs = [ _ndk_syscap_desc_file ] 600 args = [ 601 "--depfile", 602 rebase_path(depfile, root_build_dir), 603 "--system-capability-file", 604 rebase_path(_ndk_syscap_desc_file, root_build_dir), 605 "--system-capability-header-config", 606 rebase_path(_native_syscap_config_file, root_build_dir), 607 "--targets-build-config", 608 ] 609 foreach(_ndk_target, all_ndk_targets) { 610 _target_bc_file = get_label_info(_ndk_target, "target_gen_dir") + "/" + 611 get_label_info(_ndk_target, "name") + ".build_config" 612 args += [ rebase_path(_target_bc_file, root_build_dir) ] 613 } 614 } 615} 616