diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /third_party/libwebrtc/build/config/android/rules.gni | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/build/config/android/rules.gni')
-rw-r--r-- | third_party/libwebrtc/build/config/android/rules.gni | 5183 |
1 files changed, 5183 insertions, 0 deletions
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 + } +} |