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} 26 27ndk_os_irrelevant_out_dir = "$root_out_dir/${sdk_native}/os-irrelevant" 28ndk_os_specific_out_dir = "$root_out_dir/${sdk_native}/os-specific" 29ndk_signature_out_dir = "$root_out_dir/${sdk_native}/signature" 30 31ndk_headers_out_dir = "$ndk_os_irrelevant_out_dir/sysroot/usr/include" 32ndk_libraries_out_dir = "$ndk_os_irrelevant_out_dir/sysroot/usr/lib" 33ndk_docs_out_dir = "$ndk_os_irrelevant_out_dir/docs" 34 35windows_system = "windows" 36linux_system = "linux" 37darwin_system = "darwin" 38 39ndk_windows_specific_out_dir = "${ndk_os_specific_out_dir}/${windows_system}" 40ndk_darwin_specific_out_dir = "${ndk_os_specific_out_dir}/${darwin_system}" 41ndk_linux_specific_out_dir = "${ndk_os_specific_out_dir}/${linux_system}" 42 43ndk_windows_toolchains_out_dir = "${ndk_windows_specific_out_dir}/llvm" 44ndk_windows_tools_out_dir = "${ndk_windows_specific_out_dir}/build-tools" 45 46ndk_darwin_toolchains_out_dir = "${ndk_darwin_specific_out_dir}/llvm" 47ndk_darwin_tools_out_dir = "${ndk_darwin_specific_out_dir}/build-tools" 48 49ndk_linux_toolchains_out_dir = "${ndk_linux_specific_out_dir}/llvm" 50ndk_linux_tools_out_dir = "${ndk_linux_specific_out_dir}/build-tools" 51 52# Generate NDK library from NDK description file. 53# 54# Variables: 55# ndk_description_file: 56# min_compact_version: string specifies the minimal compactible version of NDK. 57# set to major_version in default. 58# 59template("ohos_ndk_library") { 60 forward_variables_from(invoker, [ "testonly" ]) 61 assert(defined(invoker.ndk_description_file), 62 "ndk description file is necessary ") 63 64 _ndk_description_file = invoker.ndk_description_file 65 66 _system_capability = "" 67 if (defined(invoker.system_capability)) { 68 _system_capability = invoker.system_capability 69 } 70 71 _system_capability_headers = "" 72 if (defined(invoker.system_capability_headers)) { 73 _system_capability_headers = invoker.system_capability_headers 74 } 75 76 _deps = [] 77 if (defined(invoker.deps)) { 78 _deps += invoker.deps 79 } 80 81 _ndk_config_output = "$target_gen_dir/$target_name.build_config" 82 _sdk_version = exec_script("//build/ohos/version.py", 83 [ 84 "--version", 85 sdk_version, 86 ], 87 "list lines") 88 _min_compact_version = _sdk_version[0] 89 if (defined(invoker.min_compact_version)) { 90 _min_compact_version = invoker.min_compact_version 91 } 92 assert(_min_compact_version != "0") # mark as used 93 94 _output_name = target_name 95 if (defined(invoker.output_name)) { 96 _output_name = invoker.output_name 97 } 98 99 _output_extension = "z.so" 100 if (defined(invoker.output_extension)) { 101 _output_extension = invoker.output_extension 102 } 103 104 _ndk_stub_target = "${target_name}__ndk_stub" 105 _generated_ndk_stub_file = target_gen_dir + "/${target_name}.ndk/" + 106 get_path_info(_ndk_description_file, "name") + ".c" 107 _current_label = get_label_info(":${target_name}", "label_with_toolchain") 108 action_with_pydeps(_ndk_stub_target) { 109 deps = _deps 110 script = "//build/ohos/ndk/generate_ndk_stub_file.py" 111 depfile = "${target_gen_dir}/${target_name}.d" 112 args = [ 113 "--output", 114 rebase_path(_generated_ndk_stub_file, root_build_dir), 115 "--ndk-description-file", 116 rebase_path(_ndk_description_file, root_build_dir), 117 "--depfile", 118 rebase_path(depfile, root_build_dir), 119 ] 120 inputs = [ _ndk_description_file ] 121 outputs = [ _generated_ndk_stub_file ] 122 123 _ndk_config_info = { 124 label = _current_label 125 lib_name = _output_name 126 system_capability = _system_capability 127 system_capability_headers = _system_capability_headers 128 } 129 metadata = { 130 ndk_config = [ _ndk_config_info ] 131 } 132 } 133 134 _ndk_config_target = "${target_name}__ndk_config" 135 generated_file(_ndk_config_target) { 136 deps = [ ":$_ndk_stub_target" ] 137 output_conversion = "json" 138 outputs = [ _ndk_config_output ] 139 140 data_keys = [ "ndk_config" ] 141 } 142 143 if (build_ohos_ndk) { 144 ndk_toolchains = [ 145 "//build/toolchain/ohos:ohos_clang_arm", 146 "//build/toolchain/ohos:ohos_clang_arm64", 147 ] 148 } else { 149 # Don't enable cross compile if build_ohos_ndk is false. 150 # Cross compiling in this case may cause build failure in some scenario, 151 # such as build for ASAN. 152 ndk_toolchains = [ "//build/toolchain/ohos:ohos_clang_${target_cpu}" ] 153 } 154 155 _accumulated_deps = [] 156 157 foreach(_toolchain, ndk_toolchains) { 158 if (_toolchain == "//build/toolchain/ohos:ohos_clang_arm") { 159 _ndk_shlib_directory = "arm-linux-ohos" 160 } else if (_toolchain == "//build/toolchain/ohos:ohos_clang_arm64") { 161 _ndk_shlib_directory = "aarch64-linux-ohos" 162 } else if (_toolchain == "//build/toolchain/ohos:ohos_clang_x86_64") { 163 _ndk_shlib_directory = "x86_64-linux-ohos" 164 } 165 166 assert(defined(_ndk_shlib_directory)) 167 _output_dir = "$ndk_libraries_out_dir/$_ndk_shlib_directory" 168 _output_ndk_shlib = "${_output_dir}/lib${_output_name}.${_output_extension}" 169 170 _toolchain_name = get_label_info(_toolchain, "name") 171 172 _ndk_shlib_target = "${target_name}_${_toolchain_name}__ndk_shlib" 173 174 shared_library(_ndk_shlib_target) { 175 forward_variables_from(invoker, 176 [ 177 "cflags", 178 "ldflags", 179 "configs", 180 "libs", 181 "include_dirs", 182 ]) 183 deps = [ ":$_ndk_stub_target" ] 184 sources = [ _generated_ndk_stub_file ] 185 output_dir = target_out_dir + "/$_toolchain_name" 186 output_name = _output_name 187 output_extension = _output_extension 188 } 189 190 _ndk_shlib_copy_target = "${target_name}_${_toolchain_name}__copy" 191 copy(_ndk_shlib_copy_target) { 192 deps = [ ":$_ndk_shlib_target($_toolchain)" ] 193 sources = [ get_label_info(":$_ndk_shlib_target($_toolchain)", 194 "target_out_dir") + 195 "/$_toolchain_name/lib$_output_name.$_output_extension" ] 196 outputs = [ _output_ndk_shlib ] 197 } 198 _accumulated_deps += [ ":$_ndk_shlib_copy_target" ] 199 _accumulated_deps += [ ":$_ndk_shlib_target" ] 200 } 201 202 _ndk_version_script_target = target_name 203 if (current_toolchain == default_toolchain) { 204 # Notice file for different toolchains are the same, it's enough to 205 # collect notice file for default toolchain. 206 _notice_target = "${target_name}__ndk_libraries_notice" 207 collect_notice(_notice_target) { 208 forward_variables_from(invoker, 209 [ 210 "testonly", 211 "license_as_sources", 212 "license_file", 213 ]) 214 module_source_dir = 215 get_label_info(":${_ndk_version_script_target}", "dir") 216 outputs = [ "$ndk_notice_dir/sysroot/usr/lib/lib$_output_name.$_output_extension.txt" ] 217 } 218 _accumulated_deps += [ ":$_notice_target" ] 219 } 220 if (defined(invoker.license_file)) { 221 not_needed(invoker, [ "license_file" ]) 222 } 223 if (defined(invoker.license_as_sources)) { 224 not_needed(invoker, [ "license_as_sources" ]) 225 } 226 227 _generated_version_script = 228 target_gen_dir + "/$target_name" + version_script_suffix 229 action_with_pydeps(_ndk_version_script_target) { 230 deps = _accumulated_deps 231 script = "//build/ohos/ndk/generate_version_script.py" 232 depfile = "${target_gen_dir}/${target_name}.d" 233 args = [ 234 "--output", 235 rebase_path(_generated_version_script, root_build_dir), 236 "--ndk-description-file", 237 rebase_path(_ndk_description_file, root_build_dir), 238 "--shlib-name", 239 _output_name, 240 "--depfile", 241 rebase_path(depfile, root_build_dir), 242 ] 243 outputs = [ _generated_version_script ] 244 } 245} 246 247# Specify an ndk copy target 248# NOTE: It's an internal template, not designed for everyone use. 249# 250# Input variables: 251# dest_dir: Root directory where sources are copied to. 252# sources: List of files and directories to copy to ${dest_dir}. 253# 254template("ohos_ndk_copy") { 255 assert(defined(invoker.sources) && defined(invoker.dest_dir), 256 "sources and dest_dir are necessary ") 257 258 _deps = [] 259 if (defined(invoker.deps)) { 260 _deps += invoker.deps 261 } 262 _dest = invoker.dest_dir 263 264 set_sources_assignment_filter([ "*os-irrelevant*" ]) 265 sources = [ _dest ] 266 if (sources == []) { 267 _notice_rel_dir = ndk_os_irrelevant_out_dir 268 } else { 269 _notice_rel_dir = ndk_os_specific_out_dir 270 } 271 set_sources_assignment_filter([]) 272 sources = [] 273 274 _main_target_name = target_name 275 _notice_target = "${target_name}__notice" 276 collect_notice(_notice_target) { 277 forward_variables_from(invoker, 278 [ 279 "testonly", 280 "license_as_sources", 281 "license_file", 282 ]) 283 module_source_dir = get_label_info(":${_main_target_name}", "dir") 284 outputs = [] 285 286 foreach(s, invoker.sources) { 287 outputs += [ ndk_notice_dir + "/" + rebase_path(_dest, _notice_rel_dir) + 288 "/" + get_path_info(s, "file") + ".txt" ] 289 } 290 } 291 _deps += [ ":$_notice_target" ] 292 293 copy_ex(target_name) { 294 forward_variables_from(invoker, 295 [ 296 "testonly", 297 "visibility", 298 ]) 299 forward_variables_from(invoker, [ "outputs" ]) 300 deps = _deps 301 sources = invoker.sources 302 303 if (!defined(outputs)) { 304 outputs = [] 305 foreach(src, invoker.sources) { 306 _all_files = [] 307 _all_files = 308 exec_script("//build/scripts/find.py", 309 [ 310 rebase_path(src, root_build_dir), 311 "--base-dir=" + rebase_path(src, root_build_dir), 312 "--return-relpath", 313 "--follow-symlinks", 314 ], 315 "list lines") 316 317 if (_all_files == [ "." ]) { 318 outputs += [ _dest + "/" + get_path_info(src, "file") ] 319 } else { 320 foreach(f, _all_files) { 321 outputs += [ _dest + "/" + get_path_info(src, "name") + "/$f" ] 322 } 323 } 324 } 325 } 326 327 dest = _dest 328 depfile = "$target_gen_dir/$target_name.d" 329 args = [ 330 "--clear", 331 "--follow-outside-symlinks", 332 "--depfile", 333 rebase_path(depfile, root_build_dir), 334 "--stamp", 335 rebase_path("$target_gen_dir/$target_name.stamp", root_build_dir), 336 ] 337 if (defined(invoker.args)) { 338 args += invoker.args 339 } 340 } 341} 342 343# Specify ndk header files 344# 345# Input variables: 346# dest_dir: Root directory where sources are copied to. 347# sources: List of files and directories to copy to ${dest_dir}. 348# 349template("ohos_ndk_headers") { 350 assert(defined(invoker.sources), "sources are necessary ") 351 352 if (defined(invoker.dest_dir)) { 353 _dest_dir = invoker.dest_dir 354 } else { 355 _dest_dir = "$ndk_headers_out_dir" 356 } 357 358 _ndk_header_signature_target = "${target_name}__ndk_signature_check" 359 _target_name = target_name 360 action_with_pydeps(_ndk_header_signature_target) { 361 if (defined(invoker.deps)) { 362 deps = invoker.deps 363 } 364 365 script = "//build/ohos/ndk/check_ndk_header_signature.py" 366 depfile = "${target_gen_dir}/${target_name}.d" 367 368 inputs = [] 369 foreach(src, invoker.sources) { 370 _all_files = [] 371 _all_files = exec_script("//build/scripts/find.py", 372 [ rebase_path(src) ], 373 "list lines") 374 375 inputs += _all_files 376 } 377 378 _output = "$target_gen_dir/$target_name.stamp" 379 380 args = [ 381 "--depfile", 382 rebase_path(depfile, root_build_dir), 383 "--generated-signature", 384 rebase_path("$ndk_signature_out_dir/$_target_name/signature.txt", 385 root_build_dir), 386 "--saved-signature", 387 rebase_path("$ndk_signature_save_dir/$_target_name/signature.txt", 388 root_build_dir), 389 "--output", 390 rebase_path(_output, root_build_dir), 391 ] 392 foreach(f, inputs) { 393 args += [ 394 "--headers", 395 rebase_path(f, root_build_dir), 396 "--root-build-dir", 397 rebase_path("//", root_build_dir), 398 ] 399 } 400 401 if (check_ndk_signature) { 402 args += [ "--check-signature" ] 403 } 404 405 outputs = [ _output ] 406 } 407 408 ohos_ndk_copy(target_name) { 409 forward_variables_from(invoker, 410 "*", 411 [ 412 "deps", 413 "args", 414 "dest_dir", 415 ]) 416 deps = [ ":$_ndk_header_signature_target" ] 417 418 if (defined(invoker.deps)) { 419 deps += invoker.deps 420 } 421 dest_dir = _dest_dir 422 423 args = [ "--ignore-stale" ] 424 if (defined(invoker.args)) { 425 args += invoker.args 426 } 427 } 428} 429 430# Specify ndk toolchains 431# 432# Input variables: 433# dest_dir: Root directory where sources are copied to. 434# sources: List of files and directories to copy to ${dest_dir}. 435# 436template("ohos_ndk_toolchains") { 437 ohos_ndk_copy(target_name) { 438 forward_variables_from(invoker, "*") 439 } 440} 441 442# Specify ndk prebuilt library 443# 444# Input variables: 445# dest_dir: Root directory where sources are copied to. 446# sources: List of files and directories to copy to ${dest_dir}. 447# 448template("ohos_ndk_prebuilt_library") { 449 if (defined(invoker.dest_dir)) { 450 _dest_dir = invoker.dest_dir 451 } else { 452 _dest_dir = "$ndk_libraries_out_dir" 453 } 454 455 ohos_ndk_copy(target_name) { 456 forward_variables_from(invoker, 457 "*", 458 [ 459 "args", 460 "dest_dir", 461 ]) 462 dest_dir = _dest_dir 463 464 args = [ "--ignore-stale" ] 465 if (defined(invoker.args)) { 466 args += invoker.args 467 } 468 } 469} 470