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 "//build/toolchain/ohos:ohos_clang_x86_64", 148 ] 149 } else { 150 # Don't enable cross compile if build_ohos_ndk is false. 151 # Cross compiling in this case may cause build failure in some scenario, 152 # such as build for ASAN. 153 ndk_toolchains = [ "//build/toolchain/ohos:ohos_clang_${target_cpu}" ] 154 } 155 156 _accumulated_deps = [] 157 158 foreach(_toolchain, ndk_toolchains) { 159 if (_toolchain == "//build/toolchain/ohos:ohos_clang_arm") { 160 _ndk_shlib_directory = "arm-linux-ohos" 161 } else if (_toolchain == "//build/toolchain/ohos:ohos_clang_arm64") { 162 _ndk_shlib_directory = "aarch64-linux-ohos" 163 } else if (_toolchain == "//build/toolchain/ohos:ohos_clang_x86_64") { 164 _ndk_shlib_directory = "x86_64-linux-ohos" 165 } 166 167 assert(defined(_ndk_shlib_directory)) 168 _output_dir = "$ndk_libraries_out_dir/$_ndk_shlib_directory" 169 _output_ndk_shlib = "${_output_dir}/lib${_output_name}.${_output_extension}" 170 171 _toolchain_name = get_label_info(_toolchain, "name") 172 173 _ndk_shlib_target = "${target_name}_${_toolchain_name}__ndk_shlib" 174 175 shared_library(_ndk_shlib_target) { 176 forward_variables_from(invoker, 177 [ 178 "cflags", 179 "ldflags", 180 "configs", 181 "libs", 182 "include_dirs", 183 ]) 184 deps = [ ":$_ndk_stub_target" ] 185 sources = [ _generated_ndk_stub_file ] 186 output_dir = target_out_dir + "/$_toolchain_name" 187 output_name = _output_name 188 output_extension = _output_extension 189 } 190 191 _ndk_shlib_copy_target = "${target_name}_${_toolchain_name}__copy" 192 copy(_ndk_shlib_copy_target) { 193 deps = [ ":$_ndk_shlib_target($_toolchain)" ] 194 sources = [ get_label_info(":$_ndk_shlib_target($_toolchain)", 195 "target_out_dir") + 196 "/$_toolchain_name/lib$_output_name.$_output_extension" ] 197 outputs = [ _output_ndk_shlib ] 198 } 199 _accumulated_deps += [ ":$_ndk_shlib_copy_target" ] 200 _accumulated_deps += [ ":$_ndk_shlib_target" ] 201 } 202 203 _ndk_version_script_target = target_name 204 if (current_toolchain == default_toolchain) { 205 # Notice file for different toolchains are the same, it's enough to 206 # collect notice file for default toolchain. 207 _notice_target = "${target_name}__ndk_libraries_notice" 208 collect_notice(_notice_target) { 209 forward_variables_from(invoker, 210 [ 211 "testonly", 212 "license_as_sources", 213 "license_file", 214 ]) 215 module_source_dir = 216 get_label_info(":${_ndk_version_script_target}", "dir") 217 outputs = [ "$ndk_notice_dir/sysroot/usr/lib/lib$_output_name.$_output_extension.txt" ] 218 } 219 _accumulated_deps += [ ":$_notice_target" ] 220 } 221 if (defined(invoker.license_file)) { 222 not_needed(invoker, [ "license_file" ]) 223 } 224 if (defined(invoker.license_as_sources)) { 225 not_needed(invoker, [ "license_as_sources" ]) 226 } 227 228 _generated_version_script = 229 target_gen_dir + "/$target_name" + version_script_suffix 230 action_with_pydeps(_ndk_version_script_target) { 231 deps = _accumulated_deps 232 script = "//build/ohos/ndk/generate_version_script.py" 233 depfile = "${target_gen_dir}/${target_name}.d" 234 args = [ 235 "--output", 236 rebase_path(_generated_version_script, root_build_dir), 237 "--ndk-description-file", 238 rebase_path(_ndk_description_file, root_build_dir), 239 "--shlib-name", 240 _output_name, 241 "--depfile", 242 rebase_path(depfile, root_build_dir), 243 ] 244 outputs = [ _generated_version_script ] 245 } 246} 247 248# Specify an ndk copy target 249# NOTE: It's an internal template, not designed for everyone use. 250# 251# Input variables: 252# dest_dir: Root directory where sources are copied to. 253# sources: List of files and directories to copy to ${dest_dir}. 254# 255template("ohos_ndk_copy") { 256 assert(defined(invoker.sources) && defined(invoker.dest_dir), 257 "sources and dest_dir are necessary ") 258 259 _deps = [] 260 if (defined(invoker.deps)) { 261 _deps += invoker.deps 262 } 263 _dest = invoker.dest_dir 264 265 set_sources_assignment_filter([ "*os-irrelevant*" ]) 266 sources = [ _dest ] 267 if (sources == []) { 268 _notice_rel_dir = ndk_os_irrelevant_out_dir 269 } else { 270 _notice_rel_dir = ndk_os_specific_out_dir 271 } 272 set_sources_assignment_filter([]) 273 sources = [] 274 275 _main_target_name = target_name 276 _notice_target = "${target_name}__notice" 277 collect_notice(_notice_target) { 278 forward_variables_from(invoker, 279 [ 280 "testonly", 281 "license_as_sources", 282 "license_file", 283 ]) 284 module_source_dir = get_label_info(":${_main_target_name}", "dir") 285 outputs = [] 286 287 foreach(s, invoker.sources) { 288 outputs += [ ndk_notice_dir + "/" + rebase_path(_dest, _notice_rel_dir) + 289 "/" + get_path_info(s, "file") + ".txt" ] 290 } 291 } 292 _deps += [ ":$_notice_target" ] 293 294 copy_ex(target_name) { 295 forward_variables_from(invoker, 296 [ 297 "testonly", 298 "visibility", 299 ]) 300 forward_variables_from(invoker, [ "outputs" ]) 301 deps = _deps 302 sources = invoker.sources 303 304 if (!defined(outputs)) { 305 outputs = [] 306 foreach(src, invoker.sources) { 307 _all_files = [] 308 _all_files = 309 exec_script("//build/scripts/find.py", 310 [ 311 rebase_path(src, root_build_dir), 312 "--base-dir=" + rebase_path(src, root_build_dir), 313 "--return-relpath", 314 "--follow-symlinks", 315 ], 316 "list lines") 317 318 if (_all_files == [ "." ]) { 319 outputs += [ _dest + "/" + get_path_info(src, "file") ] 320 } else { 321 foreach(f, _all_files) { 322 outputs += [ _dest + "/" + get_path_info(src, "name") + "/$f" ] 323 } 324 } 325 } 326 } 327 328 dest = _dest 329 depfile = "$target_gen_dir/$target_name.d" 330 args = [ 331 "--clear", 332 "--follow-outside-symlinks", 333 "--depfile", 334 rebase_path(depfile, root_build_dir), 335 "--stamp", 336 rebase_path("$target_gen_dir/$target_name.stamp", root_build_dir), 337 ] 338 if (defined(invoker.args)) { 339 args += invoker.args 340 } 341 } 342} 343 344# Specify ndk header files 345# 346# Input variables: 347# dest_dir: Root directory where sources are copied to. 348# sources: List of files and directories to copy to ${dest_dir}. 349# 350template("ohos_ndk_headers") { 351 assert(defined(invoker.sources), "sources are necessary ") 352 353 if (defined(invoker.dest_dir)) { 354 _dest_dir = invoker.dest_dir 355 } else { 356 _dest_dir = "$ndk_headers_out_dir" 357 } 358 359 _ndk_header_signature_target = "${target_name}__ndk_signature_check" 360 _target_name = target_name 361 action_with_pydeps(_ndk_header_signature_target) { 362 if (defined(invoker.deps)) { 363 deps = invoker.deps 364 } 365 366 script = "//build/ohos/ndk/check_ndk_header_signature.py" 367 depfile = "${target_gen_dir}/${target_name}.d" 368 369 inputs = [] 370 foreach(src, invoker.sources) { 371 _all_files = [] 372 _all_files = exec_script("//build/scripts/find.py", 373 [ rebase_path(src) ], 374 "list lines") 375 376 inputs += _all_files 377 } 378 379 _output = "$target_gen_dir/$target_name.stamp" 380 381 args = [ 382 "--depfile", 383 rebase_path(depfile, root_build_dir), 384 "--generated-signature", 385 rebase_path("$ndk_signature_out_dir/$_target_name/signature.txt", 386 root_build_dir), 387 "--saved-signature", 388 rebase_path("$ndk_signature_save_dir/$_target_name/signature.txt", 389 root_build_dir), 390 "--output", 391 rebase_path(_output, root_build_dir), 392 ] 393 foreach(f, inputs) { 394 args += [ 395 "--headers", 396 rebase_path(f, root_build_dir), 397 "--root-build-dir", 398 rebase_path("//", root_build_dir), 399 ] 400 } 401 402 if (check_ndk_signature) { 403 args += [ "--check-signature" ] 404 } 405 406 outputs = [ _output ] 407 } 408 409 ohos_ndk_copy(target_name) { 410 forward_variables_from(invoker, 411 "*", 412 [ 413 "deps", 414 "args", 415 "dest_dir", 416 ]) 417 deps = [ ":$_ndk_header_signature_target" ] 418 419 if (defined(invoker.deps)) { 420 deps += invoker.deps 421 } 422 dest_dir = _dest_dir 423 424 args = [ "--ignore-stale" ] 425 if (defined(invoker.args)) { 426 args += invoker.args 427 } 428 } 429} 430 431# Specify ndk toolchains 432# 433# Input variables: 434# dest_dir: Root directory where sources are copied to. 435# sources: List of files and directories to copy to ${dest_dir}. 436# 437template("ohos_ndk_toolchains") { 438 ohos_ndk_copy(target_name) { 439 forward_variables_from(invoker, "*") 440 } 441} 442 443# Specify ndk prebuilt library 444# 445# Input variables: 446# dest_dir: Root directory where sources are copied to. 447# sources: List of files and directories to copy to ${dest_dir}. 448# 449template("ohos_ndk_prebuilt_library") { 450 if (defined(invoker.dest_dir)) { 451 _dest_dir = invoker.dest_dir 452 } else { 453 _dest_dir = "$ndk_libraries_out_dir" 454 } 455 456 ohos_ndk_copy(target_name) { 457 forward_variables_from(invoker, 458 "*", 459 [ 460 "args", 461 "dest_dir", 462 ]) 463 dest_dir = _dest_dir 464 465 args = [ "--ignore-stale" ] 466 if (defined(invoker.args)) { 467 args += invoker.args 468 } 469 } 470} 471