diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/libwebrtc/build/config/android | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/build/config/android')
27 files changed, 10950 insertions, 0 deletions
diff --git a/third_party/libwebrtc/build/config/android/BUILD.gn b/third_party/libwebrtc/build/config/android/BUILD.gn new file mode 100644 index 0000000000..a77a628be4 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/BUILD.gn @@ -0,0 +1,161 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/config.gni") +import("//build/config/c++/c++.gni") +import("//build/config/compiler/compiler.gni") +import("//build/config/sanitizers/sanitizers.gni") + +if (current_toolchain == default_toolchain) { + import("//build/toolchain/concurrent_links.gni") +} + +assert(is_android) + +# This is included by reference in the //build/config/compiler config that +# is applied to all targets. It is here to separate out the logic that is +# Android-only. +config("compiler") { + cflags = [ + "-ffunction-sections", + "-fno-short-enums", + ] + defines = [ + "ANDROID", + + # The NDK has these things, but doesn't define the constants to say that it + # does. Define them here instead. + "HAVE_SYS_UIO_H", + + # Forces full rebuilds on NDK rolls. To rebuild everything when NDK version + # stays the same, increment the suffix number. + "ANDROID_NDK_VERSION_ROLL=${android_ndk_version}_1", + ] + + if (target_cpu == "mips64el") { + cflags += [ + # Have to force IAS for mips64. + "-fintegrated-as", + ] + } + + ldflags = [ + # Don't allow visible symbols from libgcc or libc++ to be + # re-exported. + "-Wl,--exclude-libs=libgcc.a", + + # Don't allow visible symbols from libraries that contain + # assembly code with symbols that aren't hidden properly. + # http://crbug.com/448386 + "-Wl,--exclude-libs=libvpx_assembly_arm.a", + ] + + # TODO(crbug.com/1184398): Move to compiler-rt when we are ready. + ldflags += [ "--rtlib=libgcc" ] + if (target_cpu == "arm64") { + # For outline atomics on AArch64 (can't pass this unconditionally + # due to unused flag warning on other targets). + cflags += [ "--rtlib=libgcc" ] + if (arm_control_flow_integrity == "standard") { + cflags += [ "-mbranch-protection=standard" ] + } + } + + # $compile_api_level corresponds to the API level used for the sysroot path + # calculation in //build/config/android/config.gni + if (android_64bit_target_cpu) { + compile_api_level = android64_ndk_api_level + } else { + compile_api_level = android32_ndk_api_level + } + + cflags += [ "--target=$android_abi_target$compile_api_level" ] + ldflags += [ "--target=$android_abi_target$compile_api_level" ] + + # Assign any flags set for the C compiler to asmflags so that they are sent + # to the assembler. + asmflags = cflags +} + +# This is included by reference in the //build/config/compiler:runtime_library +# config that is applied to all targets. It is here to separate out the logic +# that is Android-only. Please see that target for advice on what should go in +# :runtime_library vs. :compiler. +config("runtime_library") { + # Let the linker find libgcc.a. + ldflags = [ "--gcc-toolchain=" + + rebase_path(android_toolchain_root, root_build_dir) ] + + libs = [] + + # On 64-bit platforms, the only symbols provided by libandroid_support.a are + # strto{d,f,l,ul}_l. These symbols are not used by our libc++, and newer NDKs + # don't provide a libandroid_support.a on 64-bit platforms, so we only depend + # on this library on 32-bit platforms. + if (target_cpu == "arm" || target_cpu == "x86") { + libs += [ "android_support" ] + } + + # arm builds of libc++ starting in NDK r12 depend on unwind. + if (target_cpu == "arm") { + libs += [ "unwind" ] + } + + if (target_cpu == "arm" && arm_version == 6) { + libs += [ "atomic" ] + } + + if (target_cpu == "mipsel") { + libs += [ "atomic" ] + } + + # TODO(jdduke) Re-enable on mips after resolving linking + # issues with libc++ (crbug.com/456380). + if (target_cpu != "mipsel" && target_cpu != "mips64el") { + ldflags += [ "-Wl,--warn-shared-textrel" ] + } +} + +config("hide_all_but_jni_onload") { + ldflags = [ "-Wl,--version-script=" + rebase_path( + "//build/android/android_only_explicit_jni_exports.lst", + root_build_dir) ] +} + +config("hide_all_but_jni") { + ldflags = [ "-Wl,--version-script=" + + rebase_path("//build/android/android_only_jni_exports.lst", + root_build_dir) ] +} + +config("lld_pack_relocations") { + ldflags = [ "-Wl,--pack-dyn-relocs=android" ] +} + +# Used for instrumented build to generate the orderfile. +config("default_orderfile_instrumentation") { + if (use_order_profiling) { + cflags = [ "-finstrument-function-entry-bare" ] + if (use_thin_lto) { + # TODO(pcc): This should not be necessary. Remove once + # https://reviews.llvm.org/D50016 lands and gets rolled in. + ldflags = [ "-Wl,-u,__cyg_profile_func_enter_bare" ] + } + } +} + +if (current_toolchain == default_toolchain) { + pool("goma_javac_pool") { + # Override action_pool when goma is enabled for javac. + depth = 10000 + } + + # When defined, this pool should be used instead of link_pool for command + # that need 1-2GB of RAM. https://crbug.com/1078460 + if (defined(java_cmd_pool_size)) { + pool("java_cmd_pool") { + depth = java_cmd_pool_size + } + } +} diff --git a/third_party/libwebrtc/build/config/android/OWNERS b/third_party/libwebrtc/build/config/android/OWNERS new file mode 100644 index 0000000000..a74cfbe228 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/OWNERS @@ -0,0 +1 @@ +file://build/android/OWNERS diff --git a/third_party/libwebrtc/build/config/android/abi.gni b/third_party/libwebrtc/build/config/android/abi.gni new file mode 100644 index 0000000000..1dbbf0cd61 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/abi.gni @@ -0,0 +1,101 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Logic separated out from config.gni so that it can be used by compiler.gni +# without introducing a circular dependency. + +# NOTE: Because Chrome OS builds may depend on targets built with the Android +# toolchain, this GNI file may be read and processed from within Chrome OS +# toolchains. Checking |is_android| here would therefore be too restrictive. +assert(is_android || is_chromeos) + +declare_args() { + # Adds intrumentation to each function. Writes a file with the order that + # functions are called at startup. + use_order_profiling = false + + # Only effective if use_order_profiling = true. When this is true, + # instrumentation switches from startup profiling after a delay, and + # then waits for a devtools memory dump request to dump all + # profiling information. When false, the same delay is used to switch from + # startup, and then after a second delay all profiling information is dumped. + # See base::android::orderfile::StartDelayedDump for more information. + devtools_instrumentation_dumping = false + + # Only effective if use_order_profiling = true. When this is true the call + # graph based instrumentation is used. + use_call_graph = false + + # Build additional browser splits with HWASAN instrumentation enabled. + build_hwasan_splits = false + + # *For CQ puposes only* Leads to non-working APKs. + # Forces all APKs/bundles to be 64-bit only to improve build speed in the CQ + # (no need to also build 32-bit library). + skip_secondary_abi_for_cq = false +} + +assert(!devtools_instrumentation_dumping || use_order_profiling, + "devtools_instrumentation_dumping requires use_order_profiling") +assert(!use_call_graph || use_order_profiling, + "use_call_graph requires use_order_profiling") + +if (target_cpu == "x86") { + android_app_abi = "x86" + android_abi_target = "i686-linux-android" +} else if (target_cpu == "arm") { + import("//build/config/arm.gni") + if (arm_version < 7) { + android_app_abi = "armeabi" + } else { + android_app_abi = "armeabi-v7a" + } + android_abi_target = "arm-linux-androideabi" +} else if (target_cpu == "mipsel") { + android_app_abi = "mips" + android_abi_target = "mipsel-linux-android" +} else if (target_cpu == "x64") { + android_app_abi = "x86_64" + + # Place holder for x64 support, not tested. + # TODO: Enable clang support for Android x64. http://crbug.com/539781 + android_abi_target = "x86_64-linux-android" +} else if (target_cpu == "arm64") { + android_app_abi = "arm64-v8a" + android_abi_target = "aarch64-linux-android" +} else if (target_cpu == "mips64el") { + android_app_abi = "mips64" + + # Place holder for mips64 support, not tested. + android_abi_target = "mips64el-linux-android" +} else { + assert(false, "Unknown Android ABI: " + target_cpu) +} + +if (target_cpu == "arm64" || target_cpu == "x64" || target_cpu == "mips64el") { + android_64bit_target_cpu = true +} else if (target_cpu == "arm" || target_cpu == "x86" || + target_cpu == "mipsel") { + android_64bit_target_cpu = false +} else { + assert(false, "Unknown target CPU: $target_cpu") +} + +# Intentionally do not define android_app_secondary_abi_cpu and +# android_app_secondary_abi for 32-bit target_cpu, since they are not used. +if (target_cpu == "arm64") { + android_secondary_abi_cpu = "arm" + android_app_secondary_abi = "armeabi-v7a" +} else if (target_cpu == "x64") { + android_secondary_abi_cpu = "x86" + android_app_secondary_abi = "x86" +} else if (target_cpu == "mips64el") { + android_secondary_abi_cpu = "mipsel" + android_app_secondary_abi = "mips" +} + +if (defined(android_secondary_abi_cpu)) { + android_secondary_abi_toolchain = + "//build/toolchain/android:android_clang_${android_secondary_abi_cpu}" +} diff --git a/third_party/libwebrtc/build/config/android/android_nocompile.gni b/third_party/libwebrtc/build/config/android/android_nocompile.gni new file mode 100644 index 0000000000..8ffca0e138 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/android_nocompile.gni @@ -0,0 +1,113 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") + +declare_args() { + # Used by tests to enable generating build files for GN targets which should + # not compile. + enable_android_nocompile_tests = false +} + +# Defines a test suite which checks that the 'test targets' fail to compile. The +# test suite runs 'gn gen' with a custom output directory and attempts to compile +# each test target. +# +# All of the tests should be defined in the same dedicated BUILD.gn file in order +# to minimize the number of targets that are processed by 'gn gen'. +# +# Variables +# tests: List of test configurations. A test configuration has the following +# keys: +# 'target': The GN target which should not compile when +# enable_android_nocompile_tests=true The target should compile when +# enable_android_nocompile_tests=false. +# 'expected_compile_output_regex': Error message regex to search for when compile fails. +# 'nocompile_sources': Source files which do not compile. This ensures that +# the test suite is re-run when one of these files change (as the test +# targets might not depend of the files when +# enable_android_nocompile_tests=false). +template("android_nocompile_test_suite") { + assert(!enable_android_nocompile_tests) + + action(target_name) { + testonly = true + script = "//build/android/gyp/nocompile_test.py" + + _tests = invoker.tests + _test0 = _tests[0] + _test0_dir = get_label_info(_test0["target"], "dir") + _test0_target_out_dir = get_label_info(_test0["target"], "target_out_dir") + foreach(_test_config, _tests) { + assert( + _test0_dir == get_label_info(_test_config["target"], "dir"), + "To avoid running 'gn gen' for each test, all tests in an android_nocompile_test_suite() should be declared in same BUILD.gn file") + } + + deps = [] + if (defined(invoker.deps)) { + deps += invoker.deps + } + + sources = [] + if (defined(invoker.sources)) { + sources += invoker.sources + } + + # Depend on compile_java Python scripts so that the action is re-run whenever the script is + # modified. + _pydeps = [ "//build/android/gyp/compile_java.pydeps" ] + if (defined(invoker.pydeps)) { + _pydeps += invoker.pydeps + } + + inputs = [] + foreach(_pydeps_file, _pydeps) { + _pydeps_file_lines = [] + _pydeps_file_lines = read_file(_pydeps_file, "list lines") + _pydeps_entries = [] + _pydeps_entries = filter_exclude(_pydeps_file_lines, [ "#*" ]) + _pydeps_file_dir = get_path_info(_pydeps_file, "dir") + inputs += rebase_path(_pydeps_entries, ".", _pydeps_file_dir) + } + + _json_test_configs = [] + foreach(_test_config, _tests) { + _test = _test_config["target"] + deps += [ _test ] + sources += _test_config["nocompile_sources"] + _dep_dir = get_label_info(_test, "dir") + _dep_name = get_label_info(_test, "name") + _json_test_configs += [ + { + target = "${_dep_dir}:${_dep_name}" + expect_regex = _test_config["expected_compile_output_regex"] + }, + ] + } + + _config_path = "$target_gen_dir/${target_name}.nocompile_config" + write_file(_config_path, _json_test_configs, "json") + + # Compute output directory for no-compile tests based on the directory containing test + # targets instead of based on the test suite target name. This avoids calling 'gn gen' for each + # android_nocompile_test_suite() for test suites whose tests are declared in the same BUILD.gn + # file. + _out_dir = "${_test0_target_out_dir}/nocompile_out" + + _stamp_path = "${target_gen_dir}/${target_name}.stamp" + args = [ + "--gn-args-path", + "args.gn", + "--out-dir", + rebase_path(_out_dir, root_build_dir), + "--test-configs-path", + rebase_path(_config_path, root_build_dir), + "--stamp", + rebase_path(_stamp_path, root_build_dir), + ] + inputs += [ _config_path ] + outputs = [ _stamp_path ] + } +} diff --git a/third_party/libwebrtc/build/config/android/build_vars.gni b/third_party/libwebrtc/build/config/android/build_vars.gni new file mode 100644 index 0000000000..a47607dc7c --- /dev/null +++ b/third_party/libwebrtc/build/config/android/build_vars.gni @@ -0,0 +1,29 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/config.gni") + +# Contains useful GN variables that may be used by scripts that take +# --output-directory as an arg. +build_vars_file = "$root_build_dir/build_vars.json" + +android_build_vars_json = { + if (enable_java_templates) { + android_ndk_root = rebase_path(android_ndk_root, root_build_dir) + android_sdk_build_tools = + rebase_path(android_sdk_build_tools, root_build_dir) + android_sdk_build_tools_version = android_sdk_build_tools_version + android_sdk_root = rebase_path(android_sdk_root, root_build_dir) + android_sdk_version = android_sdk_version + android_tool_prefix = rebase_path(android_tool_prefix, root_build_dir) + final_android_sdk = final_android_sdk + + if (defined(android_secondary_abi_cpu)) { + android_secondary_abi_toolchain = + rebase_path(get_label_info(":foo($android_secondary_abi_toolchain)", + "root_out_dir"), + root_build_dir) + } + } +} diff --git a/third_party/libwebrtc/build/config/android/channel.gni b/third_party/libwebrtc/build/config/android/channel.gni new file mode 100644 index 0000000000..6348bb996e --- /dev/null +++ b/third_party/libwebrtc/build/config/android/channel.gni @@ -0,0 +1,14 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +declare_args() { + # The channel to build on Android: stable, beta, dev, canary, work, or + # default. "default" should be used on non-official builds. + android_channel = "default" +} + +assert(android_channel == "default" || android_channel == "canary" || + android_channel == "dev" || android_channel == "beta" || + android_channel == "stable", + "Invalid channel: " + android_channel) diff --git a/third_party/libwebrtc/build/config/android/config.gni b/third_party/libwebrtc/build/config/android/config.gni new file mode 100644 index 0000000000..13418299e6 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/config.gni @@ -0,0 +1,353 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file contains common system config stuff for the Android build. + +# NOTE: Because Chrome OS builds may depend on targets built with the Android +# toolchain, this GNI file may be read and processed from within Chrome OS +# toolchains. Checking |is_android| here would therefore be too restrictive. +if (is_android || is_chromeos) { + import("//build/config/chromecast_build.gni") + import("//build/config/dcheck_always_on.gni") + import("//build_overrides/build.gni") + import("abi.gni") + + if (build_with_chromium) { + # Some non-chromium projects (e.g. WebRTC) use our build configs + # heavily but don't write gclient args files. + + import("//build/config/gclient_args.gni") + if (defined(checkout_android_native_support)) { + n = "$0x0A" # Newline + assert(checkout_android_native_support, + "Missing native Android toolchain support. |target_os| in your " + + ".gclient configuration file (in the parent directory of " + + "src) must include \"android\" and/or \"chromeos\". For " + + "example:${n}${n}solutions = [${n}...${n}]${n}" + + "target_os=[\"chromeos\"]${n}${n}" + + "After adding |target_os| please re-run \"gclient sync\".${n}") + } + } + + has_chrome_android_internal = + exec_script("//build/dir_exists.py", + [ rebase_path("//clank", root_build_dir) ], + "string") == "True" + + # We are using a separate declare_args block for only this argument so that + # we can decide if we have to pull in definitions from the internal config + # early. + declare_args() { + # Enables using the internal Chrome for Android repository. The default + # value depends on whether the repository is available, and if it's not but + # this argument is manually set to True, the generation will fail. + # The main purpose of this argument is to avoid having to maintain 2 + # repositories to support both public only and internal builds. + enable_chrome_android_internal = has_chrome_android_internal + + # The default to use for android:minSdkVersion for targets that do + # not explicitly set it. + default_min_sdk_version = 21 + + # [WIP] Allows devs to achieve much faster edit-build-install cycles. + # Currently only works for ChromeModern apks due to incremental install. + # This needs to be in a separate declare_args as it determines some of the + # args in the main declare_args block below. + android_fast_local_dev = false + } + + declare_args() { + # Android API level for 32 bits platforms + android32_ndk_api_level = default_min_sdk_version + + # Android API level for 64 bits platforms + if (default_min_sdk_version < 21) { + android64_ndk_api_level = 21 + } else { + android64_ndk_api_level = default_min_sdk_version + } + } + + if (enable_chrome_android_internal) { + import("//clank/config.gni") + } else { + import("//build/config/android/sdk.gni") + declare_args() { + # Which Android SDK to use. + android_sdk_release = default_android_sdk_release + } + } + + if (!defined(default_android_ndk_root)) { + default_android_ndk_root = "//third_party/android_ndk" + default_android_ndk_version = "r22" + default_android_ndk_major_version = 22 + } else { + assert(defined(default_android_ndk_version)) + assert(defined(default_android_ndk_major_version)) + } + + public_android_sdk_root = "//third_party/android_sdk/public" + if (android_sdk_release == "s") { + default_android_sdk_root = public_android_sdk_root + default_android_sdk_version = "31" + default_android_sdk_build_tools_version = "31.0.0" + public_android_sdk = true + } + + # For use downstream when we are building with preview Android SDK + if (!defined(final_android_sdk)) { + final_android_sdk = public_android_sdk + } + + if (!defined(default_lint_android_sdk_root)) { + # Purposefully repeated so that downstream can change + # default_android_sdk_root without changing lint version. + default_lint_android_sdk_root = public_android_sdk_root + default_lint_android_sdk_version = 31 + } + + if (!defined(default_extras_android_sdk_root)) { + # Purposefully repeated so that downstream can change + # default_android_sdk_root without changing where we load the SDK extras + # from. (Google Play services, etc.) + default_extras_android_sdk_root = public_android_sdk_root + } + + if (!defined(default_android_keystore_path)) { + default_android_keystore_path = "//build/android/chromium-debug.keystore" + default_android_keystore_name = "chromiumdebugkey" + default_android_keystore_password = "chromium" + } + + # google_play_services_package contains the path where individual client + # targets (e.g. google_play_services_base_java) are located. + if (!defined(google_play_services_package)) { + if (is_chromecast && chromecast_branding != "public") { + google_play_services_package = "//chromecast/internal/android/prebuilt/google-play-services-first-party" + } else { + google_play_services_package = "//third_party/android_deps" + } + } + + if (!defined(dagger_java_target)) { + dagger_java_target = + "//third_party/android_deps:com_google_dagger_dagger_java" + } + + if (!defined(dagger_annotation_processor_target)) { + dagger_annotation_processor_target = + "//third_party/android_deps:com_google_dagger_dagger_compiler_java" + } + + if (!defined(guava_android_target)) { + guava_android_target = + "//third_party/android_deps:com_google_guava_guava_android_java" + } + + if (!defined(material_design_target)) { + material_design_target = + "//third_party/android_deps:com_google_android_material_material_java" + } + + if (!defined(android_protoc_bin)) { + android_protoc_bin = "//third_party/android_protoc/protoc" + android_proto_runtime = + "//third_party/android_deps:com_google_protobuf_protobuf_javalite_java" + } + + webview_public_framework_dep = + "//third_party/android_sdk:public_framework_system_java" + if (!defined(webview_framework_dep)) { + webview_framework_dep = webview_public_framework_dep + } + + assert(defined(default_android_sdk_root), + "SDK release " + android_sdk_release + " not recognized.") + + declare_args() { + android_ndk_root = default_android_ndk_root + android_ndk_version = default_android_ndk_version + android_ndk_major_version = default_android_ndk_major_version + + android_sdk_root = default_android_sdk_root + android_sdk_version = default_android_sdk_version + android_sdk_build_tools_version = default_android_sdk_build_tools_version + + lint_android_sdk_root = default_lint_android_sdk_root + lint_android_sdk_version = default_lint_android_sdk_version + + # Libc++ library directory. Override to use a custom libc++ binary. + android_libcpp_lib_dir = "" + + # Android versionCode for android_apk()s that don't explicitly set one. + android_default_version_code = "1" + + # Android versionName for android_apk()s that don't explicitly set one. + android_default_version_name = "Developer Build" + + # Forced Android versionCode + android_override_version_code = "" + + # Forced Android versionName + android_override_version_name = "" + + # The path to the keystore to use for signing builds. + android_keystore_path = default_android_keystore_path + + # The name of the keystore to use for signing builds. + android_keystore_name = default_android_keystore_name + + # The password for the keystore to use for signing builds. + android_keystore_password = default_android_keystore_password + + # Java debug on Android. Having this on enables multidexing, and turning it + # off will enable proguard. + is_java_debug = is_debug + + # Mark APKs as android:debuggable="true". + debuggable_apks = !is_official_build + + # Set to false to disable the Errorprone compiler. + # Defaults to false for official builds to reduce build times. + # Static analysis failures should have been already caught by normal bots. + # Disabled when fast_local_dev is turned on. + use_errorprone_java_compiler = !is_official_build && !android_fast_local_dev + + # Build incremental targets whenever possible. + # See //build/android/incremental_install/README.md for more details. + incremental_install = android_fast_local_dev + + # When true, updates all android_aar_prebuilt() .info files during gn gen. + # Refer to android_aar_prebuilt() for more details. + update_android_aar_prebuilts = false + + # Turns off android lint. Useful for prototyping or for faster local builds. + # Defaults to true for official builds to reduce build times. + # Static analysis failures should have been already caught by normal bots. + # Disabled when fast_local_dev is turned on. + disable_android_lint = is_official_build || android_fast_local_dev + + # Location of aapt2 used for app bundles. For now, a more recent version + # than the one distributed with the Android SDK is required. + android_sdk_tools_bundle_aapt2_dir = + "//third_party/android_build_tools/aapt2" + + # Causes expectation failures to break the build, otherwise, just warns on + # stderr and writes a failure file to $android_configuration_failure_dir: + fail_on_android_expectations = false + + # Controls whether proguard obfuscation is enabled for targets + # configured to use it. + enable_proguard_obfuscation = true + + # Controls whether |short_resource_paths| and |strip_resource_names| are + # respected. Useful when trying to analyze APKs using tools that do not + # support mapping these names. + enable_arsc_obfuscation = true + + # The target to use as the system WebView implementation. + if (android_64bit_target_cpu && skip_secondary_abi_for_cq) { + system_webview_apk_target = "//android_webview:system_webview_64_apk" + } else { + system_webview_apk_target = "//android_webview:system_webview_apk" + } + + # Where to write failed expectations for bots to read. + expectations_failure_dir = "$root_build_dir/failed_expectations" + } + + # We need a second declare_args block to make sure we are using the overridden + # value of the arguments set above. + declare_args() { + if (defined(default_android_sdk_platform_version)) { + android_sdk_platform_version = default_android_sdk_platform_version + } else { + android_sdk_platform_version = android_sdk_version + } + + # Whether java assertions and Preconditions checks are enabled. + enable_java_asserts = is_java_debug || dcheck_always_on + + # Reduce build time by using d8 incremental build. + enable_incremental_d8 = true + + # Use hashed symbol names to reduce JNI symbol overhead. + use_hashed_jni_names = !is_java_debug + + # Enables Java library desugaring. + # This will cause an extra classes.dex file to appear in every apk. + enable_jdk_library_desugaring = true + } + + # Host stuff ----------------------------------------------------------------- + + # Defines the name the Android build gives to the current host CPU + # architecture, which is different than the names GN uses. + if (host_cpu == "x64") { + android_host_arch = "x86_64" + } else if (host_cpu == "x86") { + android_host_arch = "x86" + } else { + assert(false, "Need Android toolchain support for your build CPU arch.") + } + + # Defines the name the Android build gives to the current host CPU + # architecture, which is different than the names GN uses. + if (host_os == "linux") { + android_host_os = "linux" + } else if (host_os == "mac") { + android_host_os = "darwin" + } else { + assert(false, "Need Android toolchain support for your build OS.") + } + + # Directories and files ------------------------------------------------------ + # + # We define may of the dirs strings here for each output architecture (rather + # than just the current one) since these are needed by the Android toolchain + # file to define toolchains for all possible targets in one pass. + + android_sdk = + "${android_sdk_root}/platforms/android-${android_sdk_platform_version}" + android_sdk_build_tools = + "${android_sdk_root}/build-tools/$android_sdk_build_tools_version" + + # Path to the SDK's android.jar + android_sdk_jar = "$android_sdk/android.jar" + + # Location of libgcc. This is only needed for the current GN toolchain, so we + # only need to define the current one, rather than one for every platform + # like the toolchain roots. + if (target_cpu == "x86") { + android_prebuilt_arch = "android-x86" + _binary_prefix = "i686-linux-android" + } else if (target_cpu == "arm") { + android_prebuilt_arch = "android-arm" + _binary_prefix = "arm-linux-androideabi" + } else if (target_cpu == "mipsel") { + android_prebuilt_arch = "android-mips" + _binary_prefix = "mipsel-linux-android" + } else if (target_cpu == "x64") { + android_prebuilt_arch = "android-x86_64" + _binary_prefix = "x86_64-linux-android" + } else if (target_cpu == "arm64") { + android_prebuilt_arch = "android-arm64" + _binary_prefix = "aarch64-linux-android" + } else if (target_cpu == "mips64el") { + android_prebuilt_arch = "android-mips64" + _binary_prefix = "mips64el-linux-android" + } else { + assert(false, "Need android libgcc support for your target arch.") + } + + android_toolchain_root = "$android_ndk_root/toolchains/llvm/prebuilt/${android_host_os}-${android_host_arch}" + android_tool_prefix = "$android_toolchain_root/bin/$_binary_prefix-" + android_readelf = "${android_tool_prefix}readelf" + android_objcopy = "${android_tool_prefix}objcopy" + android_gdbserver = + "$android_ndk_root/prebuilt/$android_prebuilt_arch/gdbserver/gdbserver" + + android_sdk_tools_bundle_aapt2 = "${android_sdk_tools_bundle_aapt2_dir}/aapt2" +} diff --git a/third_party/libwebrtc/build/config/android/copy_ex.gni b/third_party/libwebrtc/build/config/android/copy_ex.gni new file mode 100644 index 0000000000..d3705dd7ef --- /dev/null +++ b/third_party/libwebrtc/build/config/android/copy_ex.gni @@ -0,0 +1,72 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Copy a list of file into a destination directory. Potentially renaming +# files are they are copied. This also ensures that symlinks are followed +# during the copy (i.e. the symlinks are never copied, only their content). +# +# Variables: +# dest: Destination directory path. +# sources: List of source files or directories to copy to dest. +# renaming_sources: Optional list of source file paths that will be renamed +# during the copy operation. If provided, renaming_destinations is required. +# renaming_destinations: Optional list of destination file paths, required +# when renaming_sources is provided. Both lists should have the same size +# and matching entries. +# args: Optional. Additionnal arguments to the copy_ex.py script. +# +# The following variables have the usual GN meaning: data, deps, inputs, +# outputs, testonly, visibility. + +import("//build/config/python.gni") + +template("copy_ex") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "data", + "deps", + "public_deps", + "testonly", + "visibility", + ]) + sources = [] + if (defined(invoker.sources)) { + sources += invoker.sources + } + outputs = [] + if (defined(invoker.outputs)) { + outputs += invoker.outputs + } + if (defined(invoker.inputs)) { + inputs = invoker.inputs + } + + script = "//build/android/gyp/copy_ex.py" + + args = [ + "--dest", + rebase_path(invoker.dest, root_build_dir), + ] + rebased_sources = rebase_path(sources, root_build_dir) + args += [ "--files=$rebased_sources" ] + + if (defined(invoker.args)) { + args += invoker.args + } + + if (defined(invoker.renaming_sources) && + defined(invoker.renaming_destinations)) { + sources += invoker.renaming_sources + renaming_destinations = invoker.renaming_destinations + outputs += + get_path_info(rebase_path(renaming_destinations, ".", invoker.dest), + "abspath") + rebased_renaming_sources = + rebase_path(invoker.renaming_sources, root_build_dir) + args += [ "--renaming-sources=$rebased_renaming_sources" ] + args += [ "--renaming-destinations=$renaming_destinations" ] + } + } +} diff --git a/third_party/libwebrtc/build/config/android/extract_unwind_tables.gni b/third_party/libwebrtc/build/config/android/extract_unwind_tables.gni new file mode 100644 index 0000000000..5444c5b972 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/extract_unwind_tables.gni @@ -0,0 +1,44 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") + +template("unwind_table_asset") { + # Note: This file name is used in multiple monochrome build scripts. + _asset_path = "${target_gen_dir}/${target_name}/unwind_cfi_32" + _unwind_action = "${target_name}__extract" + + action(_unwind_action) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _root_dir = "$root_out_dir" + if (defined(android_secondary_abi_cpu)) { + _root_dir = get_label_info(":foo($android_secondary_abi_toolchain)", + "root_out_dir") + } + + script = "//build/android/gyp/extract_unwind_tables.py" + outputs = [ _asset_path ] + inputs = [ "${_root_dir}/lib.unstripped/$shlib_prefix${invoker.library_target}$shlib_extension" ] + + args = [ + "--input_path", + rebase_path( + "${_root_dir}/lib.unstripped/$shlib_prefix${invoker.library_target}$shlib_extension", + root_build_dir), + "--output_path", + rebase_path(_asset_path, root_build_dir), + "--dump_syms_path", + rebase_path("$root_out_dir/dump_syms", root_build_dir), + ] + deps = invoker.deps + deps += [ "//third_party/breakpad:dump_syms" ] + } + android_assets(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + sources = [ _asset_path ] + disable_compression = true + deps = [ ":$_unwind_action" ] + } +} diff --git a/third_party/libwebrtc/build/config/android/internal_rules.gni b/third_party/libwebrtc/build/config/android/internal_rules.gni new file mode 100644 index 0000000000..3ed306a9e7 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/internal_rules.gni @@ -0,0 +1,4368 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Do not add any imports to non-//build directories here. +# Some projects (e.g. V8) do not have non-build directories DEPS'ed in. +import("//build/config/android/config.gni") +import("//build/config/android/copy_ex.gni") +import("//build/config/compiler/compiler.gni") +import("//build/config/compute_inputs_for_analyze.gni") +import("//build/config/coverage/coverage.gni") +import("//build/config/python.gni") +import("//build/config/sanitizers/sanitizers.gni") +import("//build/toolchain/goma.gni") +import("//build/toolchain/kythe.gni") +import("//build/util/generate_wrapper.gni") +import("//build_overrides/build.gni") +if (current_toolchain == default_toolchain) { + import("//build/toolchain/concurrent_links.gni") +} +assert(is_android) + +# The following _java_*_types variables capture all the existing target types. +# If a new type is introduced, please add it to one of these categories, +# preferring the more specific resource/library types. +_java_resource_types = [ + "android_assets", + "android_resources", +] + +_java_library_types = [ + "java_library", + "system_java_library", + "android_app_bundle_module", +] + +# These are leaf java target types. They cannot be passed as deps to other +# targets. Thus their naming schemes are not enforced. +_java_leaf_types = [ + "android_apk", + "android_app_bundle", + "dist_aar", + "dist_jar", + "java_annotation_processor", + "java_binary", + "junit_binary", +] + +# All _java_resource_types targets must conform to these patterns. +_java_resource_patterns = [ + "*:*_assets", + "*android*:assets", + "*:*_apk_*resources", + "*android*:resources", + "*:*_resources", + "*:*_grd", + "*:*locale_paks", + "*:*_java_strings", + "*:*strings_java", +] + +# All _java_library_types targets must conform to these patterns. This includes +# all non-leaf targets that use java_library_impl. +_java_library_patterns = [ + "*:*_java", + "*:*_javalib", + "*:*_java_*", # e.g. chrome_java_test_support + "*:java", + "*:junit", + "*:junit_*", + "*:*_junit_*", + "*:*javatests", + "*:*_bundle_module", + + # TODO(agrieve): Rename targets below to match above patterns. + "//android_webview/glue:glue", +] + +# These identify all non-leaf targets that have .build_config.json files. This is the +# set of patterns that other targets can use to filter out java targets. +java_target_patterns = _java_library_patterns + _java_resource_patterns + +_r8_path = "//third_party/r8/lib/r8.jar" +_custom_d8_path = "//third_party/r8/custom_d8.jar" +_desugar_jdk_libs_json = "//third_party/r8/desugar_jdk_libs.json" +_desugar_jdk_libs_jar = "//third_party/android_deps/libs/com_android_tools_desugar_jdk_libs/desugar_jdk_libs-1.1.1.jar" +_desugar_jdk_libs_configuration_jar = "//third_party/android_deps/libs/com_android_tools_desugar_jdk_libs_configuration/desugar_jdk_libs_configuration-1.1.1.jar" +_desugar_runtime_jar = "$root_build_dir/obj/third_party/bazel/desugar/Desugar_runtime.processed.jar" + +_dexdump_path = "$android_sdk_build_tools/dexdump" +_dexlayout_path = "//third_party/android_build_tools/art/dexlayout" +_profman_path = "//third_party/android_build_tools/art/profman" +_art_lib_file_names = [ + "libartbase.so", + "libart-compiler.so", + "libart-dexlayout.so", + "libart-disassembler.so", + "libart-gtest.so", + "libart.so", + "libbacktrace.so", + "libbase.so", + "libcrypto-host.so", + "libc++.so", + "libcutils.so", + "libdexfile.so", + "libexpat-host.so", + "libicui18n-host.so", + "libicuuc-host.so", + "libjavacore.so", + "libjavacrypto.so", + "liblog.so", + "liblz4.so", + "liblzma.so", + "libnativebridge.so", + "libnativehelper.so", + "libnativeloader.so", + "libopenjdkjvm.so", + "libopenjdkjvmti.so", + "libopenjdk.so", + "libprofile.so", + "libsigchain.so", + "libssl-host.so", + "libunwindstack.so", + "libvixl-arm64.so", + "libvixl-arm.so", + "libvixld-arm64.so", + "libvixld-arm.so", + "libz-host.so", + "libziparchive.so", + "slicer.so", +] +_default_art_libs = [] +foreach(lib, _art_lib_file_names) { + _default_art_libs += [ "//third_party/android_build_tools/art/lib/$lib" ] +} + +# Put the bug number in the target name so that false-positives have a hint in +# the error message about why non-existent dependencies are there. +build_config_target_suffix = "__build_config_crbug_908819" + +# Write the target's .build_config.json file. This is a json file that contains a +# dictionary of information about how to build this target (things that +# require knowledge about this target's dependencies and cannot be calculated +# at gn-time). There is a special syntax to add a value in that dictionary to +# an action/action_foreachs args: +# --python-arg=@FileArg($rebased_build_config_path:key0:key1) +# At runtime, such an arg will be replaced by the value in the build_config. +# See build/android/gyp/write_build_config.py and +# build/android/gyp/util/build_utils.py:ExpandFileArgs +template("write_build_config") { + _type = invoker.type + _parent_invoker = invoker.invoker + _target_label = + get_label_info(":${_parent_invoker.target_name}", "label_no_toolchain") + + # Ensure targets match naming patterns so that __assetres, __header, __impl + # targets work properly. Those generated targets allow for effective deps + # filtering. + if (filter_exclude([ _type ], _java_resource_types) == []) { + if (filter_exclude([ _target_label ], _java_resource_patterns) != []) { + assert(false, "Invalid java resource target name: $_target_label") + } + } else if (filter_exclude([ _type ], _java_library_types) == []) { + if (filter_exclude([ _target_label ], _java_library_patterns) != [] || + filter_exclude([ _target_label ], _java_resource_patterns) == []) { + assert(false, "Invalid java library target name: $_target_label") + } + } else if (_type == "group") { + if (filter_exclude([ _target_label ], java_target_patterns) != []) { + assert(false, "Invalid java target name: $_target_label") + } + } else if (filter_exclude([ _type ], _java_leaf_types) != []) { + assert(false, "This java type needs a category: $_type") + } + + if (defined(invoker.public_target_label)) { + _target_label = invoker.public_target_label + } + + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) + if (!defined(deps)) { + deps = [] + } + if (defined(invoker.android_manifest_dep)) { + deps += [ invoker.android_manifest_dep ] + } + + script = "//build/android/gyp/write_build_config.py" + depfile = "$target_gen_dir/$target_name.d" + inputs = [] + outputs = [ invoker.build_config ] + + _deps_configs = [] + _public_deps_configs = [] + if (defined(invoker.possible_config_deps)) { + foreach(_possible_dep, invoker.possible_config_deps) { + _dep_label = get_label_info(_possible_dep, "label_no_toolchain") + if (filter_exclude([ _dep_label ], java_target_patterns) == []) { + # Put the bug number in the target name so that false-positives + # have a hint in the error message about non-existent dependencies. + deps += [ "$_dep_label$build_config_target_suffix" ] + _dep_gen_dir = get_label_info(_possible_dep, "target_gen_dir") + _dep_name = get_label_info(_possible_dep, "name") + _dep_config = "$_dep_gen_dir/$_dep_name.build_config.json" + + _deps_configs += [ _dep_config ] + if (defined(invoker.possible_config_public_deps)) { + if (filter_include([ _possible_dep ], + invoker.possible_config_public_deps) != []) { + _public_deps_configs += [ _dep_config ] + } + } + } + } + } + _rebased_deps_configs = rebase_path(_deps_configs, root_build_dir) + _rebased_public_deps_configs = + rebase_path(_public_deps_configs, root_build_dir) + + args = [ + "--type=$_type", + "--depfile", + rebase_path(depfile, root_build_dir), + "--deps-configs=$_rebased_deps_configs", + "--public-deps-configs=$_rebased_public_deps_configs", + "--build-config", + rebase_path(invoker.build_config, root_build_dir), + "--gn-target", + _target_label, + ] + + if (defined(invoker.ignore_dependency_public_deps) && + invoker.ignore_dependency_public_deps) { + args += [ "--ignore-dependency-public-deps" ] + } + + if (defined(invoker.aar_path)) { + args += [ + "--aar-path", + rebase_path(invoker.aar_path, root_build_dir), + ] + } + + if (defined(invoker.chromium_code) && !invoker.chromium_code) { + # Default to chromium code if invoker did not pass anything. + args += [ "--non-chromium-code" ] + } + + if (defined(invoker.device_jar_path)) { + args += [ + "--device-jar-path", + rebase_path(invoker.device_jar_path, root_build_dir), + ] + } + if (defined(invoker.host_jar_path)) { + args += [ + "--host-jar-path", + rebase_path(invoker.host_jar_path, root_build_dir), + ] + } + if (defined(invoker.unprocessed_jar_path)) { + args += [ + "--unprocessed-jar-path", + rebase_path(invoker.unprocessed_jar_path, root_build_dir), + ] + } + if (defined(invoker.ijar_path)) { + args += [ + "--interface-jar-path", + rebase_path(invoker.ijar_path, root_build_dir), + ] + } + if (defined(invoker.java_resources_jar)) { + args += [ + "--java-resources-jar-path", + rebase_path(invoker.java_resources_jar, root_build_dir), + ] + } + if (defined(invoker.annotation_processor_deps) && + invoker.annotation_processor_deps != []) { + _processor_configs = [] + foreach(_processor_dep, invoker.annotation_processor_deps) { + _dep_label = get_label_info(_processor_dep, "label_no_toolchain") + _dep_gen_dir = get_label_info(_processor_dep, "target_gen_dir") + _dep_name = get_label_info(_processor_dep, "name") + deps += [ "$_dep_label$build_config_target_suffix" ] + _processor_configs += [ "$_dep_gen_dir/$_dep_name.build_config.json" ] + } + _rebased_processor_configs = + rebase_path(_processor_configs, root_build_dir) + args += [ "--annotation-processor-configs=$_rebased_processor_configs" ] + } + + # Dex path for library targets, or the the intermediate library for apks. + if (defined(invoker.dex_path)) { + args += [ + "--dex-path", + rebase_path(invoker.dex_path, root_build_dir), + ] + } + + # Dex path for the final apk. + if (defined(invoker.final_dex_path)) { + args += [ + "--final-dex-path", + rebase_path(invoker.final_dex_path, root_build_dir), + ] + } + if (defined(invoker.supports_android) && invoker.supports_android) { + args += [ "--supports-android" ] + } + if (defined(invoker.requires_android) && invoker.requires_android) { + args += [ "--requires-android" ] + } + if (defined(invoker.is_prebuilt) && invoker.is_prebuilt) { + args += [ "--is-prebuilt" ] + } + if (defined(invoker.bypass_platform_checks) && + invoker.bypass_platform_checks) { + args += [ "--bypass-platform-checks" ] + } + + if (defined(invoker.apk_under_test)) { + deps += [ "${invoker.apk_under_test}$build_config_target_suffix" ] + apk_under_test_gen_dir = + get_label_info(invoker.apk_under_test, "target_gen_dir") + apk_under_test_name = get_label_info(invoker.apk_under_test, "name") + apk_under_test_config = + "$apk_under_test_gen_dir/$apk_under_test_name.build_config.json" + args += [ + "--tested-apk-config", + rebase_path(apk_under_test_config, root_build_dir), + ] + } + + if (defined(invoker.asset_sources)) { + _rebased_asset_sources = + rebase_path(invoker.asset_sources, root_build_dir) + args += [ "--asset-sources=$_rebased_asset_sources" ] + } + if (defined(invoker.asset_renaming_sources)) { + _rebased_asset_renaming_sources = + rebase_path(invoker.asset_renaming_sources, root_build_dir) + args += [ "--asset-renaming-sources=$_rebased_asset_renaming_sources" ] + + # These are zip paths, so no need to rebase. + args += [ + "--asset-renaming-destinations=${invoker.asset_renaming_destinations}", + ] + } + if (defined(invoker.disable_compression) && invoker.disable_compression) { + args += [ "--disable-asset-compression" ] + } + if (defined(invoker.treat_as_locale_paks) && invoker.treat_as_locale_paks) { + args += [ "--treat-as-locale-paks" ] + } + + if (defined(invoker.merged_android_manifest)) { + args += [ + "--merged-android-manifest", + rebase_path(invoker.merged_android_manifest, root_build_dir), + ] + } + if (defined(invoker.android_manifest)) { + inputs += [ invoker.android_manifest ] + args += [ + "--android-manifest", + rebase_path(invoker.android_manifest, root_build_dir), + ] + } + if (defined(invoker.resources_zip)) { + args += [ + "--resources-zip", + rebase_path(invoker.resources_zip, root_build_dir), + ] + } + + if (defined(invoker.resource_overlay) && invoker.resource_overlay) { + args += [ "--resource-overlay" ] + } + + if (defined(invoker.custom_package)) { + args += [ + "--package-name", + invoker.custom_package, + ] + } + if (defined(invoker.r_text)) { + args += [ + "--r-text-path", + rebase_path(invoker.r_text, root_build_dir), + ] + } + if (defined(invoker.res_size_info_path)) { + args += [ + "--res-size-info", + rebase_path(invoker.res_size_info_path, root_build_dir), + ] + } + if (defined(invoker.res_sources_path)) { + _res_sources_path = rebase_path(invoker.res_sources_path, root_build_dir) + args += [ "--res-sources-path=$_res_sources_path" ] + } + if (defined(invoker.proto_resources_path)) { + _rebased_proto_resources = + rebase_path(invoker.proto_resources_path, root_build_dir) + args += [ "--apk-proto-resources=$_rebased_proto_resources" ] + } + if (defined(invoker.r_text_path)) { + _rebased_rtxt_path = rebase_path(invoker.r_text_path, root_build_dir) + args += [ "--r-text-path=$_rebased_rtxt_path" ] + } + if (defined(invoker.module_pathmap_path)) { + _rebased_pathmap_path = + rebase_path(invoker.module_pathmap_path, root_build_dir) + args += [ "--module-pathmap-path=$_rebased_pathmap_path" ] + } + + if (defined(invoker.shared_libraries_runtime_deps_file)) { + # Don't list shared_libraries_runtime_deps_file as an input in order to + # avoid having to depend on the runtime_deps target. See comment in + # rules.gni for why we do this. + args += [ + "--shared-libraries-runtime-deps", + rebase_path(invoker.shared_libraries_runtime_deps_file, root_build_dir), + ] + } + + if (defined(invoker.base_allowlist_rtxt_path)) { + args += [ + "--base-allowlist-rtxt-path", + rebase_path(invoker.base_allowlist_rtxt_path, root_build_dir), + ] + } + + if (defined(invoker.is_base_module) && invoker.is_base_module) { + args += [ "--is-base-module" ] + } + + if (defined(invoker.loadable_modules)) { + _rebased_loadable_modules = + rebase_path(invoker.loadable_modules, root_build_dir) + args += [ "--loadable-modules=$_rebased_loadable_modules" ] + } + + if (defined(invoker.secondary_abi_shared_libraries_runtime_deps_file)) { + # Don't list secondary_abi_shared_libraries_runtime_deps_file as an + # input in order to avoid having to depend on the runtime_deps target. + # See comment in rules.gni for why we do this. + args += [ + "--secondary-abi-shared-libraries-runtime-deps", + rebase_path(invoker.secondary_abi_shared_libraries_runtime_deps_file, + root_build_dir), + ] + } + + if (defined(invoker.secondary_abi_loadable_modules) && + invoker.secondary_abi_loadable_modules != []) { + _rebased_secondary_abi_loadable_modules = + rebase_path(invoker.secondary_abi_loadable_modules, root_build_dir) + args += [ "--secondary-abi-loadable-modules=$_rebased_secondary_abi_loadable_modules" ] + } + + if (defined(invoker.native_lib_placeholders) && + invoker.native_lib_placeholders != []) { + args += [ "--native-lib-placeholders=${invoker.native_lib_placeholders}" ] + } + + if (defined(invoker.secondary_native_lib_placeholders) && + invoker.secondary_native_lib_placeholders != []) { + args += [ "--secondary-native-lib-placeholders=${invoker.secondary_native_lib_placeholders}" ] + } + + if (defined(invoker.uncompress_shared_libraries) && + invoker.uncompress_shared_libraries) { + args += [ "--uncompress-shared-libraries" ] + } + + if (defined(invoker.library_always_compress)) { + args += [ "--library-always-compress=${invoker.library_always_compress}" ] + } + + if (defined(invoker.library_renames)) { + args += [ "--library-renames=${invoker.library_renames}" ] + } + + if (defined(invoker.apk_path)) { + # TODO(tiborg): Remove APK path from build config and use + # install_artifacts from metadata instead. + _rebased_apk_path = rebase_path(invoker.apk_path, root_build_dir) + args += [ "--apk-path=$_rebased_apk_path" ] + if (defined(invoker.incremental_apk_path)) { + _rebased_incremental_apk_path = + rebase_path(invoker.incremental_apk_path, root_build_dir) + _rebased_incremental_install_json_path = + rebase_path(invoker.incremental_install_json_path, root_build_dir) + args += [ + "--incremental-install-json-path=$_rebased_incremental_install_json_path", + "--incremental-apk-path=$_rebased_incremental_apk_path", + ] + } + } + + if (defined(invoker.java_sources_file)) { + args += [ + "--java-sources-file", + rebase_path(invoker.java_sources_file, root_build_dir), + ] + } + if (defined(invoker.srcjar)) { + args += [ + "--srcjar", + rebase_path(invoker.srcjar, root_build_dir), + ] + } + if (defined(invoker.bundled_srcjars)) { + _rebased_bundled_srcjars = + rebase_path(invoker.bundled_srcjars, root_build_dir) + args += [ "--bundled-srcjars=$_rebased_bundled_srcjars" ] + } + if (defined(invoker.proguard_enabled) && invoker.proguard_enabled) { + args += [ "--proguard-enabled" ] + } + if (defined(invoker.proguard_mapping_path)) { + _rebased_proguard_mapping_path = + rebase_path(invoker.proguard_mapping_path, root_build_dir) + args += [ "--proguard-mapping-path=$_rebased_proguard_mapping_path" ] + } + if (defined(invoker.input_jars_paths)) { + _rebased_input_jars_paths = + rebase_path(invoker.input_jars_paths, root_build_dir) + args += [ "--extra-classpath-jars=$_rebased_input_jars_paths" ] + } + if (defined(invoker.low_classpath_priority) && + invoker.low_classpath_priority) { + args += [ "--low-classpath-priority" ] + } + if (defined(invoker.mergeable_android_manifests)) { + _rebased_mergeable_android_manifests = + rebase_path(invoker.mergeable_android_manifests, root_build_dir) + args += [ + "--mergeable-android-manifests=$_rebased_mergeable_android_manifests", + ] + } + if (defined(invoker.proguard_configs)) { + _rebased_proguard_configs = + rebase_path(invoker.proguard_configs, root_build_dir) + args += [ "--proguard-configs=$_rebased_proguard_configs" ] + } + if (defined(invoker.static_library_dependent_targets)) { + _dependent_configs = [] + foreach(_dep, invoker.static_library_dependent_targets) { + _dep_name = _dep.name + _dep_label = get_label_info(_dep_name, "label_no_toolchain") + deps += [ "$_dep_label$build_config_target_suffix" ] + _dep_gen_dir = get_label_info(_dep_name, "target_gen_dir") + _dep_name = get_label_info(_dep_name, "name") + _config = rebase_path("$_dep_gen_dir/$_dep_name.build_config.json", + root_build_dir) + _dependent_configs += [ _config ] + } + args += [ "--static-library-dependent-configs=$_dependent_configs" ] + } + if (defined(invoker.gradle_treat_as_prebuilt) && + invoker.gradle_treat_as_prebuilt) { + args += [ "--gradle-treat-as-prebuilt" ] + } + if (defined(invoker.main_class)) { + args += [ + "--main-class", + invoker.main_class, + ] + } + if (defined(invoker.base_module_target)) { + _base_label = + get_label_info(invoker.base_module_target, "label_no_toolchain") + _dep_gen_dir = get_label_info(_base_label, "target_gen_dir") + _dep_name = get_label_info(_base_label, "name") + deps += [ "$_base_label$build_config_target_suffix" ] + _base_module_build_config = "$_dep_gen_dir/$_dep_name.build_config.json" + inputs += [ _base_module_build_config ] + args += [ + "--base-module-build-config", + rebase_path(_base_module_build_config, root_build_dir), + ] + } + if (defined(invoker.module_build_configs)) { + inputs += invoker.module_build_configs + _rebased_configs = + rebase_path(invoker.module_build_configs, root_build_dir) + args += [ "--module-build-configs=$_rebased_configs" ] + } + if (defined(invoker.version_name)) { + args += [ + "--version-name", + invoker.version_name, + ] + } + if (defined(invoker.version_code)) { + args += [ + "--version-code", + invoker.version_code, + ] + } + if (defined(invoker.recursive_resource_deps) && + invoker.recursive_resource_deps) { + args += [ "--recursive-resource-deps" ] + } + if (current_toolchain != default_toolchain) { + # This has to be a built-time error rather than a GN assert because many + # packages have a mix of java and non-java targets. For example, the + # following would fail even though nothing depends on :bar(//baz): + # + # shared_library("foo") { + # } + # + # android_library("bar") { + # deps = [ ":foo(//baz)" ] + # assert(current_toolchain == default_toolchain) + # } + _msg = [ + "Tried to build an Android target in a non-default toolchain.", + "target: $_target_label", + "current_toolchain: $current_toolchain", + "default_toolchain: $default_toolchain", + ] + args += [ "--fail=$_msg" ] + } + } +} + +template("generate_android_wrapper") { + generate_wrapper(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + generator_script = "//build/android/gyp/generate_android_wrapper.py" + sources = [ + "//build/android/gyp/util/build_utils.py", + "//build/gn_helpers.py", + "//build/util/generate_wrapper.py", + ] + } +} + +template("generate_r_java") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + if (!defined(deps)) { + deps = [] + } + if (defined(invoker.possible_resource_deps)) { + foreach(_dep, invoker.possible_resource_deps) { + _target_label = get_label_info(_dep, "label_no_toolchain") + if (filter_exclude([ _target_label ], _java_library_patterns) == [] && + filter_exclude([ _target_label ], _java_resource_patterns) != []) { + # Depend on the java libraries' transitive __assetres target instead. + # This is required to ensure depending on java_groups works. + deps += [ "${_target_label}__assetres" ] + } else { + deps += [ _dep ] + } + } + } + depfile = "$target_gen_dir/${invoker.target_name}.d" + inputs = [ invoker.build_config ] + outputs = [ invoker.srcjar_path ] + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + script = "//build/android/gyp/create_r_java.py" + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--srcjar-out", + rebase_path(invoker.srcjar_path, root_build_dir), + "--deps-rtxts=@FileArg($_rebased_build_config:deps_info:dependency_r_txt_files)", + "--r-package=${invoker.package}", + ] + } +} + +# Generates a script in the build bin directory which runs the test +# target using the test runner script in build/android/test_runner.py. +template("test_runner_script") { + testonly = true + _test_name = invoker.test_name + _test_type = invoker.test_type + _incremental_apk = defined(invoker.incremental_apk) && invoker.incremental_apk + + _runtime_deps = + !defined(invoker.ignore_all_data_deps) || !invoker.ignore_all_data_deps + + if (_runtime_deps) { + # This runtime_deps file is used at runtime and thus cannot go in + # target_gen_dir. + _target_dir_name = get_label_info(":$target_name", "dir") + _runtime_deps_file = + "$root_out_dir/gen.runtime/$_target_dir_name/$target_name.runtime_deps" + _runtime_deps_target = "${target_name}__write_deps" + group(_runtime_deps_target) { + forward_variables_from(invoker, + [ + "data", + "deps", + "public_deps", + ]) + data_deps = [] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps + } + if (defined(invoker.additional_apks)) { + data_deps += invoker.additional_apks + } + write_runtime_deps = _runtime_deps_file + } + } + + if (defined(invoker.apk_under_test)) { + _install_artifacts_json = + "${target_gen_dir}/${target_name}.install_artifacts" + generated_file("${target_name}__install_artifacts") { + deps = [ invoker.apk_under_test ] + output_conversion = "json" + outputs = [ _install_artifacts_json ] + data_keys = [ "install_artifacts" ] + walk_keys = [ "install_artifacts_barrier" ] + rebase = root_build_dir + } + } + + generate_android_wrapper(target_name) { + wrapper_script = "$root_build_dir/bin/run_${_test_name}" + + executable = "//testing/test_env.py" + + if (defined(android_test_runner_script)) { + _runner_script = android_test_runner_script + } else { + _runner_script = "//build/android/test_runner.py" + } + + deps = [] + if (defined(invoker.deps)) { + deps = invoker.deps + } + data_deps = [ + "//build/android:test_runner_py", + "//testing:test_scripts_shared", + ] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps + } + data = [] + if (defined(invoker.data)) { + data += invoker.data + } + + executable_args = [ + "@WrappedPath(" + rebase_path(_runner_script, root_build_dir) + ")", + _test_type, + "--output-directory", + "@WrappedPath(.)", + ] + + if (_runtime_deps) { + deps += [ ":$_runtime_deps_target" ] + data += [ _runtime_deps_file ] + _rebased_runtime_deps_file = + rebase_path(_runtime_deps_file, root_build_dir) + executable_args += [ + "--runtime-deps-path", + "@WrappedPath(${_rebased_runtime_deps_file})", + ] + } + + # apk_target is not used for native executable tests + # (e.g. breakpad_unittests). + if (defined(invoker.apk_target)) { + assert(!defined(invoker.executable_dist_dir)) + deps += [ "${invoker.apk_target}$build_config_target_suffix" ] + _apk_build_config = + get_label_info(invoker.apk_target, "target_gen_dir") + "/" + + get_label_info(invoker.apk_target, "name") + ".build_config.json" + _rebased_apk_build_config = rebase_path(_apk_build_config, root_build_dir) + not_needed([ "_rebased_apk_build_config" ]) + } else if (_test_type == "gtest") { + assert( + defined(invoker.executable_dist_dir), + "Must define either apk_target or executable_dist_dir for test_runner_script()") + _rebased_executable_dist_dir = + rebase_path(invoker.executable_dist_dir, root_build_dir) + executable_args += [ + "--executable-dist-dir", + "@WrappedPath(${_rebased_executable_dist_dir})", + ] + } + + _device_test = true + if (_test_type == "gtest") { + assert(defined(invoker.test_suite)) + executable_args += [ + "--suite", + invoker.test_suite, + ] + if (use_clang_coverage) { + # Set a default coverage output directory (can be overridden by user + # passing the same flag). + _rebased_coverage_dir = + rebase_path("$root_out_dir/coverage", root_build_dir) + executable_args += [ + "--coverage-dir", + "@WrappedPath(${_rebased_coverage_dir})", + ] + } + } else if (_test_type == "instrumentation") { + _test_apk = "@WrappedPath(@FileArg($_rebased_apk_build_config:deps_info:apk_path))" + if (_incremental_apk) { + _test_apk = "@WrappedPath(@FileArg($_rebased_apk_build_config:deps_info:incremental_apk_path))" + } + _rebased_test_jar = rebase_path(invoker.test_jar, root_build_dir) + executable_args += [ + "--test-apk", + _test_apk, + "--test-jar", + "@WrappedPath(${_rebased_test_jar})", + ] + if (defined(invoker.apk_under_test)) { + if (_incremental_apk) { + deps += [ "${invoker.apk_under_test}$build_config_target_suffix" ] + _apk_under_test_build_config = + get_label_info(invoker.apk_under_test, "target_gen_dir") + "/" + + get_label_info(invoker.apk_under_test, "name") + + ".build_config.json" + _rebased_apk_under_test_build_config = + rebase_path(_apk_under_test_build_config, root_build_dir) + _apk_under_test = "@WrappedPath(@FileArg($_rebased_apk_under_test_build_config:deps_info:incremental_apk_path))" + } else { + deps += [ ":${target_name}__install_artifacts" ] + _rebased_install_artifacts_json = + rebase_path(_install_artifacts_json, root_build_dir) + _apk_under_test = + "@WrappedPath(@FileArg($_rebased_install_artifacts_json[]))" + } + executable_args += [ + "--apk-under-test", + _apk_under_test, + ] + } + if (defined(invoker.use_webview_provider)) { + deps += [ "${invoker.use_webview_provider}$build_config_target_suffix" ] + _build_config = + get_label_info(invoker.use_webview_provider, "target_gen_dir") + + "/" + get_label_info(invoker.use_webview_provider, "name") + + ".build_config.json" + _rebased_build_config = rebase_path(_build_config, root_build_dir) + executable_args += [ + "--use-webview-provider", + "@WrappedPath(@FileArg($_rebased_build_config:deps_info:apk_path))", + ] + } + if (defined(invoker.proguard_enabled) && invoker.proguard_enabled && + !_incremental_apk) { + executable_args += [ "--enable-java-deobfuscation" ] + } + if (use_jacoco_coverage) { + # Set a default coverage output directory (can be overridden by user + # passing the same flag). + _rebased_coverage_dir = + rebase_path("$root_out_dir/coverage", root_build_dir) + executable_args += [ + "--coverage-dir", + "@WrappedPath(${_rebased_coverage_dir})", + ] + } + } else if (_test_type == "junit") { + assert(defined(invoker.test_suite)) + _device_test = false + executable_args += [ + "--test-suite", + invoker.test_suite, + ] + + deps += [ ":${invoker.test_suite}$build_config_target_suffix" ] + _junit_binary_build_config = + "${target_gen_dir}/${invoker.test_suite}.build_config.json" + + _rebased_robolectric_runtime_deps_dir = + rebase_path("$root_build_dir/lib.java/third_party/robolectric", + root_build_dir) + _rebased_resource_apk = rebase_path(invoker.resource_apk, root_build_dir) + executable_args += [ + "--resource-apk", + "@WrappedPath(${_rebased_resource_apk})", + "--robolectric-runtime-deps-dir", + "@WrappedPath(${_rebased_robolectric_runtime_deps_dir})", + ] + if (use_jacoco_coverage) { + # Set a default coverage output directory (can be overridden by user + # passing the same flag). + _rebased_coverage_dir = + rebase_path("$root_out_dir/coverage", root_build_dir) + executable_args += [ + "--coverage-dir", + "@WrappedPath(${_rebased_coverage_dir})", + ] + } + } else if (_test_type == "linker") { + executable_args += [ + "--test-apk", + "@WrappedPath(@FileArg($_rebased_apk_build_config:deps_info:apk_path))", + ] + } else { + assert(false, "Invalid test type: $_test_type.") + } + + if (defined(invoker.additional_apks)) { + foreach(additional_apk, invoker.additional_apks) { + deps += [ "$additional_apk$build_config_target_suffix" ] + _build_config = + get_label_info(additional_apk, "target_gen_dir") + "/" + + get_label_info(additional_apk, "name") + ".build_config.json" + _rebased_build_config = rebase_path(_build_config, root_build_dir) + executable_args += [ + "--additional-apk", + "@WrappedPath(@FileArg($_rebased_build_config:deps_info:apk_path))", + ] + } + } + if (defined(invoker.shard_timeout)) { + executable_args += [ "--shard-timeout=${invoker.shard_timeout}" ] + } + if (_incremental_apk) { + executable_args += [ + "--test-apk-incremental-install-json", + "@WrappedPath(@FileArg($_rebased_apk_build_config:deps_info:incremental_install_json_path))", + ] + if (defined(invoker.apk_under_test)) { + executable_args += [ + "--apk-under-test-incremental-install-json", + "@WrappedPath(@FileArg($_rebased_apk_under_test_build_config:deps_info:incremental_install_json_path))", + ] + } + executable_args += [ "--fast-local-dev" ] + } + if (_device_test && is_asan) { + executable_args += [ "--tool=asan" ] + } + + if (defined(invoker.modules)) { + foreach(module, invoker.modules) { + executable_args += [ + "--module", + module, + ] + } + } + + if (defined(invoker.fake_modules)) { + foreach(fake_module, invoker.fake_modules) { + executable_args += [ + "--fake-module", + fake_module, + ] + } + } + + if (defined(invoker.additional_locales)) { + foreach(locale, invoker.additional_locales) { + executable_args += [ + "--additional-locale", + locale, + ] + } + } + + if (defined(invoker.extra_args)) { + executable_args += invoker.extra_args + } + } +} + +if (enable_java_templates) { + template("android_lint") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + if (!defined(deps)) { + deps = [] + } + + # https://crbug.com/1098752 Fix for bot OOM (https://crbug.com/1098333). + if (defined(java_cmd_pool_size)) { + pool = "//build/config/android:java_cmd_pool($default_toolchain)" + } else { + pool = "//build/toolchain:link_pool($default_toolchain)" + } + + # Lint requires generated sources and generated resources from the build. + # Turbine __header targets depend on all generated sources, and the + # __assetres targets depend on all generated resources. + if (defined(invoker.deps)) { + foreach(_dep, invoker.deps) { + _target_label = get_label_info(_dep, "label_no_toolchain") + if (filter_exclude([ _target_label ], _java_library_patterns) == [] && + filter_exclude([ _target_label ], _java_resource_patterns) != + []) { + deps += [ + "${_target_label}__assetres", + "${_target_label}__header", + ] + } else { + # Keep non-java deps as they may generate files used only by lint. + # e.g. generated suppressions.xml files. + deps += [ _dep ] + } + } + } + + if (defined(invoker.min_sdk_version)) { + _min_sdk_version = invoker.min_sdk_version + } else { + _min_sdk_version = default_min_sdk_version + } + + _lint_binary_path = "$lint_android_sdk_root/cmdline-tools/latest/bin/lint" + _cache_dir = "$root_build_dir/android_lint_cache" + + # Save generated xml files in a consistent location for debugging. + _lint_gen_dir = "$target_gen_dir/$target_name" + _backported_methods = "//third_party/r8/backported_methods.txt" + + script = "//build/android/gyp/lint.py" + depfile = "$target_gen_dir/$target_name.d" + inputs = [ + _lint_binary_path, + _backported_methods, + ] + + args = [ + "--target-name", + get_label_info(":${target_name}", "label_no_toolchain"), + "--depfile", + rebase_path(depfile, root_build_dir), + "--lint-binary-path", + rebase_path(_lint_binary_path, root_build_dir), + "--cache-dir", + rebase_path(_cache_dir, root_build_dir), + "--lint-gen-dir", + rebase_path(_lint_gen_dir, root_build_dir), + "--android-sdk-version=${lint_android_sdk_version}", + "--min-sdk-version=$_min_sdk_version", + "--android-sdk-root", + rebase_path(lint_android_sdk_root, root_build_dir), + "--backported-methods", + rebase_path(_backported_methods, root_build_dir), + ] + + if (defined(invoker.skip_build_server) && invoker.skip_build_server) { + # Nocompile tests need lint to fail through ninja. + args += [ "--skip-build-server" ] + } + + if (defined(invoker.lint_suppressions_file)) { + inputs += [ invoker.lint_suppressions_file ] + + args += [ + "--config-path", + rebase_path(invoker.lint_suppressions_file, root_build_dir), + ] + } + + if (defined(testonly) && testonly) { + # Allows us to ignore unnecessary checks when linting test targets. + args += [ "--testonly" ] + } + + if (defined(invoker.manifest_package)) { + args += [ "--manifest-package=${invoker.manifest_package}" ] + } + + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + + if (defined(invoker.lint_baseline_file)) { + if (compute_inputs_for_analyze) { + # The baseline file is included in lint.py as a depfile dep. Since + # removing it regenerates the file, it is useful to not have this as + # a gn input during local development. Add it only for bots' analyze. + inputs += [ invoker.lint_baseline_file ] + } + args += [ + # Baseline allows us to turn on lint warnings without fixing all the + # pre-existing issues. This stops the flood of new issues while the + # existing ones are being fixed. + "--baseline", + rebase_path(invoker.lint_baseline_file, root_build_dir), + ] + } + + if (defined(invoker.create_cache) && invoker.create_cache) { + # Putting the stamp file in the cache dir allows us to depend on ninja + # to create the cache dir for us. + _stamp_path = "$_cache_dir/build.lint.stamp" + args += [ "--create-cache" ] + } else { + _stamp_path = "$target_out_dir/$target_name/build.lint.stamp" + deps += [ + "//build/android:prepare_android_lint_cache", + invoker.build_config_dep, + ] + inputs += [ invoker.build_config ] + _rebased_build_config = + rebase_path(invoker.build_config, root_build_dir) + + args += [ + "--manifest-path=@FileArg($_rebased_build_config:deps_info:lint_android_manifest)", + "--extra-manifest-paths=@FileArg($_rebased_build_config:deps_info:lint_extra_android_manifests)", + + # Lint requires all source and all resource files to be passed in the + # same invocation for checks like UnusedResources. + "--java-sources=@FileArg($_rebased_build_config:deps_info:lint_java_sources)", + "--aars=@FileArg($_rebased_build_config:deps_info:lint_aars)", + "--srcjars=@FileArg($_rebased_build_config:deps_info:lint_srcjars)", + "--resource-sources=@FileArg($_rebased_build_config:deps_info:lint_resource_sources)", + "--resource-zips=@FileArg($_rebased_build_config:deps_info:lint_resource_zips)", + + # The full classpath is required for annotation checks like @IntDef. + "--classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)", + ] + } + + outputs = [ _stamp_path ] + args += [ + "--stamp", + rebase_path(_stamp_path, root_build_dir), + ] + } + } + + template("proguard") { + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "data", + "data_deps", + "public_deps", + ]) + _script = "//build/android/gyp/proguard.py" + _deps = invoker.deps + + _inputs = [ + invoker.build_config, + _r8_path, + ] + if (defined(invoker.inputs)) { + _inputs += invoker.inputs + } + if (defined(invoker.proguard_mapping_path)) { + _mapping_path = invoker.proguard_mapping_path + } else { + _mapping_path = "${invoker.output_path}.mapping" + } + + _enable_jdk_library_desugaring = enable_jdk_library_desugaring + if (defined(invoker.supports_jdk_library_desugaring) && + !invoker.supports_jdk_library_desugaring) { + _enable_jdk_library_desugaring = false + } + + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + _args = [ + "--mapping-output", + rebase_path(_mapping_path, root_build_dir), + "--classpath", + "@FileArg($_rebased_build_config:deps_info:proguard_classpath_jars)", + "--classpath", + "@FileArg($_rebased_build_config:android:sdk_jars)", + "--r8-path", + rebase_path(_r8_path, root_build_dir), + ] + if (treat_warnings_as_errors) { + _args += [ "--warnings-as-errors" ] + } + if (defined(invoker.desugar_jars_paths)) { + _rebased_desugar_jars_paths = + rebase_path(invoker.desugar_jars_paths, root_build_dir) + args += [ "--classpath=${_rebased_desugar_jars_paths}" ] + } + + if ((!defined(invoker.proguard_enable_obfuscation) || + invoker.proguard_enable_obfuscation) && enable_proguard_obfuscation) { + _proguard_sourcefile_suffix = "" + if (defined(invoker.proguard_sourcefile_suffix)) { + _proguard_sourcefile_suffix = "-${invoker.proguard_sourcefile_suffix}" + } + + # This is generally the apk name, and serves to identify the mapping + # file that would be required to deobfuscate a stacktrace. + _mapping_id = get_path_info(_mapping_path, "name") + _args += [ + "--enable-obfuscation", + "--sourcefile", + "chromium-${_mapping_id}${_proguard_sourcefile_suffix}", + ] + } else if (defined(invoker.proguard_sourcefile_suffix)) { + not_needed(invoker, [ "proguard_sourcefile_suffix" ]) + } + + if (defined(invoker.modules)) { + foreach(_feature_module, invoker.modules) { + _rebased_module_build_config = + rebase_path(_feature_module.build_config, root_build_dir) + _args += [ + "--feature-name=${_feature_module.name}", + "--dex-dest=@FileArg($_rebased_module_build_config:final_dex:path)", + "--feature-jars=@FileArg($_rebased_module_build_config:deps_info:device_classpath)", + ] + if (defined(_feature_module.uses_split)) { + _args += [ "--uses-split=${_feature_module.name}:${_feature_module.uses_split}" ] + } + _deps += [ _feature_module.build_config_target ] + } + _stamp = "${target_gen_dir}/${target_name}.r8.stamp" + _outputs = [ _stamp ] + _output_arg = [ + "--stamp", + rebase_path(_stamp, root_build_dir), + ] + } else { + # We don't directly set the output arg on the _args variable since it is + # shared with the expectation target that uses its own stamp file and + # does not take an --output-path. + _output_arg = [ + "--output-path", + rebase_path(invoker.output_path, root_build_dir), + ] + _outputs = [ invoker.output_path ] + } + _outputs += [ _mapping_path ] + + if (defined(invoker.disable_r8_outlining) && invoker.disable_r8_outlining) { + _args += [ "--disable-outlining" ] + } + + if (defined(invoker.enable_proguard_checks) && + !invoker.enable_proguard_checks) { + _args += [ "--disable-checks" ] + } + + if (defined(invoker.is_static_library) && invoker.is_static_library) { + _args += [ + "--extra-mapping-output-paths", + "@FileArg($_rebased_build_config:deps_info:static_library_proguard_mapping_output_paths)", + ] + } + + if (_enable_jdk_library_desugaring) { + _args += [ + "--desugar-jdk-libs-json", + rebase_path(_desugar_jdk_libs_json, root_build_dir), + ] + _inputs += [ _desugar_jdk_libs_json ] + + _args += [ + "--desugar-jdk-libs-jar", + rebase_path(_desugar_jdk_libs_jar, root_build_dir), + "--desugar-jdk-libs-configuration-jar", + rebase_path(_desugar_jdk_libs_configuration_jar, root_build_dir), + ] + _inputs += [ + _desugar_jdk_libs_jar, + _desugar_jdk_libs_configuration_jar, + ] + + _desugared_library_keep_rule_output_path = + "$target_gen_dir/$target_name.desugared_library_keep_rules.flags" + _args += [ + "--desugared-library-keep-rule-output", + rebase_path(_desugared_library_keep_rule_output_path, root_build_dir), + ] + } + _ignore_desugar_missing_deps = + defined(invoker.ignore_desugar_missing_deps) && + invoker.ignore_desugar_missing_deps + if (!_ignore_desugar_missing_deps) { + _args += [ "--show-desugar-default-interface-warnings" ] + } + + if (enable_java_asserts) { + # The default for generating dex file format is + # --force-disable-assertions. + _args += [ "--force-enable-assertions" ] + } + + if (defined(invoker.args)) { + _args += invoker.args + } + + if (defined(invoker.expected_proguard_config)) { + _expectations_target = + "${invoker.top_target_name}_validate_proguard_config" + action_with_pydeps(_expectations_target) { + script = _script + + # Need to depend on all deps so that proguard.txt within .aar files get + # extracted. + deps = _deps + depfile = "${target_gen_dir}/${target_name}.d" + inputs = [ + invoker.build_config, + invoker.expected_proguard_config, + ] + _actual_file = "$target_gen_dir/$target_name.proguard_configs" + _failure_file = + "$expectations_failure_dir/" + + string_replace(invoker.expected_proguard_config, "/", "_") + outputs = [ + _actual_file, + _failure_file, + ] + args = _args + [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--failure-file", + rebase_path(_failure_file, root_build_dir), + "--expected-file", + rebase_path(invoker.expected_proguard_config, root_build_dir), + "--actual-file", + rebase_path(_actual_file, root_build_dir), + "--only-verify-expectations", + ] + if (defined(invoker.expected_proguard_config_base)) { + inputs += [ invoker.expected_proguard_config_base ] + args += [ + "--expected-file-base", + rebase_path(invoker.expected_proguard_config_base, root_build_dir), + ] + } + if (fail_on_android_expectations) { + args += [ "--fail-on-expectations" ] + } + } + _deps += [ ":$_expectations_target" ] + } + action_with_pydeps(target_name) { + script = _script + deps = _deps + inputs = _inputs + outputs = _outputs + depfile = "${target_gen_dir}/${target_name}.d" + args = _args + _output_arg + [ + "--depfile", + rebase_path(depfile, root_build_dir), + ] + + # http://crbug.com/725224. Fix for bots running out of memory. + if (defined(java_cmd_pool_size)) { + pool = "//build/config/android:java_cmd_pool($default_toolchain)" + } else { + pool = "//build/toolchain:link_pool($default_toolchain)" + } + } + } + + # Generates a script in the build bin directory to run a java binary. + # + # Variables + # main_class: The class containing the program entry point. + # build_config: Path to .build_config.json for the jar (contains classpath). + # script_name: Name of the script to generate. + # wrapper_script_args: List of extra arguments to pass to the executable. + # tiered_stop_at_level_one: Whether to pass --tiered-stop-at-level-one + # + template("java_binary_script") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + + _main_class = invoker.main_class + _build_config = invoker.build_config + _script_name = invoker.script_name + + script = "//build/android/gyp/create_java_binary_script.py" + inputs = [ _build_config ] + _java_script = "$root_build_dir/bin/$_script_name" + outputs = [ _java_script ] + _rebased_build_config = rebase_path(_build_config, root_build_dir) + args = [ + "--output", + rebase_path(_java_script, root_build_dir), + "--main-class", + _main_class, + ] + args += [ + "--classpath=@FileArg($_rebased_build_config:deps_info:host_classpath)", + ] + + if (use_jacoco_coverage) { + args += [ + "--classpath", + rebase_path("//third_party/jacoco/lib/jacocoagent.jar", + root_build_dir), + ] + } + if (use_jacoco_coverage || !treat_warnings_as_errors) { + args += [ "--noverify" ] + } + if (defined(invoker.tiered_stop_at_level_one) && + invoker.tiered_stop_at_level_one) { + args += [ "--tiered-stop-at-level-one" ] + } + if (defined(invoker.wrapper_script_args)) { + args += [ "--" ] + invoker.wrapper_script_args + } + } + } + + # Variables + # apply_mapping: The path to the ProGuard mapping file to apply. + # disable_incremental: Disable incremental dexing. + template("dex") { + _min_sdk_version = default_min_sdk_version + if (defined(invoker.min_sdk_version)) { + _min_sdk_version = invoker.min_sdk_version + } + + _proguard_enabled = + defined(invoker.proguard_enabled) && invoker.proguard_enabled + _is_dex_merging = defined(invoker.input_dex_filearg) + _enable_multidex = + !defined(invoker.enable_multidex) || invoker.enable_multidex + _enable_main_dex_list = _enable_multidex && _min_sdk_version < 21 + _enable_desugar = !defined(invoker.enable_desugar) || invoker.enable_desugar + _use_classic_desugar = + defined(invoker.use_classic_desugar) && invoker.use_classic_desugar + _desugar_needs_classpath = _enable_desugar && !_use_classic_desugar + + # It's not safe to dex merge with libraries dex'ed at higher api versions. + assert(!_is_dex_merging || _min_sdk_version >= default_min_sdk_version) + + # For D8's backported method desugaring to work properly, the dex merge step + # must not be set to a higher minSdkVersion than it was for the libraries. + if (_enable_desugar && _is_dex_merging) { + _min_sdk_version = default_min_sdk_version + } + + assert(defined(invoker.output) || + (_proguard_enabled && defined(invoker.modules))) + assert(!_proguard_enabled || !(defined(invoker.input_dex_filearg) || + defined(invoker.input_classes_filearg) || + defined(invoker.input_class_jars)), + "Cannot explicitly set inputs when proguarding a dex.") + + # Dex merging should not also be dexing. + assert(!(_is_dex_merging && defined(invoker.input_classes_filearg))) + assert(!(_is_dex_merging && defined(invoker.input_class_jars))) + + assert(!(defined(invoker.apply_mapping) && !_proguard_enabled), + "apply_mapping can only be specified if proguard is enabled.") + + if (_enable_main_dex_list) { + _main_dex_rules = "//build/android/main_dex_classes.flags" + } + + if (_desugar_needs_classpath || _proguard_enabled) { + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + } + + if (_proguard_enabled) { + _proguard_target_name = target_name + + proguard(_proguard_target_name) { + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "build_config", + "data", + "data_deps", + "deps", + "desugar_jars_paths", + "disable_r8_outlining", + "enable_proguard_checks", + "expected_proguard_config", + "expected_proguard_config_base", + "ignore_desugar_missing_deps", + "is_static_library", + "modules", + "proguard_enable_obfuscation", + "proguard_mapping_path", + "proguard_sourcefile_suffix", + "supports_jdk_library_desugaring", + "top_target_name", + ]) + inputs = [] + if (defined(invoker.inputs)) { + inputs += invoker.inputs + } + if (defined(invoker.proguard_configs)) { + inputs += invoker.proguard_configs + } + + args = [ + "--proguard-configs=@FileArg($_rebased_build_config:deps_info:proguard_all_configs)", + "--min-api=$_min_sdk_version", + ] + if (defined(invoker.has_apk_under_test) && invoker.has_apk_under_test) { + args += [ "--input-paths=@FileArg($_rebased_build_config:deps_info:device_classpath_extended)" ] + } else { + args += [ "--input-paths=@FileArg($_rebased_build_config:deps_info:device_classpath)" ] + } + if (_use_classic_desugar) { + deps += [ "//third_party/bazel/desugar:desugar_runtime_java" ] + inputs += [ _desugar_runtime_jar ] + args += [ + "--input-paths", + rebase_path(_desugar_runtime_jar, root_build_dir), + ] + } + if (defined(invoker.proguard_args)) { + args += invoker.proguard_args + } + + if (defined(invoker.apply_mapping)) { + _rebased_apply_mapping_path = + rebase_path(invoker.apply_mapping, root_build_dir) + args += [ "--apply-mapping=$_rebased_apply_mapping_path" ] + } + + if (_enable_main_dex_list) { + if (defined(invoker.extra_main_dex_proguard_config)) { + args += [ + "--main-dex-rules-path", + rebase_path(invoker.extra_main_dex_proguard_config, + root_build_dir), + ] + inputs += [ invoker.extra_main_dex_proguard_config ] + } + args += [ + "--main-dex-rules-path", + rebase_path(_main_dex_rules, root_build_dir), + ] + inputs += [ _main_dex_rules ] + } + + if (defined(invoker.output)) { + output_path = invoker.output + } else if (!defined(proguard_mapping_path)) { + proguard_mapping_path = "$target_out_dir/$target_name.mapping" + } + } + } else { # !_proguard_enabled + _is_library = defined(invoker.is_library) && invoker.is_library + _input_class_jars = [] + if (defined(invoker.input_class_jars)) { + _input_class_jars = invoker.input_class_jars + } + _deps = invoker.deps + + if (!_is_library && _use_classic_desugar) { + # It would be more efficient to use the pre-dex'ed copy of the runtime, + # but it's easier to add it in this way. + _deps += [ "//third_party/bazel/desugar:desugar_runtime_java" ] + _input_class_jars += [ _desugar_runtime_jar ] + } + if (_input_class_jars != []) { + _rebased_input_class_jars = + rebase_path(_input_class_jars, root_build_dir) + } + + action_with_pydeps(target_name) { + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "data", + "data_deps", + ]) + script = "//build/android/gyp/dex.py" + deps = _deps + depfile = "$target_gen_dir/$target_name.d" + outputs = [ invoker.output ] + inputs = [ + _r8_path, + _custom_d8_path, + ] + + if (!_is_library) { + # http://crbug.com/725224. Fix for bots running out of memory. + if (defined(java_cmd_pool_size)) { + pool = "//build/config/android:java_cmd_pool($default_toolchain)" + } else { + pool = "//build/toolchain:link_pool($default_toolchain)" + } + } + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--output", + rebase_path(outputs[0], root_build_dir), + "--min-api=$_min_sdk_version", + "--r8-jar-path", + rebase_path(_r8_path, root_build_dir), + "--custom-d8-jar-path", + rebase_path(_custom_d8_path, root_build_dir), + + # Uncomment when rebuilding custom_d8.jar. + #"--skip-custom-d8", + ] + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + + if (enable_incremental_d8 && !(defined(invoker.disable_incremental) && + invoker.disable_incremental)) { + # Don't use incremental dexing for ProGuarded inputs as a precaution. + args += [ + "--incremental-dir", + rebase_path("$target_out_dir/$target_name", root_build_dir), + ] + } + + if (_enable_multidex) { + args += [ "--multi-dex" ] + if (_enable_main_dex_list) { + if (defined(invoker.extra_main_dex_proguard_config)) { + args += [ + "--main-dex-rules-path", + rebase_path(invoker.extra_main_dex_proguard_config, + root_build_dir), + ] + inputs += [ invoker.extra_main_dex_proguard_config ] + } + args += [ + "--main-dex-rules-path", + rebase_path(_main_dex_rules, root_build_dir), + ] + inputs += [ _main_dex_rules ] + } + } + if (_is_library) { + args += [ "--library" ] + } + if (defined(invoker.input_dex_filearg)) { + inputs += [ invoker.build_config ] + args += [ "--dex-inputs-filearg=${invoker.input_dex_filearg}" ] + } + if (defined(invoker.input_classes_filearg)) { + inputs += [ invoker.build_config ] + args += [ "--class-inputs-filearg=${invoker.input_classes_filearg}" ] + } + if (_input_class_jars != []) { + inputs += _input_class_jars + args += [ "--class-inputs=${_rebased_input_class_jars}" ] + } + + if (defined(invoker.dexlayout_profile)) { + args += [ + "--dexlayout-profile", + rebase_path(invoker.dexlayout_profile, root_build_dir), + "--dexlayout-path", + rebase_path(_dexlayout_path, root_build_dir), + "--profman-path", + rebase_path(_profman_path, root_build_dir), + "--dexdump-path", + rebase_path(_dexdump_path, root_build_dir), + ] + inputs += [ + _dexlayout_path, + _profman_path, + _dexdump_path, + invoker.dexlayout_profile, + ] + inputs += _default_art_libs + } + + # Never compile intemediates with --release in order to: + # 1) not require recompiles when toggling is_java_debug, + # 2) allow incremental_install=1 to still have local variable + # information even when is_java_debug=false. + if (!is_java_debug && !_is_library) { + args += [ "--release" ] + } + + if (_enable_desugar) { + args += [ "--desugar" ] + + # Passing the flag for dex merging causes invalid dex files to be created. + if (enable_jdk_library_desugaring && !_is_dex_merging) { + inputs += [ _desugar_jdk_libs_json ] + args += [ + "--desugar-jdk-libs-json", + rebase_path(_desugar_jdk_libs_json, root_build_dir), + ] + } + _ignore_desugar_missing_deps = + defined(invoker.ignore_desugar_missing_deps) && + invoker.ignore_desugar_missing_deps + if (!_ignore_desugar_missing_deps && !_use_classic_desugar) { + args += [ "--show-desugar-default-interface-warnings" ] + } + } + if (_desugar_needs_classpath) { + _desugar_dependencies_path = + "$target_gen_dir/$target_name.desugardeps" + args += [ + "--desugar-dependencies", + rebase_path(_desugar_dependencies_path, root_build_dir), + "--bootclasspath=@FileArg($_rebased_build_config:android:sdk_jars)", + + # Pass the full classpath to find new dependencies that are not in + # the .desugardeps file. + "--classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)", + ] + if (defined(invoker.desugar_jars_paths)) { + _rebased_desugar_jars_paths = + rebase_path(invoker.desugar_jars_paths, root_build_dir) + args += [ "--classpath=${_rebased_desugar_jars_paths}" ] + } + if (defined(invoker.final_ijar_path)) { + # Need to include the input .interface.jar on the classpath in order to make + # jar_excluded_patterns classes visible to desugar. + args += [ + "--classpath", + rebase_path(invoker.final_ijar_path, root_build_dir), + ] + inputs += [ invoker.final_ijar_path ] + } + } else { + not_needed(invoker, [ "desugar_jars_paths" ]) + } + + if (enable_java_asserts) { + # The default for generating dex file format is + # --force-disable-assertions. + args += [ "--force-enable-assertions" ] + } + } + } + } + + # Variables + # output: Path to output ".l8.dex". + # min_sdk_version: The minimum Android SDK version this target supports. + template("dex_jdk_libs") { + action_with_pydeps(target_name) { + script = "//build/android/gyp/dex_jdk_libs.py" + inputs = [ + _r8_path, + _desugar_jdk_libs_json, + _desugar_jdk_libs_jar, + _desugar_jdk_libs_configuration_jar, + ] + outputs = [ invoker.output ] + args = [ + "--r8-path", + rebase_path(_r8_path, root_build_dir), + "--desugar-jdk-libs-json", + rebase_path(_desugar_jdk_libs_json, root_build_dir), + "--desugar-jdk-libs-jar", + rebase_path(_desugar_jdk_libs_jar, root_build_dir), + "--desugar-jdk-libs-configuration-jar", + rebase_path(_desugar_jdk_libs_configuration_jar, root_build_dir), + "--output", + rebase_path(invoker.output, root_build_dir), + "--min-api=${invoker.min_sdk_version}", + ] + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + } + } + + template("jacoco_instr") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "deps", + "public_deps", + ]) + + # The name needs to match the SOURCES_JSON_FILES_SUFFIX in + # generate_coverage_metadata_for_java.py. + _sources_json_file = "$target_out_dir/${target_name}__jacoco_sources.json" + _jacococli_jar = "//third_party/jacoco/lib/jacococli.jar" + + script = "//build/android/gyp/jacoco_instr.py" + inputs = invoker.java_files + [ + _jacococli_jar, + invoker.input_jar_path, + ] + outputs = [ + _sources_json_file, + invoker.output_jar_path, + ] + args = [ + "--input-path", + rebase_path(invoker.input_jar_path, root_build_dir), + "--output-path", + rebase_path(invoker.output_jar_path, root_build_dir), + "--sources-json-file", + rebase_path(_sources_json_file, root_build_dir), + "--java-sources-file", + rebase_path(invoker.java_sources_file, root_build_dir), + "--jacococli-jar", + rebase_path(_jacococli_jar, root_build_dir), + ] + if (coverage_instrumentation_input_file != "") { + args += [ + "--files-to-instrument", + rebase_path(coverage_instrumentation_input_file, root_build_dir), + ] + } + } + } + + template("filter_jar") { + action_with_pydeps(target_name) { + script = "//build/android/gyp/filter_zip.py" + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + inputs = [ invoker.input_jar ] + if (defined(invoker.inputs)) { + inputs += invoker.inputs + } + outputs = [ invoker.output_jar ] + + _jar_excluded_patterns = [] + if (defined(invoker.jar_excluded_patterns)) { + _jar_excluded_patterns = invoker.jar_excluded_patterns + } + _jar_included_patterns = [] + if (defined(invoker.jar_included_patterns)) { + _jar_included_patterns = invoker.jar_included_patterns + } + args = [ + "--input", + rebase_path(invoker.input_jar, root_build_dir), + "--output", + rebase_path(invoker.output_jar, root_build_dir), + "--exclude-globs=${_jar_excluded_patterns}", + "--include-globs=${_jar_included_patterns}", + ] + } + } + + template("process_java_library") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _deps = invoker.jar_deps + _previous_output_jar = invoker.input_jar_path + + if (invoker.is_device_jar && invoker.enable_desugar) { + _desugar_target = "${target_name}_device__desugar" + _desugar_output_jar = "$target_out_dir/$target_name.desugar.jar" + + action_with_pydeps(_desugar_target) { + script = "//build/android/gyp/desugar.py" + deps = _deps + invoker.classpath_deps + depfile = "$target_gen_dir/$target_name.d" + _rebased_build_config = + rebase_path(invoker.build_config, root_build_dir) + _desugar_jar = "//third_party/bazel/desugar/Desugar.jar" + + inputs = [ + invoker.build_config, + _previous_output_jar, + _desugar_jar, + ] + outputs = [ _desugar_output_jar ] + args = [ + "--desugar-jar", + rebase_path(_desugar_jar, root_build_dir), + "--input-jar", + rebase_path(_previous_output_jar, root_build_dir), + "--output-jar", + rebase_path(_desugar_output_jar, root_build_dir), + + # Temporarily using java_full_interface_classpath until classpath validation of targets + # is implemented, see http://crbug.com/885273 + "--classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)", + "--bootclasspath=@FileArg($_rebased_build_config:android:sdk_interface_jars)", + "--depfile", + rebase_path(depfile, root_build_dir), + ] + if (defined(invoker.desugar_jars_paths)) { + _rebased_desugar_jars_paths = + rebase_path(invoker.desugar_jars_paths, root_build_dir) + args += [ "--classpath=${_rebased_desugar_jars_paths}" ] + } + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + } + + _deps = [] + _deps = [ ":$_desugar_target" ] + _previous_output_jar = _desugar_output_jar + } + + if (invoker.jacoco_instrument) { + _filter_jar_target_name = "${target_name}__filter_jar" + _filter_jar_output_jar = "$target_out_dir/$target_name.filter.jar" + } else { + _filter_jar_target_name = target_name + _filter_jar_output_jar = invoker.output_jar_path + } + + filter_jar(_filter_jar_target_name) { + forward_variables_from(invoker, + [ + "jar_excluded_patterns", + "jar_included_patterns", + ]) + deps = _deps + input_jar = _previous_output_jar + output_jar = _filter_jar_output_jar + } + + if (invoker.jacoco_instrument) { + # Jacoco must run after desugar (or else desugar sometimes fails). + # It must run after filtering to avoid the same (filtered) class mapping + # to multiple .jar files. + # We run offline code coverage processing here rather than with a + # javaagent as the desired coverage data was not being generated. + # See crbug.com/1097815. + jacoco_instr(target_name) { + deps = [ ":$_filter_jar_target_name" ] + invoker.jar_deps + forward_variables_from(invoker, + [ + "java_files", + "java_sources_file", + ]) + + input_jar_path = _filter_jar_output_jar + output_jar_path = invoker.output_jar_path + } + } + } + + template("bytecode_processor") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + _bytecode_checker_script = "$root_build_dir/bin/helper/bytecode_processor" + script = "//build/android/gyp/bytecode_processor.py" + inputs = [ + invoker.build_config, + invoker.input_jar, + _bytecode_checker_script, + ] + outputs = [ "$target_out_dir/$target_name.bytecode.stamp" ] + deps = + invoker.deps + + [ "//build/android/bytecode:bytecode_processor($default_toolchain)" ] + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + args = [ + "--target-name", + get_label_info(":${target_name}", "label_no_toolchain"), + "--script", + rebase_path(_bytecode_checker_script, root_build_dir), + "--gn-target=${invoker.target_label}", + "--input-jar", + rebase_path(invoker.input_jar, root_build_dir), + "--stamp", + rebase_path(outputs[0], root_build_dir), + "--direct-classpath-jars=@FileArg($_rebased_build_config:javac:classpath)", + "--full-classpath-jars=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)", + "--full-classpath-gn-targets=@FileArg($_rebased_build_config:deps_info:javac_full_classpath_targets)", + ] + if (invoker.requires_android) { + args += [ "--sdk-classpath-jars=@FileArg($_rebased_build_config:android:sdk_jars)" ] + } + if (invoker.is_prebuilt) { + args += [ "--is-prebuilt" ] + } + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + if (defined(invoker.missing_classes_allowlist)) { + args += [ + "--missing-classes-allowlist=${invoker.missing_classes_allowlist}", + ] + } + } + } + + template("merge_manifests") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + script = "//build/android/gyp/merge_manifest.py" + depfile = "$target_gen_dir/$target_name.d" + + inputs = [ + invoker.build_config, + invoker.input_manifest, + ] + + outputs = [ invoker.output_manifest ] + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--android-sdk-cmdline-tools", + rebase_path("${public_android_sdk_root}/cmdline-tools/latest", + root_build_dir), + "--root-manifest", + rebase_path(invoker.input_manifest, root_build_dir), + "--output", + rebase_path(invoker.output_manifest, root_build_dir), + "--extras", + "@FileArg($_rebased_build_config:extra_android_manifests)", + "--min-sdk-version=${invoker.min_sdk_version}", + "--target-sdk-version=${invoker.target_sdk_version}", + ] + + if (defined(invoker.manifest_package)) { + args += [ "--manifest-package=${invoker.manifest_package}" ] + } + + if (defined(invoker.max_sdk_version)) { + args += [ "--max-sdk-version=${invoker.max_sdk_version}" ] + } + + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + } + } + + # This template is used to parse a set of resource directories and + # create the R.txt, .srcjar and .resources.zip for it. + # + # Input variables: + # deps: Specifies the input dependencies for this target. + # + # build_config: Path to the .build_config.json file corresponding to the target. + # + # sources: + # List of input resource files. + # + # custom_package: (optional) + # Package name for the generated R.java source file. Optional if + # android_manifest is not provided. + # + # android_manifest: (optional) + # If custom_package is not provided, path to an AndroidManifest.xml file + # that is only used to extract a package name out of it. + # + # r_text_in_path: (optional) + # Path to an input R.txt file to use to generate the R.java file. + # The default is to use 'aapt' to generate the file from the content + # of the resource directories. + # + # Output variables: + # resources_zip: + # Path to a .resources.zip that will simply contain all the + # input resources, collected in a single archive. + # + # r_text_out_path: Path for the generated R.txt file. + # + template("prepare_resources") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "deps", + "sources", + ]) + script = "//build/android/gyp/prepare_resources.py" + + depfile = "$target_gen_dir/${invoker.target_name}.d" + outputs = [ + invoker.resources_zip, + invoker.resources_zip + ".info", + invoker.r_text_out_path, + ] + + inputs = [ invoker.res_sources_path ] + + _rebased_res_sources_path = + rebase_path(invoker.res_sources_path, root_build_dir) + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--res-sources-path=$_rebased_res_sources_path", + "--resource-zip-out", + rebase_path(invoker.resources_zip, root_build_dir), + "--r-text-out", + rebase_path(invoker.r_text_out_path, root_build_dir), + ] + + if (defined(invoker.r_text_in_path)) { + _r_text_in_path = invoker.r_text_in_path + inputs += [ _r_text_in_path ] + args += [ + "--r-text-in", + rebase_path(_r_text_in_path, root_build_dir), + ] + } + + if (defined(invoker.strip_drawables) && invoker.strip_drawables) { + args += [ "--strip-drawables" ] + } + if (defined(invoker.allow_missing_resources) && + invoker.allow_missing_resources) { + args += [ "--allow-missing-resources" ] + } + } + } + + # A template that is used to compile all resources needed by a binary + # (e.g. an android_apk or a junit_binary) into an intermediate .ar_ + # archive. It can also generate an associated .srcjar that contains the + # final R.java sources for all resource packages the binary depends on. + # + # Input variables: + # android_sdk_dep: The sdk dep that these resources should compile against. + # + # deps: Specifies the input dependencies for this target. + # + # build_config: Path to the .build_config.json file corresponding to the target. + # + # build_config_dep: Dep target to generate the .build_config.json file. + # + # android_manifest: Path to root manifest for the binary. + # + # version_code: (optional) + # + # version_name: (optional) + # + # shared_resources: (optional) + # If true, make all variables in each generated R.java file non-final, + # and provide an onResourcesLoaded() method that can be used to reset + # their package index at load time. Useful when the APK corresponds to + # a library that is loaded at runtime, like system_webview_apk or + # monochrome_apk. + # + # app_as_shared_lib: (optional) + # If true, same effect as shared_resources, but also ensures that the + # resources can be used by the APK when it is loaded as a regular + # application as well. Useful for the monochrome_public_apk target + # which is both an application and a shared runtime library that + # implements the system webview feature. + # + # shared_resources_allowlist: (optional) + # Path to an R.txt file. If provided, acts similar to shared_resources + # except that it restricts the list of non-final resource variables + # to the list from the input R.txt file. Overrides shared_resources + # when both are specified. + # + # shared_resources_allowlist_locales: (optional) + # If shared_resources_allowlist is used, provide an optional list of + # Chromium locale names to determine which localized shared string + # resources to put in the final output, even if aapt_locale_allowlist + # is defined to a smaller subset. + # + # aapt_locale_allowlist: (optional) + # Restrict compiled locale-dependent resources to a specific allowlist. + # NOTE: This is a list of Chromium locale names, not Android ones. + # + # r_java_root_package_name: (optional) + # Short package name for this target's root R java file (ex. input of + # "base" would become "gen.base_module" for the root R java package name). + # Optional as defaults to "base". + # + # resource_exclusion_regex: (optional) + # + # resource_exclusion_exceptions: (optional) + # + # resource_values_filter_rules: (optional) + # + # no_xml_namespaces: (optional) + # + # png_to_webp: (optional) + # If true, convert all PNG resources (except 9-patch files) to WebP. + # + # post_process_script: (optional) + # + # package_name: (optional) + # Name of the package for the purpose of creating R class. + # + # package_id: (optional) + # Use a custom package ID in resource IDs. + # + # arsc_package_name: (optional) + # Use this package name in the arsc file rather than the package name + # found in the AndroidManifest.xml. Does not affect the package name + # used in AndroidManifest.xml. + # + # resource_ids_provider_dep: (optional) + # Use resource IDs provided by another APK target when compiling resources + # (via. "aapt2 link --stable-ids") + # + # + # Output variables: + # arsc_output: Path to output .ap_ file (optional). + # + # proto_output: Path to output .proto.ap_ file (optional). + # + # r_text_out_path: (optional): + # Path for the corresponding generated R.txt file. + # + # proguard_file: (optional) + # Path to proguard configuration file for this apk target. + # + # proguard_file_main_dex: (optional) + # + template("compile_resources") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _deps = [ + invoker.android_sdk_dep, + invoker.build_config_dep, + ] + if (defined(invoker.android_manifest_dep)) { + _deps += [ invoker.android_manifest_dep ] + } + foreach(_dep, invoker.deps) { + _target_label = get_label_info(_dep, "label_no_toolchain") + if (filter_exclude([ _target_label ], _java_library_patterns) == [] && + filter_exclude([ _target_label ], _java_resource_patterns) != []) { + # Depend on the java libraries' transitive __assetres target instead. + _deps += [ "${_target_label}__assetres" ] + } else { + _deps += [ _dep ] + } + } + + if (defined(invoker.arsc_output)) { + _arsc_output = invoker.arsc_output + } + _final_srcjar_path = "${target_gen_dir}/${target_name}.srcjar" + + _script = "//build/android/gyp/compile_resources.py" + + _inputs = [ + invoker.build_config, + android_sdk_tools_bundle_aapt2, + ] + + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + + _args = [ + "--include-resources=@FileArg($_rebased_build_config:android:sdk_jars)", + "--aapt2-path", + rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir), + "--dependencies-res-zips=@FileArg($_rebased_build_config:deps_info:dependency_zips)", + "--extra-res-packages=@FileArg($_rebased_build_config:deps_info:extra_package_names)", + "--extra-main-r-text-files=@FileArg($_rebased_build_config:deps_info:extra_main_r_text_files)", + "--min-sdk-version=${invoker.min_sdk_version}", + "--target-sdk-version=${invoker.target_sdk_version}", + "--webp-cache-dir=obj/android-webp-cache", + ] + + _inputs += [ invoker.android_manifest ] + _outputs = [ _final_srcjar_path ] + _args += [ + "--android-manifest", + rebase_path(invoker.android_manifest, root_build_dir), + "--srcjar-out", + rebase_path(_final_srcjar_path, root_build_dir), + ] + if (defined(invoker.no_xml_namespaces) && invoker.no_xml_namespaces) { + _args += [ "--no-xml-namespaces" ] + } + if (defined(invoker.version_code)) { + _args += [ + "--version-code", + invoker.version_code, + ] + } + if (defined(invoker.version_name)) { + _args += [ + "--version-name", + invoker.version_name, + ] + } + if (defined(_arsc_output)) { + _outputs += [ _arsc_output ] + _args += [ + "--arsc-path", + rebase_path(_arsc_output, root_build_dir), + ] + } + if (defined(invoker.proto_output)) { + _outputs += [ invoker.proto_output ] + _args += [ + "--proto-path", + rebase_path(invoker.proto_output, root_build_dir), + ] + } + if (defined(invoker.size_info_path)) { + _outputs += [ invoker.size_info_path ] + _args += [ + "--info-path", + rebase_path(invoker.size_info_path, root_build_dir), + ] + } + + if (defined(invoker.r_java_root_package_name)) { + _args += [ + "--r-java-root-package-name", + invoker.r_java_root_package_name, + ] + } + + # Useful to have android:debuggable in the manifest even for Release + # builds. Just omit it for officai + if (debuggable_apks) { + _args += [ "--debuggable" ] + } + + if (defined(invoker.r_text_out_path)) { + _outputs += [ invoker.r_text_out_path ] + _args += [ + "--r-text-out", + rebase_path(invoker.r_text_out_path, root_build_dir), + ] + } + + if (defined(invoker.rename_manifest_package)) { + _args += [ + "--rename-manifest-package", + invoker.rename_manifest_package, + ] + } + + # Define the flags related to shared resources. + # + # Note the small sanity check to ensure that the package ID of the + # generated resources table is correct. It should be 0x02 for runtime + # shared libraries, and 0x7f otherwise. + + if (defined(invoker.shared_resources) && invoker.shared_resources) { + _args += [ "--shared-resources" ] + } + if (defined(invoker.app_as_shared_lib) && invoker.app_as_shared_lib) { + _args += [ "--app-as-shared-lib" ] + } + if (defined(invoker.package_id)) { + _args += [ "--package-id=${invoker.package_id}" ] + } + if (defined(invoker.package_name)) { + _args += [ + "--package-name", + invoker.package_name, + ] + } + if (defined(invoker.arsc_package_name)) { + _args += [ + "--arsc-package-name", + invoker.arsc_package_name, + ] + } + + if (defined(invoker.shared_resources_allowlist)) { + _inputs += [ invoker.shared_resources_allowlist ] + _args += [ + "--shared-resources-allowlist", + rebase_path(invoker.shared_resources_allowlist, root_build_dir), + ] + } + if (defined(invoker.shared_resources_allowlist_locales)) { + _args += [ "--shared-resources-allowlist-locales=" + + "${invoker.shared_resources_allowlist_locales}" ] + } + + if (!defined(testonly) || !testonly || + (defined(invoker.enforce_resource_overlays_in_tests) && + invoker.enforce_resource_overlays_in_tests)) { + _args += [ "--dependencies-res-zip-overlays=@FileArg($_rebased_build_config:deps_info:dependency_zip_overlays)" ] + } else { + _args += [ "--dependencies-res-zip-overlays=@FileArg($_rebased_build_config:deps_info:dependency_zips)" ] + } + + if (defined(invoker.proguard_file)) { + _outputs += [ invoker.proguard_file ] + _args += [ + "--proguard-file", + rebase_path(invoker.proguard_file, root_build_dir), + ] + } + + if (defined(invoker.proguard_file_main_dex)) { + _outputs += [ invoker.proguard_file_main_dex ] + _args += [ + "--proguard-file-main-dex", + rebase_path(invoker.proguard_file_main_dex, root_build_dir), + ] + } + + if (defined(invoker.aapt_locale_allowlist)) { + _args += [ "--locale-allowlist=${invoker.aapt_locale_allowlist}" ] + } + if (defined(invoker.png_to_webp) && invoker.png_to_webp) { + _webp_target = "//third_party/libwebp:cwebp($host_toolchain)" + _webp_binary = get_label_info(_webp_target, "root_out_dir") + "/cwebp" + _deps += [ _webp_target ] + _inputs += [ _webp_binary ] + _args += [ + "--png-to-webp", + "--webp-binary", + rebase_path(_webp_binary, root_build_dir), + ] + } + if (defined(invoker.resource_exclusion_regex)) { + _args += + [ "--resource-exclusion-regex=${invoker.resource_exclusion_regex}" ] + if (defined(invoker.resource_exclusion_exceptions)) { + _args += [ "--resource-exclusion-exceptions=${invoker.resource_exclusion_exceptions}" ] + } + } + if (defined(invoker.resource_values_filter_rules)) { + _args += + [ "--values-filter-rules=${invoker.resource_values_filter_rules}" ] + } + + if (defined(invoker.include_resource)) { + _rebased_include_resources = + rebase_path(invoker.include_resource, root_build_dir) + _args += [ "--include-resources=$_rebased_include_resources" ] + } + + if (defined(invoker._args)) { + _args += invoker._args + } + + if (defined(invoker.emit_ids_out_path)) { + _outputs += [ invoker.emit_ids_out_path ] + _rebased_emit_ids_path = + rebase_path(invoker.emit_ids_out_path, root_out_dir) + _args += [ "--emit-ids-out=$_rebased_emit_ids_path" ] + } + + if (defined(invoker.resource_ids_provider_dep)) { + _compile_res_dep = + "${invoker.resource_ids_provider_dep}__compile_resources" + _gen_dir = get_label_info(_compile_res_dep, "target_gen_dir") + _name = get_label_info(_compile_res_dep, "name") + _resource_ids_path = "$_gen_dir/$_name.resource_ids" + _inputs += [ _resource_ids_path ] + _rebased_ids_path = rebase_path(_resource_ids_path, root_out_dir) + _args += [ "--use-resource-ids-path=$_rebased_ids_path" ] + _deps += [ _compile_res_dep ] + } + + if (defined(invoker.max_sdk_version)) { + _max_sdk_version = invoker.max_sdk_version + _args += [ "--max-sdk-version=$_max_sdk_version" ] + } + + if (defined(invoker.manifest_package)) { + _args += [ "--manifest-package=${invoker.manifest_package}" ] + } + + if (defined(invoker.is_bundle_module) && invoker.is_bundle_module) { + _args += [ "--is-bundle-module" ] + } + + if (defined(invoker.uses_split)) { + assert(invoker.is_bundle_module) + _args += [ "--uses-split=${invoker.uses_split}" ] + } + + if (defined(invoker.expected_android_manifest)) { + _expectations_target = + "${invoker.top_target_name}_validate_android_manifest" + action_with_pydeps(_expectations_target) { + _actual_file = "${invoker.android_manifest}.normalized" + _failure_file = + "$expectations_failure_dir/" + + string_replace(invoker.expected_android_manifest, "/", "_") + inputs = [ + invoker.android_manifest, + invoker.build_config, + invoker.expected_android_manifest, + ] + outputs = [ + _actual_file, + _failure_file, + ] + deps = [ + invoker.android_manifest_dep, + invoker.build_config_dep, + ] + script = _script + args = _args + [ + "--expected-file", + rebase_path(invoker.expected_android_manifest, root_build_dir), + "--actual-file", + rebase_path(_actual_file, root_build_dir), + "--failure-file", + rebase_path(_failure_file, root_build_dir), + "--only-verify-expectations", + ] + if (defined(invoker.expected_android_manifest_base)) { + args += [ + "--expected-file-base", + rebase_path(invoker.expected_android_manifest_base, root_build_dir), + ] + inputs += [ invoker.expected_android_manifest_base ] + } + if (fail_on_android_expectations) { + args += [ "--fail-on-expectations" ] + } + if (defined(invoker.extra_verification_manifest)) { + inputs += [ invoker.extra_verification_manifest ] + args += [ + "--extra-verification-manifest", + rebase_path(invoker.extra_verification_manifest, root_build_dir), + ] + if (defined(invoker.extra_verification_manifest_dep)) { + deps += [ invoker.extra_verification_manifest_dep ] + } + } + } + _deps += [ ":$_expectations_target" ] + } + + action_with_pydeps(target_name) { + script = _script + depfile = "$target_gen_dir/${target_name}.d" + inputs = _inputs + outputs = _outputs + deps = _deps + args = _args + [ + "--depfile", + rebase_path(depfile, root_build_dir), + ] + } + } + + # A template that is used to optimize compiled resources using aapt2 optimize. + # + # proto_input_path: + # Path to input compiled .proto.ap_ file. + # + # short_resource_paths: (optional) + # Rename the paths within a the apk to be randomly generated short + # strings to reduce binary size. + # + # strip_resource_names: (optional) + # Strip resource names from the resources table of the apk. + # + # resources_configs_paths: (optional) + # List of resource configs to use for optimization. + # + # optimized_proto_output: + # Path to output optimized .proto.ap_ file. + # + # resources_path_map_out_path: (optional): + # Path for the generated map between original resource paths and + # shortened resource paths. + template("optimize_resources") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + action_with_pydeps(target_name) { + forward_variables_from(invoker, [ "deps" ]) + script = "//build/android/gyp/optimize_resources.py" + outputs = [ invoker.optimized_proto_output ] + inputs = [ + android_sdk_tools_bundle_aapt2, + invoker.r_text_path, + invoker.proto_input_path, + ] + args = [ + "--aapt2-path", + rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir), + "--r-text-in", + rebase_path(invoker.r_text_path, root_build_dir), + "--proto-path", + rebase_path(invoker.proto_input_path, root_build_dir), + "--optimized-proto-path", + rebase_path(invoker.optimized_proto_output, root_build_dir), + ] + + if (defined(invoker.resources_config_paths)) { + inputs += invoker.resources_config_paths + _rebased_resource_configs = + rebase_path(invoker.resources_config_paths, root_build_dir) + args += [ "--resources-config-paths=${_rebased_resource_configs}" ] + } + + if (defined(invoker.short_resource_paths) && + invoker.short_resource_paths) { + args += [ "--short-resource-paths" ] + if (defined(invoker.resources_path_map_out_path)) { + outputs += [ invoker.resources_path_map_out_path ] + args += [ + "--resources-path-map-out-path", + rebase_path(invoker.resources_path_map_out_path, root_build_dir), + ] + } + } + + if (defined(invoker.strip_resource_names) && + invoker.strip_resource_names) { + args += [ "--strip-resource-names" ] + } + } + } + + # A template that is used to find unused resources. + template("unused_resources") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + script = "//build/android/gyp/unused_resources.py" + depfile = "$target_gen_dir/${target_name}.d" + _unused_resources_script = "$root_build_dir/bin/helper/unused_resources" + inputs = [ _unused_resources_script ] + outputs = [ invoker.output_config ] + if (!defined(deps)) { + deps = [] + } + deps += [ "//build/android/unused_resources:unused_resources" ] + _rebased_module_build_config = + rebase_path(invoker.build_config, root_build_dir) + args = [ + "--script", + rebase_path(_unused_resources_script, root_build_dir), + "--output-config", + rebase_path(invoker.output_config, root_build_dir), + "--r-text=@FileArg($_rebased_module_build_config:deps_info:r_text_path)", + "--dependencies-res-zips=@FileArg($_rebased_module_build_config:deps_info:dependency_zips)", + "--depfile", + rebase_path(depfile, root_build_dir), + ] + + if (defined(invoker.proguard_mapping_path)) { + inputs += [ invoker.proguard_mapping_path ] + args += [ + "--proguard-mapping", + rebase_path(invoker.proguard_mapping_path, root_build_dir), + ] + } + + foreach(_build_config, invoker.all_module_build_configs) { + inputs += [ _build_config ] + _rebased_build_config = rebase_path(_build_config, root_build_dir) + args += [ + "--dexes=@FileArg($_rebased_build_config:final_dex:path)", + "--android-manifests=@FileArg($_rebased_build_config:deps_info:merged_android_manifest)", + ] + } + } + } + + # Create an .jar.info file by merging several .jar.info files into one. + # + # Variables: + # build_config: Path to APK's build config file. Used to extract the + # list of input .jar files from its dependencies. + # name: Name of the apk or app bundle (e.g. "Foo.apk"). + # res_size_info_path: Path to input .ap_.info file (for apks). + # + template("create_size_info_files") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + script = "//build/android/gyp/create_size_info_files.py" + _jar_info_path = "$root_build_dir/size-info/${invoker.name}.jar.info" + _pak_info_path = "$root_build_dir/size-info/${invoker.name}.pak.info" + _res_info_path = "$root_build_dir/size-info/${invoker.name}.res.info" + outputs = [ + _jar_info_path, + _pak_info_path, + _res_info_path, + ] + depfile = "$target_gen_dir/$target_name.d" + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--jar-info-path", + rebase_path(_jar_info_path, root_build_dir), + "--pak-info-path", + rebase_path(_pak_info_path, root_build_dir), + "--res-info-path", + rebase_path(_res_info_path, root_build_dir), + ] + _is_bundle = defined(invoker.module_build_configs) + if (_is_bundle) { + inputs = invoker.module_build_configs + foreach(_build_config, invoker.module_build_configs) { + _rebased_build_config = rebase_path(_build_config, root_build_dir) + args += [ + "--jar-files=@FileArg($_rebased_build_config:deps_info:unprocessed_jar_path)", + "--jar-files=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)", + "--in-res-info-path=@FileArg($_rebased_build_config:deps_info:res_size_info)", + "--assets=@FileArg($_rebased_build_config:assets)", + "--uncompressed-assets=@FileArg($_rebased_build_config:uncompressed_assets)", + ] + } + } else { + inputs = [ + invoker.build_config, + invoker.res_size_info_path, + ] + _rebased_build_config = + rebase_path(invoker.build_config, root_build_dir) + args += [ + "--jar-files=@FileArg($_rebased_build_config:deps_info:unprocessed_jar_path)", + "--jar-files=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)", + "--in-res-info-path", + rebase_path(invoker.res_size_info_path, root_build_dir), + "--assets=@FileArg($_rebased_build_config:assets)", + "--uncompressed-assets=@FileArg($_rebased_build_config:uncompressed_assets)", + ] + } + } + } + + # Creates a signed and aligned .apk. + # + # Variables + # apk_name: (optional) APK name (without .apk suffix). If provided, will + # be used to generate .info files later used by the supersize tool. + # assets_build_config: Path to android_apk .build_config.json containing merged + # asset information. + # deps: Specifies the dependencies of this target. + # dex_path: Path to classes.dex file to include (optional). + # expected_libs_and_assets: Verify the list of included native libraries + # and assets is consistent with the given expectation file. + # expected_libs_and_assets_base: Treat expected_libs_and_assets as a diff + # with this file as the base. + # jdk_libs_dex: Path to classes.dex for desugar_jdk_libs. + # packaged_resources_path: Path to .ap_ to use. + # output_apk_path: Output path for the generated .apk. + # min_sdk_version: The minimum Android SDK version this target supports. + # native_lib_placeholders: List of placeholder filenames to add to the apk + # (optional). + # secondary_native_lib_placeholders: List of placeholder filenames to add to + # the apk for the secondary ABI (optional). + # loadable_modules: List of native libraries. + # native_libs_filearg: @FileArg() of additionally native libraries. + # secondary_abi_loadable_modules: (optional) List of native libraries for + # secondary ABI. + # secondary_abi_native_libs_filearg: (optional). @FileArg() of additional + # secondary ABI native libs. + # keystore_path: Path to keystore to use for signing. + # keystore_name: Key alias to use. + # keystore_password: Keystore password. + # uncompress_shared_libraries: (optional, default false) Whether to store + # native libraries inside the APK uncompressed and page-aligned. + template("package_apk") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "public_deps" ]) + _deps = invoker.deps + _native_lib_placeholders = [] + if (defined(invoker.native_lib_placeholders)) { + _native_lib_placeholders = invoker.native_lib_placeholders + } + _secondary_native_lib_placeholders = [] + if (defined(invoker.secondary_native_lib_placeholders)) { + _secondary_native_lib_placeholders = + invoker.secondary_native_lib_placeholders + } + + _script = "//build/android/gyp/apkbuilder.py" + _apksigner = "$android_sdk_build_tools/lib/apksigner.jar" + _zipalign = "$android_sdk_build_tools/zipalign" + + _inputs = [ + invoker.build_config, + invoker.keystore_path, + invoker.packaged_resources_path, + _apksigner, + _zipalign, + ] + + _outputs = [ invoker.output_apk_path ] + _data = [ invoker.output_apk_path ] + + _rebased_compiled_resources_path = + rebase_path(invoker.packaged_resources_path, root_build_dir) + _rebased_packaged_apk_path = + rebase_path(invoker.output_apk_path, root_build_dir) + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + _args = [ + "--resource-apk=$_rebased_compiled_resources_path", + "--output-apk=$_rebased_packaged_apk_path", + "--assets=@FileArg($_rebased_build_config:assets)", + "--uncompressed-assets=@FileArg($_rebased_build_config:uncompressed_assets)", + "--apksigner-jar", + rebase_path(_apksigner, root_build_dir), + "--zipalign-path", + rebase_path(_zipalign, root_build_dir), + "--key-path", + rebase_path(invoker.keystore_path, root_build_dir), + "--key-name", + invoker.keystore_name, + "--key-passwd", + invoker.keystore_password, + "--min-sdk-version=${invoker.min_sdk_version}", + + # TODO(mlopatkin) We are relying on the fact that build_config is an APK + # build_config. + "--java-resources=@FileArg($_rebased_build_config:java_resources_jars)", + ] + if (is_official_build) { + _args += [ "--best-compression" ] + } + if (defined(invoker.uncompress_dex) && invoker.uncompress_dex) { + _args += [ "--uncompress-dex" ] + } + if (defined(invoker.uncompress_shared_libraries) && + invoker.uncompress_shared_libraries) { + _args += [ "--uncompress-shared-libraries=True" ] + } + if (defined(invoker.library_always_compress)) { + _args += + [ "--library-always-compress=${invoker.library_always_compress}" ] + } + if (defined(invoker.library_renames)) { + _args += [ "--library-renames=${invoker.library_renames}" ] + } + if (defined(invoker.dex_path)) { + _inputs += [ invoker.dex_path ] + _args += [ + "--dex-file", + rebase_path(invoker.dex_path, root_build_dir), + ] + } + if (defined(invoker.jdk_libs_dex)) { + _inputs += [ invoker.jdk_libs_dex ] + _args += [ + "--jdk-libs-dex-file", + rebase_path(invoker.jdk_libs_dex, root_build_dir), + ] + } + if ((defined(invoker.loadable_modules) && invoker.loadable_modules != []) || + defined(invoker.native_libs_filearg) || + _native_lib_placeholders != []) { + _args += [ "--android-abi=$android_app_abi" ] + } + if (defined(android_app_secondary_abi)) { + _args += [ "--secondary-android-abi=$android_app_secondary_abi" ] + } + if (defined(invoker.loadable_modules) && invoker.loadable_modules != []) { + _inputs += invoker.loadable_modules + _rebased_loadable_modules = + rebase_path(invoker.loadable_modules, root_build_dir) + _args += [ "--native-libs=$_rebased_loadable_modules" ] + } + if (defined(invoker.native_libs_filearg)) { + _args += [ "--native-libs=${invoker.native_libs_filearg}" ] + } + if (_native_lib_placeholders != []) { + _args += [ "--native-lib-placeholders=$_native_lib_placeholders" ] + } + + if (defined(invoker.secondary_abi_native_libs_filearg)) { + _args += [ + "--secondary-native-libs=${invoker.secondary_abi_native_libs_filearg}", + ] + } + if (defined(invoker.secondary_abi_loadable_modules)) { + _rebased_secondary_abi_loadable_modules = + rebase_path(invoker.secondary_abi_loadable_modules, root_build_dir) + _args += + [ "--secondary-native-libs=$_rebased_secondary_abi_loadable_modules" ] + } + if (_secondary_native_lib_placeholders != []) { + _args += [ "--secondary-native-lib-placeholders=$_secondary_native_lib_placeholders" ] + } + if (treat_warnings_as_errors) { + _args += [ "--warnings-as-errors" ] + } + + if (defined(invoker.expected_libs_and_assets)) { + _expectations_target = + "${invoker.top_target_name}_validate_libs_and_assets" + action_with_pydeps(_expectations_target) { + _actual_file = "$target_gen_dir/$target_name.libs_and_assets" + _failure_file = + "$expectations_failure_dir/" + + string_replace(invoker.expected_libs_and_assets, "/", "_") + inputs = [ + invoker.build_config, + invoker.expected_libs_and_assets, + ] + deps = [ invoker.build_config_dep ] + outputs = [ + _actual_file, + _failure_file, + ] + script = _script + args = _args + [ + "--expected-file", + rebase_path(invoker.expected_libs_and_assets, root_build_dir), + "--actual-file", + rebase_path(_actual_file, root_build_dir), + "--failure-file", + rebase_path(_failure_file, root_build_dir), + "--only-verify-expectations", + ] + if (defined(invoker.expected_libs_and_assets_base)) { + inputs += [ invoker.expected_libs_and_assets_base ] + args += [ + "--expected-file-base", + rebase_path(invoker.expected_libs_and_assets_base, root_build_dir), + ] + } + if (fail_on_android_expectations) { + args += [ "--fail-on-expectations" ] + } + } + _deps += [ ":$_expectations_target" ] + } + action_with_pydeps(target_name) { + depfile = "$target_gen_dir/$target_name.d" + inputs = _inputs + deps = _deps + data = _data + outputs = _outputs + script = _script + args = _args + [ + "--depfile", + rebase_path(depfile, root_build_dir), + ] + } + } + + # Compile Java source files into a .jar file, potentially using an + # annotation processor, and/or the errorprone compiler. + # + # Note that the only way to specify custom annotation processors is + # by using build_config to point to a file that corresponds to a java-related + # target that includes javac:processor_classes entries (i.e. there is no + # variable here that can be used for this purpose). + # + # Note also the peculiar use of java_files / java_sources_file. The content + # of the java_files list and the java_sources_file file must match exactly. + # This rule uses java_files only to list the inputs to the action that + # calls compile_java.py, but will pass the list of Java source files + # with the '@${java_sources_file}" command-line syntax. Not a problem in + # practice since this is only called from java_library_impl() that sets up + # the variables properly. + # + # Variables: + # main_target_name: Used when extracting srcjars for codesearch. + # java_files: Optional list of Java source file paths. + # srcjar_deps: Optional list of .srcjar dependencies (not file paths). + # The corresponding source files they contain will be compiled too. + # java_sources_file: Optional path to file containing list of Java source + # file paths. This must always be provided if java_files is not empty + # and must match it exactly. + # build_config: Path to the .build_config.json file of the corresponding + # java_library_impl() target. The following entries will be used by this + # template: javac:srcjars, deps_info:javac_full_classpath, + # deps_info:javac_full_interface_classpath, javac:processor_classpath, + # javac:processor_classes + # javac_jar_path: Path to the final output .jar file. + # javac_args: Optional list of extra arguments to pass to javac. + # chromium_code: Whether this corresponds to Chromium-specific sources. + # requires_android: True if these sources can only run on Android. + # additional_jar_files: Optional list of files to copy into the resulting + # .jar file (by default, only .class files are put there). Each entry + # has the 'srcPath:dstPath' format. + # enable_errorprone: If True, use the errorprone compiler to check for + # error-prone constructs in the language. If not provided, whether this is + # enabled depends on chromium_code and the global + # use_errorprone_java_compiler variable. + # use_turbine: If True, compile headers using turbine.py. + # apk_name: Optional APK name. If provided, will tell compile_java.py to also + # generate an .apk.jar.info file under size-info/${apk_name}.apk.jar.info + # processor_args_javac: List of annotation processor arguments, each one + # will be passed to javac as -A<entry>. + # deps: Dependencies for the corresponding target. + # testonly: Usual meaning (should be True for test-only targets) + # + # [1] https://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html + # + template("compile_java") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _build_config = invoker.build_config + _chromium_code = invoker.chromium_code + + _processor_args = [] + if (defined(invoker.processor_args_javac)) { + _processor_args = invoker.processor_args_javac + } + + _additional_jar_files = [] + if (defined(invoker.additional_jar_files)) { + _additional_jar_files = invoker.additional_jar_files + } + + _srcjar_deps = [] + if (defined(invoker.srcjar_deps)) { + _srcjar_deps += invoker.srcjar_deps + } + + _java_srcjars = [] + foreach(dep, _srcjar_deps) { + _dep_gen_dir = get_label_info(dep, "target_gen_dir") + _dep_name = get_label_info(dep, "name") + _java_srcjars += [ "$_dep_gen_dir/$_dep_name.srcjar" ] + } + + # generated_jar_path is an output when use_turbine and an input otherwise. + if (!invoker.use_turbine) { + _java_srcjars += [ invoker.generated_jar_path ] + } + + _javac_args = [] + if (defined(invoker.javac_args)) { + _javac_args = invoker.javac_args + } + + action_with_pydeps(target_name) { + if (invoker.use_turbine) { + script = "//build/android/gyp/turbine.py" + } else { + script = "//build/android/gyp/compile_java.py" + } + + if (target_name == "chrome_java__header") { + # Regression test for: https://crbug.com/1154302 + assert_no_deps = [ "//base:base_java__impl" ] + } + + depfile = "$target_gen_dir/$target_name.d" + deps = _srcjar_deps + if (defined(invoker.deps)) { + deps += invoker.deps + } + + outputs = [ invoker.output_jar_path ] + if (!invoker.enable_errorprone && !invoker.use_turbine) { + outputs += [ invoker.output_jar_path + ".info" ] + } + inputs = invoker.java_files + _java_srcjars + [ _build_config ] + if (invoker.java_files != []) { + inputs += [ invoker.java_sources_file ] + } + + _rebased_build_config = rebase_path(_build_config, root_build_dir) + _rebased_output_jar_path = + rebase_path(invoker.output_jar_path, root_build_dir) + _rebased_java_srcjars = rebase_path(_java_srcjars, root_build_dir) + _rebased_depfile = rebase_path(depfile, root_build_dir) + _rebased_generated_dir = rebase_path( + "$target_gen_dir/${invoker.main_target_name}/generated_java", + root_build_dir) + args = [ + "--depfile=$_rebased_depfile", + "--generated-dir=$_rebased_generated_dir", + "--jar-path=$_rebased_output_jar_path", + "--java-srcjars=$_rebased_java_srcjars", + "--target-name", + get_label_info(":${target_name}", "label_no_toolchain"), + ] + + if (defined(invoker.header_jar_path)) { + inputs += [ invoker.header_jar_path ] + args += [ + "--header-jar", + rebase_path(invoker.header_jar_path, root_build_dir), + ] + _header_jar_classpath = + [ rebase_path(invoker.header_jar_path, root_build_dir) ] + args += [ "--classpath=$_header_jar_classpath" ] + } + + if (invoker.use_turbine) { + # Prefer direct deps for turbine as much as possible. + args += [ "--classpath=@FileArg($_rebased_build_config:javac:interface_classpath)" ] + } else { + args += [ "--classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)" ] + } + + if (invoker.use_turbine) { + args += [ + "--processorpath=@FileArg($_rebased_build_config:javac:processor_classpath)", + "--processors=@FileArg($_rebased_build_config:javac:processor_classes)", + ] + } + + if (invoker.use_turbine) { + _turbine_jar_path = "//third_party/turbine/turbine.jar" + inputs += [ _turbine_jar_path ] + outputs += [ invoker.generated_jar_path ] + args += [ + "--turbine-jar-path", + rebase_path(_turbine_jar_path, root_build_dir), + "--generated-jar-path", + rebase_path(invoker.generated_jar_path, root_build_dir), + ] + } + + # Currently turbine does not support JDK11. + if (invoker.supports_android || invoker.use_turbine) { + args += [ "--java-version=1.8" ] + } + if (use_java_goma) { + args += [ "--gomacc-path=$goma_dir/gomacc" ] + + # Override the default action_pool when goma is enabled. + pool = "//build/config/android:goma_javac_pool" + } + + # Flag enable_kythe_annotations requires + # checkout_android_prebuilts_build_tools=True in .gclient. + if (enable_kythe_annotations && !invoker.enable_errorprone) { + args += [ "--enable-kythe-annotations" ] + } + if (invoker.requires_android) { + args += [ "--bootclasspath=@FileArg($_rebased_build_config:android:sdk_interface_jars)" ] + } + if (_chromium_code) { + args += [ "--chromium-code=1" ] + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + } + if (defined(invoker.jar_excluded_patterns)) { + args += [ "--jar-info-exclude-globs=${invoker.jar_excluded_patterns}" ] + } + + if (invoker.enable_errorprone) { + # Our custom plugin pulls in the main errorprone dep transitively. + _errorprone_dep = "//tools/android/errorprone_plugin:errorprone_plugin" + deps += [ _errorprone_dep ] + _dep_gen_dir = get_label_info(_errorprone_dep, "target_gen_dir") + _dep_name = get_label_info(_errorprone_dep, "name") + _rebased_errorprone_buildconfig = + rebase_path("$_dep_gen_dir/$_dep_name.build_config.json", + root_build_dir) + args += [ + "--processorpath=@FileArg($_rebased_errorprone_buildconfig:deps_info:host_classpath)", + "--enable-errorprone", + ] + } + if (defined(invoker.skip_build_server) && invoker.skip_build_server) { + # Nocompile tests need lint to fail through ninja. + args += [ "--skip-build-server" ] + } + + foreach(e, _processor_args) { + args += [ "--processor-arg=" + e ] + } + + foreach(file_tuple, _additional_jar_files) { + # Each element is of length two, [ path_to_file, path_to_put_in_jar ] + inputs += [ file_tuple[0] ] + args += + [ "--additional-jar-file=" + + rebase_path(file_tuple[0], root_build_dir) + ":" + file_tuple[1] ] + } + if (invoker.java_files != []) { + args += [ "@" + rebase_path(invoker.java_sources_file, root_build_dir) ] + } + foreach(e, _javac_args) { + args += [ "--javac-arg=" + e ] + } + } + } + + template("java_lib_group") { + forward_variables_from(invoker, [ "testonly" ]) + _group_name = invoker.group_name + not_needed([ "_group_name" ]) + group(target_name) { + if (defined(invoker.deps)) { + deps = [] + foreach(_dep, invoker.deps) { + _target_label = get_label_info(_dep, "label_no_toolchain") + if (filter_exclude([ _target_label ], _java_library_patterns) == [] && + filter_exclude([ _target_label ], _java_resource_patterns) != + []) { + # This is a java library dep, so replace it. + deps += [ "${_target_label}__${_group_name}" ] + } else { + # Transitive java group targets should also include direct deps. + deps += [ _dep ] + } + } + } + } + } + + # Create an interface jar from a normal jar. + # + # Variables + # input_jar: Path to input .jar. + # output_jar: Path to output .ijar. + # + template("generate_interface_jar") { + action_with_pydeps(target_name) { + _ijar_target = "//third_party/ijar:ijar($host_toolchain)" + _ijar_executable = get_label_info(_ijar_target, "root_out_dir") + "/ijar" + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "data", + "data_deps", + "public_deps", + ]) + script = "//build/android/gyp/ijar.py" + deps = [ _ijar_target ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + inputs = [ + invoker.input_jar, + _ijar_executable, + ] + if (defined(invoker.inputs)) { + inputs += invoker.inputs + } + outputs = [ invoker.output_jar ] + args = [ + rebase_path(_ijar_executable, root_build_dir), + rebase_path(invoker.input_jar, root_build_dir), + rebase_path(invoker.output_jar, root_build_dir), + ] + } + } + + # A rule that will handle multiple Java-related targets. + # + # The caller can provide a list of source files with 'java_files' + # and 'srcjar_deps', or a prebuilt .jar file through 'jar_path'. + # + # In the case of a 'java_binary' target type, it can even provide none of + # that (and the rule will just generate its wrapper script). + # + # The template will process the input .jar file (either the prebuilt one, + # or the result of compiling the sources), for example to apply Proguard, + # but also other ranges of bytecode-level rewriting schemes. + # + # Variables: + # type: type of Java target, valid values: 'java_library', 'java_binary', + # 'junit_binary', 'java_annotation_processor', and 'android_apk' + # main_target_name: optional. If provided, overrides target_name when + # creating sub-targets (e.g. "${main_target_name}__dex") and + # some output files (e.g. "${main_target_name}.sources"). Only used + # for 'android_apk' types at the moment, where main_target_name will + # be the name of the main APK target. + # supports_android: Optional. True if target can run on Android. + # requires_android: Optional. True if target can only run on Android. + # java_files: Optional list of Java source file paths for this target. + # javac_args: Optional list of extra arguments to pass to javac. + # errorprone_args: Optional list of extra arguments to pass to. + # srcjar_deps: Optional list of .srcjar targets (not file paths). The Java + # source files they contain will also be compiled for this target. + # java_sources_file: Optional path to a file which will be written with + # the content of java_files. If not provided, the file will be written + # under $target_gen_dir/$main_target_name.sources. Ignored if + # java_files is empty. If not + # jar_path: Optional path to a prebuilt .jar file for this target. + # Mutually exclusive with java_files and srcjar_deps. + # output_name: Optional output name for the final jar path. Used to + # determine the name of the final jar. Default is to use the same + # name as jar_path, if provided, or main_target_name. + # main_class: Main Java class name for 'java_binary', 'junit_binary' and + # 'java_annotation_processor' target types. Should not be set for other + # ones. + # deps: Dependencies for this target. + # public_deps: Dependencies that this target exposes as part of its public API. + # public_deps do not need to be listed in both the 'deps' and 'public_deps' lists. + # testonly: True iff target should only be used for tests. + # chromium_code: Optional. Whether this is Chromium-specific code. If not + # provided, this is determined automatically, based on the location of + # the source files (i.e. anything under third_party/ is not + # Chromium-specific unless it is in a 'chromium' sub-directory). + # jacoco_never_instrument: Optional. If provided, whether to forbid + # instrumentation with the Jacoco coverage processor. If not provided, + # this is controlled by the global use_jacoco_coverage build arg variable + # and only used for non-test Chromium code. + # include_android_sdk: Optional. Whether or not the android SDK dep + # should be added to deps. Defaults to true for non-system libraries + # that support android. + # alternative_android_sdk_dep: Optional. Alternative Android system + # android java target to use. + # annotation_processor_deps: Optional list of dependencies corresponding + # to annotation processors used to compile these sources. + # input_jars_paths: Optional list of additional .jar file paths, which will + # be added to the compile-time classpath when building this target (but + # not to the runtime classpath). + # desugar_jars_paths: Optional list of additional .jar file paths, which will + # be added to the desugar classpath when building this target (but not to + # any other classpath). This is only used to break dependency cycles. + # gradle_treat_as_prebuilt: Cause generate_gradle.py to reference this + # library via its built .jar rather than including its .java sources. + # proguard_enabled: Optional. True to enable ProGuard obfuscation. + # proguard_configs: Optional list of additional proguard config file paths. + # bypass_platform_checks: Optional. If True, platform checks will not + # be performed. They are used to verify that every target with + # requires_android only depends on targets that, at least supports_android. + # Similarly, if a target has !supports_android, then it cannot depend on + # any other target that has requires_android. + # include_java_resources: Optional. If True, include Java (not Android) + # resources into final .jar file. + # jar_excluded_patterns: Optional list of .class file patterns to exclude + # from the final .jar file. + # jar_included_patterns: Optional list of .class file patterns to include + # in the final .jar file. jar_excluded_patterns take precedence over this. + # low_classpath_priority: Indicates that the library should be placed at the + # end of the classpath. The default classpath order has libraries ordered + # before the libraries that they depend on. 'low_classpath_priority' is + # useful when one java_library() overrides another via + # 'jar_excluded_patterns' and the overriding library does not depend on the + # overridee. + # + # For 'android_apk' and 'android_app_bundle_module' targets only: + # + # apk_path: Path to the final APK file. + # android_manifest: Path to AndroidManifest.xml file for the APK. + # android_manifest_dep: Optional. Dependency target that generates + # android_manifest. + # apk_under_test: For 'android_apk' targets used to test other APKs, + # this is the target name of APK being tested. + # incremental_apk_path: Path to the incremental APK. + # incremental_install_json_path: Path to the incremental install json. + # native_lib_placeholders: Optional. List of placeholder filenames to add to + # the APK. + # proguard_mapping_path: Path to .mapping file produced from ProGuard step. + # shared_libraries_runtime_deps_file: Optional. Path to a file listing the + # native shared libraries required at runtime by the APK. + # secondary_abi_shared_libraries_runtime_deps_file: + # secondary_native_lib_placeholders: Optional. List of placeholder filenames + # to add to the APK for the secondary ABI. + # loadable_modules: Optional list of extra native libraries to + # be stored in the APK. + # secondary_abi_loadable_modules: Optional list of native libraries for + # secondary ABI. + # uncompress_shared_libraries: Optional. True to store native shared + # libraries uncompressed and page-aligned. + # proto_resources_path: The path of an zip archive containing the APK's + # resources compiled to the protocol buffer format (instead of regular + # binary xml + resources.arsc). + # r_text_path: The path of the R.txt file generated when compiling the + # resources for this target. + # module_pathmap_path: The path of the pathmap file generated when compiling + # the resources for the bundle module, if path shortening is enabled. + # base_allowlist_rtxt_path: The path of the R.txt file containing the + # list of string resources to keep in the base split APK for any bundle + # that uses this target. + # + # For 'java_binary' and 'junit_binary' targets only. Ignored by others: + # + # wrapper_script_name: Optional name for the generated wrapper script. + # Default is main target name. + # wrapper_script_args: Optional list of extra arguments used by the + # generated wrapper script. + # + template("java_library_impl") { + # TODO(crbug.com/1042017): Remove. + not_needed(invoker, [ "no_build_hooks" ]) + + forward_variables_from(invoker, [ "testonly" ]) + _is_prebuilt = defined(invoker.jar_path) + _is_annotation_processor = invoker.type == "java_annotation_processor" + _is_java_binary = + invoker.type == "java_binary" || invoker.type == "junit_binary" + _supports_android = + defined(invoker.supports_android) && invoker.supports_android + _requires_android = + defined(invoker.requires_android) && invoker.requires_android + + _invoker_deps = [] + if (defined(invoker.deps)) { + _invoker_deps += invoker.deps + } + if (defined(invoker.public_deps)) { + foreach(_public_dep, invoker.public_deps) { + if (filter_include([ _public_dep ], _invoker_deps) != []) { + assert(false, "'public_deps' and 'deps' overlap: $_public_dep") + } + } + _invoker_deps += invoker.public_deps + } + + _main_target_name = target_name + if (defined(invoker.main_target_name)) { + _main_target_name = invoker.main_target_name + } + + if (defined(invoker.resources_package)) { + _resources_package = invoker.resources_package + } + + _java_files = [] + if (defined(invoker.sources)) { + _java_files = invoker.sources + } + _srcjar_deps = [] + if (defined(invoker.srcjar_deps)) { + _srcjar_deps = invoker.srcjar_deps + } + _has_sources = _java_files != [] || _srcjar_deps != [] + + if (_is_prebuilt) { + assert(!_has_sources) + } else { + # Allow java_binary to not specify any sources. This is needed when a prebuilt + # is needed as a library as well as a binary. + assert(_is_annotation_processor || _is_java_binary || _has_sources) + } + + if (_is_java_binary) { + assert(defined(invoker.main_class), + "${invoker.type}() must set main_class") + } else if (_is_annotation_processor) { + assert(defined(invoker.main_class), + "java_annotation_processor() must set main_class") + } else { + assert(!defined(invoker.main_class), + "main_class cannot be used for target of type ${invoker.type}") + } + + if (defined(invoker.chromium_code)) { + _chromium_code = invoker.chromium_code + } else { + # Default based on whether target is in third_party. + _chromium_code = + filter_exclude([ get_label_info(":$_main_target_name", "dir") ], + [ "*\bthird_party\b*" ]) != [] + if (!_chromium_code && !_is_prebuilt && _java_files != []) { + # Unless third_party code has an org.chromium file in it. + _chromium_code = + filter_exclude(_java_files, [ "*\bchromium\b*" ]) != _java_files + } + } + + # Define build_config_deps which will be a list of targets required to + # build the _build_config. + _build_config = "$target_gen_dir/$_main_target_name.build_config.json" + _build_config_target_name = + "${_main_target_name}$build_config_target_suffix" + + # The only target that might have no prebuilt and no sources is a java_binary. + _build_host_jar = false + _build_device_jar = false + if (_is_prebuilt || _has_sources) { + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } else if (_is_prebuilt) { + _output_name = get_path_info(invoker.jar_path, "name") + } else { + _output_name = _main_target_name + } + + _build_host_jar = _is_java_binary || _is_annotation_processor || + invoker.type == "java_library" + _build_device_jar = + invoker.type != "system_java_library" && _supports_android + + _jacoco_instrument = + use_jacoco_coverage && _chromium_code && _java_files != [] && + _build_device_jar && (!defined(invoker.testonly) || !invoker.testonly) + if (defined(invoker.jacoco_never_instrument)) { + _jacoco_instrument = + !invoker.jacoco_never_instrument && _jacoco_instrument + } + + if (_build_host_jar) { + # Jar files can be needed at runtime (by Robolectric tests or java binaries), + # so do not put them under obj/. + # TODO(agrieve): I suspect it would be better to use dist_jar for java_binary + # rather than archiving unnecessary .jar files within lib.java. + _target_dir_name = get_label_info(":$_main_target_name", "dir") + _host_processed_jar_path = + "$root_out_dir/lib.java$_target_dir_name/$_output_name.jar" + } + if (_build_device_jar) { + _dex_path = "$target_out_dir/$_main_target_name.dex.jar" + _enable_desugar = + !defined(invoker.enable_desugar) || invoker.enable_desugar + _use_classic_desugar = + defined(invoker.use_classic_desugar) && invoker.use_classic_desugar + + # Build speed optimization: Skip "process device" step if the step + # would be just a copy and avoid the copy. + _process_device_jar = + defined(invoker.bytecode_rewriter_target) || _jacoco_instrument || + (_enable_desugar && _use_classic_desugar) || + defined(invoker.jar_excluded_patterns) || + defined(invoker.jar_included_patterns) + if (!_process_device_jar && _is_prebuilt) { + _device_processed_jar_path = invoker.jar_path + } else { + _device_processed_jar_path = + "$target_out_dir/$_output_name.processed.jar" + } + } + + # For static libraries, the javac jar output is created at the intermediate + # path so that it can be processed by another target and moved to the final + # spot that the .build_config.json knows about. Technically this should be done + # for the ijar as well, but this is only used for APK targets where + # the ijar path isn't actually used. + if (_has_sources) { + _final_ijar_path = "$target_out_dir/$_output_name.turbine.jar" + } else { + _final_ijar_path = "$target_out_dir/$_output_name.ijar.jar" + } + + if (_has_sources) { + if (_build_device_jar && !_process_device_jar) { + _javac_jar_path = _device_processed_jar_path + } else { + _javac_jar_path = "$target_out_dir/$_main_target_name.javac.jar" + } + _generated_jar_path = + "$target_gen_dir/$_main_target_name.generated.srcjar" + } + + if (_is_prebuilt) { + _unprocessed_jar_path = invoker.jar_path + } else { + _unprocessed_jar_path = _javac_jar_path + } + } + + if (_is_prebuilt || _has_sources) { + _java_res_deps = [] + _java_header_deps = [] + _java_impl_deps = [] + _non_java_deps = [] + foreach(_dep, _invoker_deps) { + _target_label = get_label_info(_dep, "label_no_toolchain") + if (filter_exclude([ _target_label ], _java_resource_patterns) == []) { + _java_res_deps += [ _dep ] + } else if (filter_exclude([ _target_label ], _java_library_patterns) == + []) { + # This is a java library dep, so it has header and impl targets. + _java_header_deps += [ "${_target_label}__header" ] + _java_impl_deps += [ "${_target_label}__impl" ] + } else { + _non_java_deps += [ _dep ] + } + } + + # Don't need to depend on the apk-under-test to be packaged. + if (defined(invoker.apk_under_test)) { + _java_header_deps += [ "${invoker.apk_under_test}__java__header" ] + _java_impl_deps += [ "${invoker.apk_under_test}__java__impl" ] + } + + # These deps cannot be passed via invoker.deps since bundle_module targets + # have bundle_module.build_config without the __java suffix, so they are + # special and cannot be passed as regular deps to write_build_config. + if (defined(invoker.base_module_target)) { + _java_header_deps += [ "${invoker.base_module_target}__java__header" ] + _java_impl_deps += [ "${invoker.base_module_target}__java__impl" ] + } + + _extra_java_deps = [] + if (_jacoco_instrument) { + _extra_java_deps += [ "//third_party/jacoco:jacocoagent_java" ] + } + + _include_android_sdk = _build_device_jar + if (defined(invoker.include_android_sdk)) { + _include_android_sdk = invoker.include_android_sdk + } + if (_include_android_sdk) { + _sdk_java_dep = "//third_party/android_sdk:android_sdk_java" + if (defined(invoker.alternative_android_sdk_dep)) { + _sdk_java_dep = invoker.alternative_android_sdk_dep + } + + # This is an android_system_java_prebuilt target, so no headers. + _extra_java_deps += [ _sdk_java_dep ] + } + + # Classpath deps is used for header and dex targets, they do not need + # resource deps. + _classpath_deps = _java_header_deps + _non_java_deps + _extra_java_deps + + [ ":$_build_config_target_name" ] + + _full_classpath_deps = + _java_impl_deps + _java_res_deps + _non_java_deps + _extra_java_deps + + [ ":$_build_config_target_name" ] + } + + # Often needed, but too hard to figure out when ahead of time. + not_needed([ + "_classpath_deps", + "_full_classpath_deps", + ]) + + if (_java_files != []) { + _java_sources_file = "$target_gen_dir/$_main_target_name.sources" + if (defined(invoker.java_sources_file)) { + _java_sources_file = invoker.java_sources_file + } + write_file(_java_sources_file, rebase_path(_java_files, root_build_dir)) + } + + write_build_config(_build_config_target_name) { + forward_variables_from(invoker, + [ + "aar_path", + "annotation_processor_deps", + "base_allowlist_rtxt_path", + "gradle_treat_as_prebuilt", + "input_jars_paths", + "low_classpath_priority", + "main_class", + "proguard_configs", + "proguard_enabled", + "proguard_mapping_path", + "public_target_label", + "r_text_path", + "type", + ]) + if (type == "android_apk" || type == "android_app_bundle_module") { + forward_variables_from( + invoker, + [ + "android_manifest", + "android_manifest_dep", + "merged_android_manifest", + "final_dex_path", + "loadable_modules", + "native_lib_placeholders", + "res_size_info_path", + "secondary_abi_loadable_modules", + "secondary_abi_shared_libraries_runtime_deps_file", + "secondary_native_lib_placeholders", + "shared_libraries_runtime_deps_file", + "static_library_dependent_targets", + "uncompress_shared_libraries", + "library_always_compress", + "library_renames", + ]) + } + if (type == "android_apk") { + forward_variables_from(invoker, + [ + "apk_path", + "apk_under_test", + "incremental_apk_path", + "incremental_install_json_path", + ]) + } + if (type == "android_app_bundle_module") { + forward_variables_from(invoker, + [ + "base_module_target", + "is_base_module", + "module_pathmap_path", + "proto_resources_path", + "version_name", + "version_code", + ]) + } + chromium_code = _chromium_code + build_config = _build_config + is_prebuilt = _is_prebuilt + + # Specifically avoid passing in invoker.base_module_target as one of the + # possible_config_deps. + possible_config_deps = _invoker_deps + if (defined(_extra_java_deps)) { + possible_config_deps += _extra_java_deps + } + if (defined(apk_under_test)) { + possible_config_deps += [ apk_under_test ] + } + + if (defined(invoker.public_deps)) { + possible_config_public_deps = invoker.public_deps + } + + supports_android = _supports_android + requires_android = _requires_android + bypass_platform_checks = defined(invoker.bypass_platform_checks) && + invoker.bypass_platform_checks + + if (defined(_resources_package)) { + custom_package = _resources_package + } + if (_is_prebuilt || _has_sources) { + ijar_path = _final_ijar_path + unprocessed_jar_path = _unprocessed_jar_path + } + if (_build_host_jar) { + host_jar_path = _host_processed_jar_path + } + if (_build_device_jar) { + device_jar_path = _device_processed_jar_path + dex_path = _dex_path + } + if (_java_files != []) { + java_sources_file = _java_sources_file + } + + bundled_srcjars = [] + foreach(d, _srcjar_deps) { + _dep_gen_dir = get_label_info(d, "target_gen_dir") + _dep_name = get_label_info(d, "name") + bundled_srcjars += [ "$_dep_gen_dir/$_dep_name.srcjar" ] + } + if (defined(invoker.include_java_resources) && + invoker.include_java_resources) { + java_resources_jar = _unprocessed_jar_path + if (defined(invoker.jar_path)) { + # Use original jar_path because _jar_path points to a library without + # resources. + } else { + java_resources_jar = _device_processed_jar_path + } + } + } + + if (_is_prebuilt || _has_sources) { + _header_target_name = "${target_name}__header" + } + + _public_deps = [] + _analysis_public_deps = [] + _analysis_files = [] + + if (defined(invoker.proguard_configs)) { + assert(_build_host_jar || _build_device_jar) + + # proguard_configs listed on java_library targets need to be marked + # as inputs to at least one action so that "gn analyze" will know + # about them. Although this target doesn't use them, it's a convenient spot + # to list them. + # https://crbug.com/827197 + _analysis_files = invoker.proguard_configs + _analysis_public_deps = + _non_java_deps + _srcjar_deps # For the aapt-generated + # proguard rules. + } + + if (_has_sources) { + if (defined(invoker.enable_errorprone)) { + _enable_errorprone = invoker.enable_errorprone + } else { + _enable_errorprone = + _java_files != [] && _chromium_code && use_errorprone_java_compiler + } + + _type = invoker.type + + _uses_fake_rjava = _type == "java_library" && _requires_android + + if (_uses_fake_rjava && defined(_resources_package)) { + # has _resources at the end so it looks like a resources pattern, since + # it does act like one (and other resources patterns need to depend on + # this before they can read its output R.txt). + _fake_rjava_target = "${target_name}__rjava_resources" + _possible_resource_deps = _invoker_deps + generate_r_java(_fake_rjava_target) { + deps = [ ":$_build_config_target_name" ] + if (defined(_possible_resource_deps)) { + possible_resource_deps = _possible_resource_deps + } + build_config = _build_config + + # Filepath has to be exactly this because compile_java looks for the + # srcjar of srcjar_deps at this location $gen_dir/$target_name.srcjar + srcjar_path = "$target_gen_dir/$target_name.srcjar" + package = _resources_package + } + _srcjar_deps += [ ":$_fake_rjava_target" ] + } + + template("compile_java_helper") { + _enable_errorprone = + defined(invoker.enable_errorprone) && invoker.enable_errorprone + if (_enable_errorprone) { + # Rely on the header jar to provide all .class files so that it is + # safe to omit generated files entirely for errorprone. + _filtered_java_files = + filter_exclude(_java_files, [ "$root_gen_dir*" ]) + } + if (_enable_errorprone && _filtered_java_files == []) { + # Filtering out generated files resulted in no files left. + group(target_name) { + not_needed(invoker, "*") + } + } else { + compile_java(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + output_jar_path = invoker.output_jar_path + enable_errorprone = _enable_errorprone + use_turbine = defined(invoker.use_turbine) && invoker.use_turbine + + main_target_name = _main_target_name + build_config = _build_config + + if (_enable_errorprone) { + java_files = _filtered_java_files + } else { + java_files = _java_files + srcjar_deps = _srcjar_deps + } + + if (java_files != []) { + java_sources_file = _java_sources_file + } + chromium_code = _chromium_code + supports_android = _supports_android + requires_android = _requires_android + if (!defined(deps)) { + deps = [] + } + deps += _classpath_deps + } + } + } + _compile_java_forward_variables = [ + "additional_jar_files", + "apk_name", + "jar_excluded_patterns", + "javac_args", + "processor_args_javac", + "skip_build_server", + ] + _annotation_processor_deps = [] + if (defined(invoker.annotation_processor_deps)) { + _annotation_processor_deps = invoker.annotation_processor_deps + } + + compile_java_helper(_header_target_name) { + forward_variables_from(invoker, _compile_java_forward_variables) + use_turbine = true + output_jar_path = _final_ijar_path + generated_jar_path = _generated_jar_path + deps = _annotation_processor_deps + } + _public_deps += [ ":$_header_target_name" ] + + _compile_java_target = "${_main_target_name}__compile_java" + compile_java_helper(_compile_java_target) { + forward_variables_from(invoker, _compile_java_forward_variables) + output_jar_path = _javac_jar_path + deps = [ ":$_header_target_name" ] + header_jar_path = _final_ijar_path + generated_jar_path = _generated_jar_path + } + if (_enable_errorprone) { + _compile_java_errorprone_target = "${_main_target_name}__errorprone" + compile_java_helper(_compile_java_errorprone_target) { + forward_variables_from(invoker, _compile_java_forward_variables) + enable_errorprone = true + if (defined(invoker.errorprone_args)) { + if (!defined(javac_args)) { + javac_args = [] + } + javac_args += invoker.errorprone_args + } + deps = [ ":$_header_target_name" ] + header_jar_path = _final_ijar_path + generated_jar_path = _generated_jar_path + output_jar_path = "$target_out_dir/$target_name.errorprone.stamp" + } + _analysis_public_deps += [ ":$_compile_java_errorprone_target" ] + } + } # _has_sources + + if (_is_prebuilt || _build_device_jar || _build_host_jar) { + _unprocessed_jar_deps = [] + if (_has_sources) { + _unprocessed_jar_deps += [ ":$_compile_java_target" ] + } + } + + if (defined(invoker.bytecode_rewriter_target)) { + assert(_build_host_jar || _build_device_jar, + "A host or device jar must be created to use bytecode rewriting") + + _rewritten_jar = "$target_out_dir/${target_name}_rewritten.jar" + _rewritten_jar_target_name = "${target_name}__rewritten" + _rewriter_path = root_build_dir + "/bin/helper/" + + get_label_info(invoker.bytecode_rewriter_target, "name") + _rebased_build_config = rebase_path(_build_config, root_build_dir) + action_with_pydeps(_rewritten_jar_target_name) { + script = "//build/android/gyp/bytecode_rewriter.py" + inputs = [ + _rewriter_path, + _build_config, + _unprocessed_jar_path, + ] + outputs = [ _rewritten_jar ] + depfile = "$target_gen_dir/$target_name.d" + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--script", + rebase_path(_rewriter_path, root_build_dir), + "--classpath", + "@FileArg($_rebased_build_config:deps_info:javac_full_classpath)", + "--classpath", + "@FileArg($_rebased_build_config:android:sdk_jars)", + "--input-jar", + rebase_path(_unprocessed_jar_path, root_build_dir), + "--output-jar", + rebase_path(_rewritten_jar, root_build_dir), + ] + deps = _unprocessed_jar_deps + _full_classpath_deps + + [ invoker.bytecode_rewriter_target ] + } + + _unprocessed_jar_deps = [] + _unprocessed_jar_deps = [ ":$_rewritten_jar_target_name" ] + _unprocessed_jar_path = _rewritten_jar + } + + if (_is_prebuilt) { + generate_interface_jar(_header_target_name) { + # Always used the unfiltered .jar to create the interface jar so that + # other targets will resolve filtered classes when depending on + # BuildConfig, NativeLibraries, etc. + input_jar = _unprocessed_jar_path + output_jar = _final_ijar_path + + # Normally ijar does not require any deps, but: + # 1 - Some jars are bytecode rewritten by _unprocessed_jar_deps. + # 2 - Other jars need to be unzipped by _non_java_deps. + # 3 - It is expected that depending on a header target implies depending + # on its transitive header target deps via _java_header_deps. + deps = _unprocessed_jar_deps + _non_java_deps + _java_header_deps + } + _public_deps += [ ":$_header_target_name" ] + } + + if (_build_host_jar || _build_device_jar) { + _enable_bytecode_checks = !defined(invoker.enable_bytecode_checks) || + invoker.enable_bytecode_checks + if (_enable_bytecode_checks) { + _bytecode_checks_target = "${target_name}__validate_classpath" + bytecode_processor(_bytecode_checks_target) { + forward_variables_from(invoker, [ "missing_classes_allowlist" ]) + deps = _unprocessed_jar_deps + _full_classpath_deps + + [ ":$_build_config_target_name" ] + requires_android = _requires_android + target_label = + get_label_info(":${invoker.target_name}", "label_no_toolchain") + input_jar = _unprocessed_jar_path + build_config = _build_config + is_prebuilt = _is_prebuilt + } + _analysis_public_deps += [ ":$_bytecode_checks_target" ] + } + + if (_build_host_jar) { + _process_host_jar_target_name = "${target_name}__process_host" + process_java_library(_process_host_jar_target_name) { + forward_variables_from(invoker, + [ + "jar_excluded_patterns", + "jar_included_patterns", + ]) + input_jar_path = _unprocessed_jar_path + jar_deps = _unprocessed_jar_deps + _full_classpath_deps + is_device_jar = false + output_jar_path = _host_processed_jar_path + jacoco_instrument = _jacoco_instrument + if (_jacoco_instrument) { + java_files = _java_files + java_sources_file = _java_sources_file + } + } + _public_deps += [ ":${_process_host_jar_target_name}" ] + } + + if (_build_device_jar) { + if (_process_device_jar) { + _process_device_jar_target_name = "${target_name}__process_device" + process_java_library(_process_device_jar_target_name) { + forward_variables_from(invoker, + [ + "jar_excluded_patterns", + "jar_included_patterns", + ]) + input_jar_path = _unprocessed_jar_path + jar_deps = _unprocessed_jar_deps + _full_classpath_deps + is_device_jar = true + output_jar_path = _device_processed_jar_path + jacoco_instrument = _jacoco_instrument + if (_jacoco_instrument) { + java_files = _java_files + java_sources_file = _java_sources_file + } + enable_desugar = _enable_desugar && _use_classic_desugar + if (enable_desugar) { + build_config = _build_config + classpath_deps = _classpath_deps + forward_variables_from(invoker, [ "desugar_jars_paths" ]) + } + } + _process_device_jar_deps = [ ":${_process_device_jar_target_name}" ] + _public_deps += _process_device_jar_deps + } else { + assert(_unprocessed_jar_path == _device_processed_jar_path) + _process_device_jar_deps = + _unprocessed_jar_deps + _full_classpath_deps + } + + dex("${target_name}__dex") { + forward_variables_from(invoker, + [ + "desugar_jars_paths", + "proguard_enable_obfuscation", + "use_classic_desugar", + ]) + input_class_jars = [ _device_processed_jar_path ] + enable_desugar = _enable_desugar + ignore_desugar_missing_deps = !_enable_bytecode_checks + + # There's no value in per-class dexing prebuilts since they never + # change just one class at a time. + disable_incremental = _is_prebuilt + output = _dex_path + deps = _process_device_jar_deps + + if (enable_desugar && !_use_classic_desugar) { + # Desugaring with D8 requires full classpath. + build_config = _build_config + final_ijar_path = _final_ijar_path + deps += _classpath_deps + [ ":$_header_target_name" ] + } + + enable_multidex = false + is_library = true + } + _public_deps += [ ":${target_name}__dex" ] + } + } + + if (_is_java_binary) { + # Targets might use the generated script while building, so make it a dep + # rather than a data_dep. + java_binary_script("${target_name}__java_binary_script") { + forward_variables_from(invoker, + [ + "tiered_stop_at_level_one", + "main_class", + "wrapper_script_args", + ]) + build_config = _build_config + script_name = _main_target_name + if (defined(invoker.wrapper_script_name)) { + script_name = invoker.wrapper_script_name + } + deps = [ ":$_build_config_target_name" ] + } + _public_deps += [ ":${target_name}__java_binary_script" ] + } + + # The __impl target contains all non-analysis steps for this template. + # Having this separated out from the main target (which contains analysis + # steps) allows analysis steps for this target to be run concurrently with + # the non-analysis steps of other targets that depend on this one. + group("${target_name}__impl") { + public_deps = _public_deps + } + + java_lib_group("${target_name}__assetres") { + deps = _invoker_deps + group_name = "assetres" + + if (defined(_fake_rjava_target)) { + deps += [ ":$_fake_rjava_target" ] + } + } + + group(target_name) { + forward_variables_from(invoker, + [ + "assert_no_deps", + "data", + "data_deps", + "deps", + "public_deps", + "visibility", + ]) + if (!defined(public_deps)) { + public_deps = [] + } + public_deps += [ ":${target_name}__impl" ] + if (!defined(data)) { + data = [] + } + data += _analysis_files + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += _analysis_public_deps + } + } +} + +# Create a zip archive corresponding to an application bundle module. +# +# Compile all the components of a given android_apk_or_module() target into a +# zip archive suitable to later create an android_app_bundle() target. This +# archive's format is very similar to that on an APK, except for a few +# differences in internal directory layouts, and the fact that resources, as +# well as xml files, are compiled using a protocol-buffer based format (instead +# of the regular binary xml + resources.arsc). +# +# A final application bundle is built from one or more module bundle modules, +# plus some configuration file. +# +# Variables: +# module_zip_path: Output module path. +# build_config: Path to build_config of the android_apk_or_module() target. +# dex_path: If module is proguarded separately from the base module, dex_path +# is the path to its dex file and is passed directly to the creation script. +# Otherwise, dex_path is undefined and we retrieve the module's dex file +# using its build_config. +# expected_libs_and_assets: Verify the list of included native libraries +# and assets is consistent with the given expectation file. +# expected_libs_and_assets_base: Treat expected_libs_and_assets as a diff +# with this file as the base. +# is_multi_abi: If true will add a library placeholder for the missing ABI if +# either the primary or the secondary ABI has no native libraries set. +# module_name: The module's name. +# native_libraries_config: Path to file listing native libraries to be +# packaged into each module. +# proguard_enabled: Optional. True if proguarding is enabled for this +# bundle. Default is to enable this only for release builds. Note that +# this will always perform synchronized proguarding. +template("create_android_app_bundle_module") { + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + _rebased_native_libraries_config = + rebase_path(invoker.native_libraries_config, root_build_dir) + _proguard_enabled = + defined(invoker.proguard_enabled) && invoker.proguard_enabled + + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + _deps = invoker.deps + _script = "//build/android/gyp/apkbuilder.py" + + # NOTE: Compared to the inputs of the "package_apk" template action, + # this list is much smaller, since finalize_apk is never called + # by apkbuild.py --format=bundle-module. This means not using + # apksigner and zipalign as well, nor the keystore. Other + # dependencies like extra native libraries are all pulled from the + # .build_config.json through @FileArg() references (see below) and + # will be listed in the generated depfile instead. + _inputs = [ + invoker.build_config, + invoker.native_libraries_config, + ] + _outputs = [ invoker.module_zip_path ] + _args = [ + "--format=bundle-module", + "--output-apk", + rebase_path(invoker.module_zip_path, root_build_dir), + "--resource-apk=@FileArg(" + + "$_rebased_build_config:deps_info:proto_resources_path)", + "--assets=@FileArg($_rebased_build_config:assets)", + "--uncompressed-assets=@FileArg(" + + "$_rebased_build_config:uncompressed_assets)", + "--native-libs=@FileArg($_rebased_native_libraries_config" + + ":${invoker.module_name})", + "--native-lib-placeholders=@FileArg($_rebased_build_config" + + ":native:native_library_placeholders)", + "--secondary-native-lib-placeholders=@FileArg($_rebased_build_config" + + ":native:secondary_native_library_placeholders)", + "--android-abi=$android_app_abi", + "--min-sdk-version=${invoker.min_sdk_version}", + "--uncompress-shared-libraries=@FileArg(" + + "$_rebased_build_config:native:uncompress_shared_libraries)", + "--library-always-compress=@FileArg($_rebased_build_config:native:library_always_compress)", + "--library-renames=@FileArg($_rebased_build_config:native:library_renames)", + ] + if (defined(android_app_secondary_abi)) { + _rebased_secondary_abi_native_libraries_config = + rebase_path(invoker.secondary_abi_native_libraries_config, + root_build_dir) + _args += [ + "--secondary-native-libs", + "@FileArg($_rebased_secondary_abi_native_libraries_config" + + ":${invoker.module_name})", + "--secondary-android-abi=$android_app_secondary_abi", + ] + } + if (defined(invoker.is_multi_abi) && invoker.is_multi_abi) { + _args += [ "--is-multi-abi" ] + } + if (defined(invoker.uncompress_dex) && invoker.uncompress_dex) { + _args += [ "--uncompress-dex" ] + } + + # Use either provided dex path or build config path based on type of module. + if (defined(invoker.dex_path)) { + _inputs += [ invoker.dex_path ] + _rebased_dex_path = rebase_path(invoker.dex_path, root_build_dir) + _args += [ "--dex-file=$_rebased_dex_path" ] + } else { + _args += [ "--dex-file=@FileArg($_rebased_build_config:final_dex:path)" ] + } + + # The library is imported via proguard when proguard is enabled. + if (!_proguard_enabled && enable_jdk_library_desugaring && + invoker.module_name == "base") { + _all_jdk_libs = "//build/android:all_jdk_libs" + _deps += [ _all_jdk_libs ] + _jdk_libs_dex = + get_label_info(_all_jdk_libs, "target_out_dir") + "/all_jdk_libs.l8.dex" + _inputs += [ _jdk_libs_dex ] + _args += [ + "--jdk-libs-dex-file", + rebase_path(_jdk_libs_dex, root_build_dir), + ] + } + + if (treat_warnings_as_errors) { + _args += [ "--warnings-as-errors" ] + } + + if (defined(invoker.expected_libs_and_assets)) { + _expectations_target = "${invoker.top_target_name}_validate_libs_and_assets" + action_with_pydeps(_expectations_target) { + _actual_file = "$target_gen_dir/$target_name.libs_and_assets" + _failure_file = "$expectations_failure_dir/" + + string_replace(invoker.expected_libs_and_assets, "/", "_") + inputs = [ + invoker.expected_libs_and_assets, + invoker.build_config, + invoker.native_libraries_config, + ] + deps = [ + invoker.build_config_target, + invoker.native_libraries_config_target, + ] + if (defined(android_app_secondary_abi)) { + inputs += [ invoker.secondary_abi_native_libraries_config ] + deps += [ invoker.secondary_abi_native_libraries_config_target ] + } + outputs = [ + _actual_file, + _failure_file, + ] + script = _script + args = _args + [ + "--expected-file", + rebase_path(invoker.expected_libs_and_assets, root_build_dir), + "--actual-file", + rebase_path(_actual_file, root_build_dir), + "--failure-file", + rebase_path(_failure_file, root_build_dir), + "--only-verify-expectations", + ] + if (defined(invoker.expected_libs_and_assets_base)) { + inputs += [ invoker.expected_libs_and_assets_base ] + args += [ + "--expected-file-base", + rebase_path(invoker.expected_libs_and_assets_base, root_build_dir), + ] + } + if (fail_on_android_expectations) { + args += [ "--fail-on-expectations" ] + } + } + _deps += [ ":$_expectations_target" ] + } + + action_with_pydeps(target_name) { + deps = _deps + inputs = _inputs + outputs = _outputs + script = _script + depfile = "$target_gen_dir/$target_name.d" + args = _args + [ + "--depfile", + rebase_path(depfile, root_build_dir), + ] + } +} + +# Splits input dex file(s) based on given feature jars into seperate dex files +# for each feature. +# +# Variables: +# proguard_mapping: Path to input proguard mapping produced by synchronized +# proguarding. +# input_dex_zip: Path to zipped dex files to split. +# all_modules: Path to list of all modules. Each Module must have +# build_config, name, and build_config_target properties. +# feature_jars_args: Optional list of args to be passed to dexsplitter.py. +# If used should include the jars owned by each feature (in the same order +# as all_modules). Allows invoker to pull the list of jars from a different +# .build_config.json than the module's .build_config. +template("dexsplitter") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, [ "deps" ]) + script = "//build/android/gyp/dexsplitter.py" + _stamp = "${target_gen_dir}/${target_name}.stamp" + outputs = [ _stamp ] + + depfile = "${target_gen_dir}/${target_name}.d" + args = [ + "--stamp", + rebase_path(_stamp, root_build_dir), + "--depfile", + rebase_path(depfile, root_build_dir), + "--r8-path", + rebase_path(_r8_path, root_build_dir), + "--input-dex-zip", + rebase_path(invoker.input_dex_zip, root_build_dir), + "--proguard-mapping-file", + rebase_path(invoker.proguard_mapping, root_build_dir), + ] + + foreach(_feature_module, invoker.all_modules) { + _rebased_module_build_config = + rebase_path(_feature_module.build_config, root_build_dir) + args += [ + "--feature-name", + _feature_module.name, + "--dex-dest=@FileArg($_rebased_module_build_config:final_dex:path)", + ] + if (!defined(invoker.feature_jars_args)) { + args += [ "--feature-jars=@FileArg($_rebased_module_build_config:deps_info:device_classpath)" ] + } + deps += [ _feature_module.build_config_target ] + } + if (defined(invoker.feature_jars_args)) { + args += invoker.feature_jars_args + } + } +} + +# Allots native libraries depended on by feature modules to the module the +# libraries should be packaged into. The packaging module may be different from +# the dependee module in case a library is depended on by multiple modules. In +# that case the library will be allotted to the closest ancestor given a module +# dependency tree (see |parent| below). +# +# Variables: +# modules: List of scopes with the following format: +# name: The module's name. +# parent: The module's parent's name. +# build_config: Path to the module's build config. +# build_config_target: Target creating |build_config|. +# native_libraries_filearg_keys: Keys to be used in +# @FileArg(|build_config|:<keys>) expressions pointing to a list of native +# libraries to consider in |build_config|. +# output: Path to native libraries config. +template("allot_native_libraries") { + action_with_pydeps(target_name) { + script = "//build/android/gyp/allot_native_libraries.py" + args = [ + "--output", + rebase_path(invoker.output, root_build_dir), + ] + outputs = [ invoker.output ] + deps = [] + if (defined(invoker.deps)) { + deps += invoker.deps + } + inputs = [] + foreach(_module, invoker.modules) { + deps += [ _module.build_config_target ] + inputs += [ _module.build_config ] + _rebased_build_config = rebase_path(_module.build_config, root_out_dir) + foreach(_key, invoker.native_libraries_filearg_keys) { + args += [ + "--libraries", + "${_module.name},@FileArg($_rebased_build_config:$_key)", + ] + } + if (defined(_module.parent)) { + args += [ + "--dep", + "${_module.parent}:${_module.name}", + ] + } + } + } +} diff --git a/third_party/libwebrtc/build/config/android/linker_version_script.gni b/third_party/libwebrtc/build/config/android/linker_version_script.gni new file mode 100644 index 0000000000..96d8b665d1 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/linker_version_script.gni @@ -0,0 +1,43 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/python.gni") + +# Generate a custom linker version script that can later be used with +# "-Wl,--version-script=<path>" ldflags. +# +# Variables: +# export_java_symbols: Optional. If true, also export all Java_* symbols +# exported for JNI. +# export_symbol_allowlist_files: Optional. List of paths to input files containing +# lists of symbols to export. +# linker_script: Path to output linker version script. +# +template("generate_linker_version_script") { + action_with_pydeps(target_name) { + script = "//build/android/gyp/generate_linker_version_script.py" + outputs = [ invoker.linker_script ] + inputs = [] + args = [ "--output=" + rebase_path(invoker.linker_script, root_build_dir) ] + + if (defined(invoker.export_java_symbols) && invoker.export_java_symbols) { + args += [ "--export-java-symbols" ] + } + + if (defined(invoker.export_feature_registrations) && + invoker.export_feature_registrations) { + args += [ "--export-feature-registrations" ] + } + + if (defined(invoker.export_symbol_allowlist_files)) { + foreach(file_, invoker.export_symbol_allowlist_files) { + inputs += [ file_ ] + args += [ + "--export-symbol-allowlist-file", + rebase_path(file_, root_build_dir), + ] + } + } + } +} diff --git a/third_party/libwebrtc/build/config/android/rules.gni b/third_party/libwebrtc/build/config/android/rules.gni new file mode 100644 index 0000000000..45499a3781 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/rules.gni @@ -0,0 +1,5183 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Do not add any imports to non-//build directories here. +# Some projects (e.g. V8) do not have non-build directories DEPS'ed in. + +import("//build/config/android/channel.gni") +import("//build/config/android/config.gni") +import("//build/config/android/internal_rules.gni") +import("//build/config/clang/clang.gni") +import("//build/config/compiler/compiler.gni") +import("//build/config/coverage/coverage.gni") +import("//build/config/python.gni") +import("//build/config/rts.gni") +import("//build/config/zip.gni") +import("//build/toolchain/toolchain.gni") + +assert(is_android) + +declare_args() { + enable_jni_tracing = false +} + +if (target_cpu == "arm") { + _sanitizer_arch = "arm" +} else if (target_cpu == "arm64") { + _sanitizer_arch = "aarch64" +} else if (target_cpu == "x86") { + _sanitizer_arch = "i686" +} + +_sanitizer_runtimes = [] +if (use_cfi_diag || is_ubsan || is_ubsan_security || is_ubsan_vptr) { + _sanitizer_runtimes = [ "$clang_base_path/lib/clang/$clang_version/lib/linux/libclang_rt.ubsan_standalone-$_sanitizer_arch-android.so" ] +} + +# Creates a dist directory for a native executable. +# +# Running a native executable on a device requires all the shared library +# dependencies of that executable. To make it easier to install and run such an +# executable, this will create a directory containing the native exe and all +# it's library dependencies. +# +# Note: It's usually better to package things as an APK than as a native +# executable. +# +# Variables +# dist_dir: Directory for the exe and libraries. Everything in this directory +# will be deleted before copying in the exe and libraries. +# binary: Path to (stripped) executable. +# extra_files: List of extra files to copy in (optional). +# +# Example +# create_native_executable_dist("foo_dist") { +# dist_dir = "$root_build_dir/foo_dist" +# binary = "$root_build_dir/foo" +# deps = [ ":the_thing_that_makes_foo" ] +# } +template("create_native_executable_dist") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _libraries_list = "${target_gen_dir}/${target_name}_library_dependencies.list" + + _sanitizer_runtimes_target_name = "${target_name}__sanitizer_runtimes" + group(_sanitizer_runtimes_target_name) { + metadata = { + shared_libraries = _sanitizer_runtimes + } + } + + generated_file("${target_name}__library_list") { + forward_variables_from(invoker, [ "deps" ]) + if (!defined(deps)) { + deps = [] + } + deps += [ ":${_sanitizer_runtimes_target_name}" ] + output_conversion = "json" + outputs = [ _libraries_list ] + data_keys = [ "shared_libraries" ] + walk_keys = [ "shared_libraries_barrier" ] + rebase = root_build_dir + } + + copy_ex(target_name) { + inputs = [ + _libraries_list, + invoker.binary, + ] + + dest = invoker.dist_dir + data = [ "${invoker.dist_dir}/" ] + + _rebased_libraries_list = rebase_path(_libraries_list, root_build_dir) + _rebased_binaries_list = rebase_path([ invoker.binary ], root_build_dir) + args = [ + "--clear", + "--files=@FileArg($_rebased_libraries_list)", + "--files=$_rebased_binaries_list", + ] + if (defined(invoker.extra_files)) { + _rebased_extra_files = rebase_path(invoker.extra_files, root_build_dir) + args += [ "--files=$_rebased_extra_files" ] + } + + _depfile = "$target_gen_dir/$target_name.d" + _stamp_file = "$target_gen_dir/$target_name.stamp" + outputs = [ _stamp_file ] + args += [ + "--depfile", + rebase_path(_depfile, root_build_dir), + "--stamp", + rebase_path(_stamp_file, root_build_dir), + ] + + deps = [ ":${target_name}__library_list" ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + } +} + +if (enable_java_templates) { + import("//build/config/sanitizers/sanitizers.gni") + + # JNI target implementation. See generate_jni or generate_jar_jni for usage. + template("generate_jni_impl") { + _jni_output_dir = "${target_gen_dir}/${target_name}" + if (defined(invoker.jni_generator_include)) { + _jni_generator_include = invoker.jni_generator_include + _jni_generator_include_deps = [] + } else { + _jni_generator_include = + "//base/android/jni_generator/jni_generator_helper.h" + _jni_generator_include_deps = [ + # Using //base/android/jni_generator/jni_generator_helper.h introduces + # a dependency on buildflags targets indirectly through + # base/android/jni_android.h, which is part of the //base target. + # This can't depend directly on //base without causing a dependency + # cycle, though. + "//base:debugging_buildflags", + "//base:logging_buildflags", + "//build:chromeos_buildflags", + ] + } + + action_with_pydeps(target_name) { + # The sources aren't compiled so don't check their dependencies. + check_includes = false + script = "//base/android/jni_generator/jni_generator.py" + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "deps", + "public_deps", + ]) + if (!defined(public_deps)) { + public_deps = [] + } + public_deps += _jni_generator_include_deps + inputs = [] + args = [ + "--ptr_type=long", + "--includes", + rebase_path(_jni_generator_include, _jni_output_dir), + ] + + if (defined(invoker.classes)) { + if (defined(invoker.jar_file)) { + _jar_file = invoker.jar_file + } else { + _jar_file = android_sdk_jar + } + inputs += [ _jar_file ] + args += [ + "--jar_file", + rebase_path(_jar_file, root_build_dir), + ] + _input_args = invoker.classes + _input_names = invoker.classes + if (defined(invoker.always_mangle) && invoker.always_mangle) { + args += [ "--always_mangle" ] + } + } else { + assert(defined(invoker.sources)) + inputs += invoker.sources + _input_args = rebase_path(invoker.sources, root_build_dir) + _input_names = invoker.sources + if (use_hashed_jni_names) { + args += [ "--use_proxy_hash" ] + } + if (defined(invoker.namespace)) { + args += [ "-n ${invoker.namespace}" ] + } + } + if (defined(invoker.split_name)) { + args += [ "--split_name=${invoker.split_name}" ] + } + + outputs = [] + foreach(_name, _input_names) { + _name_part = get_path_info(_name, "name") + outputs += [ "${_jni_output_dir}/${_name_part}_jni.h" ] + } + + # Avoid passing GN lists because not all webrtc embedders use //build. + foreach(_output, outputs) { + args += [ + "--output_file", + rebase_path(_output, root_build_dir), + ] + } + foreach(_input, _input_args) { + args += [ "--input_file=$_input" ] + } + + if (enable_profiling) { + args += [ "--enable_profiling" ] + } + if (enable_jni_tracing) { + args += [ "--enable_tracing" ] + } + } + } + + # Declare a jni target + # + # This target generates the native jni bindings for a set of .java files. + # + # See base/android/jni_generator/jni_generator.py for more info about the + # format of generating JNI bindings. + # + # Variables + # sources: list of .java files to generate jni for + # namespace: Specify the namespace for the generated header file. + # deps, public_deps: As normal + # + # Example + # # Target located in base/BUILD.gn. + # generate_jni("foo_jni") { + # # Generates gen/base/foo_jni/Foo_jni.h + # # To use: #include "base/foo_jni/Foo_jni.h" + # sources = [ + # "android/java/src/org/chromium/foo/Foo.java", + # ..., + # ] + # } + template("generate_jni") { + generate_jni_impl(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + } + } + + # Declare a jni target for a prebuilt jar + # + # This target generates the native jni bindings for a set of classes in a .jar. + # + # See base/android/jni_generator/jni_generator.py for more info about the + # format of generating JNI bindings. + # + # Variables + # classes: list of .class files in the jar to generate jni for. These should + # include the full path to the .class file. + # jar_file: the path to the .jar. If not provided, will default to the sdk's + # android.jar + # always_mangle: Mangle all generated method names. By default, the script + # only mangles methods that cause ambiguity due to method overload. + # deps, public_deps: As normal + # + # Example + # # Target located in base/BUILD.gn. + # generate_jar_jni("foo_jni") { + # # Generates gen/base/foo_jni/Runnable_jni.h + # # To use: #include "base/foo_jni/Runnable_jni.h" + # classes = [ + # "android/view/Foo.class", + # ] + # } + template("generate_jar_jni") { + generate_jni_impl(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + } + } + + # Declare a jni registration target. + # + # This target generates a srcjar containing a copy of GEN_JNI.java, which has + # the native methods of all dependent java files. It can also create a .h file + # for use with manual JNI registration. + # + # The script does not scan any generated sources (those within .srcjars, or + # within root_build_dir). This could be fixed by adding deps & logic to scan + # .srcjars, but isn't currently needed. + # + # See base/android/jni_generator/jni_registration_generator.py for more info + # about the format of the header file. + # + # Variables + # targets: List of .build_config.json supported targets to provide java sources. + # header_output: Path to the generated .h file (optional). + # sources_exclusions: List of .java files that should be skipped. (optional) + # namespace: Registration functions will be wrapped into this. (optional) + # require_native_mocks: Enforce that any native calls using + # org.chromium.base.annotations.NativeMethods must have a mock set + # (optional). + # enable_native_mocks: Allow native calls using + # org.chromium.base.annotations.NativeMethods to be mocked in tests + # (optional). + # no_transitive_deps: Generate registration for only the Java source in the + # specified target(s). This is useful for generating registration for + # feature modules, without including base module dependencies. + # + # Example + # generate_jni_registration("chrome_jni_registration") { + # targets = [ ":chrome_public_apk" ] + # header_output = "$target_gen_dir/$target_name.h" + # sources_exclusions = [ + # "//path/to/Exception.java", + # ] + # } + template("generate_jni_registration") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + script = "//base/android/jni_generator/jni_registration_generator.py" + inputs = [] + deps = [] + _srcjar_output = "$target_gen_dir/$target_name.srcjar" + outputs = [ _srcjar_output ] + depfile = "$target_gen_dir/$target_name.d" + + args = [ + "--srcjar-path", + rebase_path(_srcjar_output, root_build_dir), + "--depfile", + rebase_path(depfile, root_build_dir), + ] + foreach(_target, invoker.targets) { + deps += [ "${_target}$build_config_target_suffix($default_toolchain)" ] + _build_config = + get_label_info("${_target}($default_toolchain)", "target_gen_dir") + + "/" + get_label_info("${_target}($default_toolchain)", "name") + + ".build_config.json" + _rebased_build_config = rebase_path(_build_config, root_build_dir) + inputs += [ _build_config ] + + if (defined(invoker.no_transitive_deps) && invoker.no_transitive_deps) { + args += [ "--sources-files=@FileArg($_rebased_build_config:deps_info:java_sources_file)" ] + } else { + args += [ + # This is a list of .sources files. + "--sources-files=@FileArg($_rebased_build_config:deps_info:jni:all_source)", + ] + } + } + + if (use_hashed_jni_names) { + args += [ "--use_proxy_hash" ] + } + + if (defined(invoker.enable_native_mocks) && invoker.enable_native_mocks) { + args += [ "--enable_proxy_mocks" ] + + if (defined(invoker.require_native_mocks) && + invoker.require_native_mocks) { + args += [ "--require_mocks" ] + } + } + + if (defined(invoker.header_output)) { + outputs += [ invoker.header_output ] + args += [ + "--header-path", + rebase_path(invoker.header_output, root_build_dir), + ] + } + + if (defined(invoker.sources_exclusions)) { + _rebase_sources_exclusions = + rebase_path(invoker.sources_exclusions, root_build_dir) + args += [ "--sources-exclusions=$_rebase_sources_exclusions" ] + } + + if (defined(invoker.namespace)) { + args += [ "--namespace=${invoker.namespace}" ] + } + } + } + + # Declare a target for c-preprocessor-generated java files + # + # NOTE: For generating Java conterparts to enums prefer using the java_cpp_enum + # rule instead. + # + # This target generates java files using the host C pre-processor. Each file in + # sources will be compiled using the C pre-processor. If include_path is + # specified, it will be passed (with --I) to the pre-processor. + # + # This target will create a single .srcjar. Adding this target to an + # android_library target's srcjar_deps will make the generated java files be + # included in that library's final outputs. + # + # Variables + # sources: list of files to be processed by the C pre-processor. For each + # file in sources, there will be one .java file in the final .srcjar. For a + # file named FooBar.template, a java file will be created with name + # FooBar.java. + # inputs: additional compile-time dependencies. Any files + # `#include`-ed in the templates should be listed here. + # defines: List of -D arguments for the preprocessor. + # + # Example + # java_cpp_template("foo_generated_enum") { + # sources = [ + # "android/java/templates/Foo.template", + # ] + # inputs = [ + # "android/java/templates/native_foo_header.h", + # ] + # } + template("java_cpp_template") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "data_deps", + "deps", + "inputs", + "public_deps", + "sources", + "testonly", + "visibility", + ]) + script = "//build/android/gyp/gcc_preprocess.py" + outputs = [ "$target_gen_dir/$target_name.srcjar" ] + + _include_dirs = [ + "//", + root_gen_dir, + ] + _rebased_include_dirs = rebase_path(_include_dirs, root_build_dir) + args = [ + "--include-dirs=$_rebased_include_dirs", + "--output", + rebase_path(outputs[0], root_build_dir), + ] + if (defined(invoker.defines)) { + foreach(_define, invoker.defines) { + args += [ + "--define", + _define, + ] + } + } + args += rebase_path(sources, root_build_dir) + } + } + + # Declare a target for generating Java classes from C++ enums. + # + # This target generates Java files from C++ enums using a script. + # + # This target will create a single .srcjar. Adding this target to an + # android_library target's srcjar_deps will make the generated java files be + # included in that library's final outputs. + # + # Variables + # sources: list of files to be processed by the script. For each annotated + # enum contained in the sources files the script will generate a .java + # file with the same name as the name of the enum. + # + # Example + # java_cpp_enum("foo_generated_enum") { + # sources = [ + # "src/native_foo_header.h", + # ] + # } + template("java_cpp_enum") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "sources" ]) + + # The sources aren't compiled so don't check their dependencies. + check_includes = false + script = "//build/android/gyp/java_cpp_enum.py" + + _srcjar_path = "${target_gen_dir}/${target_name}.srcjar" + _rebased_srcjar_path = rebase_path(_srcjar_path, root_build_dir) + _rebased_sources = rebase_path(invoker.sources, root_build_dir) + + args = [ "--srcjar=$_rebased_srcjar_path" ] + _rebased_sources + outputs = [ _srcjar_path ] + } + } + + # Declare a target for generating Java classes with string constants matching + # those found in C++ files using a python script. + # + # This target will create a single .srcjar. Adding this target to an + # android_library target's srcjar_deps will make the generated java files be + # included in that library's final outputs. + # + # Variables + # sources: list of files to be processed by the script. For each string + # constant in the source files, the script will add a corresponding + # Java string to the specified template file. + # Example + # java_cpp_strings("foo_switches") { + # sources = [ + # "src/foo_switches.cc", + # ] + # template = "src/templates/FooSwitches.java.tmpl + # } + # + # foo_switches.cc: + # + # // A switch. + # const char kASwitch = "a-switch"; + # + # FooSwitches.java.tmpl + # + # // Copyright {YEAR} The Chromium Authors. All rights reserved. + # // Use of this source code is governed by a BSD-style license that can be + # // found in the LICENSE file. + # + # // This file is autogenerated by + # // {SCRIPT_NAME} + # // From + # // {SOURCE_PATH}, and + # // {TEMPLATE_PATH} + # + # package my.java.package; + # + # public abstract class FooSwitches {{ + # // ...snip... + # {NATIVE_STRINGS} + # // ...snip... + # }} + # + # result: + # A FooSwitches.java file, defining a class named FooSwitches in the package + # my.java.package. + template("java_cpp_strings") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "sources" ]) + + # The sources aren't compiled so don't check their dependencies. + check_includes = false + script = "//build/android/gyp/java_cpp_strings.py" + + _srcjar_path = "${target_gen_dir}/${target_name}.srcjar" + _rebased_srcjar_path = rebase_path(_srcjar_path, root_build_dir) + _rebased_sources = rebase_path(invoker.sources, root_build_dir) + _rebased_template = rebase_path(invoker.template, root_build_dir) + + args = [ + "--srcjar=$_rebased_srcjar_path", + "--template=$_rebased_template", + ] + args += _rebased_sources + sources += [ invoker.template ] + + outputs = [ _srcjar_path ] + } + } + + # Declare a target for generating Java classes with string constants matching + # those found in C++ base::Feature declarations, using a python script. + # + # This target will create a single .srcjar. Adding this target to an + # android_library target's srcjar_deps will make the generated java files be + # included in that library's final outputs. + # + # Variables + # sources: list of files to be processed by the script. For each + # base::Feature in the source files, the script will add a + # corresponding Java string for that feature's name to the + # specified template file. + # Example + # java_cpp_features("foo_features") { + # sources = [ + # "src/foo_features.cc", + # ] + # template = "src/templates/FooFeatures.java.tmpl + # } + # + # foo_features.cc: + # + # // A feature. + # const base::Feature kSomeFeature{"SomeFeature", + # base::FEATURE_DISABLED_BY_DEFAULT}; + # + # FooFeatures.java.tmpl + # + # // Copyright $YEAR The Chromium Authors. All rights reserved. + # // Use of this source code is governed by a BSD-style license that can be + # // found in the LICENSE file. + # + # package my.java.package; + # + # public final class FooFeatures {{ + # // ...snip... + # {NATIVE_STRINGS} + # // ...snip... + # // Do not instantiate this class. + # private FooFeatures() {{}} + # }} + # + # result: + # A FooFeatures.java file, defining a class named FooFeatures in the package + # my.java.package. + template("java_cpp_features") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "sources" ]) + + # The sources aren't compiled so don't check their dependencies. + check_includes = false + script = "//build/android/gyp/java_cpp_features.py" + + _srcjar_path = "${target_gen_dir}/${target_name}.srcjar" + _rebased_srcjar_path = rebase_path(_srcjar_path, root_build_dir) + _rebased_sources = rebase_path(invoker.sources, root_build_dir) + _rebased_template = rebase_path(invoker.template, root_build_dir) + + args = [ + "--srcjar=$_rebased_srcjar_path", + "--template=$_rebased_template", + ] + args += _rebased_sources + sources += [ invoker.template ] + + outputs = [ _srcjar_path ] + } + } + + # Declare a target for processing a Jinja template. + # + # Variables + # input: The template file to be processed. + # includes: List of files {% include %}'ed by input. + # output: Where to save the result. + # variables: (Optional) A list of variables to make available to the template + # processing environment, e.g. ["name=foo", "color=red"]. + # + # Example + # jinja_template("chrome_public_manifest") { + # input = "java/AndroidManifest.xml" + # output = "$target_gen_dir/AndroidManifest.xml" + # } + template("jinja_template") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + inputs = [ invoker.input ] + if (defined(invoker.includes)) { + inputs += invoker.includes + } + script = "//build/android/gyp/jinja_template.py" + + outputs = [ invoker.output ] + + args = [ + "--loader-base-dir", + rebase_path("//", root_build_dir), + "--inputs", + rebase_path(invoker.input, root_build_dir), + "--output", + rebase_path(invoker.output, root_build_dir), + "--check-includes", + ] + if (defined(invoker.includes)) { + _rebased_includes = rebase_path(invoker.includes, root_build_dir) + args += [ "--includes=$_rebased_includes" ] + } + if (defined(invoker.variables)) { + args += [ "--variables=${invoker.variables}" ] + } + } + } + + # Writes native libraries to a NativeLibaries.java file. + # + # This target will create a single .srcjar. Adding this target to an + # android_library target's srcjar_deps will make the generated java files be + # included in that library's final outputs. + # + # Variables: + # native_libraries_list_file: (Optional) Path to file listing all native + # libraries to write. + # version_number: (Optional) String of expected version of 'main' native + # library. + # enable_chromium_linker: (Optional) Whether to use the Chromium linker. + # load_library_from_apk: (Optional) Whether libraries should be loaded from + # the APK without uncompressing. + # use_final_fields: True to use final fields. When false, all other + # variables must not be set. + template("write_native_libraries_java") { + _native_libraries_file = "$target_gen_dir/$target_name.srcjar" + if (target_cpu == "arm" || target_cpu == "arm64") { + _cpu_family = "CPU_FAMILY_ARM" + } else if (target_cpu == "x86" || target_cpu == "x64") { + _cpu_family = "CPU_FAMILY_X86" + } else if (target_cpu == "mipsel" || target_cpu == "mips64el") { + _cpu_family = "CPU_FAMILY_MIPS" + } else { + assert(false, "Unsupported CPU family") + } + + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + script = "//build/android/gyp/write_native_libraries_java.py" + outputs = [ _native_libraries_file ] + args = [ + "--output", + rebase_path(_native_libraries_file, root_build_dir), + "--cpu-family", + _cpu_family, + ] + if (invoker.use_final_fields) { + # Write native_libraries_list_file via depfile rather than specifyin it + # as a dep in order allow R8 to run in parallel with native compilation. + depfile = "$target_gen_dir/$target_name.d" + args += [ + "--final", + "--depfile", + rebase_path(depfile, root_build_dir), + "--native-libraries-list", + rebase_path(invoker.native_libraries_list_file, root_build_dir), + ] + if (defined(invoker.main_component_library)) { + args += [ + "--main-component-library", + invoker.main_component_library, + ] + } + if (defined(invoker.enable_chromium_linker) && + invoker.enable_chromium_linker) { + args += [ "--enable-chromium-linker" ] + } + if (defined(invoker.load_library_from_apk) && + invoker.load_library_from_apk) { + args += [ "--load-library-from-apk" ] + } + if (defined(invoker.use_modern_linker) && invoker.use_modern_linker) { + args += [ "--use-modern-linker" ] + } + } + } + } + + # Declare a target for a set of Android resources generated at build + # time and stored in a single zip archive. The content of the archive + # should match the layout of a regular Android res/ folder (but the + # archive should not include a top-level res/ directory). + # + # Note that there is no associated .srcjar, R.txt or package name + # associated with this target. + # + # Variables: + # generated_resources_zip: Generated zip archive path. + # generating_target: Name of the target generating + # generated_resources_zip. This rule will check that it is part + # of its outputs. + # deps: Specifies the dependencies of this target. Any Android resources + # listed here will be also be included *after* this one when compiling + # all resources for a final apk or junit binary. This is useful to + # ensure that the resources of the current target override those of the + # dependency as well (and would not work if you have these deps to the + # generating target's dependencies). + # + # Example + # _zip_archive = "$target_gen_dir/${target_name}.resources_zip" + # + # action("my_resources__create_zip") { + # _depfile = "$target_gen_dir/${target_name}.d" + # script = "//build/path/to/create_my_resources_zip.py" + # args = [ + # "--depfile", rebase_path(_depfile, root_build_dir), + # "--output-zip", rebase_path(_zip_archive, root_build_dir), + # ] + # inputs = [] + # outputs = _zip_archive + # depfile = _depfile + # } + # + # android_generated_resources("my_resources") { + # generated_resources_zip = _zip_archive + # generating_target = ":my_resources__create_zip" + # } + # + template("android_generated_resources") { + forward_variables_from(invoker, [ "testonly" ]) + _build_config = "$target_gen_dir/${target_name}.build_config.json" + _rtxt_out_path = "$target_gen_dir/${target_name}.R.txt" + write_build_config("$target_name$build_config_target_suffix") { + forward_variables_from(invoker, [ "resource_overlay" ]) + + build_config = _build_config + resources_zip = invoker.generated_resources_zip + type = "android_resources" + if (defined(invoker.deps)) { + possible_config_deps = invoker.deps + } + r_text = _rtxt_out_path + } + action_with_pydeps(target_name) { + forward_variables_from(invoker, [ "visibility" ]) + public_deps = [ + ":$target_name$build_config_target_suffix", + invoker.generating_target, + ] + inputs = [ invoker.generated_resources_zip ] + outputs = [ _rtxt_out_path ] + script = "//build/android/gyp/create_r_txt.py" + args = [ + "--resources-zip-path", + rebase_path(invoker.generated_resources_zip, root_build_dir), + "--rtxt-path", + rebase_path(_rtxt_out_path, root_build_dir), + ] + } + } + + # Declare a target for processing Android resources as Jinja templates. + # + # This takes an Android resource directory where each resource is a Jinja + # template, processes each template, then packages the results in a zip file + # which can be consumed by an android resources, library, or apk target. + # + # If this target is included in the deps of an android resources/library/apk, + # the resources will be included with that target. + # + # Variables + # resources: The list of resources files to process. + # res_dir: The resource directory containing the resources. + # variables: (Optional) A list of variables to make available to the template + # processing environment, e.g. ["name=foo", "color=red"]. + # + # Example + # jinja_template_resources("chrome_public_template_resources") { + # res_dir = "res_template" + # resources = ["res_template/xml/syncable.xml"] + # variables = ["color=red"] + # } + template("jinja_template_resources") { + _resources_zip = "$target_out_dir/${target_name}.resources.zip" + _generating_target_name = "${target_name}__template" + + action_with_pydeps(_generating_target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + inputs = invoker.resources + script = "//build/android/gyp/jinja_template.py" + + outputs = [ _resources_zip ] + + _rebased_resources = rebase_path(invoker.resources, root_build_dir) + args = [ + "--inputs=${_rebased_resources}", + "--inputs-base-dir", + rebase_path(invoker.res_dir, root_build_dir), + "--outputs-zip", + rebase_path(_resources_zip, root_build_dir), + "--check-includes", + ] + if (defined(invoker.variables)) { + variables = invoker.variables + args += [ "--variables=${variables}" ] + } + } + + android_generated_resources(target_name) { + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "deps", + "resource_overlay", + ]) + generating_target = ":$_generating_target_name" + generated_resources_zip = _resources_zip + } + } + + # Declare a prebuilt android native library. + # + # This takes a base directory and library name and then looks for the library + # in <base dir>/$android_app_abi/<library name>. + # + # If you depend on this target, the library is stripped and output to the + # same locations non-prebuilt libraries are output. + # + # Variables + # base_dir: Directory where all ABIs of the library live. + # library_name: Name of the library .so file. + # + # Example + # android_native_prebuilt("elements_native") { + # base_dir = "//third_party/elements" + # lib_name = "elements.so" + # } + template("android_native_prebuilt") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) + script = "//build/android/gyp/process_native_prebuilt.py" + _lib_path = "${invoker.base_dir}/$android_app_abi/${invoker.lib_name}" + _stripped_output_path = "$root_out_dir/${invoker.lib_name}" + _unstripped_output_path = + "$root_out_dir/lib.unstripped/${invoker.lib_name}" + inputs = [ _lib_path ] + outputs = [ + _stripped_output_path, + _unstripped_output_path, + ] + + # Add unstripped output to runtime deps for use by bots during stacktrace + # symbolization. + data = [ _unstripped_output_path ] + + _rebased_lib_path = rebase_path(_lib_path, root_build_dir) + _rebased_stripped_ouput_path = + rebase_path(_stripped_output_path, root_build_dir) + _rebased_unstripped_ouput_path = + rebase_path(_unstripped_output_path, root_build_dir) + _strip_tool_path = + rebase_path("//buildtools/third_party/eu-strip/bin/eu-strip", + root_build_dir) + + args = [ + "--strip-path=$_strip_tool_path", + "--input-path=$_rebased_lib_path", + "--stripped-output-path=$_rebased_stripped_ouput_path", + "--unstripped-output-path=$_rebased_unstripped_ouput_path", + ] + } + } + + # Declare an Android resources target + # + # This creates a resources zip file that will be used when building an Android + # library or apk and included into a final apk. + # + # To include these resources in a library/apk, this target should be listed in + # the library's deps. A library/apk will also include any resources used by its + # own dependencies. + # + # Variables + # sources: List of resource files for this target. + # deps: Specifies the dependencies of this target. Any Android resources + # listed in deps will be included by libraries/apks that depend on this + # target. + # alternative_android_sdk_dep: Optional. Alternative Android system + # android java target to use. + # android_manifest: AndroidManifest.xml for this target (optional). Will be + # merged into apks that directly or indirectly depend on this target. + # android_manifest_dep: Target that generates AndroidManifest (if applicable) + # custom_package: java package for generated .java files. + # allow_missing_resources: Do not fail if a resource exists in a directory + # but is not listed in sources. + # shared_resources: If true make a resource package that can be loaded by a + # different application at runtime to access the package's resources. + # resource_overlay: Whether the resources in 'sources' should override + # resources with the same name. Does not affect the behaviour of any + # android_resources() deps of this target. If a target with + # resource_overlay=true depends on another target with + # resource_overlay=true the target with the dependency overrides the + # other. + # r_text_file: (optional) path to pre-generated R.txt to be used when + # generating R.java instead of resource-based aapt-generated one. + # recursive_resource_deps: (optional) whether deps should be walked + # recursively to find resource deps. + # + # Example: + # android_resources("foo_resources") { + # deps = [":foo_strings_grd"] + # sources = [ + # "res/drawable/foo1.xml", + # "res/drawable/foo2.xml", + # ] + # custom_package = "org.chromium.foo" + # } + # + # android_resources("foo_resources_overrides") { + # deps = [":foo_resources"] + # sources = [ + # "res_overrides/drawable/foo1.xml", + # "res_overrides/drawable/foo2.xml", + # ] + # } + template("android_resources") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _base_path = "$target_gen_dir/$target_name" + if (defined(invoker.v14_skip)) { + not_needed(invoker, [ "v14_skip" ]) + } + + _res_sources_path = "$target_gen_dir/${invoker.target_name}.res.sources" + + _resources_zip = "$target_out_dir/$target_name.resources.zip" + _r_text_out_path = _base_path + "_R.txt" + _build_config = _base_path + ".build_config.json" + _build_config_target_name = "$target_name$build_config_target_suffix" + + _deps = [] + if (defined(invoker.deps)) { + _deps += invoker.deps + } + + if (defined(invoker.alternative_android_sdk_dep)) { + _deps += [ invoker.alternative_android_sdk_dep ] + } else { + _deps += [ "//third_party/android_sdk:android_sdk_java" ] + } + + _resource_files = [] + if (defined(invoker.sources)) { + _resource_files += invoker.sources + } + + _rebased_resource_files = rebase_path(_resource_files, root_build_dir) + write_file(_res_sources_path, _rebased_resource_files) + + # This is necessary so we only lint chromium resources. + if (defined(invoker.chromium_code)) { + _chromium_code = invoker.chromium_code + } else { + # Default based on whether target is in third_party. + _chromium_code = + filter_exclude([ get_label_info(":$target_name", "dir") ], + [ "*\bthird_party\b*" ]) != [] + } + + write_build_config(_build_config_target_name) { + type = "android_resources" + build_config = _build_config + resources_zip = _resources_zip + res_sources_path = _res_sources_path + chromium_code = _chromium_code + + forward_variables_from(invoker, + [ + "android_manifest", + "android_manifest_dep", + "custom_package", + "mergeable_android_manifests", + "resource_overlay", + "recursive_resource_deps", + ]) + + r_text = _r_text_out_path + possible_config_deps = _deps + + # Always merge manifests from resources. + # * Might want to change this at some point for consistency and clarity, + # but keeping for backwards-compatibility. + if (!defined(mergeable_android_manifests) && defined(android_manifest)) { + mergeable_android_manifests = [ android_manifest ] + } + } + + prepare_resources(target_name) { + forward_variables_from(invoker, + [ + "strip_drawables", + "allow_missing_resources", + "visibility", + ]) + deps = _deps + + res_sources_path = _res_sources_path + sources = _resource_files + + resources_zip = _resources_zip + r_text_out_path = _r_text_out_path + + if (defined(invoker.r_text_file)) { + r_text_in_path = invoker.r_text_file + } + } + } + + # Declare an Android assets target. + # + # Defines a set of files to include as assets in a dependent apk. + # + # To include these assets in an apk, this target should be listed in + # the apk's deps, or in the deps of a library target used by an apk. + # + # Variables + # deps: Specifies the dependencies of this target. Any Android assets + # listed in deps will be included by libraries/apks that depend on this + # target. + # sources: List of files to include as assets. + # renaming_sources: List of files to include as assets and be renamed. + # renaming_destinations: List of asset paths for files in renaming_sources. + # disable_compression: Whether to disable compression for files that are + # known to be compressable (default: false). + # treat_as_locale_paks: Causes base's BuildConfig.java to consider these + # assets to be locale paks. + # + # Example: + # android_assets("content_shell_assets") { + # deps = [ + # ":generates_foo", + # ":other_assets", + # ] + # sources = [ + # "//path/asset1.png", + # "//path/asset2.png", + # "$target_gen_dir/foo.dat", + # ] + # } + # + # android_assets("overriding_content_shell_assets") { + # deps = [ ":content_shell_assets" ] + # # Override foo.dat from content_shell_assets. + # sources = [ "//custom/foo.dat" ] + # renaming_sources = [ "//path/asset2.png" ] + # renaming_destinations = [ "renamed/asset2.png" ] + # } + template("android_assets") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _build_config = "$target_gen_dir/$target_name.build_config.json" + _build_config_target_name = "$target_name$build_config_target_suffix" + + write_build_config(_build_config_target_name) { + type = "android_assets" + build_config = _build_config + + forward_variables_from(invoker, + [ + "disable_compression", + "treat_as_locale_paks", + ]) + + if (defined(invoker.deps)) { + possible_config_deps = invoker.deps + } + + if (defined(invoker.sources)) { + asset_sources = invoker.sources + } + if (defined(invoker.renaming_sources)) { + assert(defined(invoker.renaming_destinations)) + _source_count = 0 + foreach(_, invoker.renaming_sources) { + _source_count += 1 + } + _dest_count = 0 + foreach(_, invoker.renaming_destinations) { + _dest_count += 1 + } + assert( + _source_count == _dest_count, + "android_assets() renaming_sources.length != renaming_destinations.length") + asset_renaming_sources = invoker.renaming_sources + asset_renaming_destinations = invoker.renaming_destinations + } + } + + group(target_name) { + forward_variables_from(invoker, [ "deps" ]) + public_deps = [ ":$_build_config_target_name" ] + } + } + + # Declare a group() that supports forwarding java dependency information. + # + # Example + # java_group("conditional_deps") { + # if (enable_foo) { + # deps = [":foo_java"] + # } + # } + template("java_group") { + _build_config_vars = [ + "input_jars_paths", + "mergeable_android_manifests", + "proguard_configs", + ] + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + write_build_config("$target_name$build_config_target_suffix") { + forward_variables_from(invoker, _build_config_vars) + type = "group" + build_config = "$target_gen_dir/${invoker.target_name}.build_config.json" + supports_android = true + if (defined(invoker.deps)) { + possible_config_deps = invoker.deps + } + } + foreach(_group_name, + [ + "header", + "impl", + "assetres", + ]) { + java_lib_group("${target_name}__${_group_name}") { + forward_variables_from(invoker, [ "deps" ]) + group_name = _group_name + } + } + group(target_name) { + forward_variables_from(invoker, + "*", + _build_config_vars + TESTONLY_AND_VISIBILITY) + if (!defined(deps)) { + deps = [] + } + deps += [ ":$target_name$build_config_target_suffix" ] + } + } + + # Declare a Java executable target + # + # Same as java_library, but also creates a wrapper script within + # $root_out_dir/bin. + # + # Supports all variables of java_library(), plus: + # main_class: When specified, a wrapper script is created within + # $root_build_dir/bin to launch the binary with the given class as the + # entrypoint. + # wrapper_script_name: Filename for the wrapper script (default=target_name) + # wrapper_script_args: List of additional arguments for the wrapper script. + # + # Example + # java_binary("foo") { + # sources = [ "org/chromium/foo/FooMain.java" ] + # deps = [ ":bar_java" ] + # main_class = "org.chromium.foo.FooMain" + # } + # + # java_binary("foo") { + # jar_path = "lib/prebuilt.jar" + # deps = [ ":bar_java" ] + # main_class = "org.chromium.foo.FooMain" + # } + template("java_binary") { + java_library_impl(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + type = "java_binary" + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += [ "//third_party/jdk:java_data" ] + } + } + + # Declare a Java Annotation Processor. + # + # Supports all variables of java_library(), plus: + # jar_path: Path to a prebuilt jar. Mutually exclusive with sources & + # srcjar_deps. + # main_class: The fully-quallified class name of the processor's entry + # point. + # + # Example + # java_annotation_processor("foo_processor") { + # sources = [ "org/chromium/foo/FooProcessor.java" ] + # deps = [ ":bar_java" ] + # main_class = "org.chromium.foo.FooProcessor" + # } + # + # java_annotation_processor("foo_processor") { + # jar_path = "lib/prebuilt.jar" + # main_class = "org.chromium.foo.FooMain" + # } + # + # java_library("...") { + # annotation_processor_deps = [":foo_processor"] + # } + # + template("java_annotation_processor") { + java_library_impl(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + type = "java_annotation_processor" + } + } + + # Declare a Junit executable target + # + # This target creates an executable from java code for running as a junit test + # suite. The executable will be in the output folder's /bin/ directory. + # + # Supports all variables of java_binary(). + # + # Example + # junit_binary("foo") { + # sources = [ "org/chromium/foo/FooTest.java" ] + # deps = [ ":bar_java" ] + # } + template("junit_binary") { + testonly = true + + _java_binary_target_name = "${target_name}__java_binary" + _test_runner_target_name = "${target_name}__test_runner_script" + _main_class = "org.chromium.testing.local.JunitTestMain" + + _build_config = "$target_gen_dir/$target_name.build_config.json" + _build_config_target_name = "$target_name$build_config_target_suffix" + _deps = [ + "//testing/android/junit:junit_test_support", + "//third_party/android_deps:robolectric_all_java", + "//third_party/junit", + "//third_party/mockito:mockito_java", + ] + if (defined(invoker.deps)) { + _deps += invoker.deps + } + if (defined(invoker.alternative_android_sdk_dep)) { + _android_sdk_dep = invoker.alternative_android_sdk_dep + } else { + _android_sdk_dep = "//third_party/android_sdk:android_sdk_java" + } + + # a package name or a manifest is required to have resources. This is + # added so that junit tests that do not care about the package name can + # still use resources without having to explicitly set one. + if (defined(invoker.package_name)) { + _package_name = invoker.package_name + } else if (!defined(invoker.android_manifest)) { + _package_name = "org.chromium.test" + } + + _resource_arsc_output = "${target_gen_dir}/${target_name}.ap_" + _compile_resources_target = "${target_name}__compile_resources" + compile_resources(_compile_resources_target) { + forward_variables_from(invoker, [ "android_manifest" ]) + deps = _deps + android_sdk_dep = _android_sdk_dep + build_config_dep = ":$_build_config_target_name" + build_config = _build_config + if (defined(_package_name)) { + rename_manifest_package = _package_name + } + if (!defined(android_manifest)) { + android_manifest = "//build/android/AndroidManifest.xml" + } + arsc_output = _resource_arsc_output + min_sdk_version = default_min_sdk_version + target_sdk_version = android_sdk_version + } + + _jni_srcjar_target = "${target_name}__final_jni" + _outer_target_name = target_name + generate_jni_registration(_jni_srcjar_target) { + enable_native_mocks = true + require_native_mocks = true + targets = [ ":$_outer_target_name" ] + } + + java_library_impl(_java_binary_target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY + [ "deps" ]) + type = "junit_binary" + main_target_name = invoker.target_name + + # Include the android SDK jar(s) for resource processing. + include_android_sdk = true + + # Robolectric can handle deps that set !supports_android as well those + # that set requires_android. + bypass_platform_checks = true + deps = _deps + testonly = true + main_class = _main_class + wrapper_script_name = "helper/$main_target_name" + + # As of April 2021, adding -XX:TieredStopAtLevel=1 does not affect the + # wall time of a single robolectric shard, but does reduce the CPU time by + # 66%, which makes sharding more effective. + tiered_stop_at_level_one = true + + if (!defined(srcjar_deps)) { + srcjar_deps = [] + } + srcjar_deps += [ + ":$_compile_resources_target", + ":$_jni_srcjar_target", + + # This dep is required for any targets that depend on //base:base_java. + "//build/android:build_config_gen", + ] + } + + test_runner_script(_test_runner_target_name) { + test_name = invoker.target_name + test_suite = invoker.target_name + test_type = "junit" + ignore_all_data_deps = true + resource_apk = _resource_arsc_output + } + + group(target_name) { + forward_variables_from(invoker, + [ + "assert_no_deps", + "visibility", + ]) + public_deps = [ + ":$_build_config_target_name", + ":$_java_binary_target_name", + ":$_test_runner_target_name", + ] + } + } + + # Declare a java library target + # + # Variables + # deps: Specifies the dependencies of this target. Java targets in this list + # will be added to the javac classpath. + # public_deps: Dependencies that this target exposes as part of its public API. + # public_deps do not need to be listed in both the 'deps' and 'public_deps' lists. + # annotation_processor_deps: List of java_annotation_processor targets to + # use when compiling. + # + # jar_path: Path to a prebuilt jar. Mutually exclusive with sources & + # srcjar_deps. + # sources: List of .java files included in this library. + # srcjar_deps: List of srcjar dependencies. The .java files in the srcjars + # will be added to sources and be included in this library. + # + # input_jars_paths: A list of paths to the jars that should be included + # in the compile-time classpath. These are in addition to library .jars + # that appear in deps. + # + # chromium_code: If true, extra analysis warning/errors will be enabled. + # enable_errorprone: If true, enables the errorprone compiler. + # skip_build_server: If true, avoids sending tasks to the build server. + # + # jar_excluded_patterns: List of patterns of .class files to exclude. + # jar_included_patterns: List of patterns of .class files to include. + # When omitted, all classes not matched by jar_excluded_patterns are + # included. When specified, all non-matching .class files are stripped. + # + # low_classpath_priority: Indicates that the library should be placed at the + # end of the classpath. The default classpath order has libraries ordered + # before the libraries that they depend on. 'low_classpath_priority' is + # useful when one java_library() overrides another via + # 'jar_excluded_patterns' and the overriding library does not depend on + # the overridee. + # + # output_name: File name for the output .jar (not including extension). + # Defaults to the input .jar file name. + # + # proguard_configs: List of proguard configs to use in final apk step for + # any apk that depends on this library. + # + # supports_android: If true, Android targets (android_library, android_apk) + # may depend on this target. Note: if true, this target must only use the + # subset of Java available on Android. + # bypass_platform_checks: Disables checks about cross-platform (Java/Android) + # dependencies for this target. This will allow depending on an + # android_library target, for example. + # enable_desugar: If false, disables desugaring of lambdas, etc. Use this + # only when you are sure the library does not require desugaring. E.g. + # to hide warnings shown from desugaring. + # + # additional_jar_files: Use to package additional files (Java resources) + # into the output jar. Pass a list of length-2 lists with format: + # [ [ path_to_file, path_to_put_in_jar ] ] + # + # javac_args: Additional arguments to pass to javac. + # errorprone_args: Additional arguments to pass to errorprone. + # + # data_deps, testonly + # + # Example + # java_library("foo_java") { + # sources = [ + # "org/chromium/foo/Foo.java", + # "org/chromium/foo/FooInterface.java", + # "org/chromium/foo/FooService.java", + # ] + # deps = [ + # ":bar_java" + # ] + # srcjar_deps = [ + # ":foo_generated_enum" + # ] + # jar_excluded_patterns = [ + # "*/FooService.class", "org/chromium/FooService\$*.class" + # ] + # } + template("java_library") { + java_library_impl(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + type = "java_library" + } + } + + # Declare a java library target for a prebuilt jar + # + # Supports all variables of java_library(). + # + # Example + # java_prebuilt("foo_java") { + # jar_path = "foo.jar" + # deps = [ + # ":foo_resources", + # ":bar_java" + # ] + # } + template("java_prebuilt") { + java_library_impl(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + type = "java_library" + } + } + + # Combines all dependent .jar files into a single .jar file. + # + # Variables: + # output: Path to the output jar. + # override_build_config: Use a pre-existing .build_config. Must be of type + # "apk". + # use_interface_jars: Use all dependent interface .jars rather than + # implementation .jars. + # use_unprocessed_jars: Use unprocessed / undesugared .jars. + # direct_deps_only: Do not recurse on deps. + # jar_excluded_patterns (optional) + # List of globs for paths to exclude. + # + # Example + # dist_jar("lib_fatjar") { + # deps = [ ":my_java_lib" ] + # output = "$root_build_dir/MyLibrary.jar" + # } + template("dist_jar") { + # TODO(crbug.com/1042017): Remove. + not_needed(invoker, [ "no_build_hooks" ]) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + _supports_android = + !defined(invoker.supports_android) || invoker.supports_android + _use_interface_jars = + defined(invoker.use_interface_jars) && invoker.use_interface_jars + _use_unprocessed_jars = + defined(invoker.use_unprocessed_jars) && invoker.use_unprocessed_jars + _direct_deps_only = + defined(invoker.direct_deps_only) && invoker.direct_deps_only + assert(!(_use_unprocessed_jars && _use_interface_jars), + "Cannot set both use_interface_jars and use_unprocessed_jars") + + _jar_target_name = target_name + + _deps = [] + if (defined(invoker.deps)) { + _deps = invoker.deps + } + if (_supports_android) { + _deps += [ "//third_party/android_sdk:android_sdk_java" ] + } + + if (defined(invoker.override_build_config)) { + _build_config = invoker.override_build_config + } else { + _build_config = "$target_gen_dir/$target_name.build_config.json" + _build_config_target_name = "$target_name$build_config_target_suffix" + + write_build_config(_build_config_target_name) { + type = "dist_jar" + supports_android = _supports_android + requires_android = + defined(invoker.requires_android) && invoker.requires_android + possible_config_deps = _deps + ignore_dependency_public_deps = _direct_deps_only + build_config = _build_config + } + + _deps += [ ":$_build_config_target_name" ] + } + + _rebased_build_config = rebase_path(_build_config, root_build_dir) + action_with_pydeps(_jar_target_name) { + forward_variables_from(invoker, [ "data" ]) + script = "//build/android/gyp/zip.py" + depfile = "$target_gen_dir/$target_name.d" + deps = _deps + + inputs = [ _build_config ] + + outputs = [ invoker.output ] + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--output", + rebase_path(invoker.output, root_build_dir), + "--no-compress", + ] + + if (_direct_deps_only) { + if (_use_interface_jars) { + args += [ "--input-zips=@FileArg($_rebased_build_config:javac:interface_classpath)" ] + } else if (_use_unprocessed_jars) { + args += [ + "--input-zips=@FileArg($_rebased_build_config:javac:classpath)", + ] + } else { + assert( + false, + "direct_deps_only does not work without use_interface_jars or use_unprocessed_jars") + } + } else { + if (_use_interface_jars) { + args += [ "--input-zips=@FileArg($_rebased_build_config:dist_jar:all_interface_jars)" ] + } else if (_use_unprocessed_jars) { + args += [ "--input-zips=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)" ] + } else { + args += [ "--input-zips=@FileArg($_rebased_build_config:deps_info:device_classpath)" ] + } + } + _excludes = [] + if (defined(invoker.jar_excluded_patterns)) { + _excludes += invoker.jar_excluded_patterns + } + if (_use_interface_jars) { + # Turbine adds files like: META-INF/TRANSITIVE/.../Foo.class + # These confuse proguard: https://crbug.com/1081443 + _excludes += [ "META-INF/*" ] + } + if (_excludes != []) { + args += [ "--input-zips-excluded-globs=$_excludes" ] + } + } + } + + # Combines all dependent .jar files into a single proguarded .dex file. + # + # Variables: + # output: Path to the output dex. + # proguard_enabled: Whether to enable R8. + # proguard_configs: List of proguard configs. + # proguard_enable_obfuscation: Whether to enable obfuscation (default=true). + # + # Example + # dist_dex("lib_fatjar") { + # deps = [ ":my_java_lib" ] + # output = "$root_build_dir/MyLibrary.jar" + # } + template("dist_dex") { + _deps = [ "//third_party/android_sdk:android_sdk_java" ] + if (defined(invoker.deps)) { + _deps += invoker.deps + } + + _build_config = "$target_gen_dir/$target_name.build_config.json" + _build_config_target_name = "$target_name$build_config_target_suffix" + + write_build_config(_build_config_target_name) { + type = "dist_jar" + forward_variables_from(invoker, + [ + "proguard_configs", + "proguard_enabled", + ]) + supports_android = true + requires_android = true + possible_config_deps = _deps + build_config = _build_config + } + + _deps += [ ":$_build_config_target_name" ] + + dex(target_name) { + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "data", + "data_deps", + "proguard_configs", + "proguard_enabled", + "proguard_enable_obfuscation", + "min_sdk_version", + ]) + deps = _deps + build_config = _build_config + enable_multidex = false + output = invoker.output + if (defined(proguard_enabled) && proguard_enabled) { + # The individual dependencies would have caught real missing deps in + # their respective dex steps. False positives that were suppressed at + # per-target dex steps are emitted here since this is using jar files + # rather than dex files. + ignore_desugar_missing_deps = true + + # When trying to build a stand-alone .dex, don't add in jdk_libs_dex. + supports_jdk_library_desugaring = false + } else { + _rebased_build_config = rebase_path(_build_config, root_build_dir) + input_dex_filearg = + "@FileArg(${_rebased_build_config}:final_dex:all_dex_files)" + } + } + } + + # Creates an Android .aar library. + # + # Currently supports: + # * AndroidManifest.xml + # * classes.jar + # * jni/ + # * res/ + # * R.txt + # * proguard.txt + # Does not yet support: + # * public.txt + # * annotations.zip + # * assets/ + # See: https://developer.android.com/studio/projects/android-library.html#aar-contents + # + # Variables: + # output: Path to the output .aar. + # proguard_configs: List of proguard configs (optional). + # android_manifest: Path to AndroidManifest.xml (optional). + # native_libraries: list of native libraries (optional). + # direct_deps_only: Do not recurse on deps. (optional, defaults false). + # jar_excluded_patterns (optional): List of globs for paths to exclude. + # jar_included_patterns (optional): List of globs for paths to include. + # + # Example + # dist_aar("my_aar") { + # deps = [ ":my_java_lib" ] + # output = "$root_build_dir/MyLibrary.aar" + # } + template("dist_aar") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _deps = [] + if (defined(invoker.deps)) { + _deps = invoker.deps + } + + _direct_deps_only = + defined(invoker.direct_deps_only) && invoker.direct_deps_only + + _build_config = "$target_gen_dir/$target_name.build_config.json" + _build_config_target_name = "$target_name$build_config_target_suffix" + + write_build_config(_build_config_target_name) { + type = "dist_aar" + forward_variables_from(invoker, [ "proguard_configs" ]) + possible_config_deps = _deps + supports_android = true + requires_android = true + ignore_dependency_public_deps = _direct_deps_only + build_config = _build_config + } + + _deps += [ ":$_build_config_target_name" ] + + _rebased_build_config = rebase_path(_build_config, root_build_dir) + + action_with_pydeps(target_name) { + forward_variables_from(invoker, [ "data" ]) + depfile = "$target_gen_dir/$target_name.d" + deps = _deps + script = "//build/android/gyp/dist_aar.py" + + inputs = [ _build_config ] + + # Although these will be listed as deps in the depfile, they must also + # appear here so that "gn analyze" knows about them. + # https://crbug.com/827197 + if (defined(invoker.proguard_configs)) { + inputs += invoker.proguard_configs + } + + outputs = [ invoker.output ] + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--output", + rebase_path(invoker.output, root_build_dir), + "--dependencies-res-zips=@FileArg($_rebased_build_config:deps_info:dependency_zips)", + "--r-text-files=@FileArg($_rebased_build_config:deps_info:dependency_r_txt_files)", + "--proguard-configs=@FileArg($_rebased_build_config:deps_info:proguard_all_configs)", + ] + if (_direct_deps_only) { + args += [ "--jars=@FileArg($_rebased_build_config:javac:classpath)" ] + } else { + args += [ "--jars=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)" ] + } + if (defined(invoker.android_manifest)) { + args += [ + "--android-manifest", + rebase_path(invoker.android_manifest, root_build_dir), + ] + } + if (defined(invoker.native_libraries) && invoker.native_libraries != []) { + inputs += invoker.native_libraries + _rebased_native_libraries = + rebase_path(invoker.native_libraries, root_build_dir) + + args += [ + "--native-libraries=$_rebased_native_libraries", + "--abi=$android_app_abi", + ] + } + if (defined(invoker.jar_excluded_patterns)) { + args += [ "--jar-excluded-globs=${invoker.jar_excluded_patterns}" ] + } + if (defined(invoker.jar_included_patterns)) { + args += [ "--jar-included-globs=${invoker.jar_included_patterns}" ] + } + if (defined(invoker.resource_included_patterns)) { + args += [ + "--resource-included-globs=${invoker.resource_included_patterns}", + ] + } + } + } + + # Declare an Android library target + # + # This target creates an Android library containing java code and Android + # resources. + # + # Supports all variables of java_library(), plus: + # deps: In addition to defining java deps, this can also include + # android_assets() and android_resources() targets. + # alternative_android_sdk_ijar: if set, the given android_sdk_ijar file + # replaces the default android_sdk_ijar. + # alternative_android_sdk_ijar_dep: the target that generates + # alternative_android_sdk_ijar, must be set if alternative_android_sdk_ijar + # is used. + # alternative_android_sdk_jar: actual jar corresponding to + # alternative_android_sdk_ijar, must be set if alternative_android_sdk_ijar + # is used. + # + # Example + # android_library("foo_java") { + # sources = [ + # "android/org/chromium/foo/Foo.java", + # "android/org/chromium/foo/FooInterface.java", + # "android/org/chromium/foo/FooService.java", + # ] + # deps = [ + # ":bar_java" + # ] + # srcjar_deps = [ + # ":foo_generated_enum" + # ] + # jar_excluded_patterns = [ + # "*/FooService.class", "org/chromium/FooService\$*.class" + # ] + # } + template("android_library") { + java_library(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + supports_android = true + requires_android = true + + if (!defined(jar_excluded_patterns)) { + jar_excluded_patterns = [] + } + jar_excluded_patterns += [ + "*/R.class", + "*/R\$*.class", + "*/Manifest.class", + "*/Manifest\$*.class", + "*/GEN_JNI.class", + ] + } + } + + # Declare an Android library target for a prebuilt jar + # + # This target creates an Android library containing java code and Android + # resources. + # + # Supports all variables of android_library(). + # + # Example + # android_java_prebuilt("foo_java") { + # jar_path = "foo.jar" + # deps = [ + # ":foo_resources", + # ":bar_java" + # ] + # } + template("android_java_prebuilt") { + android_library(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + } + } + + template("android_system_java_prebuilt") { + java_library_impl(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + supports_android = true + type = "system_java_library" + } + } + + # Creates org/chromium/build/BuildConfig.java + # This doesn't really belong in //build since it genates a file for //base. + # However, we don't currently have a better way to include this file in all + # apks that depend on //base:base_java. + # + # Variables: + # use_final_fields: True to use final fields. When false, all other + # variables must not be set. + # enable_multidex: Value for ENABLE_MULTIDEX. + # min_sdk_version: Value for MIN_SDK_VERSION. + # bundles_supported: Whether or not this target can be treated as a bundle. + # resources_version_variable: + # is_incremental_install: + # isolated_splits_enabled: Value for ISOLATED_SPLITS_ENABLED. + template("generate_build_config_srcjar") { + java_cpp_template(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + sources = [ "//build/android/java/templates/BuildConfig.template" ] + defines = [] + + # Set these even when !use_final_fields so that they have correct default + # values within junit_binary(), which ignores jar_excluded_patterns. + if (enable_java_asserts) { + defines += [ "_ENABLE_ASSERTS" ] + } + if (use_cfi_diag || is_ubsan || is_ubsan_security || is_ubsan_vptr) { + defines += [ "_IS_UBSAN" ] + } + + if (is_chrome_branded) { + defines += [ "_IS_CHROME_BRANDED" ] + } + + if (is_chromecast && chromecast_branding == "internal") { + defines += [ "_IS_CHROMECAST_BRANDING_INTERNAL" ] + } + + if (defined(invoker.bundles_supported) && invoker.bundles_supported) { + defines += [ "_BUNDLES_SUPPORTED" ] + } + + if (defined(invoker.isolated_splits_enabled) && + invoker.isolated_splits_enabled) { + defines += [ "_ISOLATED_SPLITS_ENABLED" ] + } + + if (defined(invoker.is_incremental_install) && + invoker.is_incremental_install) { + defines += [ "_IS_INCREMENTAL_INSTALL" ] + } + + if (invoker.use_final_fields) { + forward_variables_from(invoker, [ "deps" ]) + defines += [ "USE_FINAL" ] + if (invoker.enable_multidex) { + defines += [ "ENABLE_MULTIDEX" ] + } + if (defined(invoker.min_sdk_version)) { + defines += [ "_MIN_SDK_VERSION=${invoker.min_sdk_version}" ] + } + if (defined(invoker.resources_version_variable)) { + defines += [ + "_RESOURCES_VERSION_VARIABLE=${invoker.resources_version_variable}", + ] + } + } + } + } + + # Creates ProductConfig.java, a file containing product-specific configuration. + # + # Currently, this includes the list of locales, both in their compressed and + # uncompressed format, as well as library loading + # + # Variables: + # build_config: Path to build_config used for locale lists. + # is_bundle_module: Whether or not this target is part of a bundle build. + # java_package: Java package for the generated class. + # use_chromium_linker: + # use_modern_linker: + template("generate_product_config_srcjar") { + java_cpp_template(target_name) { + defines = [] + _use_final = + defined(invoker.build_config) || + defined(invoker.use_chromium_linker) || + defined(invoker.use_modern_linker) || defined(invoker.is_bundle) + if (_use_final) { + defines += [ "USE_FINAL" ] + } + + sources = [ "//build/android/java/templates/ProductConfig.template" ] + defines += [ "PACKAGE=${invoker.java_package}" ] + + _use_chromium_linker = + defined(invoker.use_chromium_linker) && invoker.use_chromium_linker + _use_modern_linker = + defined(invoker.use_modern_linker) && invoker.use_modern_linker + _is_bundle = defined(invoker.is_bundle_module) && invoker.is_bundle_module + defines += [ + "USE_CHROMIUM_LINKER_VALUE=$_use_chromium_linker", + "USE_MODERN_LINKER_VALUE=$_use_modern_linker", + "IS_BUNDLE_VALUE=$_is_bundle", + ] + if (defined(invoker.build_config)) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + _rebased_build_config = + rebase_path(invoker.build_config, root_build_dir) + defines += [ "LOCALE_LIST=@FileArg($_rebased_build_config:deps_info:locales_java_list)" ] + } + } + } + + # Declare an Android app module target, which is used as the basis for an + # Android APK or an Android app bundle module. + # + # Supports all variables of android_library(), plus: + # android_manifest: Path to AndroidManifest.xml. NOTE: This manifest must + # not contain a <uses-sdk> element. Use [min|target|max]_sdk_version + # instead. + # android_manifest_dep: Target that generates AndroidManifest (if applicable) + # png_to_webp: If true, pngs (with the exception of 9-patch) are + # converted to webp during resource packaging. + # loadable_modules: List of paths to native libraries to include. Different + # from |shared_libraries| in that: + # * dependencies of this .so are not automatically included + # * ".cr.so" is never added + # * they are not side-loaded when incremental_install=true. + # * load_library_from_apk, use_chromium_linker, + # and enable_relocation_packing do not apply + # Use this instead of shared_libraries when you are going to load the library + # conditionally, and only when shared_libraries doesn't work for you. + # secondary_abi_loadable_modules: This is the loadable_modules analog to + # secondary_abi_shared_libraries. + # shared_libraries: List shared_library targets to bundle. If these + # libraries depend on other shared_library targets, those dependencies will + # also be included in the apk (e.g. for is_component_build). + # secondary_abi_shared_libraries: secondary abi shared_library targets to + # bundle. If these libraries depend on other shared_library targets, those + # dependencies will also be included in the apk (e.g. for is_component_build). + # native_lib_placeholders: List of placeholder filenames to add to the apk + # (optional). + # secondary_native_lib_placeholders: List of placeholder filenames to add to + # the apk for the secondary ABI (optional). + # generate_buildconfig_java: If defined and false, skip generating the + # BuildConfig java class describing the build configuration. The default + # is true when building with Chromium for non-test APKs. + # generate_final_jni: If defined and false, skip generating the + # GEN_JNI srcjar. + # jni_registration_header: If specified, causes the + # ${target_name}__final_jni target to additionally output a + # header file to this path for use with manual JNI registration. + # jni_sources_exclusions: List of source path to exclude from the + # final_jni step. + # aapt_locale_allowlist: If set, all locales not in this list will be + # stripped from resources.arsc. + # resource_exclusion_regex: Causes all drawable images matching the regex to + # be excluded (mipmaps are still included). + # resource_exclusion_exceptions: A list of globs used when + # resource_exclusion_regex is set. Files that match this list will + # still be included. + # resource_values_filter_rules: List of "source_path:name_regex" used to + # filter out unwanted values/ resources. + # shared_resources: True if this is a runtime shared library APK, like + # the system_webview_apk target. Ensures that its resources can be + # used by the loading application process. + # app_as_shared_lib: True if this is a regular application apk that can + # also serve as a runtime shared library, like the monochrome_public_apk + # target. Ensures that the resources are usable both by the APK running + # as an application, or by another process that loads it at runtime. + # shared_resources_allowlist_target: Optional name of a target specifying + # an input R.txt file that lists the resources that can be exported + # by the APK when shared_resources or app_as_shared_lib is defined. + # uncompress_shared_libraries: True if shared libraries should be stored + # uncompressed in the APK. Must be unset or true if load_library_from_apk + # is set to true. + # uncompress_dex: Store final .dex files uncompressed in the apk. + # strip_resource_names: True if resource names should be stripped from the + # resources.arsc file in the apk or module. + # strip_unused_resources: True if unused resources should be stripped from + # the apk or module. + # short_resource_paths: True if resource paths should be shortened in the + # apk or module. + # resources_config_paths: List of paths to the aapt2 optimize config files + # that tags resources with acceptable/non-acceptable optimizations. + # expected_android_manifest: Enables verification of expected merged + # manifest based on a golden file. + # resource_ids_provider_dep: If passed, this target will use the resource + # IDs generated by {resource_ids_provider_dep}__compile_res during + # resource compilation. + # enforce_resource_overlays_in_tests: Enables check for testonly targets that + # dependent resource targets which override another target set + # overlay_resources=true. This check is on for non-test targets and + # cannot be disabled. + # static_library_dependent_targets: A list of scopes describing targets that + # use this target as a static library. Common Java code from the targets + # listed in static_library_dependent_targets will be moved into this + # target. Scope members are name and is_resource_ids_provider. + # static_library_provider: Specifies a single target that this target will + # use as a static library APK. + # static_library_synchronized_proguard: When proguard is enabled, the + # static_library_provider target will provide the dex file(s) for this + # target. + # min_sdk_version: The minimum Android SDK version this target supports. + # Optional, default $default_min_sdk_version. + # target_sdk_version: The target Android SDK version for this target. + # Optional, default to android_sdk_version. + # max_sdk_version: The maximum Android SDK version this target supports. + # Optional, default not set. + # require_native_mocks: Enforce that any native calls using + # org.chromium.base.annotations.NativeMethods must have a mock set + # (optional). + # enable_native_mocks: Allow native calls using + # org.chromium.base.annotations.NativeMethods to be mocked in tests + # (optional). + # product_config_java_packages: Optional list of java packages. If given, a + # ProductConfig.java file will be generated for each package. + # enable_proguard_checks: Turns on -checkdiscard directives and missing + # symbols check in the proguard step (default=true). + # disable_r8_outlining: Turn off outlining during the proguard step. + # annotation_processor_deps: List of java_annotation_processor targets to + # use when compiling the sources given to this target (optional). + # processor_args_javac: List of args to pass to annotation processors when + # compiling sources given to this target (optional). + # bundles_supported: Enable Java code to treat this target as a bundle + # whether (by default determined by the target type). + # main_component_library: Specifies the name of the base component's library + # in a component build. If given, the system will find dependent native + # libraries at runtime by inspecting this library (optional). + # expected_libs_and_assets: Verify the list of included native libraries + # and assets is consistent with the given expectation file. + # expected_libs_and_assets_base: Treat expected_libs_and_assets as a diff + # with this file as the base. + # expected_proguard_config: Checks that the merged set of proguard flags + # matches the given config. + # expected_proguard_config_base: Treat expected_proguard_config as a diff + # with this file as the base. + template("android_apk_or_module") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + assert(defined(invoker.android_manifest)) + _base_path = "$target_out_dir/$target_name/$target_name" + _build_config = "$target_gen_dir/$target_name.build_config.json" + _build_config_target = "$target_name$build_config_target_suffix" + + _min_sdk_version = default_min_sdk_version + _target_sdk_version = android_sdk_version + if (defined(invoker.min_sdk_version)) { + _min_sdk_version = invoker.min_sdk_version + } + if (defined(invoker.target_sdk_version)) { + _target_sdk_version = invoker.target_sdk_version + } + + _template_name = target_name + + _is_bundle_module = + defined(invoker.is_bundle_module) && invoker.is_bundle_module + if (_is_bundle_module) { + _is_base_module = + defined(invoker.is_base_module) && invoker.is_base_module + } + + _enable_multidex = + !defined(invoker.enable_multidex) || invoker.enable_multidex + + if (!_is_bundle_module) { + _final_apk_path = invoker.final_apk_path + _final_rtxt_path = "${_final_apk_path}.R.txt" + } + + _res_size_info_path = "$target_out_dir/$target_name.ap_.info" + if (!_is_bundle_module) { + _final_apk_path_no_ext_list = + process_file_template([ _final_apk_path ], + "{{source_dir}}/{{source_name_part}}") + _final_apk_path_no_ext = _final_apk_path_no_ext_list[0] + not_needed([ "_final_apk_path_no_ext" ]) + } + + # Non-base bundle modules create only proto resources. + if (!_is_bundle_module || _is_base_module) { + _arsc_resources_path = "$target_out_dir/$target_name.ap_" + } + if (_is_bundle_module) { + # Path to the intermediate proto-format resources zip file. + _proto_resources_path = "$target_out_dir/$target_name.proto.ap_" + } else { + # resource_sizes.py needs to be able to find the unpacked resources.arsc + # file based on apk name to compute normatlized size. + _resource_sizes_arsc_path = + "$root_out_dir/arsc/" + + rebase_path(_final_apk_path_no_ext, root_build_dir) + ".ap_" + } + + if (defined(invoker.version_code)) { + _version_code = invoker.version_code + } else { + _version_code = android_default_version_code + } + + if (android_override_version_code != "") { + _version_code = android_override_version_code + } + + if (defined(invoker.version_name)) { + _version_name = invoker.version_name + } else { + _version_name = android_default_version_name + } + + if (android_override_version_name != "") { + _version_name = android_override_version_name + } + + _deps = [] + if (defined(invoker.deps)) { + _deps = invoker.deps + } + + _srcjar_deps = [] + if (defined(invoker.srcjar_deps)) { + _srcjar_deps = invoker.srcjar_deps + } + + _android_root_manifest_deps = [] + if (defined(invoker.android_manifest_dep)) { + _android_root_manifest_deps = [ invoker.android_manifest_dep ] + } + _android_root_manifest = invoker.android_manifest + + _use_chromium_linker = + defined(invoker.use_chromium_linker) && invoker.use_chromium_linker + _use_modern_linker = + defined(invoker.use_modern_linker) && invoker.use_modern_linker + + _load_library_from_apk = + defined(invoker.load_library_from_apk) && invoker.load_library_from_apk + + not_needed([ + "_use_chromium_linker", + "_use_modern_linker", + ]) + assert(!_load_library_from_apk || _use_chromium_linker, + "load_library_from_apk requires use_chromium_linker") + + # Make sure that uncompress_shared_libraries is set to true if + # load_library_from_apk is true. + if (defined(invoker.uncompress_shared_libraries)) { + _uncompress_shared_libraries = invoker.uncompress_shared_libraries + assert(!_load_library_from_apk || _uncompress_shared_libraries) + } else { + _uncompress_shared_libraries = _load_library_from_apk + } + + # The dependency that makes the chromium linker, if any is needed. + _native_libs_deps = [] + _shared_libraries_is_valid = + defined(invoker.shared_libraries) && invoker.shared_libraries != [] + + if (_shared_libraries_is_valid) { + _native_libs_deps += invoker.shared_libraries + + # Write shared library output files of all dependencies to a file. Those + # will be the shared libraries packaged into the APK. + _shared_library_list_file = + "$target_gen_dir/${_template_name}.native_libs" + generated_file("${_template_name}__shared_library_list") { + deps = _native_libs_deps + outputs = [ _shared_library_list_file ] + data_keys = [ "shared_libraries" ] + walk_keys = [ "shared_libraries_barrier" ] + rebase = root_build_dir + } + } else { + # Must exist for instrumentation_test_apk() to depend on. + group("${_template_name}__shared_library_list") { + } + } + + _secondary_abi_native_libs_deps = [] + + if (defined(invoker.secondary_abi_shared_libraries) && + invoker.secondary_abi_shared_libraries != []) { + _secondary_abi_native_libs_deps = invoker.secondary_abi_shared_libraries + + # Write shared library output files of all dependencies to a file. Those + # will be the shared libraries packaged into the APK. + _secondary_abi_shared_library_list_file = + "$target_gen_dir/${_template_name}.secondary_abi_native_libs" + generated_file("${_template_name}__secondary_abi_shared_library_list") { + deps = _secondary_abi_native_libs_deps + outputs = [ _secondary_abi_shared_library_list_file ] + data_keys = [ "shared_libraries" ] + walk_keys = [ "shared_libraries_barrier" ] + rebase = root_build_dir + } + } else { + # Must exist for instrumentation_test_apk() to depend on. + group("${_template_name}__secondary_abi_shared_library_list") { + } + } + + _rebased_build_config = rebase_path(_build_config, root_build_dir) + assert(_rebased_build_config != "") # Mark as used. + + _generate_buildconfig_java = !defined(invoker.apk_under_test) + if (defined(invoker.generate_buildconfig_java)) { + _generate_buildconfig_java = invoker.generate_buildconfig_java + } + + _generate_productconfig_java = defined(invoker.product_config_java_packages) + + # JNI generation usually goes hand-in-hand with buildconfig generation. + _generate_final_jni = _generate_buildconfig_java + if (defined(invoker.generate_final_jni)) { + _generate_final_jni = invoker.generate_final_jni + } + + _proguard_enabled = + defined(invoker.proguard_enabled) && invoker.proguard_enabled + + if (!_is_bundle_module && _proguard_enabled) { + _proguard_mapping_path = "$_final_apk_path.mapping" + } + + # TODO(http://crbug.com/901465): Move shared Java code to static libraries + # when !_proguard_enabled too. + _is_static_library_provider = + defined(invoker.static_library_dependent_targets) && _proguard_enabled + if (_is_static_library_provider) { + _static_library_sync_dex_path = "$_base_path.synchronized.r8dex.jar" + _resource_ids_provider_deps = [] + foreach(_target, invoker.static_library_dependent_targets) { + if (_target.is_resource_ids_provider) { + assert(_resource_ids_provider_deps == [], + "Can only have 1 resource_ids_provider_dep") + _resource_ids_provider_deps += [ _target.name ] + } + } + _resource_ids_provider_dep = _resource_ids_provider_deps[0] + } else if (defined(invoker.resource_ids_provider_dep)) { + _resource_ids_provider_dep = invoker.resource_ids_provider_dep + } + + if (_is_static_library_provider) { + _shared_resources_allowlist_target = _resource_ids_provider_dep + } else if (defined(invoker.shared_resources_allowlist_target)) { + _shared_resources_allowlist_target = + invoker.shared_resources_allowlist_target + } + + _uses_static_library = defined(invoker.static_library_provider) + _uses_static_library_synchronized_proguard = + defined(invoker.static_library_synchronized_proguard) && + invoker.static_library_synchronized_proguard + + if (_uses_static_library_synchronized_proguard) { + assert(_uses_static_library) + + # These will be provided by the static library APK. + _generate_buildconfig_java = false + _generate_final_jni = false + } + + # TODO(crbug.com/864142): Allow incremental installs of bundle modules. + _incremental_apk = !_is_bundle_module && + !(defined(invoker.never_incremental) && + invoker.never_incremental) && incremental_install + if (_incremental_apk) { + _target_dir_name = get_label_info(target_name, "dir") + _incremental_install_json_path = "$root_out_dir/gen.runtime/$_target_dir_name/$target_name.incremental.json" + _incremental_apk_path = "${_final_apk_path_no_ext}_incremental.apk" + } + + if (!_incremental_apk) { + # Bundle modules don't build the dex here, but need to write this path + # to their .build_config.json file. + if (_proguard_enabled) { + _final_dex_path = "$_base_path.r8dex.jar" + } else { + _final_dex_path = "$_base_path.mergeddex.jar" + } + } + + _android_manifest = + "$target_gen_dir/${_template_name}_manifest/AndroidManifest.xml" + _merge_manifest_target = "${_template_name}__merge_manifests" + merge_manifests(_merge_manifest_target) { + forward_variables_from(invoker, + [ + "manifest_package", + "max_sdk_version", + ]) + input_manifest = _android_root_manifest + output_manifest = _android_manifest + build_config = _build_config + min_sdk_version = _min_sdk_version + target_sdk_version = _target_sdk_version + deps = _android_root_manifest_deps + [ ":$_build_config_target" ] + } + + _final_deps = [] + + _enable_main_dex_list = _enable_multidex && _min_sdk_version < 21 + if (_enable_main_dex_list) { + _generated_proguard_main_dex_config = + "$_base_path.resources.main-dex-proguard.txt" + } + _generated_proguard_config = "$_base_path.resources.proguard.txt" + + if (_generate_buildconfig_java && + defined(invoker.product_version_resources_dep)) { + # Needs to be added as a .build_config.json dep to pick up resources. + _deps += [ invoker.product_version_resources_dep ] + } + + if (defined(invoker.alternative_android_sdk_dep)) { + _android_sdk_dep = invoker.alternative_android_sdk_dep + } else { + _android_sdk_dep = "//third_party/android_sdk:android_sdk_java" + } + + if (defined(_shared_resources_allowlist_target)) { + _allowlist_gen_dir = + get_label_info(_shared_resources_allowlist_target, "target_gen_dir") + _allowlist_target_name = + get_label_info(_shared_resources_allowlist_target, "name") + _allowlist_r_txt_path = + "${_allowlist_gen_dir}/${_allowlist_target_name}" + + "__compile_resources_R.txt" + _allowlist_deps = + "${_shared_resources_allowlist_target}__compile_resources" + } + + _compile_resources_target = "${_template_name}__compile_resources" + _compile_resources_rtxt_out = + "${target_gen_dir}/${_compile_resources_target}_R.txt" + _compile_resources_emit_ids_out = + "${target_gen_dir}/${_compile_resources_target}.resource_ids" + compile_resources(_compile_resources_target) { + forward_variables_from(invoker, + [ + "aapt_locale_allowlist", + "app_as_shared_lib", + "enforce_resource_overlays_in_tests", + "expected_android_manifest", + "expected_android_manifest_base", + "extra_verification_manifest", + "extra_verification_manifest_dep", + "manifest_package", + "max_sdk_version", + "no_xml_namespaces", + "package_id", + "package_name", + "png_to_webp", + "r_java_root_package_name", + "resource_exclusion_exceptions", + "resource_exclusion_regex", + "resource_values_filter_rules", + "shared_resources", + "shared_resources_allowlist_locales", + "uses_split", + ]) + android_manifest = _android_manifest + android_manifest_dep = ":$_merge_manifest_target" + version_code = _version_code + version_name = _version_name + min_sdk_version = _min_sdk_version + target_sdk_version = _target_sdk_version + + if (defined(expected_android_manifest)) { + top_target_name = _template_name + } + + if (defined(_resource_ids_provider_dep)) { + resource_ids_provider_dep = _resource_ids_provider_dep + } + + if (defined(invoker.post_process_package_resources_script)) { + post_process_script = invoker.post_process_package_resources_script + } + r_text_out_path = _compile_resources_rtxt_out + emit_ids_out_path = _compile_resources_emit_ids_out + size_info_path = _res_size_info_path + proguard_file = _generated_proguard_config + if (_enable_main_dex_list) { + proguard_file_main_dex = _generated_proguard_main_dex_config + } + + build_config = _build_config + build_config_dep = ":$_build_config_target" + android_sdk_dep = _android_sdk_dep + deps = _deps + + # The static library uses the R.txt files generated by the + # static_library_dependent_targets when generating the final R.java file. + if (_is_static_library_provider) { + foreach(_dep, invoker.static_library_dependent_targets) { + deps += [ "${_dep.name}__compile_resources" ] + } + } + + if (defined(invoker.apk_under_test)) { + # Set the arsc package name to match the apk_under_test package name + # So that test resources can references under_test resources via + # @type/name syntax. + r_java_root_package_name = "test" + arsc_package_name = + "@FileArg($_rebased_build_config:deps_info:arsc_package_name)" + + # Passing in the --emit-ids mapping will cause aapt2 to assign resources + # IDs that do not conflict with those from apk_under_test. + assert(!defined(resource_ids_provider_dep)) + resource_ids_provider_dep = invoker.apk_under_test + + include_resource = + get_label_info(invoker.apk_under_test, "target_out_dir") + "/" + + get_label_info(invoker.apk_under_test, "name") + ".ap_" + _link_against = invoker.apk_under_test + } + + if (_is_bundle_module) { + is_bundle_module = true + proto_output = _proto_resources_path + + if (defined(invoker.base_module_target)) { + include_resource = + get_label_info(invoker.base_module_target, "target_out_dir") + + "/" + get_label_info(invoker.base_module_target, "name") + ".ap_" + _link_against = invoker.base_module_target + } + } + + if (defined(_link_against)) { + deps += [ "${_link_against}__compile_resources" ] + include_resource = get_label_info(_link_against, "target_out_dir") + + "/" + get_label_info(_link_against, "name") + ".ap_" + } + + # Bundle modules have to reference resources from the base module. + if (!_is_bundle_module || _is_base_module) { + arsc_output = _arsc_resources_path + } + + if (defined(_shared_resources_allowlist_target)) { + # Used to ensure that the WebView resources are properly shared + # (i.e. are non-final and with package ID 0). + shared_resources_allowlist = _allowlist_r_txt_path + deps += [ _allowlist_deps ] + } + } + _srcjar_deps += [ ":$_compile_resources_target" ] + + # We don't ship apks anymore, only optimize bundle builds + if (_is_bundle_module) { + _short_resource_paths = + defined(invoker.short_resource_paths) && + invoker.short_resource_paths && enable_arsc_obfuscation + _strip_resource_names = + defined(invoker.strip_resource_names) && + invoker.strip_resource_names && enable_arsc_obfuscation + _strip_unused_resources = defined(invoker.strip_unused_resources) && + invoker.strip_unused_resources + _optimize_resources = _strip_resource_names || _short_resource_paths || + _strip_unused_resources + } + + if (_is_bundle_module && _optimize_resources) { + _optimized_proto_resources_path = + "$target_out_dir/$target_name.optimized.proto.ap_" + if (_short_resource_paths) { + _resources_path_map_out_path = + "${target_gen_dir}/${_template_name}_resources_path_map.txt" + } + _optimize_resources_target = "${_template_name}__optimize_resources" + optimize_resources(_optimize_resources_target) { + deps = _deps + [ ":$_compile_resources_target" ] + short_resource_paths = _short_resource_paths + strip_resource_names = _strip_resource_names + if (_short_resource_paths) { + resources_path_map_out_path = _resources_path_map_out_path + } + r_text_path = _compile_resources_rtxt_out + proto_input_path = _proto_resources_path + optimized_proto_output = _optimized_proto_resources_path + if (_strip_unused_resources) { + # These need to be kept in sync with the target names + output paths + # in the android_app_bundle template. + _unused_resources_target = "${_template_name}__unused_resources" + _unused_resources_config_path = + "$target_gen_dir/${_template_name}_unused_resources.config" + resources_config_paths = [ _unused_resources_config_path ] + deps += [ ":$_unused_resources_target" ] + } else { + resources_config_paths = [] + } + if (defined(invoker.resources_config_paths)) { + resources_config_paths += invoker.resources_config_paths + } + } + } + + if (!_is_bundle_module) { + # Output the R.txt file to a more easily discoverable location for + # archiving. This is necessary when stripping resource names so that we + # have an archive of resource names to ids for shipped apks (for + # debugging purposes). We copy the file rather than change the location + # of the original because other targets rely on the location of the R.txt + # file. + _copy_rtxt_target = "${_template_name}__copy_rtxt" + copy(_copy_rtxt_target) { + deps = [ ":$_compile_resources_target" ] + sources = [ _compile_resources_rtxt_out ] + outputs = [ _final_rtxt_path ] + } + _final_deps += [ ":$_copy_rtxt_target" ] + } + + if (defined(_resource_sizes_arsc_path)) { + _copy_arsc_target = "${_template_name}__copy_arsc" + copy(_copy_arsc_target) { + deps = [ ":$_compile_resources_target" ] + + # resource_sizes.py doesn't care if it gets the optimized .arsc. + sources = [ _arsc_resources_path ] + outputs = [ _resource_sizes_arsc_path ] + } + _final_deps += [ ":$_copy_arsc_target" ] + } + + _generate_native_libraries_java = + (!_is_bundle_module || _is_base_module) && + (_native_libs_deps != [] || _secondary_abi_native_libs_deps != []) && + !_uses_static_library_synchronized_proguard + if (_generate_native_libraries_java) { + write_native_libraries_java("${_template_name}__native_libraries") { + forward_variables_from(invoker, [ "main_component_library" ]) + + # Do not add a dep on the generated_file target in order to avoid having + # to build the native libraries before this target. The dependency is + # instead captured via a depfile. + if (_native_libs_deps != []) { + native_libraries_list_file = _shared_library_list_file + } else { + native_libraries_list_file = _secondary_abi_shared_library_list_file + } + enable_chromium_linker = _use_chromium_linker + load_library_from_apk = _load_library_from_apk + use_modern_linker = _use_modern_linker + use_final_fields = true + } + _srcjar_deps += [ ":${_template_name}__native_libraries" ] + } + + _loadable_modules = [] + if (defined(invoker.loadable_modules)) { + _loadable_modules = invoker.loadable_modules + } + + if (_native_libs_deps != []) { + _loadable_modules += _sanitizer_runtimes + } + + if (_generate_buildconfig_java) { + generate_build_config_srcjar("${_template_name}__build_config_srcjar") { + forward_variables_from(invoker, + [ + "min_sdk_version", + "isolated_splits_enabled", + ]) + _bundles_supported = _is_bundle_module || _is_static_library_provider + if (defined(invoker.bundles_supported)) { + _bundles_supported = invoker.bundles_supported + } + bundles_supported = _bundles_supported + use_final_fields = true + enable_multidex = _enable_multidex + is_incremental_install = _incremental_apk + if (defined(invoker.product_version_resources_dep)) { + resources_version_variable = + "org.chromium.base.R.string.product_version" + } + deps = [ ":$_build_config_target" ] + } + _srcjar_deps += [ ":${_template_name}__build_config_srcjar" ] + } + + if (_generate_productconfig_java) { + foreach(_package, invoker.product_config_java_packages) { + _locale_target_name = + "${_template_name}_${_package}__product_config_srcjar" + generate_product_config_srcjar("$_locale_target_name") { + forward_variables_from(invoker, [ "is_bundle_module" ]) + build_config = _build_config + java_package = _package + use_chromium_linker = _use_chromium_linker + use_modern_linker = _use_modern_linker + deps = [ ":$_build_config_target" ] + } + _srcjar_deps += [ ":$_locale_target_name" ] + } + } + + if (_generate_final_jni) { + generate_jni_registration("${_template_name}__final_jni") { + forward_variables_from(invoker, + [ + "enable_native_mocks", + "require_native_mocks", + ]) + if (defined(invoker.bundle_target)) { + targets = [ invoker.bundle_target ] + } else { + targets = [ ":$_template_name" ] + } + if (_is_static_library_provider) { + foreach(_target, invoker.static_library_dependent_targets) { + targets += [ _target.name ] + } + } + if (defined(invoker.jni_registration_header)) { + header_output = invoker.jni_registration_header + } + if (defined(invoker.jni_sources_exclusions)) { + sources_exclusions = invoker.jni_sources_exclusions + } + } + _srcjar_deps += [ ":${_template_name}__final_jni" ] + } else { + not_needed(invoker, + [ + "enable_native_mocks", + "jni_registration_header", + ]) + } + + _java_target = "${_template_name}__java" + + java_library_impl(_java_target) { + forward_variables_from(invoker, + [ + "alternative_android_sdk_dep", + "android_manifest", + "android_manifest_dep", + "annotation_processor_deps", + "apk_under_test", + "base_module_target", + "chromium_code", + "jacoco_never_instrument", + "jar_excluded_patterns", + "javac_args", + "native_lib_placeholders", + "processor_args_javac", + "secondary_abi_loadable_modules", + "secondary_native_lib_placeholders", + "sources", + "static_library_dependent_targets", + "use_classic_desugar", + "library_always_compress", + "library_renames", + ]) + deps = _deps + if (_uses_static_library_synchronized_proguard) { + if (!defined(jar_excluded_patterns)) { + jar_excluded_patterns = [] + } + + # The static library will provide all R.java files, but we still need to + # make the base module R.java files available at compile time since DFM + # R.java classes extend base module classes. + jar_excluded_patterns += [ + "*/R.class", + "*/R\$*.class", + ] + } + if (_is_bundle_module) { + type = "android_app_bundle_module" + res_size_info_path = _res_size_info_path + is_base_module = _is_base_module + forward_variables_from(invoker, + [ + "version_code", + "version_name", + ]) + } else { + type = "android_apk" + } + r_text_path = _compile_resources_rtxt_out + main_target_name = _template_name + supports_android = true + requires_android = true + srcjar_deps = _srcjar_deps + merged_android_manifest = _android_manifest + if (defined(_final_dex_path)) { + final_dex_path = _final_dex_path + } + + if (_is_bundle_module) { + proto_resources_path = _proto_resources_path + if (_optimize_resources) { + proto_resources_path = _optimized_proto_resources_path + if (_short_resource_paths) { + module_pathmap_path = _resources_path_map_out_path + } + } + } else { + apk_path = _final_apk_path + if (_incremental_apk) { + incremental_apk_path = _incremental_apk_path + incremental_install_json_path = _incremental_install_json_path + } + } + + proguard_enabled = _proguard_enabled + if (_proguard_enabled) { + proguard_configs = [ _generated_proguard_config ] + if (defined(invoker.proguard_configs)) { + proguard_configs += invoker.proguard_configs + } + if (!enable_java_asserts && (!defined(testonly) || !testonly) && + # Injected JaCoCo code causes -checkdiscards to fail. + !use_jacoco_coverage) { + proguard_configs += [ "//build/android/dcheck_is_off.flags" ] + } + if (!_is_bundle_module) { + proguard_mapping_path = _proguard_mapping_path + } + } + + # Do not add a dep on the generated_file target in order to avoid having + # to build the native libraries before this target. The dependency is + # instead captured via a depfile. + if (_native_libs_deps != []) { + shared_libraries_runtime_deps_file = _shared_library_list_file + } + if (defined(_secondary_abi_shared_library_list_file)) { + secondary_abi_shared_libraries_runtime_deps_file = + _secondary_abi_shared_library_list_file + } + + loadable_modules = _loadable_modules + + uncompress_shared_libraries = _uncompress_shared_libraries + + if (defined(_allowlist_r_txt_path) && _is_bundle_module) { + # Used to write the file path to the target's .build_config.json only. + base_allowlist_rtxt_path = _allowlist_r_txt_path + } + } + + # TODO(cjhopman): This is only ever needed to calculate the list of tests to + # run. See build/android/pylib/instrumentation/test_jar.py. We should be + # able to just do that calculation at build time instead. + if (defined(invoker.dist_ijar_path)) { + _dist_ijar_path = invoker.dist_ijar_path + dist_jar("${_template_name}_dist_ijar") { + override_build_config = _build_config + output = _dist_ijar_path + data = [ _dist_ijar_path ] + use_interface_jars = true + deps = [ + ":$_build_config_target", + ":$_java_target", + ] + } + } + + if (_uses_static_library_synchronized_proguard) { + _final_dex_target_dep = "${invoker.static_library_provider}__dexsplitter" + } else if (_is_bundle_module && _proguard_enabled) { + _final_deps += [ ":$_java_target" ] + } else if (_incremental_apk) { + if (defined(invoker.enable_proguard_checks)) { + not_needed(invoker, [ "enable_proguard_checks" ]) + } + if (defined(invoker.disable_r8_outlining)) { + not_needed(invoker, [ "disable_r8_outlining" ]) + } + if (defined(invoker.dexlayout_profile)) { + not_needed(invoker, [ "dexlayout_profile" ]) + } + } else { + # Dex generation for app bundle modules with proguarding enabled takes + # place later due to synchronized proguarding. + _final_dex_target_name = "${_template_name}__final_dex" + dex(_final_dex_target_name) { + forward_variables_from(invoker, + [ + "disable_r8_outlining", + "dexlayout_profile", + "enable_proguard_checks", + "proguard_enable_obfuscation", + ]) + min_sdk_version = _min_sdk_version + proguard_enabled = _proguard_enabled + build_config = _build_config + deps = [ + ":$_build_config_target", + ":$_java_target", + ] + if (_proguard_enabled) { + deps += _deps + [ ":$_compile_resources_target" ] + proguard_mapping_path = _proguard_mapping_path + proguard_sourcefile_suffix = "$android_channel-$_version_code" + has_apk_under_test = defined(invoker.apk_under_test) + } else if (_min_sdk_version >= default_min_sdk_version) { + # Enable dex merging only when min_sdk_version is >= what the library + # .dex files were created with. + input_dex_filearg = + "@FileArg(${_rebased_build_config}:final_dex:all_dex_files)" + } else { + input_classes_filearg = + "@FileArg($_rebased_build_config:deps_info:device_classpath)" + } + + if (_is_static_library_provider) { + # The list of input jars is already recorded in the .build_config.json, but + # we need to explicitly add the java deps here to ensure they're + # available to be used as inputs to the dex step. + foreach(_dep, invoker.static_library_dependent_targets) { + _target_label = get_label_info(_dep.name, "label_no_toolchain") + deps += [ "${_target_label}__java" ] + } + output = _static_library_sync_dex_path + is_static_library = true + } else { + output = _final_dex_path + } + enable_multidex = _enable_multidex + + # The individual dependencies would have caught real missing deps in + # their respective dex steps. False positives that were suppressed at + # per-target dex steps are emitted here since this may use jar files + # rather than dex files. + ignore_desugar_missing_deps = true + + if (_enable_main_dex_list) { + extra_main_dex_proguard_config = _generated_proguard_main_dex_config + deps += [ ":$_compile_resources_target" ] + } + } + + _final_dex_target_dep = ":$_final_dex_target_name" + + # For static libraries, a single Proguard run is performed that includes + # code from the static library APK and the APKs that use the static + # library (done via. classpath merging in write_build_config.py). + # This dexsplitter target splits the synchronized dex output into dex + # files for each APK/Bundle. In the Bundle case, another dexsplitter step + # is later performed to split the dex further for each feature module. + if (_is_static_library_provider && _proguard_enabled) { + _static_library_modules = [] + foreach(_target, invoker.static_library_dependent_targets) { + _apk_as_module = _target.name + _module_config_target = "${_apk_as_module}$build_config_target_suffix" + _module_gen_dir = get_label_info(_apk_as_module, "target_gen_dir") + _module_name = get_label_info(_apk_as_module, "name") + _module_config = "$_module_gen_dir/$_module_name.build_config.json" + _static_library_modules += [ + { + name = _module_name + build_config = _module_config + build_config_target = _module_config_target + }, + ] + } + + _static_library_dexsplitter_target = "${_template_name}__dexsplitter" + dexsplitter(_static_library_dexsplitter_target) { + input_dex_zip = _static_library_sync_dex_path + proguard_mapping = _proguard_mapping_path + deps = [ + ":$_build_config_target", + "$_final_dex_target_dep", + ] + all_modules = [ + { + name = "base" + build_config = _build_config + build_config_target = ":$_build_config_target" + }, + ] + _static_library_modules + feature_jars_args = [ + "--feature-jars", + "@FileArg($_rebased_build_config:deps_info:" + + "static_library_dependent_classpath_configs:" + + "$_rebased_build_config)", + ] + foreach(_module, _static_library_modules) { + _rebased_module_config = + rebase_path(_module.build_config, root_build_dir) + feature_jars_args += [ + "--feature-jars", + "@FileArg($_rebased_build_config:deps_info:" + + "static_library_dependent_classpath_configs:" + + "$_rebased_module_config)", + ] + } + } + _final_deps += [ ":$_static_library_dexsplitter_target" ] + _validate_dex_target = "${_template_name}__validate_dex" + action_with_pydeps(_validate_dex_target) { + depfile = "$target_gen_dir/$target_name.d" + script = + "//build/android/gyp/validate_static_library_dex_references.py" + inputs = [ _build_config ] + _stamp = "$target_gen_dir/$target_name.stamp" + outputs = [ _stamp ] + deps = [ + ":$_build_config_target", + ":$_static_library_dexsplitter_target", + ] + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--stamp", + rebase_path(_stamp, root_build_dir), + "--static-library-dex", + "@FileArg($_rebased_build_config:final_dex:path)", + ] + foreach(_module, _static_library_modules) { + inputs += [ _module.build_config ] + _rebased_config = rebase_path(_module.build_config, root_build_dir) + deps += [ _module.build_config_target ] + args += [ + "--static-library-dependent-dex", + "@FileArg($_rebased_config:final_dex:path)", + ] + } + } + + # TODO(crbug.com/1032609): Switch to using R8's support for feature + # aware ProGuard and get rid of "_validate_dex_target" or figure out + # why some classes aren't properly being kept. + # _final_deps += [ ":$_validate_dex_target" ] + _final_dex_target_dep = ":$_static_library_dexsplitter_target" + } + } + + _all_native_libs_deps = _native_libs_deps + _secondary_abi_native_libs_deps + if (_all_native_libs_deps != []) { + _native_libs_filearg_dep = ":$_build_config_target" + _all_native_libs_deps += [ _native_libs_filearg_dep ] + + if (!_is_bundle_module) { + _native_libs_filearg = + "@FileArg($_rebased_build_config:native:libraries)" + } + } + + if (_is_bundle_module) { + _final_deps += [ + ":$_merge_manifest_target", + ":$_build_config_target", + ":$_compile_resources_target", + ] + _all_native_libs_deps + if (_optimize_resources) { + _final_deps += [ ":$_optimize_resources_target" ] + } + if (defined(_final_dex_target_dep)) { + not_needed([ "_final_dex_target_dep" ]) + } + } else { + # Generate size-info/*.jar.info files. + if (defined(invoker.name)) { + # Create size info files for targets that care about size + # (have proguard enabled). + _include_size_info = + defined(invoker.include_size_info) && invoker.include_size_info + if (_include_size_info || _proguard_enabled) { + _size_info_target = "${target_name}__size_info" + create_size_info_files(_size_info_target) { + name = "${invoker.name}.apk" + build_config = _build_config + res_size_info_path = _res_size_info_path + deps = _deps + [ + ":$_build_config_target", + ":$_compile_resources_target", + ":$_java_target", + ] + } + _final_deps += [ ":$_size_info_target" ] + } else { + not_needed(invoker, [ "name" ]) + } + } + + _keystore_path = android_keystore_path + _keystore_name = android_keystore_name + _keystore_password = android_keystore_password + + if (defined(invoker.keystore_path)) { + _keystore_path = invoker.keystore_path + _keystore_name = invoker.keystore_name + _keystore_password = invoker.keystore_password + } + + if (_incremental_apk) { + _incremental_compiled_resources_path = "${_base_path}_incremental.ap_" + _incremental_compile_resources_target_name = + "${target_name}__compile_incremental_resources" + + action_with_pydeps(_incremental_compile_resources_target_name) { + deps = [ + ":$_build_config_target", + ":$_compile_resources_target", + ":$_merge_manifest_target", + ] + script = + "//build/android/incremental_install/generate_android_manifest.py" + inputs = [ + _android_manifest, + _build_config, + _arsc_resources_path, + ] + outputs = [ _incremental_compiled_resources_path ] + + args = [ + "--disable-isolated-processes", + "--src-manifest", + rebase_path(_android_manifest, root_build_dir), + "--in-apk", + rebase_path(_arsc_resources_path, root_build_dir), + "--out-apk", + rebase_path(_incremental_compiled_resources_path, root_build_dir), + "--aapt2-path", + rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir), + "--android-sdk-jars=@FileArg($_rebased_build_config:android:sdk_jars)", + ] + } + } + + _create_apk_target = "${_template_name}__create" + _final_deps += [ ":$_create_apk_target" ] + package_apk("$_create_apk_target") { + forward_variables_from(invoker, + [ + "expected_libs_and_assets", + "expected_libs_and_assets_base", + "native_lib_placeholders", + "secondary_abi_loadable_modules", + "secondary_native_lib_placeholders", + "uncompress_dex", + "uncompress_shared_libraries", + "library_always_compress", + "library_renames", + ]) + + if (defined(expected_libs_and_assets)) { + build_config_dep = ":$_build_config_target" + top_target_name = _template_name + } + + build_config = _build_config + keystore_name = _keystore_name + keystore_path = _keystore_path + keystore_password = _keystore_password + min_sdk_version = _min_sdk_version + uncompress_shared_libraries = _uncompress_shared_libraries + + deps = _deps + [ ":$_build_config_target" ] + + if ((!_proguard_enabled || _incremental_apk) && + enable_jdk_library_desugaring) { + _all_jdk_libs = "//build/android:all_jdk_libs" + deps += [ _all_jdk_libs ] + jdk_libs_dex = get_label_info(_all_jdk_libs, "target_out_dir") + + "/all_jdk_libs.l8.dex" + } + + if (_incremental_apk) { + _dex_target = "//build/android/incremental_install:apk_dex" + + deps += [ + ":${_incremental_compile_resources_target_name}", + _dex_target, + ] + + dex_path = get_label_info(_dex_target, "target_out_dir") + "/apk.dex" + + # All native libraries are side-loaded, so use a placeholder to force + # the proper bitness for the app. + _has_native_libs = + defined(_native_libs_filearg) || _loadable_modules != [] + if (_has_native_libs && !defined(native_lib_placeholders)) { + native_lib_placeholders = [ "libfix.crbug.384638.so" ] + } + + packaged_resources_path = _incremental_compiled_resources_path + output_apk_path = _incremental_apk_path + } else { + loadable_modules = _loadable_modules + deps += _all_native_libs_deps + [ + ":$_merge_manifest_target", + ":$_compile_resources_target", + ] + + if (defined(_final_dex_path)) { + dex_path = _final_dex_path + deps += [ _final_dex_target_dep ] + } + + packaged_resources_path = _arsc_resources_path + + if (defined(_native_libs_filearg)) { + native_libs_filearg = _native_libs_filearg + secondary_abi_native_libs_filearg = "@FileArg($_rebased_build_config:native:secondary_abi_libraries)" + } + output_apk_path = _final_apk_path + } + } + } + + if (_incremental_apk) { + _write_installer_json_rule_name = "${_template_name}__incremental_json" + action_with_pydeps(_write_installer_json_rule_name) { + script = "//build/android/incremental_install/write_installer_json.py" + deps = [ ":$_build_config_target" ] + _all_native_libs_deps + + data = [ _incremental_install_json_path ] + inputs = [ _build_config ] + outputs = [ _incremental_install_json_path ] + + _rebased_incremental_apk_path = + rebase_path(_incremental_apk_path, root_build_dir) + _rebased_incremental_install_json_path = + rebase_path(_incremental_install_json_path, root_build_dir) + args = [ + "--apk-path=$_rebased_incremental_apk_path", + "--output-path=$_rebased_incremental_install_json_path", + "--dex-file=@FileArg($_rebased_build_config:final_dex:all_dex_files)", + ] + if (_proguard_enabled) { + args += [ "--show-proguard-warning" ] + } + if (defined(_native_libs_filearg)) { + args += [ "--native-libs=$_native_libs_filearg" ] + deps += [ _native_libs_filearg_dep ] + } + if (_loadable_modules != []) { + _rebased_loadable_modules = + rebase_path(_loadable_modules, root_build_dir) + args += [ "--native-libs=$_rebased_loadable_modules" ] + } + } + _final_deps += [ + ":$_java_target", + ":$_write_installer_json_rule_name", + ] + } + + # Generate apk operation related script. + if (!_is_bundle_module && + (!defined(invoker.create_apk_script) || invoker.create_apk_script)) { + if (_uses_static_library) { + _install_artifacts_target = "${target_name}__install_artifacts" + _install_artifacts_json = + "${target_gen_dir}/${target_name}.install_artifacts" + generated_file(_install_artifacts_target) { + output_conversion = "json" + deps = [ invoker.static_library_provider ] + outputs = [ _install_artifacts_json ] + data_keys = [ "install_artifacts" ] + rebase = root_build_dir + } + } + _apk_operations_target_name = "${target_name}__apk_operations" + action_with_pydeps(_apk_operations_target_name) { + _generated_script = "$root_build_dir/bin/${invoker.target_name}" + script = "//build/android/gyp/create_apk_operations_script.py" + outputs = [ _generated_script ] + args = [ + "--script-output-path", + rebase_path(_generated_script, root_build_dir), + "--target-cpu=$target_cpu", + ] + if (defined(invoker.command_line_flags_file)) { + args += [ + "--command-line-flags-file", + invoker.command_line_flags_file, + ] + } + if (_incremental_apk) { + args += [ + "--incremental-install-json-path", + rebase_path(_incremental_install_json_path, root_build_dir), + ] + } else { + args += [ + "--apk-path", + rebase_path(_final_apk_path, root_build_dir), + ] + } + if (_uses_static_library) { + deps = [ ":$_install_artifacts_target" ] + _rebased_install_artifacts_json = + rebase_path(_install_artifacts_json, root_build_dir) + _static_library_apk_path = + "@FileArg($_rebased_install_artifacts_json[])" + args += [ + "--additional-apk", + _static_library_apk_path, + ] + } + data = [] + data_deps = [ + "//build/android:apk_operations_py", + "//build/android:stack_tools", + ] + + if (_proguard_enabled && !_incremental_apk) { + # Required by logcat command. + data_deps += [ "//build/android/stacktrace:java_deobfuscate" ] + data += [ "$_final_apk_path.mapping" ] + args += [ + "--proguard-mapping-path", + rebase_path("$_final_apk_path.mapping", root_build_dir), + ] + } + } + _final_deps += [ ":$_apk_operations_target_name" ] + } + + _enable_lint = defined(invoker.enable_lint) && invoker.enable_lint && + !disable_android_lint + if (_enable_lint) { + android_lint("${target_name}__lint") { + forward_variables_from(invoker, + [ + "lint_baseline_file", + "lint_suppressions_file", + "min_sdk_version", + ]) + build_config = _build_config + build_config_dep = ":$_build_config_target" + deps = [ ":$_java_target" ] + if (defined(invoker.lint_suppressions_dep)) { + deps += [ invoker.lint_suppressions_dep ] + } + if (defined(invoker.lint_min_sdk_version)) { + min_sdk_version = invoker.lint_min_sdk_version + } + } + } else { + not_needed(invoker, + [ + "lint_baseline_file", + "lint_min_sdk_version", + "lint_suppressions_dep", + "lint_suppressions_file", + ]) + } + + group(target_name) { + forward_variables_from(invoker, + [ + "assert_no_deps", + "data", + "data_deps", + "metadata", + ]) + + # Generate apk related operations at runtime. + public_deps = _final_deps + + if (!defined(data_deps)) { + data_deps = [] + } + + # Include unstripped native libraries so tests can symbolize stacks. + data_deps += _all_native_libs_deps + + if (_enable_lint) { + data_deps += [ ":${target_name}__lint" ] + } + + if (_uses_static_library) { + data_deps += [ invoker.static_library_provider ] + } + } + } + + # Declare an Android APK target + # + # This target creates an Android APK containing java code, resources, assets, + # and (possibly) native libraries. + # + # Supports all variables of android_apk_or_module(), plus: + # apk_name: Name for final apk. + # final_apk_path: (Optional) path to output APK. + # + # Example + # android_apk("foo_apk") { + # android_manifest = "AndroidManifest.xml" + # sources = [ + # "android/org/chromium/foo/FooApplication.java", + # "android/org/chromium/foo/FooActivity.java", + # ] + # deps = [ + # ":foo_support_java" + # ":foo_resources" + # ] + # srcjar_deps = [ + # ":foo_generated_enum" + # ] + # shared_libraries = [ + # ":my_shared_lib", + # ] + # } + template("android_apk") { + # TODO(crbug.com/1042017): Remove. + not_needed(invoker, [ "no_build_hooks" ]) + android_apk_or_module(target_name) { + forward_variables_from(invoker, + [ + "aapt_locale_allowlist", + "additional_jar_files", + "alternative_android_sdk_dep", + "android_manifest", + "android_manifest_dep", + "annotation_processor_deps", + "apk_under_test", + "app_as_shared_lib", + "assert_no_deps", + "bundles_supported", + "chromium_code", + "command_line_flags_file", + "create_apk_script", + "data", + "data_deps", + "deps", + "dexlayout_profile", + "disable_r8_outlining", + "dist_ijar_path", + "enable_lint", + "enable_multidex", + "enable_native_mocks", + "enable_proguard_checks", + "enforce_resource_overlays_in_tests", + "expected_android_manifest", + "expected_android_manifest_base", + "expected_libs_and_assets", + "expected_libs_and_assets_base", + "generate_buildconfig_java", + "generate_final_jni", + "include_size_info", + "input_jars_paths", + "use_modern_linker", + "jacoco_never_instrument", + "javac_args", + "jni_registration_header", + "jni_sources_exclusions", + "keystore_name", + "keystore_password", + "keystore_path", + "lint_baseline_file", + "lint_min_sdk_version", + "lint_suppressions_dep", + "lint_suppressions_file", + "load_library_from_apk", + "loadable_modules", + "manifest_package", + "max_sdk_version", + "product_config_java_packages", + "main_component_library", + "min_sdk_version", + "native_lib_placeholders", + "never_incremental", + "no_xml_namespaces", + "png_to_webp", + "post_process_package_resources_script", + "processor_args_javac", + "product_version_resources_dep", + "proguard_configs", + "proguard_enabled", + "proguard_enable_obfuscation", + "r_java_root_package_name", + "resource_exclusion_exceptions", + "resource_exclusion_regex", + "resource_ids_provider_dep", + "resource_values_filter_rules", + "require_native_mocks", + "secondary_abi_loadable_modules", + "secondary_abi_shared_libraries", + "secondary_native_lib_placeholders", + "shared_libraries", + "shared_resources", + "shared_resources_allowlist_locales", + "shared_resources_allowlist_target", + "sources", + "srcjar_deps", + "static_library_dependent_targets", + "static_library_provider", + "static_library_synchronized_proguard", + "target_sdk_version", + "testonly", + "uncompress_dex", + "uncompress_shared_libraries", + "use_classic_desugar", + "library_always_compress", + "library_renames", + "use_chromium_linker", + "version_code", + "version_name", + "visibility", + ]) + is_bundle_module = false + name = invoker.apk_name + if (defined(invoker.final_apk_path)) { + final_apk_path = invoker.final_apk_path + } else { + final_apk_path = "$root_build_dir/apks/${invoker.apk_name}.apk" + } + metadata = { + install_artifacts = [ final_apk_path ] + } + if (defined(invoker.static_library_provider)) { + metadata.install_artifacts_barrier = [] + } + } + } + + # Declare an Android app bundle module target. + # + # The module can be used for an android_apk_or_module(). + # + # Supports all variables of android_library(), plus: + # module_name: Name of the module. + # is_base_module: If defined and true, indicates that this is the bundle's + # base module (optional). + # base_module_target: Base module target of the bundle this module will be + # added to (optional). Can only be specified for non-base modules. + # bundle_target: Bundle target that this module belongs to (optional). + # Can only be specified for base modules. + template("android_app_bundle_module") { + _is_base_module = defined(invoker.is_base_module) && invoker.is_base_module + + if (_is_base_module) { + assert(!defined(invoker.base_module_target)) + } else { + assert(!defined(invoker.app_as_shared_lib)) + assert(!defined(invoker.shared_resources)) + assert(!defined(invoker.shared_resources_allowlist_target)) + assert(!defined(invoker.shared_resources_allowlist_locales)) + assert(defined(invoker.base_module_target)) + assert(!defined(invoker.bundle_target)) + } + + # TODO(tiborg): We have several flags that are necessary for workarounds + # that come from the fact that the resources get compiled in the bundle + # module target, but bundle modules have to have certain flags in + # common or bundle modules have to know information about the base module. + # Those flags include version_code, version_name, and base_module_target. + # It would be better to move the resource compile target into the bundle + # target. Doing so would keep the bundle modules independent from the bundle + # and potentially reuse the same bundle modules for multiple bundles. + android_apk_or_module(target_name) { + forward_variables_from(invoker, + [ + "aapt_locale_allowlist", + "additional_jar_files", + "alternative_android_sdk_dep", + "android_manifest", + "android_manifest_dep", + "annotation_processor_deps", + "app_as_shared_lib", + "assert_no_deps", + "base_module_target", + "bundle_target", + "chromium_code", + "data", + "data_deps", + "deps", + "enable_multidex", + "expected_android_manifest", + "expected_android_manifest_base", + "extra_verification_manifest", + "extra_verification_manifest_dep", + "generate_buildconfig_java", + "generate_final_jni", + "input_jars_paths", + "isolated_splits_enabled", + "is_base_module", + "jacoco_never_instrument", + "jar_excluded_patterns", + "javac_args", + "jni_registration_header", + "jni_sources_exclusions", + "load_library_from_apk", + "loadable_modules", + "product_config_java_packages", + "manifest_package", + "max_sdk_version", + "min_sdk_version", + "native_lib_placeholders", + "no_xml_namespaces", + "package_id", + "package_name", + "png_to_webp", + "processor_args_javac", + "product_version_resources_dep", + "proguard_configs", + "proguard_enabled", + "proguard_enable_obfuscation", + "resource_exclusion_exceptions", + "resource_exclusion_regex", + "resource_ids_provider_dep", + "resource_values_filter_rules", + "resources_config_paths", + "secondary_abi_loadable_modules", + "secondary_abi_shared_libraries", + "secondary_native_lib_placeholders", + "shared_libraries", + "shared_resources", + "shared_resources_allowlist_locales", + "shared_resources_allowlist_target", + "short_resource_paths", + "srcjar_deps", + "static_library_provider", + "static_library_synchronized_proguard", + "strip_resource_names", + "strip_unused_resources", + "target_sdk_version", + "testonly", + "uncompress_shared_libraries", + "library_always_compress", + "library_renames", + "use_chromium_linker", + "use_modern_linker", + "uses_split", + "version_code", + "version_name", + "visibility", + ]) + is_bundle_module = true + generate_buildconfig_java = _is_base_module + } + } + + # Declare an Android instrumentation test runner. + # + # This target creates a wrapper script to run Android instrumentation tests. + # + # Arguments: + # android_test_apk: The target containing the tests. + # android_test_apk_name: The apk_name in android_test_apk + # + # The following args are optional: + # apk_under_test: The target being tested. + # additional_apks: Additional targets to install on device. + # data: List of runtime data file dependencies. + # data_deps: List of non-linked dependencies. + # deps: List of private dependencies. + # extra_args: Extra arguments set for test runner. + # ignore_all_data_deps: Don't build data_deps and additional_apks. + # modules: Extra dynamic feature modules to install for test target. Can + # only be used if |apk_under_test| is an Android app bundle. + # fake_modules: Similar to |modules| but fake installed instead. + # never_incremental: Disable incremental builds. + # proguard_enabled: Enable proguard + # public_deps: List of public dependencies + # + # Example + # instrumentation_test_runner("foo_test_for_bar") { + # android_test_apk: ":foo" + # android_test_apk_name: "Foo" + # apk_under_test: ":bar" + # } + template("instrumentation_test_runner") { + if (use_rts) { + action("${invoker.target_name}__rts_filters") { + script = "//build/add_rts_filters.py" + rts_file = "${root_build_dir}/gen/rts/${invoker.target_name}.filter" + args = [ rebase_path(rts_file, root_build_dir) ] + outputs = [ rts_file ] + } + } + test_runner_script(target_name) { + forward_variables_from(invoker, + [ + "additional_apks", + "additional_locales", + "apk_under_test", + "data", + "data_deps", + "deps", + "extra_args", + "fake_modules", + "ignore_all_data_deps", + "modules", + "proguard_enabled", + "public_deps", + "use_webview_provider", + ]) + test_name = invoker.target_name + test_type = "instrumentation" + _apk_target_name = get_label_info(invoker.android_test_apk, "name") + apk_target = ":$_apk_target_name" + test_jar = "$root_build_dir/test.lib.java/" + + invoker.android_test_apk_name + ".jar" + incremental_apk = !(defined(invoker.never_incremental) && + invoker.never_incremental) && incremental_install + + public_deps = [ + ":$_apk_target_name", + + # Required by test runner to enumerate test list. + ":${_apk_target_name}_dist_ijar", + ] + if (defined(invoker.apk_under_test)) { + public_deps += [ invoker.apk_under_test ] + } + if (defined(invoker.additional_apks)) { + public_deps += invoker.additional_apks + } + if (use_rts) { + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += [ ":${invoker.target_name}__rts_filters" ] + } + } + } + + # Declare an Android instrumentation test apk + # + # This target creates an Android instrumentation test apk. + # + # Supports all variables of android_apk(), plus: + # apk_under_test: The apk being tested (optional). + # + # Example + # android_test_apk("foo_test_apk") { + # android_manifest = "AndroidManifest.xml" + # apk_name = "FooTest" + # apk_under_test = "Foo" + # sources = [ + # "android/org/chromium/foo/FooTestCase.java", + # "android/org/chromium/foo/FooExampleTest.java", + # ] + # deps = [ + # ":foo_test_support_java" + # ] + # } + template("android_test_apk") { + android_apk(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + testonly = true + + # The size info enables the test_runner to find the source file location + # of a test after it is ran. + include_size_info = true + data = [ "$root_build_dir/size-info/${invoker.apk_name}.apk.jar.info" ] + if (defined(invoker.data)) { + data += invoker.data + } + + deps = [ "//testing/android/broker:broker_java" ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + data_deps = [ + # Ensure unstripped libraries are included in runtime deps so that + # symbolization can be done. + ":${target_name}__secondary_abi_shared_library_list", + ":${target_name}__shared_library_list", + ] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps + } + if (defined(invoker.apk_under_test)) { + data_deps += [ invoker.apk_under_test ] + } else { + enable_native_mocks = true + } + + if (defined(invoker.apk_under_test)) { + _under_test_label = + get_label_info(invoker.apk_under_test, "label_no_toolchain") + data_deps += [ + "${_under_test_label}__secondary_abi_shared_library_list", + "${_under_test_label}__shared_library_list", + ] + } + + if (defined(invoker.additional_apks)) { + data_deps += invoker.additional_apks + } + if (defined(invoker.use_webview_provider)) { + data_deps += [ invoker.use_webview_provider ] + } + + if (defined(invoker.proguard_enabled) && invoker.proguard_enabled && + !incremental_install) { + # When ProGuard is on, we use ProGuard to combine the under test java + # code and the test java code. This is to allow us to apply all ProGuard + # optimizations that we ship with, but not have them break tests. The + # apk under test will still have the same resources, assets, and + # manifest, all of which are the ones used in the tests. + proguard_configs = [ "//testing/android/proguard_for_test.flags" ] + if (defined(invoker.proguard_configs)) { + proguard_configs += invoker.proguard_configs + } + enable_proguard_checks = false + if (defined(invoker.final_apk_path)) { + _final_apk_path = final_apk_path + } else { + _final_apk_path = "$root_build_dir/apks/${invoker.apk_name}.apk" + } + data += [ "$_final_apk_path.mapping" ] + } + + dist_ijar_path = "$root_build_dir/test.lib.java/${invoker.apk_name}.jar" + create_apk_script = false + + forward_variables_from(invoker, + "*", + TESTONLY_AND_VISIBILITY + [ + "data", + "data_deps", + "deps", + "proguard_configs", + ]) + } + } + + # Declare an Android instrumentation test apk with wrapper script. + # + # This target creates an Android instrumentation test apk with wrapper script + # to run the test. + # + # Supports all variables of android_test_apk. + template("instrumentation_test_apk") { + assert(defined(invoker.apk_name)) + _apk_target_name = "${target_name}__test_apk" + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + android_test_apk(_apk_target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + } + instrumentation_test_runner(target_name) { + forward_variables_from(invoker, + [ + "additional_apks", + "apk_under_test", + "data", + "data_deps", + "deps", + "extra_args", + "ignore_all_data_deps", + "modules", + "never_incremental", + "proguard_enabled", + "proguard_enable_obfuscation", + "public_deps", + "use_webview_provider", + ]) + android_test_apk = ":${_apk_target_name}" + android_test_apk_name = invoker.apk_name + } + } + + # Declare an Android gtest apk + # + # This target creates an Android apk for running gtest-based unittests. + # + # Variables + # deps: Specifies the dependencies of this target. These will be passed to + # the underlying android_apk invocation and should include the java and + # resource dependencies of the apk. + # shared_library: shared_library target that contains the unit tests. + # apk_name: The name of the produced apk. If unspecified, it uses the name + # of the shared_library target suffixed with "_apk". + # use_default_launcher: Whether the default activity (NativeUnitTestActivity) + # should be used for launching tests. + # allow_cleartext_traffic: (Optional) Whether to allow cleartext network + # requests during the test. + # use_native_activity: Test implements ANativeActivity_onCreate(). + # + # Example + # unittest_apk("foo_unittests_apk") { + # deps = [ ":foo_java", ":foo_resources" ] + # shared_library = ":foo_unittests" + # } + template("unittest_apk") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + _use_native_activity = + defined(invoker.use_native_activity) && invoker.use_native_activity + _android_manifest = "$target_gen_dir/$target_name/AndroidManifest.xml" + assert(invoker.shared_library != "") + + # This trivial assert is needed in case android_manifest is defined, + # as otherwise _use_native_activity and _android_manifest would not be used. + assert(_use_native_activity != "" && _android_manifest != "") + + if (!defined(invoker.android_manifest)) { + _allow_cleartext_traffic = defined(invoker.allow_cleartext_traffic) && + invoker.allow_cleartext_traffic + jinja_template("${target_name}_manifest") { + _native_library_name = get_label_info(invoker.shared_library, "name") + if (defined(invoker.android_manifest_template)) { + input = invoker.android_manifest_template + } else { + input = + "//testing/android/native_test/java/AndroidManifest.xml.jinja2" + } + output = _android_manifest + variables = [ + "is_component_build=${is_component_build}", + "native_library_name=${_native_library_name}", + "use_native_activity=${_use_native_activity}", + "allow_cleartext_traffic=${_allow_cleartext_traffic}", + ] + } + } + + android_apk(target_name) { + data_deps = [] + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + testonly = true + create_apk_script = false + enable_native_mocks = true + + # TODO(crbug.com/1099849): Figure out why angle tests fail to launch + # with newer target_sdk_version. + if (!defined(invoker.target_sdk_version) && _use_native_activity) { + target_sdk_version = 24 + } + + assert(!defined(invoker.proguard_enabled) || !invoker.proguard_enabled || + invoker.proguard_configs != []) + + if (!defined(apk_name)) { + apk_name = get_label_info(invoker.shared_library, "name") + } + + if (!defined(android_manifest)) { + android_manifest_dep = ":${target_name}_manifest" + android_manifest = _android_manifest + } + + final_apk_path = "$root_build_dir/${apk_name}_apk/${apk_name}-debug.apk" + + if (!defined(use_default_launcher) || use_default_launcher) { + deps += [ + "//base:base_java", + "//build/android/gtest_apk:native_test_instrumentation_test_runner_java", + "//testing/android/native_test:native_test_java", + ] + } + shared_libraries = [ invoker.shared_library ] + deps += [ + ":${target_name}__secondary_abi_shared_library_list", + ":${target_name}__shared_library_list", + ] + } + } + + # Generate .java files from .aidl files. + # + # This target will store the .java files in a srcjar and should be included in + # an android_library or android_apk's srcjar_deps. + # + # Variables + # sources: Paths to .aidl files to compile. + # import_include: Path to directory containing .java files imported by the + # .aidl files. + # interface_file: Preprocessed aidl file to import. + # + # Example + # android_aidl("foo_aidl") { + # import_include = "java/src" + # sources = [ + # "java/src/com/foo/bar/FooBarService.aidl", + # "java/src/com/foo/bar/FooBarServiceCallback.aidl", + # ] + # } + template("android_aidl") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + script = "//build/android/gyp/aidl.py" + depfile = "$target_gen_dir/$target_name.d" + sources = invoker.sources + + _srcjar_path = "${target_gen_dir}/${target_name}.srcjar" + _aidl_path = "${android_sdk_build_tools}/aidl" + _framework_aidl = "$android_sdk/framework.aidl" + _imports = [ _framework_aidl ] + if (defined(invoker.interface_file)) { + assert(invoker.interface_file != "") + _imports += [ invoker.interface_file ] + } + + inputs = [ _aidl_path ] + _imports + + outputs = [ _srcjar_path ] + _rebased_imports = rebase_path(_imports, root_build_dir) + args = [ + "--aidl-path", + rebase_path(_aidl_path, root_build_dir), + "--imports=$_rebased_imports", + "--srcjar", + rebase_path(_srcjar_path, root_build_dir), + "--depfile", + rebase_path(depfile, root_build_dir), + ] + if (defined(invoker.import_include) && invoker.import_include != []) { + _rebased_import_paths = [] + foreach(_import_path, invoker.import_include) { + _rebased_import_path = [] + _rebased_import_path = [ rebase_path(_import_path, root_build_dir) ] + _rebased_import_paths += _rebased_import_path + } + args += [ "--includes=$_rebased_import_paths" ] + } + args += rebase_path(sources, root_build_dir) + } + } + + # Compile a protocol buffer to java. + # + # This generates java files from protocol buffers and creates an Android library + # containing the classes. + # + # Variables + # sources (required) + # Paths to .proto files to compile. + # + # proto_path (required) + # Root directory of .proto files. + # + # deps (optional) + # Additional dependencies. Passed through to both the action and the + # android_library targets. + # + # import_dirs (optional) + # A list of extra import directories to be passed to protoc compiler. + # WARNING: This circumvents proto checkdeps, and should only be used + # when needed, typically when proto files cannot cleanly import through + # absolute paths, such as for third_party or generated .proto files. + # http://crbug.com/691451 tracks fixing this. + # + # Example: + # proto_java_library("foo_proto_java") { + # proto_path = "src/foo" + # sources = [ "$proto_path/foo.proto" ] + # } + template("proto_java_library") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _template_name = target_name + + action_with_pydeps("${_template_name}__protoc_java") { + # The suffix "__protoc_java.srcjar" is used by SuperSize to identify + # protobuf symbols. + _srcjar_path = "$target_gen_dir/$target_name.srcjar" + script = "//build/protoc_java.py" + + deps = [] + if (defined(invoker.deps)) { + deps += invoker.deps + } + + sources = invoker.sources + depfile = "$target_gen_dir/$target_name.d" + outputs = [ _srcjar_path ] + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--protoc", + rebase_path(android_protoc_bin, root_build_dir), + "--proto-path", + rebase_path(invoker.proto_path, root_build_dir), + "--srcjar", + rebase_path(_srcjar_path, root_build_dir), + ] + rebase_path(sources, root_build_dir) + + if (defined(invoker.import_dirs)) { + foreach(_import_dir, invoker.import_dirs) { + args += [ + "--import-dir", + rebase_path(_import_dir, root_build_dir), + ] + } + } + } + + android_library(target_name) { + chromium_code = false + sources = [] + srcjar_deps = [ ":${_template_name}__protoc_java" ] + deps = [ "//third_party/android_deps:protobuf_lite_runtime_java" ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + } + } + + # Declare an Android library target for a prebuilt AAR. + # + # This target creates an Android library containing java code and Android + # resources. For libraries without resources, it will not generate + # corresponding android_resources targets. + # + # To avoid slowing down "gn gen", an associated .info file must be committed + # along with the .aar file. In order to create this file, define the target + # and then run once with the gn arg "update_android_aar_prebuilts = true". + # + # Variables + # aar_path: Path to the AAR. + # info_path: Path to the .aar.info file (generated via + # update_android_aar_prebuilts GN arg). + # proguard_configs: List of proguard configs to use in final apk step for + # any apk that depends on this library. + # ignore_aidl: Whether to ignore .aidl files found with the .aar. + # ignore_assets: Whether to ignore assets found in the .aar. + # ignore_manifest: Whether to ignore creating manifest. + # ignore_native_libraries: Whether to ignore .so files found in the .aar. + # See also extract_native_libraries. + # ignore_proguard_configs: Whether to ignore proguard configs. + # ignore_info_updates: Whether to ignore the info file when + # update_android_aar_prebuilts gn arg is true. However, the info file + # will still be verified regardless of the value of this flag. + # strip_resources: Whether to ignore android resources found in the .aar. + # custom_package: Java package for generated R.java files. + # extract_native_libraries: Whether to extract .so files found in the .aar. + # If the file contains .so, either extract_native_libraries or + # ignore_native_libraries must be set. + # TODO(jbudorick@): remove this arguments after crbug.com/522043 is fixed. + # requires_android: Whether this target can only be used for compiling + # Android related targets. + # + # Example + # android_aar_prebuilt("foo_java") { + # aar_path = "foo.aar" + # } + template("android_aar_prebuilt") { + _info_path = "$target_name.info" + if (defined(invoker.info_path)) { + _info_path = invoker.info_path + } + _output_path = "${target_out_dir}/${target_name}" + + # Some targets only differ by _java with other targets so _java and _junit + # need to be replaced by non-empty strings to avoid duplicate targets. (e.g. + # androidx_window_window_java vs androidx_window_window_java_java). + _target_name_without_java_or_junit = + string_replace(string_replace(target_name, "_java", "_J"), + "_junit", + "_U") + + # This unpack target is a python action, not a valid java target. Since the + # java targets below depend on it, its name must not match the java patterns + # in internal_rules.gni. + _unpack_target_name = "${_target_name_without_java_or_junit}__unpack_aar" + _ignore_aidl = defined(invoker.ignore_aidl) && invoker.ignore_aidl + _ignore_assets = defined(invoker.ignore_assets) && invoker.ignore_assets + _ignore_manifest = + defined(invoker.ignore_manifest) && invoker.ignore_manifest + _ignore_native_libraries = defined(invoker.ignore_native_libraries) && + invoker.ignore_native_libraries + _ignore_proguard_configs = defined(invoker.ignore_proguard_configs) && + invoker.ignore_proguard_configs + _extract_native_libraries = defined(invoker.extract_native_libraries) && + invoker.extract_native_libraries + _strip_resources = + defined(invoker.strip_resources) && invoker.strip_resources + + # Allow 'resource_overlay' parameter even if there are no resources in order + # to keep the logic for generated 'android_aar_prebuilt' rules simple. + not_needed(invoker, [ "resource_overlay" ]) + + _ignore_info_updates = + defined(invoker.ignore_info_updates) && invoker.ignore_info_updates + + # Scan the AAR file and determine the resources and jar files. + # Some libraries might not have resources; others might have two jars. + if (!_ignore_info_updates && update_android_aar_prebuilts) { + print("Writing " + rebase_path(_info_path, "//")) + exec_script("//build/android/gyp/aar.py", + [ + "list", + rebase_path(invoker.aar_path, root_build_dir), + "--output", + rebase_path(_info_path, root_build_dir), + ]) + } + + # If "gn gen" is failing on the following line, you need to generate an + # .info file for your new target by running: + # gn gen --args='target_os="android" update_android_aar_prebuilts=true' out/tmp + # rm -r out/tmp + _scanned_files = read_file(_info_path, "scope") + + _use_scanned_assets = !_ignore_assets && _scanned_files.assets != [] + + assert(_ignore_aidl || _scanned_files.aidl == [], + "android_aar_prebuilt() aidl not yet supported." + + " Implement or use ignore_aidl = true." + + " http://crbug.com/644439") + assert( + !_scanned_files.has_native_libraries || + (_ignore_native_libraries || _extract_native_libraries), + "android_aar_prebuilt() contains .so files." + + " Please set ignore_native_libraries or extract_native_libraries.") + assert( + !(_ignore_native_libraries && _extract_native_libraries), + "ignore_native_libraries and extract_native_libraries cannot both be set.") + assert(!_scanned_files.has_native_libraries || + _scanned_files.native_libraries != []) + assert(_scanned_files.has_classes_jar || _scanned_files.subjars == []) + + action_with_pydeps(_unpack_target_name) { + script = "//build/android/gyp/aar.py" # Unzips the AAR + args = [ + "extract", + rebase_path(invoker.aar_path, root_build_dir), + "--output-dir", + rebase_path(_output_path, root_build_dir), + "--assert-info-file", + rebase_path(_info_path, root_build_dir), + ] + if (_strip_resources) { + args += [ "--ignore-resources" ] + } + inputs = [ invoker.aar_path ] + outputs = [ "${_output_path}/AndroidManifest.xml" ] + if (!_strip_resources && _scanned_files.has_r_text_file) { + # Certain packages, in particular Play Services have no R.txt even + # though its presence is mandated by AAR spec. Such packages cause + # spurious rebuilds if this output is specified unconditionally. + outputs += [ "${_output_path}/R.txt" ] + } + + if (!_strip_resources && _scanned_files.resources != []) { + outputs += get_path_info( + rebase_path(_scanned_files.resources, "", _output_path), + "abspath") + } + if (_scanned_files.has_classes_jar) { + outputs += [ "${_output_path}/classes.jar" ] + } + outputs += + get_path_info(rebase_path(_scanned_files.subjars, "", _output_path), + "abspath") + if (!_ignore_proguard_configs) { + if (_scanned_files.has_proguard_flags) { + outputs += [ "${_output_path}/proguard.txt" ] + } + } + + if (_extract_native_libraries && _scanned_files.has_native_libraries) { + outputs += get_path_info( + rebase_path(_scanned_files.native_libraries, "", _output_path), + "abspath") + } + if (_use_scanned_assets) { + outputs += + get_path_info(rebase_path(_scanned_files.assets, "", _output_path), + "abspath") + } + } + + _has_unignored_resources = + !_strip_resources && + (_scanned_files.resources != [] || _scanned_files.has_r_text_file) + + _should_process_manifest = + !_ignore_manifest && !_scanned_files.is_manifest_empty + + # Create the android_resources target for resources. + if (_has_unignored_resources || _should_process_manifest) { + _res_target_name = "${target_name}__resources" + android_resources(_res_target_name) { + forward_variables_from(invoker, + [ + "custom_package", + "resource_overlay", + "testonly", + "strip_drawables", + ]) + deps = [ ":$_unpack_target_name" ] + if (_should_process_manifest) { + android_manifest_dep = ":$_unpack_target_name" + android_manifest = "${_output_path}/AndroidManifest.xml" + } else if (defined(_scanned_files.manifest_package) && + !defined(custom_package)) { + custom_package = _scanned_files.manifest_package + } + + sources = [] + if (!_strip_resources) { + sources = rebase_path(_scanned_files.resources, "", _output_path) + } + if (!_strip_resources && _scanned_files.has_r_text_file) { + r_text_file = "${_output_path}/R.txt" + } + } + } else if (defined(invoker.strip_drawables)) { + not_needed(invoker, [ "strip_drawables" ]) + } + + if (_ignore_manifest) { + # Having this available can be useful for DFMs that depend on AARs. It + # provides a way to have manifest entries go into the base split while + # the code goes into a DFM. + java_group("${target_name}__ignored_manifest") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + deps = [ ":$_unpack_target_name" ] + mergeable_android_manifests = [ "${_output_path}/AndroidManifest.xml" ] + } + } + + # Create the android_assets target for assets + if (_use_scanned_assets) { + _assets_target_name = "${target_name}__assets" + android_assets(_assets_target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + renaming_sources = [] + renaming_destinations = [] + foreach(_asset_file, _scanned_files.assets) { + _original_path = + get_path_info(rebase_path(_asset_file, "", _output_path), + "abspath") + _updated_path = string_replace(_asset_file, "assets/", "", 1) + renaming_sources += [ _original_path ] + renaming_destinations += [ _updated_path ] + } + } + } + + # Create android_java_prebuilt target for classes.jar. + if (_scanned_files.has_classes_jar) { + _java_library_vars = [ + "bytecode_rewriter_target", + "enable_bytecode_checks", + "jar_excluded_patterns", + "jar_included_patterns", + "missing_classes_allowlist", + "requires_android", + "testonly", + "use_classic_desugar", + ] + + # Create android_java_prebuilt target for extra jars within jars/. + _subjar_targets = [] + foreach(_tuple, _scanned_files.subjar_tuples) { + _current_target = "${target_name}__subjar_${_tuple[0]}" + _subjar_targets += [ ":$_current_target" ] + java_prebuilt(_current_target) { + forward_variables_from(invoker, _java_library_vars) + deps = [ ":$_unpack_target_name" ] + if (!defined(requires_android)) { + requires_android = true + } + supports_android = true + jar_path = "$_output_path/${_tuple[1]}" + _base_output_name = get_path_info(jar_path, "name") + output_name = "${invoker.target_name}-$_base_output_name" + public_target_label = invoker.target_name + } + } + + _jar_target_name = "${target_name}__classes" + java_prebuilt(_jar_target_name) { + forward_variables_from(invoker, _java_library_vars) + forward_variables_from(invoker, + [ + "deps", + "input_jars_paths", + "proguard_configs", + ]) + if (!defined(deps)) { + deps = [] + } + deps += _subjar_targets + [ ":$_unpack_target_name" ] + if (defined(_res_target_name)) { + deps += [ ":$_res_target_name" ] + } + if (!defined(requires_android)) { + requires_android = true + } + supports_android = true + jar_path = "$_output_path/classes.jar" + aar_path = invoker.aar_path + output_name = invoker.target_name + + if (!_ignore_proguard_configs) { + if (!defined(proguard_configs)) { + proguard_configs = [] + } + if (_scanned_files.has_proguard_flags) { + proguard_configs += [ "$_output_path/proguard.txt" ] + } + } + public_target_label = invoker.target_name + } + } + + java_group(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + public_deps = [ ":$_unpack_target_name" ] + deps = [] + if (defined(_jar_target_name)) { + deps += [ ":$_jar_target_name" ] + + # Although subjars are meant to be private, we add them as deps here + # because in practice they seem to contain classes required to be in the + # classpath. + deps += _subjar_targets + } + if (defined(_res_target_name)) { + deps += [ ":$_res_target_name" ] + } + if (defined(_assets_target_name)) { + deps += [ ":$_assets_target_name" ] + } + } + } + + # Create an Android application bundle from one base android_apk target, + # and zero or more associated android_apk. + # + # Variables: + # base_module_target: Name of the android_app_bundle_module target + # corresponding to the base module for this application bundle. The + # bundle file will include the same content in its base module, though in + # a slightly different format. + # + # bundle_base_path: Optional. If set, the bundle will be output to this + # directory. Defaults to "$root_build_dir/apks". + # + # bundle_name: Optional. If set, the bundle will be output to the + # filename "${bundle_name}.aab". + # + # extra_modules: Optional list of scopes, one per extra module used by + # this bundle. Each scope must have a 'name' field that specifies the + # module name (which cannot be 'base', since this is reserved for the + # base module), and an 'apk_target' field that specified the + # corresponding android_apk target name the module is modeled on. + # + # enable_language_splits: Optional. If true, enable APK splits based + # on languages. + # + # keystore_path: optional keystore path, used only when generating APKs. + # keystore_name: optional keystore name, used only when generating APKs. + # keystore_password: optional keystore password, used only when + # generating APKs. + # + # command_line_flags_file: Optional. If provided, named of the on-device + # file that will be used to store command-line arguments. The default + # is 'command_line_flags_file', but this is typically redefined to + # something more specific for certain bundles (e.g. the Chromium based + # APKs use 'chrome-command-line', the WebView one uses + # 'webview-command-line'). + # + # proguard_enabled: Optional. True if proguarding is enabled for this + # bundle. Default is to enable this only for release builds. Note that + # this will always perform synchronized proguarding. + # + # proguard_enable_obfuscation: Whether to enable obfuscation (default=true) + # + # enable_multidex: Optional. Enable multidexing of optimized modules jars + # when using synchronized proguarding. Only applies to base module. + # + # proguard_android_sdk_dep: Optional. android_system_java_prebuilt() target + # used as a library jar for synchronized proguarding. + # + # compress_shared_libraries: Optional. Whether to compress shared libraries + # such that they are extracted upon install. Libraries prefixed with + # "crazy." are never compressed. + # + # system_image_locale_allowlist: List of locales that should be included + # on system APKs generated from this bundle. + # + # static_library_provider: Specifies a single target that this target will + # use as a static library APK. + # Additionally, when allotting libraries to be packaged into modules, the + # libraries packaged into the static library will be accounted for to + # avoid library duplication. Effectively, the static library will be + # treated as the parent of the base module. + # + # expected_libs_and_assets: Verify the list of included native libraries + # and assets is consistent with the given expectation file. + # expected_libs_and_assets_base: Treat expected_libs_and_assets as a diff + # with this file as the base. + # expected_proguard_config: Checks that the merged set of proguard flags + # matches the given config. + # expected_proguard_config_base: Treat expected_proguard_config as a diff + # with this file as the base. + # + # version_code: Optional. Version code of the target. + # + # is_multi_abi: If true will add a library placeholder for the missing ABI + # if either the primary or the secondary ABI has no native libraries set. + # + # default_modules_for_testing: (optional): A list of DFM that the wrapper + # script should install. This is for local testing only, and does not + # affect the actual DFM in production. + # Example: + # android_app_bundle("chrome_public_bundle") { + # base_module_target = "//chrome/android:chrome_public_apk" + # extra_modules = [ + # { # NOTE: Scopes require one field per line, and no comma separators. + # name = "my_module" + # module_target = ":my_module" + # }, + # ] + # } + # + template("android_app_bundle") { + _target_name = target_name + _uses_static_library = defined(invoker.static_library_provider) + _proguard_enabled = + defined(invoker.proguard_enabled) && invoker.proguard_enabled + + if (defined(invoker.version_code)) { + _version_code = invoker.version_code + } else { + _version_code = android_default_version_code + } + + if (android_override_version_code != "") { + _version_code = android_override_version_code + } + + # Prevent "unused variable". + not_needed([ "_version_code" ]) + + _bundle_base_path = "$root_build_dir/apks" + if (defined(invoker.bundle_base_path)) { + _bundle_base_path = invoker.bundle_base_path + } + + _bundle_name = _target_name + if (defined(invoker.bundle_name)) { + _bundle_name = invoker.bundle_name + } + _bundle_path = "$_bundle_base_path/${_bundle_name}.aab" + _rebased_bundle_path = rebase_path(_bundle_path, root_build_dir) + + _base_target_name = get_label_info(invoker.base_module_target, "name") + _base_target_gen_dir = + get_label_info(invoker.base_module_target, "target_gen_dir") + _base_module_build_config = + "$_base_target_gen_dir/${_base_target_name}.build_config.json" + _base_module_build_config_target = + "${invoker.base_module_target}$build_config_target_suffix" + _rebased_base_module_build_config = + rebase_path(_base_module_build_config, root_build_dir) + + _modules = [ + { + name = "base" + module_target = invoker.base_module_target + build_config = _base_module_build_config + build_config_target = _base_module_build_config_target + if (_uses_static_library) { + parent = "lib" + } + }, + ] + + _enable_multidex = + !defined(invoker.enable_multidex) || invoker.enable_multidex + + # Prevent "unused variable". + not_needed([ "_enable_multidex" ]) + + if (_proguard_enabled) { + _uses_static_library_synchronized_proguard = + defined(invoker.static_library_synchronized_proguard) && + invoker.static_library_synchronized_proguard + + # TODO(crbug.com/1032609): Remove dexsplitter from Trichrome Proguard. + _dex_target = "${_target_name}__dex" + _proguard_mapping_path = "${_bundle_path}.mapping" + } + + assert(_proguard_enabled || !defined(invoker.enable_multidex), + "Bundle only adds dexing step if proguarding is enabled.") + + if (defined(invoker.extra_modules)) { + _module_count = 0 + not_needed([ "_module_count" ]) + + foreach(_module, invoker.extra_modules) { + _module_count += 1 + assert(defined(_module.name), + "Missing 'name' field for extra module #${_module_count}.") + assert(_module.name != "base", + "Module name 'base' is reserved for the main bundle module") + assert( + defined(_module.module_target), + "Missing 'module_target' field for extra module ${_module.name}.") + _module_target = _module.module_target + _module_target_name = get_label_info(_module_target, "name") + _module_target_gen_dir = + get_label_info(_module_target, "target_gen_dir") + _module.build_config = + "$_module_target_gen_dir/${_module_target_name}.build_config.json" + _module.build_config_target = + "$_module_target$build_config_target_suffix" + _module.parent = "base" + _modules += [ _module ] + } + } + + # Make build config, which is required for synchronized proguarding. + _module_java_targets = [] + _module_build_configs = [] + _module_targets = [] + foreach(_module, _modules) { + _module_targets += [ _module.module_target ] + _module_java_targets += [ "${_module.module_target}__java" ] + _module_build_configs += [ _module.build_config ] + } + + if (_uses_static_library) { + _lib_proxy_module = { + name = "lib" + } + _static_library_target_name = + get_label_info(invoker.static_library_provider, "name") + _static_library_gen_dir = + get_label_info(invoker.static_library_provider, "target_gen_dir") + _lib_proxy_module.build_config = "$_static_library_gen_dir/$_static_library_target_name.build_config.json" + _lib_proxy_module.build_config_target = + "${invoker.static_library_provider}$build_config_target_suffix" + } + + # Allot native libraries to modules they should be packaged into. This is + # necessary since all libraries that are depended on by multiple modules + # have to go into base or the static shared library if it exists. + # TODO(crbug.com/1021565): It would be nice if this lived outside the + # android_app_bundle template and the static shared library would pull in + # the libs as allotted by this step. + _native_libraries_config = + "$target_gen_dir/$_target_name.native_libraries_config" + _native_libraries_config_target = "${_target_name}__allot_native_libraries" + allot_native_libraries(_native_libraries_config_target) { + modules = _modules + native_libraries_filearg_keys = [ + "native:libraries", + "native:loadable_modules", + ] + output = _native_libraries_config + if (_uses_static_library) { + modules += [ _lib_proxy_module ] + } + } + if (defined(android_app_secondary_abi)) { + _secondary_abi_native_libraries_config = + "$target_gen_dir/$_target_name.secondary_abi_native_libraries_config" + _secondary_abi_native_libraries_config_target = + "${_target_name}__allot_secondary_abi_native_libraries" + allot_native_libraries(_secondary_abi_native_libraries_config_target) { + modules = _modules + native_libraries_filearg_keys = [ + "native:secondary_abi_libraries", + "native:secondary_abi_loadable_modules", + ] + output = _secondary_abi_native_libraries_config + if (_uses_static_library) { + modules += [ _lib_proxy_module ] + } + } + } + + # Used to expose the module Java targets of the bundle. + group("${_target_name}__java") { + deps = _module_java_targets + } + group("${_target_name}__compile_resources") { + deps = [ "${invoker.base_module_target}__compile_resources" ] + } + + _build_config = "$target_gen_dir/${_target_name}.build_config.json" + _rebased_build_config = rebase_path(_build_config, root_build_dir) + _build_config_target = "$_target_name$build_config_target_suffix" + if (defined(invoker.proguard_android_sdk_dep)) { + proguard_android_sdk_dep_ = invoker.proguard_android_sdk_dep + } else { + proguard_android_sdk_dep_ = "//third_party/android_sdk:android_sdk_java" + } + + if (_proguard_enabled) { + _proguard_mapping_path = "${_bundle_path}.mapping" + } + + write_build_config(_build_config_target) { + type = "android_app_bundle" + possible_config_deps = _module_targets + [ proguard_android_sdk_dep_ ] + build_config = _build_config + proguard_enabled = _proguard_enabled + module_build_configs = _module_build_configs + + if (_proguard_enabled) { + proguard_mapping_path = _proguard_mapping_path + } + } + + if (_proguard_enabled) { + # If this Bundle uses a static library, the static library APK will + # create the synchronized dex file path. + if (!_uses_static_library_synchronized_proguard) { + dex(_dex_target) { + forward_variables_from(invoker, + [ + "expected_proguard_config", + "expected_proguard_config_base", + "min_sdk_version", + "proguard_enable_obfuscation", + ]) + if (defined(expected_proguard_config)) { + top_target_name = _target_name + } + enable_multidex = _enable_multidex + proguard_enabled = true + proguard_mapping_path = _proguard_mapping_path + proguard_sourcefile_suffix = "$android_channel-$_version_code" + build_config = _build_config + + deps = _module_java_targets + [ ":$_build_config_target" ] + modules = _modules + } + } + } + + _all_create_module_targets = [] + _all_module_zip_paths = [] + _all_module_build_configs = [] + _all_module_unused_resources_deps = [] + foreach(_module, _modules) { + _module_target = _module.module_target + _module_build_config = _module.build_config + _module_build_config_target = _module.build_config_target + + if (!_proguard_enabled) { + _dex_target_for_module = "${_module_target}__final_dex" + } else { + _dex_target_for_module = ":$_dex_target" + } + + # Generate one module .zip file per bundle module. + # + # Important: the bundle tool uses the module's zip filename as + # the internal module name inside the final bundle, in other words, + # this file *must* be named ${_module.name}.zip + _create_module_target = "${_target_name}__${_module.name}__create" + _module_zip_path = "$target_gen_dir/$target_name/${_module.name}.zip" + create_android_app_bundle_module(_create_module_target) { + forward_variables_from(invoker, + [ + "is_multi_abi", + "min_sdk_version", + "uncompress_dex", + "proguard_enabled", + ]) + module_name = _module.name + build_config = _module_build_config + module_zip_path = _module_zip_path + native_libraries_config = _native_libraries_config + + if (module_name == "base" && + defined(invoker.expected_libs_and_assets)) { + forward_variables_from(invoker, + [ + "expected_libs_and_assets", + "expected_libs_and_assets_base", + ]) + top_target_name = _target_name + build_config_target = _module_build_config_target + native_libraries_config_target = ":$_native_libraries_config_target" + if (defined(android_app_secondary_abi)) { + secondary_abi_native_libraries_config_target = + ":$_secondary_abi_native_libraries_config_target" + } + } + + deps = [ + ":$_native_libraries_config_target", + _dex_target_for_module, + _module_build_config_target, + _module_target, + ] + + if (defined(android_app_secondary_abi)) { + secondary_abi_native_libraries_config = + _secondary_abi_native_libraries_config + deps += [ ":$_secondary_abi_native_libraries_config_target" ] + } + } + + _all_create_module_targets += [ + ":$_create_module_target", + _module_build_config_target, + "${_module_target}__compile_resources", + ] + _all_module_zip_paths += [ _module_zip_path ] + _all_module_build_configs += [ _module_build_config ] + _all_module_unused_resources_deps += [ + "${_module_target}__compile_resources", + _dex_target_for_module, + _module_build_config_target, + ] + } + if (defined(invoker.strip_unused_resources) && + invoker.strip_unused_resources) { + # Resources only live in the base module so we define the unused resources + # target only on the base module target. + _unused_resources_target = "${_base_target_name}__unused_resources" + _unused_resources_config = + "${_base_target_gen_dir}/${_base_target_name}_unused_resources.config" + unused_resources(_unused_resources_target) { + deps = _all_module_unused_resources_deps + all_module_build_configs = _all_module_build_configs + build_config = _base_module_build_config + if (_proguard_enabled) { + proguard_mapping_path = _proguard_mapping_path + } + output_config = _unused_resources_config + } + } + + _all_rebased_module_zip_paths = + rebase_path(_all_module_zip_paths, root_build_dir) + + _enable_language_splits = defined(invoker.enable_language_splits) && + invoker.enable_language_splits + + _split_dimensions = [] + if (_enable_language_splits) { + _split_dimensions += [ "language" ] + } + + _keystore_path = android_keystore_path + _keystore_password = android_keystore_password + _keystore_name = android_keystore_name + + if (defined(invoker.keystore_path)) { + _keystore_path = invoker.keystore_path + _keystore_password = invoker.keystore_password + _keystore_name = invoker.keystore_name + } + + _rebased_keystore_path = rebase_path(_keystore_path, root_build_dir) + + _bundle_target_name = "${_target_name}__bundle" + action_with_pydeps(_bundle_target_name) { + script = "//build/android/gyp/create_app_bundle.py" + inputs = _all_module_zip_paths + _all_module_build_configs + outputs = [ _bundle_path ] + deps = _all_create_module_targets + [ ":$_build_config_target" ] + args = [ + "--out-bundle=$_rebased_bundle_path", + "--rtxt-out-path=$_rebased_bundle_path.R.txt", + "--pathmap-out-path=$_rebased_bundle_path.pathmap.txt", + "--module-zips=$_all_rebased_module_zip_paths", + ] + if (_split_dimensions != []) { + args += [ "--split-dimensions=$_split_dimensions" ] + } + if (defined(invoker.compress_shared_libraries) && + invoker.compress_shared_libraries) { + args += [ "--compress-shared-libraries" ] + } + _min_sdk_version = default_min_sdk_version + if (defined(invoker.min_sdk_version)) { + _min_sdk_version = invoker.min_sdk_version + } + + # Android P+ support loading from stored dex. + if (_min_sdk_version < 27) { + args += [ "--compress-dex" ] + } + + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + + if (_enable_language_splits) { + args += [ + "--base-allowlist-rtxt-path=@FileArg(" + "${_rebased_base_module_build_config}:deps_info:base_allowlist_rtxt_path)", + "--base-module-rtxt-path=@FileArg(" + + "${_rebased_base_module_build_config}:deps_info:r_text_path)", + ] + } + if (defined(invoker.validate_services) && invoker.validate_services) { + args += [ "--validate-services" ] + } + + foreach(_module, _modules) { + _rebased_build_config = + rebase_path(_module.build_config, root_build_dir) + args += [ + "--uncompressed-assets=@FileArg(" + + "$_rebased_build_config:uncompressed_assets)", + "--rtxt-in-paths=@FileArg(" + + "$_rebased_build_config:deps_info:r_text_path)", + "--pathmap-in-paths=@FileArg(" + + "$_rebased_build_config:deps_info:module_pathmap_path)", + "--module-name=" + _module.name, + ] + } + + # http://crbug.com/725224. Fix for bots running out of memory. + if (defined(java_cmd_pool_size)) { + pool = "//build/config/android:java_cmd_pool($default_toolchain)" + } else { + pool = "//build/toolchain:link_pool($default_toolchain)" + } + } + + # Create size info files for targets that care about size + # (have proguard enabled). + if (_proguard_enabled) { + # Merge all module targets to obtain size info files for all targets. + _all_module_targets = _module_targets + + _size_info_target = "${_target_name}__size_info" + create_size_info_files(_size_info_target) { + name = "$_bundle_name.aab" + deps = _all_module_targets + [ ":$_build_config_target" ] + module_build_configs = _all_module_build_configs + } + } + + if (_uses_static_library) { + _install_artifacts_target = "${target_name}__install_artifacts" + _install_artifacts_json = + "${target_gen_dir}/${target_name}.install_artifacts" + generated_file(_install_artifacts_target) { + output_conversion = "json" + deps = [ invoker.static_library_provider ] + outputs = [ _install_artifacts_json ] + data_keys = [ "install_artifacts" ] + rebase = root_build_dir + } + } + + # Generate a wrapper script for the bundle. + _android_aapt2_path = android_sdk_tools_bundle_aapt2 + + _bundle_apks_path = "$_bundle_base_path/$_bundle_name.apks" + _bundle_wrapper_script_dir = "$root_build_dir/bin" + _bundle_wrapper_script_path = "$_bundle_wrapper_script_dir/$_target_name" + + action_with_pydeps("${_target_name}__wrapper_script") { + script = "//build/android/gyp/create_bundle_wrapper_script.py" + inputs = [ _base_module_build_config ] + outputs = [ _bundle_wrapper_script_path ] + + # Telemetry for bundles uses the wrapper script for installation. + data = [ + _bundle_wrapper_script_path, + _android_aapt2_path, + _keystore_path, + _bundle_path, + ] + data_deps = [ + "//build/android:apk_operations_py", + "//build/android:stack_tools", + ] + + deps = [ _base_module_build_config_target ] + args = [ + "--script-output-path", + rebase_path(_bundle_wrapper_script_path, root_build_dir), + "--package-name=@FileArg(" + + "$_rebased_base_module_build_config:deps_info:package_name)", + "--aapt2", + rebase_path(_android_aapt2_path, root_build_dir), + "--bundle-path", + _rebased_bundle_path, + "--bundle-apks-path", + rebase_path(_bundle_apks_path, root_build_dir), + "--target-cpu=$target_cpu", + "--keystore-path", + _rebased_keystore_path, + "--keystore-password", + _keystore_password, + "--key-name", + _keystore_name, + ] + if (defined(invoker.default_modules_for_testing)) { + args += [ "--default-modules" ] + invoker.default_modules_for_testing + } + if (defined(invoker.system_image_locale_allowlist)) { + args += [ + "--system-image-locales=${invoker.system_image_locale_allowlist}", + ] + } + if (defined(invoker.command_line_flags_file)) { + args += [ + "--command-line-flags-file", + invoker.command_line_flags_file, + ] + } + if (_uses_static_library) { + deps += [ ":$_install_artifacts_target" ] + _rebased_install_artifacts_json = + rebase_path(_install_artifacts_json, root_build_dir) + _static_library_apk_path = + "@FileArg($_rebased_install_artifacts_json[])" + args += [ + "--additional-apk", + _static_library_apk_path, + ] + } + + if (_proguard_enabled) { + args += [ + "--proguard-mapping-path", + rebase_path(_proguard_mapping_path, root_build_dir), + ] + + # Required by logcat command. + data_deps += [ "//build/android/stacktrace:java_deobfuscate" ] + data += [ _proguard_mapping_path ] + } + } + + _enable_lint = defined(invoker.enable_lint) && invoker.enable_lint && + !disable_android_lint + if (_enable_lint) { + android_lint("${target_name}__lint") { + forward_variables_from(invoker, + [ + "lint_baseline_file", + "lint_suppressions_file", + "min_sdk_version", + ]) + build_config = _build_config + build_config_dep = ":$_build_config_target" + deps = _module_java_targets + if (defined(invoker.lint_suppressions_dep)) { + deps += [ invoker.lint_suppressions_dep ] + } + if (defined(invoker.lint_min_sdk_version)) { + min_sdk_version = invoker.lint_min_sdk_version + } + } + } else { + not_needed(invoker, + [ + "lint_baseline_file", + "lint_min_sdk_version", + "lint_suppressions_dep", + "lint_suppressions_file", + ]) + } + + group(_target_name) { + public_deps = [ + ":$_bundle_target_name", + ":${_target_name}__wrapper_script", + ] + if (defined(_size_info_target)) { + public_deps += [ ":$_size_info_target" ] + } + if (_enable_lint) { + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += [ ":${target_name}__lint" ] + } + } + + _apks_path = "$root_build_dir/apks/$_bundle_name.apks" + action_with_pydeps("${_target_name}_apks") { + script = "//build/android/gyp/create_app_bundle_apks.py" + inputs = [ _bundle_path ] + outputs = [ _apks_path ] + data = [ _apks_path ] + args = [ + "--bundle", + _rebased_bundle_path, + "--output", + rebase_path(_apks_path, root_build_dir), + "--aapt2-path", + rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir), + "--keystore-path", + rebase_path(android_keystore_path, root_build_dir), + "--keystore-name", + android_keystore_name, + "--keystore-password", + android_keystore_password, + ] + if (debuggable_apks) { + args += [ "--local-testing" ] + } + deps = [ ":$_bundle_target_name" ] + metadata = { + install_artifacts = [ _apks_path ] + } + if (defined(invoker.static_library_provider)) { + metadata.install_artifacts_barrier = [] + } + + # http://crbug.com/725224. Fix for bots running out of memory. + if (defined(java_cmd_pool_size)) { + pool = "//build/config/android:java_cmd_pool($default_toolchain)" + } else { + pool = "//build/toolchain:link_pool($default_toolchain)" + } + } + } + + # Create an .apks file from an .aab file. The .apks file will contain the + # minimal set of .apk files needed for tracking binary size. + # The file will be created at "$bundle_path_without_extension.minimal.apks". + # + # Variables: + # bundle_path: Path to the input .aab file. + # + # Example: + # create_app_bundle_minimal_apks("minimal_apks") { + # deps = [ + # ":bundle_target", + # ] + # bundle_path = "$root_build_dir/apks/Bundle.aab" + # } + template("create_app_bundle_minimal_apks") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + script = "//build/android/gyp/create_app_bundle_apks.py" + _dir = get_path_info(invoker.bundle_path, "dir") + _name = get_path_info(invoker.bundle_path, "name") + _output_path = "$_dir/$_name.minimal.apks" + outputs = [ _output_path ] + inputs = [ invoker.bundle_path ] + args = [ + "--bundle", + rebase_path(invoker.bundle_path, root_build_dir), + "--output", + rebase_path(_output_path, root_build_dir), + "--aapt2-path", + rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir), + "--keystore-path", + rebase_path(android_keystore_path, root_build_dir), + "--keystore-name", + android_keystore_name, + "--keystore-password", + android_keystore_password, + "--minimal", + ] + } + } +} + +# Generate an Android resources target that contains localized strings +# describing the current locale used by the Android framework to display +# UI strings. These are used by +# org.chromium.chrome.browser.ChromeLocalizationUtils. +# +# Variables: +# ui_locales: List of Chromium locale names to generate resources for. +# +template("generate_ui_locale_resources") { + _generating_target_name = "${target_name}__generate" + _rebased_output_zip_path = rebase_path(target_gen_dir, root_gen_dir) + _output_zip = "${root_out_dir}/resource_zips/${_rebased_output_zip_path}/" + + "${target_name}.zip" + + action_with_pydeps(_generating_target_name) { + script = "//build/android/gyp/create_ui_locale_resources.py" + outputs = [ _output_zip ] + args = [ + "--locale-list=${invoker.ui_locales}", + "--output-zip", + rebase_path(_output_zip, root_build_dir), + ] + } + + android_generated_resources(target_name) { + generating_target = ":$_generating_target_name" + generated_resources_zip = _output_zip + } +} diff --git a/third_party/libwebrtc/build/config/android/sdk.gni b/third_party/libwebrtc/build/config/android/sdk.gni new file mode 100644 index 0000000000..8547170167 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/sdk.gni @@ -0,0 +1,10 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# The default SDK release used by public builds. Value may differ in +# internal builds. +default_android_sdk_release = "s" + +# SDK releases against which public builds are supported. +public_sdk_releases = [ "s" ] diff --git a/third_party/libwebrtc/build/config/android/test/classpath_order/BUILD.gn b/third_party/libwebrtc/build/config/android/test/classpath_order/BUILD.gn new file mode 100644 index 0000000000..decd1a84d2 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/classpath_order/BUILD.gn @@ -0,0 +1,111 @@ +# Copyright 2021 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") + +template("test_resources") { + jinja_template_resources(target_name) { + forward_variables_from(invoker, "*") + testonly = true + variables = [ "resource_name=$resource_name" ] + res_dir = "java/res_template" + resources = [ "java/res_template/values/values.xml" ] + } +} + +template("generate_dummy_android_library") { + # No underscores to avoid crbug.com/908819. + _generate_java_source_target_name = "${target_name}generatejavasource" + jinja_template(_generate_java_source_target_name) { + testonly = true + input = "java/src/org/chromium/build/classpath_order/Dummy.java.jinja2" + output = "$target_gen_dir/java/src/org/chromium/build/classpath_order/${invoker.class_name}.java" + variables = [ "class_name=${invoker.class_name}" ] + } + + android_library(target_name) { + forward_variables_from(invoker, "*") + + if (!defined(invoker.deps)) { + deps = [] + } + + sources = get_target_outputs(":${_generate_java_source_target_name}") + deps += [ ":${_generate_java_source_target_name}" ] + } +} + +# Test that classpath order keeps resources accessible when multiple targets generate +# resources for the same package. Specifically, test that an android_library precedes +# its dependencies regardless of the relative lexographic order. + +test_resources("a1_dependency_resources") { + resource_name = "a1_dependency_resource" +} + +generate_dummy_android_library("a1_dependency_java") { + testonly = true + class_name = "A1Dependency" + resources_package = "org.chromium.build.classpath_order.test1" + deps = [ ":a1_dependency_resources" ] +} + +test_resources("z1_master_resources") { + resource_name = "z1_master_resource" + deps = [ ":a1_dependency_resources" ] +} + +generate_dummy_android_library("z1_master_java") { + testonly = true + class_name = "Z1Master" + resources_package = "org.chromium.build.classpath_order.test1" + deps = [ + ":a1_dependency_java", + ":z1_master_resources", + ] +} + +test_resources("z2_dependency_resources") { + resource_name = "z2_dependency_resource" +} + +generate_dummy_android_library("z2_dependency_java") { + testonly = true + class_name = "Z2Dependency" + resources_package = "org.chromium.build.classpath_order.test2" + deps = [ ":z2_dependency_resources" ] +} + +test_resources("a2_master_resources") { + resource_name = "a2_master_resource" + deps = [ ":z2_dependency_resources" ] +} + +generate_dummy_android_library("a2_master_java") { + testonly = true + class_name = "A2Master" + resources_package = "org.chromium.build.classpath_order.test2" + deps = [ + ":a2_master_resources", + ":z2_dependency_java", + ] +} + +java_library("junit_tests") { + bypass_platform_checks = true + testonly = true + sources = + [ "java/src/org/chromium/build/classpath_order/ClassPathOrderTest.java" ] + deps = [ + ":a1_dependency_java", + ":a2_master_java", + ":z1_master_java", + ":z2_dependency_java", + "//testing/android/junit:junit_test_support", + "//third_party/android_deps:robolectric_all_java", + "//third_party/android_support_test_runner:runner_java", + "//third_party/androidx:androidx_test_runner_java", + "//third_party/junit", + ] +} diff --git a/third_party/libwebrtc/build/config/android/test/classpath_order/java/res_template/values/values.xml b/third_party/libwebrtc/build/config/android/test/classpath_order/java/res_template/values/values.xml new file mode 100644 index 0000000000..ee706b289b --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/classpath_order/java/res_template/values/values.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2021 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + + +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + <integer name="{{resource_name}}">42</integer> +</resources> diff --git a/third_party/libwebrtc/build/config/android/test/classpath_order/java/src/org/chromium/build/classpath_order/ClassPathOrderTest.java b/third_party/libwebrtc/build/config/android/test/classpath_order/java/src/org/chromium/build/classpath_order/ClassPathOrderTest.java new file mode 100644 index 0000000000..c5a9202605 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/classpath_order/java/src/org/chromium/build/classpath_order/ClassPathOrderTest.java @@ -0,0 +1,32 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.build.classpath_order; + +import static org.junit.Assert.assertTrue; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +import org.chromium.testing.local.LocalRobolectricTestRunner; + +/** + * Test that resources defined in different android_resources() targets but with the same + * package are accessible. + */ +@RunWith(LocalRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public final class ClassPathOrderTest { + @Test + @SmallTest + public void testAll() { + assertTrue(org.chromium.build.classpath_order.test1.R.integer.a1_dependency_resource >= 0); + assertTrue(org.chromium.build.classpath_order.test1.R.integer.z1_master_resource >= 0); + assertTrue(org.chromium.build.classpath_order.test2.R.integer.z2_dependency_resource >= 0); + assertTrue(org.chromium.build.classpath_order.test2.R.integer.a2_master_resource >= 0); + } +} diff --git a/third_party/libwebrtc/build/config/android/test/classpath_order/java/src/org/chromium/build/classpath_order/Dummy.java.jinja2 b/third_party/libwebrtc/build/config/android/test/classpath_order/java/src/org/chromium/build/classpath_order/Dummy.java.jinja2 new file mode 100644 index 0000000000..0ccf28b284 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/classpath_order/java/src/org/chromium/build/classpath_order/Dummy.java.jinja2 @@ -0,0 +1,8 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.build.classpath_order; + +public class {{class_name}} { +} diff --git a/third_party/libwebrtc/build/config/android/test/proto/BUILD.gn b/third_party/libwebrtc/build/config/android/test/proto/BUILD.gn new file mode 100644 index 0000000000..a28111a66a --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/proto/BUILD.gn @@ -0,0 +1,103 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") +import("//third_party/protobuf/proto_library.gni") + +# The purpose of these targets is test that |deps| satisfies java compilation +# dependencies, and that |import_dirs| allows us to deal with various relative +# imports to other proto dependencies. Although we should strive to avoid using +# |import_dirs| and relative import paths, preferring to use absolute imports +# whenever possible. See https://crbug.com/691451. While this target is +# primarily to test that the Java proto targets build correctly, also build the +# C++ versions of the protos as well. There are currently some configurations of +# Java protos that can be built but will not work for C++, see +# https://crbug.com/1039014, so make sure we don't create any tests that would +# violate that. +group("test_build_protos") { + deps = [ + ":absolute_root_proto", + ":absolute_root_proto_java", + ":relative_root_proto", + ":relative_root_proto_java", + ] +} + +proto_java_library("absolute_root_proto_java") { + proto_path = "//" + import_dirs = [ "relative_dep/" ] + sources = [ + "root/absolute_child.proto", + "root/absolute_root.proto", + ] + deps = [ + ":absolute_dep_proto_java", + ":relative_dep_proto_java", + ] +} + +proto_java_library("relative_root_proto_java") { + proto_path = "root/" + import_dirs = [ + "relative_dep/", + "//", + ] + sources = [ + "root/relative_child.proto", + "root/relative_root.proto", + ] + deps = [ + ":absolute_dep_proto_java", + ":relative_dep_proto_java", + ] +} + +proto_java_library("absolute_dep_proto_java") { + proto_path = "//" + sources = [ "absolute_dep/absolute_dep.proto" ] +} + +proto_java_library("relative_dep_proto_java") { + proto_path = "relative_dep/" + sources = [ "relative_dep/relative_dep.proto" ] +} + +proto_library("absolute_root_proto") { + proto_in_dir = "//" + import_dirs = [ "relative_dep/" ] + sources = [ + "root/absolute_child.proto", + "root/absolute_root.proto", + ] + link_deps = [ + ":absolute_dep_proto", + ":relative_dep_proto", + ] +} + +proto_library("relative_root_proto") { + proto_in_dir = "root/" + import_dirs = [ + "relative_dep/", + "//", + ] + sources = [ + "root/relative_child.proto", + "root/relative_root.proto", + ] + link_deps = [ + ":absolute_dep_proto", + ":relative_dep_proto", + ] +} + +proto_library("absolute_dep_proto") { + proto_in_dir = "//" + sources = [ "absolute_dep/absolute_dep.proto" ] +} + +proto_library("relative_dep_proto") { + proto_in_dir = "relative_dep/" + sources = [ "relative_dep/relative_dep.proto" ] +} diff --git a/third_party/libwebrtc/build/config/android/test/proto/absolute_dep/absolute_dep.proto b/third_party/libwebrtc/build/config/android/test/proto/absolute_dep/absolute_dep.proto new file mode 100644 index 0000000000..46dcce7679 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/proto/absolute_dep/absolute_dep.proto @@ -0,0 +1,10 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +package build.config.android.test; +option java_package = "build.config.android.test"; + +message AbsoluteDep {} diff --git a/third_party/libwebrtc/build/config/android/test/proto/relative_dep/relative_dep.proto b/third_party/libwebrtc/build/config/android/test/proto/relative_dep/relative_dep.proto new file mode 100644 index 0000000000..600b6ca7fe --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/proto/relative_dep/relative_dep.proto @@ -0,0 +1,10 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +package build.config.android.test; +option java_package = "build.config.android.test"; + +message RelativeDep {} diff --git a/third_party/libwebrtc/build/config/android/test/proto/root/absolute_child.proto b/third_party/libwebrtc/build/config/android/test/proto/root/absolute_child.proto new file mode 100644 index 0000000000..d6a6a13f36 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/proto/root/absolute_child.proto @@ -0,0 +1,10 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +package build.config.android.test; +option java_package = "build.config.android.test"; + +message AbsoluteChild {} diff --git a/third_party/libwebrtc/build/config/android/test/proto/root/absolute_root.proto b/third_party/libwebrtc/build/config/android/test/proto/root/absolute_root.proto new file mode 100644 index 0000000000..3e200978d9 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/proto/root/absolute_root.proto @@ -0,0 +1,18 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +package build.config.android.test; +option java_package = "build.config.android.test"; + +import "build/config/android/test/proto/root/absolute_child.proto"; +import "build/config/android/test/proto/absolute_dep/absolute_dep.proto"; +import "relative_dep.proto"; + +message AbsoluteRoot { + optional AbsoluteChild absolute_child = 1; + optional AbsoluteDep absolute_dep = 2; + optional RelativeDep relative_dep = 3; +} diff --git a/third_party/libwebrtc/build/config/android/test/proto/root/relative_child.proto b/third_party/libwebrtc/build/config/android/test/proto/root/relative_child.proto new file mode 100644 index 0000000000..10f7ed4277 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/proto/root/relative_child.proto @@ -0,0 +1,10 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +package build.config.android.test; +option java_package = "build.config.android.test"; + +message RelativeChild {} diff --git a/third_party/libwebrtc/build/config/android/test/proto/root/relative_root.proto b/third_party/libwebrtc/build/config/android/test/proto/root/relative_root.proto new file mode 100644 index 0000000000..a37a268b4f --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/proto/root/relative_root.proto @@ -0,0 +1,18 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +package build.config.android.test; +option java_package = "build.config.android.test"; + +import "relative_child.proto"; +import "build/config/android/test/proto/absolute_dep/absolute_dep.proto"; +import "relative_dep.proto"; + +message RelativeRoot { + optional RelativeChild relative_child = 1; + optional AbsoluteDep absolute_dep = 2; + optional RelativeDep relative_dep = 3; +} diff --git a/third_party/libwebrtc/build/config/android/test/resource_overlay/BUILD.gn b/third_party/libwebrtc/build/config/android/test/resource_overlay/BUILD.gn new file mode 100644 index 0000000000..4a063d2215 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/resource_overlay/BUILD.gn @@ -0,0 +1,60 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") + +# Tests for 'resource_overlay' parameter in android_resources() template. + +template("test_resources") { + jinja_template_resources(target_name) { + forward_variables_from(invoker, "*") + testonly = true + variables = [ + "resource_name=$resource_name", + "resource_value=$resource_value", + ] + res_dir = "java/res_template" + resources = [ "java/res_template/values/values.xml" ] + } +} + +test_resources("dependency_tagged_dependency_resources") { + resource_overlay = true + resource_name = "resource_overlay_dependency_tagged_secret" + resource_value = 41 +} + +test_resources("dependency_tagged_root_resources") { + resource_name = "resource_overlay_dependency_tagged_secret" + resource_value = 42 + deps = [ ":dependency_tagged_dependency_resources" ] +} + +test_resources("root_tagged_dependency_resources") { + resource_name = "resource_overlay_root_tagged_secret" + resource_value = 41 +} + +test_resources("root_tagged_root_resources") { + resource_overlay = true + resource_name = "resource_overlay_root_tagged_secret" + resource_value = 42 + deps = [ ":root_tagged_dependency_resources" ] +} + +android_library("javatests") { + testonly = true + sources = [ + "java/src/org/chromium/build/resource_overlay/ResourceOverlayTest.java", + ] + resources_package = "org.chromium.build.resource_overlay" + deps = [ + ":dependency_tagged_root_resources", + ":root_tagged_root_resources", + "//base:base_java_test_support", + "//third_party/android_support_test_runner:runner_java", + "//third_party/androidx:androidx_test_runner_java", + "//third_party/junit", + ] +} diff --git a/third_party/libwebrtc/build/config/android/test/resource_overlay/java/res_template/values/values.xml b/third_party/libwebrtc/build/config/android/test/resource_overlay/java/res_template/values/values.xml new file mode 100644 index 0000000000..973f855206 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/resource_overlay/java/res_template/values/values.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 The Chromium Authors. All rights reserved. + + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> + +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + <integer name="{{resource_name}}">{{resource_value}}</integer> +</resources>
\ No newline at end of file diff --git a/third_party/libwebrtc/build/config/android/test/resource_overlay/java/src/org/chromium/build/resource_overlay/ResourceOverlayTest.java b/third_party/libwebrtc/build/config/android/test/resource_overlay/java/src/org/chromium/build/resource_overlay/ResourceOverlayTest.java new file mode 100644 index 0000000000..794cafac53 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/resource_overlay/java/src/org/chromium/build/resource_overlay/ResourceOverlayTest.java @@ -0,0 +1,49 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.build.resource_overlay; + +import static org.junit.Assert.assertEquals; + +import android.content.res.Resources; +import android.support.test.InstrumentationRegistry; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.util.Batch; + +/** + * Test for resource_overlay parameter in android_resources() build rule. + */ +@RunWith(BaseJUnit4ClassRunner.class) +@Batch(Batch.UNIT_TESTS) +public class ResourceOverlayTest { + /** + * Test that when an android_resources() target with resource_overlay=false has a resource with + * the same name but a different value as a dependency with resource_overlay=true that the value + * of the resource in the dependency is used. + */ + @Test + @SmallTest + public void testDependencyTagged() { + Resources resources = InstrumentationRegistry.getTargetContext().getResources(); + assertEquals(41, resources.getInteger(R.integer.resource_overlay_dependency_tagged_secret)); + } + + /** + * Test that when an android_resources() target with resource_overlay=true has a resource with + * the same name but different value as one of its dependencies that the value of resource in + * the target with resource_overlay=true is used. + */ + @Test + @SmallTest + public void testRootTagged() { + Resources resources = InstrumentationRegistry.getTargetContext().getResources(); + assertEquals(42, resources.getInteger(R.integer.resource_overlay_root_tagged_secret)); + } +} |