blob: 9c5ae20c878b84912b98ab0647f125665ce27388 [file] [log] [blame]
# Copyright 2015 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("//android_webview/variables.gni")
import("//base/android/linker/config.gni")
import("//base/android/resource_exclusions.gni")
import("//build/config/android/extract_unwind_tables.gni")
import("//build/config/android/rules.gni")
import("//build/config/compiler/compiler.gni")
import("//build/config/locales.gni")
import("//build/util/version.gni")
import("//chrome/android/chrome_common_shared_library.gni")
import("//chrome/android/features/dev_ui/dev_ui_module.gni")
import("//chrome/android/modules/chrome_bundle_tmpl.gni")
import("//chrome/common/features.gni")
import("//device/vr/buildflags/buildflags.gni")
import("//weblayer/variables.gni")
import("channel.gni")
default_chrome_public_jinja_variables = [
"channel=$android_channel",
"enable_vr=$enable_vr",
"include_arcore_manifest_flag=false",
]
# Enable stack unwinding only on official build with specific channels. It is
# not enabled on non-official builds to not affect build time for developers.
# The unwind file is ~2MB in apk, which is fine for Canary.
_add_unwind_tables_in_chrome_32bit_apk =
is_official_build && (target_cpu == "arm" || target_cpu == "arm64") &&
(android_channel == "default" || android_channel == "canary" ||
android_channel == "dev")
# A template used to declare any target that will implement a full Chromium
# or Chrome application, either as an APK, or an app bundle module.
#
# Variables:
# target_type: Either 'android_apk' or 'android_app_bundle_module'.
# apk_name: For APK target types, the final APK name without a suffix.
# is_base_module: For bundle module target types, true iff this is a base
# application module, instead of a feature module.
# android_manifest: Application manifest path.
# android_manifest_dep: Name of target generating the android_manifest.
# shared_libraries: List of native shared libraries targets to include in
# the final target (e.g. [ ":libchrome" ]).
# add_unwind_tables_in_apk: Optional. If true, add the unwind tables to the
# final APK or bundle.
# is_monochrome: Indicates that this target contains chrome and webview
# packaged together and can only run on Android N+.
# is_trichrome: Indicates this target relies on a trichrome static library
# target and can only run on Android P+.
# png_to_webp: Optional. If true, convert image resources to webp format.
# requires Android K+, since these were not supported by Android properly
# before 4.3.0.
# load_library_from_apk: Optional. If true, native libraries will be loaded
# directly from the APK (and stored zipaligned and uncompressed). This
# requires either the Chromium linker, or Android M+.
# version_name: Application version name (e.g. "Developer Build").
#
# Plus all other variables accepted by android_apk() or
# android_app_bundle_module(), depending on the target type.
#
template("chrome_public_common_apk_or_module_tmpl") {
assert(
invoker.target_type == "android_apk" ||
invoker.target_type == "android_app_bundle_module" ||
invoker.target_type == "instrumentation_test_apk",
"Invalid target_type definition, should be 'android_apk' or 'android_app_bundle_module'")
_is_monochrome = defined(invoker.is_monochrome) && invoker.is_monochrome
_is_trichrome = defined(invoker.is_trichrome) && invoker.is_trichrome
_is_64_bit_browser =
defined(invoker.is_64_bit_browser) && invoker.is_64_bit_browser
_is_bundle = invoker.target_type == "android_app_bundle_module"
not_needed([ "_is_64_bit_browser" ])
assert(!(_is_monochrome && _is_trichrome),
"Cannot be both trichrome and monochrome!")
assert(_is_trichrome == defined(invoker.static_library_provider),
"If trichrome library is used, static_library_provider must be set " +
"so that a dep can be added on the library APK.")
# Adds unwind table asset to the chrome apk for the given library target. This
# is not part of generic apk assets target since it depends on the main shared
# library of the apk, to extract unwind tables.
if (defined(invoker.add_unwind_tables_in_apk)) {
_add_unwind_tables = invoker.add_unwind_tables_in_apk
} else {
_needs_32bit_lib =
target_cpu == "arm" ||
(_is_monochrome && target_cpu == "arm64" && !_is_64_bit_browser) ||
(_is_trichrome && target_cpu == "arm64" && !_is_64_bit_browser)
_add_unwind_tables =
_needs_32bit_lib && _add_unwind_tables_in_chrome_32bit_apk &&
((android_64bit_target_cpu &&
defined(invoker.secondary_abi_shared_libraries)) ||
(!android_64bit_target_cpu && defined(invoker.shared_libraries)))
}
if (_add_unwind_tables) {
_unwind_asset_target = "${target_name}__unwind_assets"
unwind_table_asset(_unwind_asset_target) {
if (defined(invoker.testonly)) {
testonly = invoker.testonly
}
if (defined(invoker.shared_library_for_unwind_asset)) {
library_target = invoker.shared_library_for_unwind_asset
} else {
if (_is_monochrome || _is_trichrome) {
library_target = "monochrome"
} else {
library_target = "chrome"
}
}
if (android_64bit_target_cpu) {
deps = [ "//chrome/android:lib${library_target}($android_secondary_abi_toolchain)" ]
} else {
deps = [ "//chrome/android:lib${library_target}" ]
}
}
} else if (defined(invoker.shared_library_for_unwind_asset)) {
not_needed(invoker, [ "shared_library_for_unwind_asset" ])
}
if (!defined(invoker.target_type)) {
_target_type = "android_apk"
} else {
_target_type = invoker.target_type
}
target(_target_type, target_name) {
forward_variables_from(invoker, "*")
if (_is_trichrome) {
min_sdk_version = 29
} else if (_is_monochrome) {
min_sdk_version = 24
} else {
min_sdk_version = 21
}
resource_exclusion_regex = common_resource_exclusion_regex
resource_exclusion_exceptions = common_resource_exclusion_exceptions
# Exceptions (rationale in https://crbug.com/691733):
resource_exclusion_exceptions += [
"*ic_file_download_white*", # Bottom edge seems misaligned.
"*ic_lock.*", # Bottom edge seems misaligned.
]
# Note most of these, with the exception of resource_exclusion_exceptions,
# are currently duplicated in system_webview_apk_tmpl.gni.
# Used only by alert dialog on tiny screens.
_material_package = "com_google_android_material.*"
resource_exclusion_regex += "|${_material_package}values-small"
# Used only by date picker (which chrome doesn't use).
resource_exclusion_regex += "|${_material_package}-(w480dp-port|w360dp-port|h480dp-land|h360dp-land)"
# Material design layouts that cause views to be kept that we don't use.
# Instead of manually filtering, unused resource removal would be better:
# https://crbug.com/636448
resource_exclusion_regex += "|${_material_package}/xml.*badge_"
_material_package = "*com_google_android_material*"
if (!_is_monochrome) {
product_config_java_packages = [ "org.chromium.chrome.browser" ]
}
# Android supports webp transparent resources properly since API level 18,
# so this can only be activated for modern ones (which target API >= 21).
if (!defined(png_to_webp)) {
png_to_webp = !is_java_debug
}
# We only optimize resources for bundles since APKs are not shipped.
# Resources only live in the base module atm as such we only need to set
# these on the base module
if (_is_bundle) {
# Removes metadata needed for Resources.getIdentifier("resource_name").
strip_resource_names = !is_java_debug
# Shortens resource file names in apk eg: res/drawable/button.xml -> res/a.xml
short_resource_paths = true
# Removes unused resources from the apk. Only enabled on official builds
# since it adds a slow step and serializes the build graph causing fewer
# expensive tasks (eg: proguarding, resource optimization) to be run in
# parallel by adding dependencies between them (adds around 10-20
# seconds on my machine).
strip_unused_resources = is_official_build
}
if (!defined(aapt_locale_allowlist)) {
# Include resource strings files only for supported locales.
aapt_locale_allowlist = locales
}
if (!defined(use_chromium_linker)) {
use_chromium_linker = chromium_linker_supported
}
if (!_is_monochrome && !_is_trichrome) {
deps += [
"//chrome/android:chrome_public_v8_assets",
"//components/crash/core/app:chrome_crashpad_handler_named_as_so",
"//third_party/icu:icu_assets",
]
if (!defined(loadable_modules)) {
loadable_modules = []
}
loadable_modules += [ "$root_out_dir/libchrome_crashpad_handler.so" ]
if (!defined(library_always_compress)) {
library_always_compress = []
}
library_always_compress += [
"libchrome_crashpad_handler.so",
"libchromium_android_linker.so",
]
# Adds "crazy." prefix to avoid libraries being extracted when installed.
if (use_chromium_linker) {
if (!defined(library_renames)) {
library_renames = []
}
library_renames += [
"libchrome.so",
"libchromefortest.so",
]
}
}
if (dfmify_dev_ui && (_target_type == "android_apk" ||
_target_type == "instrumentation_test_apk")) {
# Dev UI is a feature in a DFM, and APKs don't use DFMs. To make the code
# available for APKs add a dependency on it.
deps += [ "//chrome/android/features/dev_ui:java" ]
}
if (!is_java_debug) {
proguard_enabled = true
if (!defined(proguard_configs)) {
proguard_configs = []
}
proguard_configs += [
"//chrome/android/proguard/main.flags",
"//base/android/proguard/chromium_apk.flags",
"//base/android/proguard/chromium_code.flags",
]
}
if (use_chromium_linker) {
_is_trichrome_3264 =
!_is_trichrome || !android_64bit_target_cpu || _is_64_bit_browser
if (_is_trichrome_3264) {
deps += [ "//base/android/linker:chromium_android_linker" ]
loadable_modules +=
[ "$root_out_dir/libchromium_android_linker$shlib_extension" ]
} else {
_secondary_linker = "//base/android/linker:chromium_android_linker($android_secondary_abi_toolchain)"
deps += [ _secondary_linker ]
_secondary_out_dir = get_label_info(_secondary_linker, "root_out_dir")
secondary_abi_loadable_modules +=
[ "$_secondary_out_dir/libchromium_android_linker$shlib_extension" ]
}
if (!defined(load_library_from_apk)) {
load_library_from_apk = chromium_linker_supported
}
}
if (_target_type == "android_apk") {
command_line_flags_file = "chrome-command-line"
}
if (!_is_trichrome) {
product_version_resources_dep =
"//chrome/android:product_version_resources"
}
if (defined(_unwind_asset_target)) {
deps += [ ":$_unwind_asset_target" ]
}
if (!_is_bundle || !(_is_monochrome || _is_trichrome)) {
deps += [ "//chrome/android:chrome_all_java" ]
}
# Prefer to add this data_dep on the final target instead of java targets
# like chrome_all_java so that all other targets can build in parallel with
# lint.
if (!disable_android_lint) {
if (!defined(data_deps)) {
data_deps = []
}
data_deps += [ "//chrome/android:android_lint" ]
}
if (!defined(version_code)) {
if (_is_trichrome) {
version_code = trichrome_version_code
} else if (_is_monochrome) {
version_code = monochrome_version_code
} else {
# TODO(agrieve): Merge chrome_modern_version_code with chrome_version_code.
version_code = chrome_modern_version_code
}
}
}
}
# The equivalent of chrome_common_apk_or_module_tmpl for all builds of
# monochrome and trichrome chrome.
# Variables:
# use_trichrome_library: Specifies that this target depends on a trichrome
# static library target to provide certain shared library deps, and that
# this target should not package webview deps.
template("monochrome_public_common_apk_or_module_tmpl") {
_is_bundle_module = defined(invoker.target_type) &&
invoker.target_type == "android_app_bundle_module"
chrome_public_common_apk_or_module_tmpl(target_name) {
_overrides = {
if (_is_bundle_module) {
assert(
defined(invoker.is_base_module),
"_is_bundle_module is true but the invoker does not define is_base_module!")
}
is_trichrome = defined(invoker.use_trichrome_library) &&
invoker.use_trichrome_library
is_monochrome = !is_trichrome
shared_libraries = []
if (defined(invoker.shared_libraries)) {
shared_libraries += invoker.shared_libraries
}
secondary_abi_shared_libraries = []
if (defined(invoker.secondary_abi_shared_libraries)) {
secondary_abi_shared_libraries += invoker.secondary_abi_shared_libraries
}
loadable_modules = []
if (defined(invoker.loadable_modules)) {
loadable_modules = invoker.loadable_modules
}
secondary_abi_loadable_modules = []
if (defined(invoker.secondary_abi_loadable_modules)) {
secondary_abi_loadable_modules = invoker.secondary_abi_loadable_modules
}
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
}
deps = [
"//chrome/android:chrome_public_non_pak_assets",
"//components/crash/android:handler_java",
]
if (defined(invoker.deps)) {
deps += invoker.deps
}
if (_is_bundle_module && invoker.is_base_module && enable_arcore &&
is_monochrome) {
# AR DFM is disabled - set the loadable_modules /
# secondary_abi_loadable_modules to what would be brought in by the
# module. The AR Java will be brought in by the chrome_bundle target.
# This needs to happen for monochrome builds of base module if ARCore is
# enabled. For Trichrome, the native library is added to
# TrichromeLibrary.apk so it's not needed here.
_libarcore_dir = get_label_info(
"//third_party/arcore-android-sdk-client:com_google_ar_core_java($default_toolchain)",
"target_out_dir") + "/com_google_ar_core_java/jni"
if (android_64bit_target_cpu) {
if (invoker.is_64_bit_browser) {
loadable_modules +=
[ "$_libarcore_dir/arm64-v8a/libarcore_sdk_c.so" ]
} else {
secondary_abi_loadable_modules +=
[ "$_libarcore_dir/armeabi-v7a/libarcore_sdk_c.so" ]
}
} else {
loadable_modules +=
[ "$_libarcore_dir/armeabi-v7a/libarcore_sdk_c.so" ]
}
}
if (_is_bundle_module) {
# Sets ISOLATED_SPLITS_ENABLED in BuildConfig.java.
isolated_splits_enabled = true
deps += [ ":${target_name}__all_dfm_resources" ]
}
if (_is_bundle_module && invoker.is_base_module) {
# If the manifest is being verified, add the chrome module's manifest.
if (defined(invoker.expected_android_manifest)) {
_bundle_target_gen_dir =
get_label_info(invoker.bundle_target, "target_gen_dir")
_bundle_name = get_label_info(invoker.bundle_target, "name")
extra_verification_manifest = "${_bundle_target_gen_dir}/${_bundle_name}__chrome_bundle_module_manifest/AndroidManifest.xml"
extra_verification_manifest_dep =
"${invoker.bundle_target}__chrome_bundle_module__merge_manifests"
}
# The arcore manifest needs to be merged into the base module because
# the Play Store verifies the com.google.ar.core.min_apk_version
# meta-data tag is in the base manifest.
if (enable_arcore) {
deps += [
"//third_party/arcore-android-sdk-client:com_google_ar_core_java",
"//third_party/arcore-android-sdk-client:com_google_ar_core_java__ignored_manifest",
]
}
if (is_monochrome) {
deps += [ "//chrome/android:base_monochrome_module_java" ]
} else {
deps += [ "//chrome/android:base_module_java" ]
}
}
if (is_monochrome) {
product_config_java_packages = [
"org.chromium.chrome.browser",
webview_product_config_java_package,
]
if (webview_includes_weblayer) {
product_config_java_packages +=
[ weblayer_product_config_java_package ]
}
# Flag whether additional deps and libs should be included for each ABI.
_include_primary_support = false
_include_secondary_support = false
if (android_64bit_target_cpu) {
# Build //android_webview:monochrome with the opposite bitness that
# Chrome runs in.
if (invoker.is_64_bit_browser) {
_include_primary_support = true
shared_libraries += [ "//chrome/android:libmonochrome_64" ]
if (invoker.include_32_bit_webview) {
secondary_abi_shared_libraries += [ "//android_webview:monochrome_64($android_secondary_abi_toolchain)" ]
_include_secondary_support = true
}
} else {
secondary_abi_shared_libraries +=
[ "//chrome/android:monochrome_secondary_abi_lib" ]
_include_secondary_support = true
if (invoker.include_64_bit_webview) {
shared_libraries += [ "//android_webview:monochrome" ]
_include_primary_support = true
}
}
} else {
shared_libraries += [ "//chrome/android:libmonochrome" ]
_include_primary_support = true
}
deps += [
"//android_webview/glue:glue_java",
"//android_webview/nonembedded:nonembedded_java",
]
if (!_is_bundle_module) {
deps += [ "//chrome/android:monochrome_java" ]
}
if (_include_primary_support) {
deps += [
"//android_webview:monochrome_webview_primary_abi_assets",
"//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
]
loadable_modules +=
[ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
}
if (_include_secondary_support) {
_trampoline =
"//third_party/crashpad/crashpad/handler:" +
"crashpad_handler_trampoline($android_secondary_abi_toolchain)"
deps += [
"//android_webview:monochrome_webview_secondary_abi_assets",
_trampoline,
]
_secondary_out_dir = get_label_info(_trampoline, "root_out_dir")
secondary_abi_loadable_modules +=
[ "$_secondary_out_dir/libcrashpad_handler_trampoline.so" ]
}
if (defined(invoker.alternative_android_sdk_dep)) {
alternative_android_sdk_dep = invoker.alternative_android_sdk_dep
} else {
alternative_android_sdk_dep = webview_framework_dep
}
if (defined(invoker.app_as_shared_lib)) {
app_as_shared_lib = invoker.app_as_shared_lib
} else {
app_as_shared_lib = true
}
_pak_prefix = "monochrome"
}
if (is_trichrome) {
# Include placeholder libraries to make Chrome multiarch in the same way
# as Monochrome, even though Chrome only runs with one of the two
# bitnesses. This allows the "32-bit" and "64-bit" versions of Chrome to
# depend on their respective versions of the shared library APK even
# though they're functionally the same.
if (android_64bit_target_cpu) {
if (invoker.is_64_bit_browser) {
native_lib_placeholders += [ "libdummy.so" ]
if (invoker.include_32_bit_webview) {
secondary_native_lib_placeholders += [ "libdummy.so" ]
}
} else {
secondary_native_lib_placeholders += [ "libdummy.so" ]
if (invoker.include_64_bit_webview) {
native_lib_placeholders += [ "libdummy.so" ]
}
}
} else {
native_lib_placeholders += [ "libdummy.so" ]
}
_pak_prefix = "trichrome_chrome"
}
use_chromium_linker = is_trichrome && chromium_linker_supported
use_modern_linker = use_chromium_linker
if (build_hwasan_splits && android_64bit_target_cpu &&
invoker.is_64_bit_browser) {
_hwasan_toolchain =
"//build/toolchain/android:android_clang_arm64_hwasan"
shared_libraries +=
[ "//chrome/android:libmonochrome_64($_hwasan_toolchain)" ]
if (use_chromium_linker) {
shared_libraries += [
"//base/android/linker:chromium_android_linker($_hwasan_toolchain)",
]
}
}
# We only optimize resources in bundles.
if (_is_bundle_module) {
# Resources config for blocklisting resource names from obfuscation
resources_config_paths = [
"//android_webview/aapt2.config",
"//chrome/android/aapt2.config",
]
if (defined(invoker.resources_config_paths)) {
resources_config_paths += invoker.resources_config_paths
}
}
if (defined(invoker.never_incremental)) {
never_incremental = invoker.never_incremental
} else if (!defined(invoker.target_type) ||
invoker.target_type == "android_apk") {
# Incremental install doesn't work for monochrome. See crbug.com/663492.
never_incremental = true
}
# Strip xml namespaces for monochrome. This should only be done for apks
# targeting API > 21 which for chrome is only Monochrome. This is due to
# how android public and private resource ids are namespaced.
if (defined(invoker.no_xml_namespaces)) {
no_xml_namespaces = invoker.no_xml_namespaces
} else {
no_xml_namespaces = true
}
# Configrations to make android load shared library from APK.
if (defined(invoker.uncompress_shared_libraries)) {
uncompress_shared_libraries = invoker.uncompress_shared_libraries
} else {
uncompress_shared_libraries = true
}
if (_is_bundle_module) {
_pak_prefix += "_bundle_module"
} else {
_pak_prefix += "_apk"
}
deps += [ "//chrome/android:${_pak_prefix}_pak_assets" ]
if (!is_java_debug) {
proguard_configs = []
if (defined(invoker.proguard_configs)) {
proguard_configs += invoker.proguard_configs
}
if (is_monochrome) {
proguard_configs +=
[ "//android_webview/nonembedded/java/proguard.flags" ]
}
}
}
# The _overrides scope is used to ensure that:
# * Values set in invoker cannot accidentally clobber values set in
# _overrides.
# * Values set in _overrides cannot accidentaly clobber values set in
# invoker (since the forward_variables_from will fail).
# Other nice properties:
# * _override_args needs to only reference values set within _overrides
# (as opposed to creating a list of values not set in it, which would be
# hard to keep up-to-date).
# * GN will issue an unused variable warning if there are entries missing
# from _override_args.
_override_args = [
"alternative_android_sdk_dep",
"app_as_shared_lib",
"deps",
"extra_verification_manifest",
"extra_verification_manifest_dep",
"is_monochrome",
"is_trichrome",
"isolated_splits_enabled",
"loadable_modules",
"native_lib_placeholders",
"never_incremental",
"no_xml_namespaces",
"product_config_java_packages",
"proguard_configs",
"resources_config_paths",
"secondary_abi_loadable_modules",
"secondary_abi_shared_libraries",
"secondary_native_lib_placeholders",
"shared_libraries",
"uncompress_shared_libraries",
"use_chromium_linker",
"use_modern_linker",
"webview_product_config_java_package",
]
forward_variables_from(invoker, "*", _override_args)
forward_variables_from(_overrides, _override_args)
}
}
# Generates an AndroidManifest.xml along with an optional second manifest
# dependent on the original.
#
# Variables:
# input: The base manifest template with the main application definition.
# output: Output path for |input|.
# split_input: Path to an alternate manifest that will be built if
# definitions_in_split is true.
# split_output: Output path for |split_input|.
# variables: Variables to pass to the jinja templates.
# definitions_in_split: If true will pass definitions_in_split=true in the
# variables passed to |input| and generate |split_output|.
template("split_manifest_template") {
_definitions_in_split =
defined(invoker.definitions_in_split) && invoker.definitions_in_split
jinja_template(target_name) {
forward_variables_from(invoker,
[
"includes",
"input",
"output",
"variables",
])
if (_definitions_in_split) {
variables += [ "definitions_in_split=true" ]
}
}
if (_definitions_in_split) {
jinja_template("${target_name}__split") {
forward_variables_from(invoker,
[
"includes",
"variables",
])
if (!defined(includes)) {
includes = []
}
includes += [ invoker.input ]
input = invoker.split_input
output = invoker.split_output
_rebased_input = rebase_path(invoker.input, "//")
variables += [ "base_manifest=${_rebased_input}" ]
}
} else {
not_needed(invoker,
[
"split_input",
"split_output",
])
}
}