summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/build/android/gyp/write_build_config.py
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/build/android/gyp/write_build_config.py')
-rwxr-xr-xthird_party/libwebrtc/build/android/gyp/write_build_config.py2091
1 files changed, 2091 insertions, 0 deletions
diff --git a/third_party/libwebrtc/build/android/gyp/write_build_config.py b/third_party/libwebrtc/build/android/gyp/write_build_config.py
new file mode 100755
index 0000000000..4756d8ac47
--- /dev/null
+++ b/third_party/libwebrtc/build/android/gyp/write_build_config.py
@@ -0,0 +1,2091 @@
+#!/usr/bin/env python3
+#
+# 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.
+
+"""Writes a build_config file.
+
+The build_config file for a target is a json file containing information about
+how to build that target based on the target's dependencies. This includes
+things like: the javac classpath, the list of android resources dependencies,
+etc. It also includes the information needed to create the build_config for
+other targets that depend on that one.
+
+Android build scripts should not refer to the build_config directly, and the
+build specification should instead pass information in using the special
+file-arg syntax (see build_utils.py:ExpandFileArgs). That syntax allows passing
+of values in a json dict in a file and looks like this:
+ --python-arg=@FileArg(build_config_path:javac:classpath)
+
+Note: If paths to input files are passed in this way, it is important that:
+ 1. inputs/deps of the action ensure that the files are available the first
+ time the action runs.
+ 2. Either (a) or (b)
+ a. inputs/deps ensure that the action runs whenever one of the files changes
+ b. the files are added to the action's depfile
+
+NOTE: All paths within .build_config files are relative to $OUTPUT_CHROMIUM_DIR.
+
+This is a technical note describing the format of .build_config files.
+Please keep it updated when changing this script. For extraction and
+visualization instructions, see build/android/docs/build_config.md
+
+------------- BEGIN_MARKDOWN ---------------------------------------------------
+The .build_config file format
+===
+
+# Introduction
+
+This document tries to explain the format of `.build_config` generated during
+the Android build of Chromium. For a higher-level explanation of these files,
+please read
+[build/android/docs/build_config.md](build/android/docs/build_config.md).
+
+# The `deps_info` top-level dictionary:
+
+All `.build_config` files have a required `'deps_info'` key, whose value is a
+dictionary describing the target and its dependencies. The latter has the
+following required keys:
+
+## Required keys in `deps_info`:
+
+* `deps_info['type']`: The target type as a string.
+
+ The following types are known by the internal GN build rules and the
+ build scripts altogether:
+
+ * [java_binary](#target_java_binary)
+ * [java_annotation_processor](#target_java_annotation_processor)
+ * [junit_binary](#target_junit_binary)
+ * [java_library](#target_java_library)
+ * [android_assets](#target_android_assets)
+ * [android_resources](#target_android_resources)
+ * [android_apk](#target_android_apk)
+ * [android_app_bundle_module](#target_android_app_bundle_module)
+ * [android_app_bundle](#target_android_app_bundle)
+ * [dist_jar](#target_dist_jar)
+ * [dist_aar](#target_dist_aar)
+ * [group](#target_group)
+
+ See later sections for more details of some of these.
+
+* `deps_info['path']`: Path to the target's `.build_config` file.
+
+* `deps_info['name']`: Nothing more than the basename of `deps_info['path']`
+at the moment.
+
+* `deps_info['deps_configs']`: List of paths to the `.build_config` files of
+all *direct* dependencies of the current target.
+
+ NOTE: Because the `.build_config` of a given target is always generated
+ after the `.build_config` of its dependencies, the `write_build_config.py`
+ script can use chains of `deps_configs` to compute transitive dependencies
+ for each target when needed.
+
+## Optional keys in `deps_info`:
+
+The following keys will only appear in the `.build_config` files of certain
+target types:
+
+* `deps_info['requires_android']`: True to indicate that the corresponding
+code uses Android-specific APIs, and thus cannot run on the host within a
+regular JVM. May only appear in Java-related targets.
+
+* `deps_info['supports_android']`:
+May appear in Java-related targets, and indicates that
+the corresponding code doesn't use Java APIs that are not available on
+Android. As such it may run either on the host or on an Android device.
+
+* `deps_info['assets']`:
+Only seen for the [`android_assets`](#target_android_assets) type. See below.
+
+* `deps_info['package_name']`: Java package name associated with this target.
+
+ NOTE: For `android_resources` targets,
+ this is the package name for the corresponding R class. For `android_apk`
+ targets, this is the corresponding package name. This does *not* appear for
+ other target types.
+
+* `deps_info['android_manifest']`:
+Path to an AndroidManifest.xml file related to the current target.
+
+* `deps_info['base_module_config']`:
+Only seen for the [`android_app_bundle`](#target_android_app_bundle) type.
+Path to the base module for the bundle.
+
+* `deps_info['is_base_module']`:
+Only seen for the
+[`android_app_bundle_module`](#target_android_app_bundle_module)
+type. Whether or not this module is the base module for some bundle.
+
+* `deps_info['dependency_zips']`:
+List of `deps_info['resources_zip']` entries for all `android_resources`
+dependencies for the current target.
+
+* `deps_info['extra_package_names']`:
+Always empty for `android_resources` types. Otherwise,
+the list of `deps_info['package_name']` entries for all `android_resources`
+dependencies for the current target. Computed automatically by
+`write_build_config.py`.
+
+* `deps_info['dependency_r_txt_files']`:
+Exists only on dist_aar. It is the list of deps_info['r_text_path'] from
+transitive dependencies. Computed automatically.
+
+
+# `.build_config` target types description:
+
+## <a name="target_group">Target type `group`</a>:
+
+This type corresponds to a simple target that is only used to group
+dependencies. It matches the `java_group()` GN template. Its only top-level
+`deps_info` keys are `supports_android` (always True), and `deps_configs`.
+
+
+## <a name="target_android_resources">Target type `android_resources`</a>:
+
+This type corresponds to targets that are used to group Android resource files.
+For example, all `android_resources` dependencies of an `android_apk` will
+end up packaged into the final APK by the build system.
+
+It uses the following keys:
+
+
+* `deps_info['res_sources_path']`:
+Path to file containing a list of resource source files used by the
+android_resources target.
+
+* `deps_info['resources_zip']`:
+*Required*. Path to the `.resources.zip` file that contains all raw/uncompiled
+resource files for this target (and also no `R.txt`, `R.java` or `R.class`).
+
+ If `deps_info['res_sources_path']` is missing, this must point to a prebuilt
+ `.aar` archive containing resources. Otherwise, this will point to a zip
+ archive generated at build time, wrapping the sources listed in
+ `deps_info['res_sources_path']` into a single zip file.
+
+* `deps_info['package_name']`:
+Java package name that the R class for this target belongs to.
+
+* `deps_info['android_manifest']`:
+Optional. Path to the top-level Android manifest file associated with these
+resources (if not provided, an empty manifest will be used to generate R.txt).
+
+* `deps_info['resource_overlay']`:
+Optional. Whether the resources in resources_zip should override resources with
+the same name. Does not affect the behaviour of any android_resources()
+dependencies 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.
+
+* `deps_info['r_text_path']`:
+Provide the path to the `R.txt` file that describes the resources wrapped by
+this target. Normally this file is generated from the content of the resource
+directories or zip file, but some targets can provide their own `R.txt` file
+if they want.
+
+* `deps_info['srcjar_path']`:
+Path to the `.srcjar` file that contains the auto-generated `R.java` source
+file corresponding to the content of `deps_info['r_text_path']`. This is
+*always* generated from the content of `deps_info['r_text_path']` by the
+`build/android/gyp/process_resources.py` script.
+
+* `deps_info['static_library_dependent_classpath_configs']`:
+Sub dictionary mapping .build_config paths to lists of jar files. For static
+library APKs, this defines which input jars belong to each
+static_library_dependent_target.
+
+* `deps_info['static_library_proguard_mapping_output_paths']`:
+Additional paths to copy the ProGuard mapping file to for static library
+APKs.
+
+## <a name="target_android_assets">Target type `android_assets`</a>:
+
+This type corresponds to targets used to group Android assets, i.e. liberal
+files that will be placed under `//assets/` within the final APK.
+
+These use an `deps_info['assets']` key to hold a dictionary of values related
+to assets covered by this target.
+
+* `assets['sources']`:
+The list of all asset source paths for this target. Each source path can
+use an optional `:<zipPath>` suffix, where `<zipPath>` is the final location
+of the assets (relative to `//assets/`) within the APK.
+
+* `assets['outputs']`:
+Optional. Some of the sources might be renamed before being stored in the
+final //assets/ sub-directory. When this happens, this contains a list of
+all renamed output file paths
+
+ NOTE: When not empty, the first items of `assets['sources']` must match
+ every item in this list. Extra sources correspond to non-renamed sources.
+
+ NOTE: This comes from the `asset_renaming_destinations` parameter for the
+ `android_assets()` GN template.
+
+* `assets['disable_compression']`:
+Optional. Will be True to indicate that these assets should be stored
+uncompressed in the final APK. For example, this is necessary for locale
+.pak files used by the System WebView feature.
+
+* `assets['treat_as_locale_paks']`:
+Optional. Will be True to indicate that these assets are locale `.pak` files
+(containing localized strings for C++). These are later processed to generate
+a special ``.build_config`.java` source file, listing all supported Locales in
+the current build.
+
+
+## <a name="target_java_library">Target type `java_library`</a>:
+
+This type is used to describe target that wrap Java bytecode, either created
+by compiling sources, or providing them with a prebuilt jar.
+
+* `deps_info['public_deps_configs']`: List of paths to the `.build_config` files
+of *direct* dependencies of the current target which are exposed as part of the
+current target's public API. This should be a subset of
+deps_info['deps_configs'].
+
+* `deps_info['ignore_dependency_public_deps']`: If true, 'public_deps' will not
+be collected from the current target's direct deps.
+
+* `deps_info['unprocessed_jar_path']`:
+Path to the original .jar file for this target, before any kind of processing
+through Proguard or other tools. For most targets this is generated
+from sources, with a name like `$target_name.javac.jar`. However, when using
+a prebuilt jar, this will point to the source archive directly.
+
+* `deps_info['device_jar_path']`:
+Path to a file that is the result of processing
+`deps_info['unprocessed_jar_path']` with various tools (ready to be dexed).
+
+* `deps_info['host_jar_path']`:
+Path to a file that is the result of processing
+`deps_info['unprocessed_jar_path']` with various tools (use by java_binary).
+
+* `deps_info['interface_jar_path']:
+Path to the interface jar generated for this library. This corresponds to
+a jar file that only contains declarations. Generated by running the `ijar` on
+`deps_info['unprocessed_jar_path']` or the `turbine` tool on source files.
+
+* `deps_info['dex_path']`:
+Path to the `.dex` file generated for this target, from
+`deps_info['device_jar_path']` unless this comes from a prebuilt `.aar` archive.
+
+* `deps_info['is_prebuilt']`:
+True to indicate that this target corresponds to a prebuilt `.jar` file.
+In this case, `deps_info['unprocessed_jar_path']` will point to the source
+`.jar` file. Otherwise, it will be point to a build-generated file.
+
+* `deps_info['java_sources_file']`:
+Path to a single `.sources` file listing all the Java sources that were used
+to generate the library (simple text format, one `.jar` path per line).
+
+* `deps_info['lint_android_manifest']`:
+Path to an AndroidManifest.xml file to use for this lint target.
+
+* `deps_info['lint_java_sources']`:
+The list of all `deps_info['java_sources_file']` entries for all library
+dependencies that are chromium code. Note: this is a list of files, where each
+file contains a list of Java source files. This is used for lint.
+
+* `deps_info['lint_aars']`:
+List of all aars from transitive java dependencies. This allows lint to collect
+their custom annotations.zip and run checks like @IntDef on their annotations.
+
+* `deps_info['lint_srcjars']`:
+List of all bundled srcjars of all transitive java library targets. Excludes
+non-chromium java libraries.
+
+* `deps_info['lint_resource_sources']`:
+List of all resource sources files belonging to all transitive resource
+dependencies of this target. Excludes resources owned by non-chromium code.
+
+* `deps_info['lint_resource_zips']`:
+List of all resource zip files belonging to all transitive resource dependencies
+of this target. Excludes resources owned by non-chromium code.
+
+* `deps_info['javac']`:
+A dictionary containing information about the way the sources in this library
+are compiled. Appears also on other Java-related targets. See the [dedicated
+section about this](#dict_javac) below for details.
+
+* `deps_info['javac_full_classpath']`:
+The classpath used when performing bytecode processing. Essentially the
+collection of all `deps_info['unprocessed_jar_path']` entries for the target
+and all its dependencies.
+
+* `deps_info['javac_full_interface_classpath']`:
+The classpath used when using the errorprone compiler.
+
+* `deps_info['proguard_enabled"]`:
+True to indicate that ProGuard processing is enabled for this target.
+
+* `deps_info['proguard_configs"]`:
+A list of paths to ProGuard configuration files related to this library.
+
+* `deps_info['extra_classpath_jars']:
+For some Java related types, a list of extra `.jar` files to use at build time
+but not at runtime.
+
+## <a name="target_java_binary">Target type `java_binary`</a>:
+
+This type corresponds to a Java binary, which is nothing more than a
+`java_library` target that also provides a main class name. It thus inherits
+all entries from the `java_library` type, and adds:
+
+* `deps_info['main_class']`:
+Name of the main Java class that serves as an entry point for the binary.
+
+* `deps_info['device_classpath']`:
+The classpath used when running a Java or Android binary. Essentially the
+collection of all `deps_info['device_jar_path']` entries for the target and all
+its dependencies.
+
+
+## <a name="target_junit_binary">Target type `junit_binary`</a>:
+
+A target type for JUnit-specific binaries. Identical to
+[`java_binary`](#target_java_binary) in the context of `.build_config` files,
+except the name.
+
+
+## <a name="target_java_annotation_processor">Target type \
+`java_annotation_processor`</a>:
+
+A target type for Java annotation processors. Identical to
+[`java_binary`](#target_java_binary) in the context of `.build_config` files,
+except the name, except that it requires a `deps_info['main_class']` entry.
+
+
+## <a name="target_android_apk">Target type `android_apk`</a>:
+
+Corresponds to an Android APK. Inherits from the
+[`java_binary`](#target_java_binary) type and adds:
+
+* `deps_info['apk_path']`:
+Path to the raw, unsigned, APK generated by this target.
+
+* `deps_info['incremental_apk_path']`:
+Path to the raw, unsigned, incremental APK generated by this target.
+
+* `deps_info['incremental_install_json_path']`:
+Path to the JSON file with per-apk details for incremental install.
+See `build/android/gyp/incremental/write_installer_json.py` for more
+details about its content.
+
+* `deps_info['dist_jar']['all_interface_jars']`:
+For `android_apk` and `dist_jar` targets, a list of all interface jar files
+that will be merged into the final `.jar` file for distribution.
+
+* `deps_info['final_dex']['path']`:
+Path to the final classes.dex file (or classes.zip in case of multi-dex)
+for this APK.
+
+* `deps_info['final_dex']['all_dex_files']`:
+The list of paths to all `deps_info['dex_path']` entries for all libraries
+that comprise this APK. Valid only for debug builds.
+
+* `native['libraries']`
+List of native libraries for the primary ABI to be embedded in this APK.
+E.g. [ "libchrome.so" ] (i.e. this doesn't include any ABI sub-directory
+prefix).
+
+* `native['java_libraries_list']`
+The same list as `native['libraries']` as a string holding a Java source
+fragment, e.g. `"{\"chrome\"}"`, without any `lib` prefix, and `.so`
+suffix (as expected by `System.loadLibrary()`).
+
+* `native['second_abi_libraries']`
+List of native libraries for the secondary ABI to be embedded in this APK.
+Empty if only a single ABI is supported.
+
+* `native['uncompress_shared_libraries']`
+A boolean indicating whether native libraries are stored uncompressed in the
+APK.
+
+* `native['loadable_modules']`
+A list of native libraries to store within the APK, in addition to those from
+`native['libraries']`. These correspond to things like the Chromium linker
+or instrumentation libraries.
+
+* `native['secondary_abi_loadable_modules']`
+Secondary ABI version of loadable_modules
+
+* `native['library_always_compress']`
+A list of library files that we always compress.
+
+* `native['library_renames']`
+A list of library files that we prepend "crazy." to their file names.
+
+* `assets`
+A list of assets stored compressed in the APK. Each entry has the format
+`<source-path>:<destination-path>`, where `<source-path>` is relative to
+`$CHROMIUM_OUTPUT_DIR`, and `<destination-path>` is relative to `//assets/`
+within the APK.
+
+NOTE: Not to be confused with the `deps_info['assets']` dictionary that
+belongs to `android_assets` targets only.
+
+* `uncompressed_assets`
+A list of uncompressed assets stored in the APK. Each entry has the format
+`<source-path>:<destination-path>` too.
+
+* `locales_java_list`
+A string holding a Java source fragment that gives the list of locales stored
+uncompressed as android assets.
+
+* `extra_android_manifests`
+A list of `deps_configs['android_manifest]` entries, for all resource
+dependencies for this target. I.e. a list of paths to manifest files for
+all the resources in this APK. These will be merged with the root manifest
+file to generate the final one used to build the APK.
+
+* `java_resources_jars`
+This is a list of `.jar` files whose *Java* resources should be included in
+the final APK. For example, this is used to copy the `.res` files from the
+EMMA Coverage tool. The copy will omit any `.class` file and the top-level
+`//meta-inf/` directory from the input jars. Everything else will be copied
+into the final APK as-is.
+
+NOTE: This has nothing to do with *Android* resources.
+
+* `jni['all_source']`
+The list of all `deps_info['java_sources_file']` entries for all library
+dependencies for this APK. Note: this is a list of files, where each file
+contains a list of Java source files. This is used for JNI registration.
+
+* `deps_info['proguard_all_configs']`:
+The collection of all 'deps_info['proguard_configs']` values from this target
+and all its dependencies.
+
+* `deps_info['proguard_classpath_jars']`:
+The collection of all 'deps_info['extra_classpath_jars']` values from all
+dependencies.
+
+* `deps_info['proguard_under_test_mapping']`:
+Applicable to apks with proguard enabled that have an apk_under_test. This is
+the path to the apk_under_test's output proguard .mapping file.
+
+## <a name="target_android_app_bundle_module">Target type \
+`android_app_bundle_module`</a>:
+
+Corresponds to an Android app bundle module. Very similar to an APK and
+inherits the same fields, except that this does not generate an installable
+file (see `android_app_bundle`), and for the following omitted fields:
+
+* `deps_info['apk_path']`, `deps_info['incremental_apk_path']` and
+ `deps_info['incremental_install_json_path']` are omitted.
+
+* top-level `dist_jar` is omitted as well.
+
+In addition to `android_apk` targets though come these new fields:
+
+* `deps_info['proto_resources_path']`:
+The path of an zip archive containing the APK's resources compiled to the
+protocol buffer format (instead of regular binary xml + resources.arsc).
+
+* `deps_info['module_rtxt_path']`:
+The path of the R.txt file generated when compiling the resources for the bundle
+module.
+
+* `deps_info['module_pathmap_path']`:
+The path of the pathmap file generated when compiling the resources for the
+bundle module, if resource path shortening is enabled.
+
+* `deps_info['base_allowlist_rtxt_path']`:
+Optional path to an R.txt file used as a allowlist for base string resources.
+This means that any string resource listed in this file *and* in
+`deps_info['module_rtxt_path']` will end up in the base split APK of any
+`android_app_bundle` target that uses this target as its base module.
+
+This ensures that such localized strings are available to all bundle installs,
+even when language based splits are enabled (e.g. required for WebView strings
+inside the Monochrome bundle).
+
+
+## <a name="target_android_app_bundle">Target type `android_app_bundle`</a>
+
+This target type corresponds to an Android app bundle, and is built from one
+or more `android_app_bundle_module` targets listed as dependencies.
+
+
+## <a name="target_dist_aar">Target type `dist_aar`</a>:
+
+This type corresponds to a target used to generate an `.aar` archive for
+distribution. The archive's content is determined by the target's dependencies.
+
+This always has the following entries:
+
+ * `deps_info['supports_android']` (always True).
+ * `deps_info['requires_android']` (always True).
+ * `deps_info['proguard_configs']` (optional).
+
+
+## <a name="target_dist_jar">Target type `dist_jar`</a>:
+
+This type is similar to [`dist_aar`](#target_dist_aar) but is not
+Android-specific, and used to create a `.jar` file that can be later
+redistributed.
+
+This always has the following entries:
+
+ * `deps_info['proguard_enabled']` (False by default).
+ * `deps_info['proguard_configs']` (optional).
+ * `deps_info['supports_android']` (True by default).
+ * `deps_info['requires_android']` (False by default).
+
+
+
+## <a name="dict_javac">The `deps_info['javac']` dictionary</a>:
+
+This dictionary appears in Java-related targets (e.g. `java_library`,
+`android_apk` and others), and contains information related to the compilation
+of Java sources, class files, and jars.
+
+* `javac['classpath']`
+The classpath used to compile this target when annotation processors are
+present.
+
+* `javac['interface_classpath']`
+The classpath used to compile this target when annotation processors are
+not present. These are also always used to known when a target needs to be
+rebuilt.
+
+* `javac['processor_classpath']`
+The classpath listing the jars used for annotation processors. I.e. sent as
+`-processorpath` when invoking `javac`.
+
+* `javac['processor_classes']`
+The list of annotation processor main classes. I.e. sent as `-processor' when
+invoking `javac`.
+
+## <a name="android_app_bundle">Target type `android_app_bundle`</a>:
+
+This type corresponds to an Android app bundle (`.aab` file).
+
+--------------- END_MARKDOWN ---------------------------------------------------
+"""
+
+from __future__ import print_function
+
+import collections
+import itertools
+import json
+import optparse
+import os
+import sys
+import xml.dom.minidom
+
+from util import build_utils
+from util import resource_utils
+
+# TODO(crbug.com/1174969): Remove this once Python2 is obsoleted.
+if sys.version_info.major == 2:
+ zip_longest = itertools.izip_longest
+else:
+ zip_longest = itertools.zip_longest
+
+
+# Types that should never be used as a dependency of another build config.
+_ROOT_TYPES = ('android_apk', 'java_binary', 'java_annotation_processor',
+ 'junit_binary', 'android_app_bundle')
+# Types that should not allow code deps to pass through.
+_RESOURCE_TYPES = ('android_assets', 'android_resources', 'system_java_library')
+
+
+class OrderedSet(collections.OrderedDict):
+ # Value |parameter| is present to avoid presubmit warning due to different
+ # number of parameters from overridden method.
+ @staticmethod
+ def fromkeys(iterable, value=None):
+ out = OrderedSet()
+ out.update(iterable)
+ return out
+
+ def add(self, key):
+ self[key] = True
+
+ def update(self, iterable):
+ for v in iterable:
+ self.add(v)
+
+
+def _ExtractMarkdownDocumentation(input_text):
+ """Extract Markdown documentation from a list of input strings lines.
+
+ This generates a list of strings extracted from |input_text|, by looking
+ for '-- BEGIN_MARKDOWN --' and '-- END_MARKDOWN --' line markers."""
+ in_markdown = False
+ result = []
+ for line in input_text.splitlines():
+ if in_markdown:
+ if '-- END_MARKDOWN --' in line:
+ in_markdown = False
+ else:
+ result.append(line)
+ else:
+ if '-- BEGIN_MARKDOWN --' in line:
+ in_markdown = True
+
+ return result
+
+class AndroidManifest(object):
+ def __init__(self, path):
+ self.path = path
+ dom = xml.dom.minidom.parse(path)
+ manifests = dom.getElementsByTagName('manifest')
+ assert len(manifests) == 1
+ self.manifest = manifests[0]
+
+ def GetInstrumentationElements(self):
+ instrumentation_els = self.manifest.getElementsByTagName('instrumentation')
+ if len(instrumentation_els) == 0:
+ return None
+ return instrumentation_els
+
+ def CheckInstrumentationElements(self, expected_package):
+ instrs = self.GetInstrumentationElements()
+ if not instrs:
+ raise Exception('No <instrumentation> elements found in %s' % self.path)
+ for instr in instrs:
+ instrumented_package = instr.getAttributeNS(
+ 'http://schemas.android.com/apk/res/android', 'targetPackage')
+ if instrumented_package != expected_package:
+ raise Exception(
+ 'Wrong instrumented package. Expected %s, got %s'
+ % (expected_package, instrumented_package))
+
+ def GetPackageName(self):
+ return self.manifest.getAttribute('package')
+
+
+dep_config_cache = {}
+def GetDepConfig(path):
+ if not path in dep_config_cache:
+ with open(path) as jsonfile:
+ dep_config_cache[path] = json.load(jsonfile)['deps_info']
+ return dep_config_cache[path]
+
+
+def DepsOfType(wanted_type, configs):
+ return [c for c in configs if c['type'] == wanted_type]
+
+
+def DepPathsOfType(wanted_type, config_paths):
+ return [p for p in config_paths if GetDepConfig(p)['type'] == wanted_type]
+
+
+def GetAllDepsConfigsInOrder(deps_config_paths, filter_func=None):
+ def GetDeps(path):
+ config = GetDepConfig(path)
+ if filter_func and not filter_func(config):
+ return []
+ return config['deps_configs']
+
+ return build_utils.GetSortedTransitiveDependencies(deps_config_paths, GetDeps)
+
+
+def GetObjectByPath(obj, key_path):
+ """Given an object, return its nth child based on a key path.
+ """
+ return GetObjectByPath(obj[key_path[0]], key_path[1:]) if key_path else obj
+
+
+def RemoveObjDups(obj, base, *key_path):
+ """Remove array items from an object[*kep_path] that are also
+ contained in the base[*kep_path] (duplicates).
+ """
+ base_target = set(GetObjectByPath(base, key_path))
+ target = GetObjectByPath(obj, key_path)
+ target[:] = [x for x in target if x not in base_target]
+
+
+class Deps(object):
+ def __init__(self, direct_deps_config_paths):
+ self._all_deps_config_paths = GetAllDepsConfigsInOrder(
+ direct_deps_config_paths)
+ self._direct_deps_configs = [
+ GetDepConfig(p) for p in direct_deps_config_paths
+ ]
+ self._all_deps_configs = [
+ GetDepConfig(p) for p in self._all_deps_config_paths
+ ]
+ self._direct_deps_config_paths = direct_deps_config_paths
+
+ def All(self, wanted_type=None):
+ if wanted_type is None:
+ return self._all_deps_configs
+ return DepsOfType(wanted_type, self._all_deps_configs)
+
+ def Direct(self, wanted_type=None):
+ if wanted_type is None:
+ return self._direct_deps_configs
+ return DepsOfType(wanted_type, self._direct_deps_configs)
+
+ def DirectAndChildPublicDeps(self, wanted_type=None):
+ """Returns direct dependencies and dependencies exported via public_deps of
+ direct dependencies.
+ """
+ dep_paths = set(self._direct_deps_config_paths)
+ for direct_dep in self._direct_deps_configs:
+ dep_paths.update(direct_dep.get('public_deps_configs', []))
+ deps_list = [GetDepConfig(p) for p in dep_paths]
+ if wanted_type is None:
+ return deps_list
+ return DepsOfType(wanted_type, deps_list)
+
+ def AllConfigPaths(self):
+ return self._all_deps_config_paths
+
+ def GradlePrebuiltJarPaths(self):
+ ret = []
+
+ def helper(cur):
+ for config in cur.Direct('java_library'):
+ if config['is_prebuilt'] or config['gradle_treat_as_prebuilt']:
+ if config['unprocessed_jar_path'] not in ret:
+ ret.append(config['unprocessed_jar_path'])
+
+ helper(self)
+ return ret
+
+ def GradleLibraryProjectDeps(self):
+ ret = []
+
+ def helper(cur):
+ for config in cur.Direct('java_library'):
+ if config['is_prebuilt']:
+ pass
+ elif config['gradle_treat_as_prebuilt']:
+ helper(Deps(config['deps_configs']))
+ elif config not in ret:
+ ret.append(config)
+
+ helper(self)
+ return ret
+
+
+def _MergeAssets(all_assets):
+ """Merges all assets from the given deps.
+
+ Returns:
+ A tuple of: (compressed, uncompressed, locale_paks)
+ |compressed| and |uncompressed| are lists of "srcPath:zipPath". srcPath is
+ the path of the asset to add, and zipPath is the location within the zip
+ (excluding assets/ prefix).
+ |locale_paks| is a set of all zipPaths that have been marked as
+ treat_as_locale_paks=true.
+ """
+ compressed = {}
+ uncompressed = {}
+ locale_paks = set()
+ for asset_dep in all_assets:
+ entry = asset_dep['assets']
+ disable_compression = entry.get('disable_compression')
+ treat_as_locale_paks = entry.get('treat_as_locale_paks')
+ dest_map = uncompressed if disable_compression else compressed
+ other_map = compressed if disable_compression else uncompressed
+ outputs = entry.get('outputs', [])
+ for src, dest in zip_longest(entry['sources'], outputs):
+ if not dest:
+ dest = os.path.basename(src)
+ # Merge so that each path shows up in only one of the lists, and that
+ # deps of the same target override previous ones.
+ other_map.pop(dest, 0)
+ dest_map[dest] = src
+ if treat_as_locale_paks:
+ locale_paks.add(dest)
+
+ def create_list(asset_map):
+ ret = ['%s:%s' % (src, dest) for dest, src in asset_map.items()]
+ # Sort to ensure deterministic ordering.
+ ret.sort()
+ return ret
+
+ return create_list(compressed), create_list(uncompressed), locale_paks
+
+
+def _ResolveGroups(config_paths):
+ """Returns a list of configs with all groups inlined."""
+ ret = list(config_paths)
+ ret_set = set(config_paths)
+ while True:
+ group_paths = DepPathsOfType('group', ret)
+ if not group_paths:
+ return ret
+ for group_path in group_paths:
+ index = ret.index(group_path)
+ expanded_config_paths = []
+ for deps_config_path in GetDepConfig(group_path)['deps_configs']:
+ if not deps_config_path in ret_set:
+ expanded_config_paths.append(deps_config_path)
+ ret[index:index + 1] = expanded_config_paths
+ ret_set.update(expanded_config_paths)
+
+
+def _DepsFromPaths(dep_paths,
+ target_type,
+ filter_root_targets=True,
+ recursive_resource_deps=False):
+ """Resolves all groups and trims dependency branches that we never want.
+
+ E.g. When a resource or asset depends on an apk target, the intent is to
+ include the .apk as a resource/asset, not to have the apk's classpath added.
+
+ This method is meant to be called to get the top nodes (i.e. closest to
+ current target) that we could then use to get a full transitive dependants
+ list (eg using Deps#all). So filtering single elements out of this list,
+ filters whole branches of dependencies. By resolving groups (i.e. expanding
+ them to their constituents), depending on a group is equivalent to directly
+ depending on each element of that group.
+ """
+ blocklist = []
+ allowlist = []
+
+ # Don't allow root targets to be considered as a dep.
+ if filter_root_targets:
+ blocklist.extend(_ROOT_TYPES)
+
+ # Don't allow java libraries to cross through assets/resources.
+ if target_type in _RESOURCE_TYPES:
+ allowlist.extend(_RESOURCE_TYPES)
+ # Pretend that this target directly depends on all of its transitive
+ # dependencies.
+ if recursive_resource_deps:
+ dep_paths = GetAllDepsConfigsInOrder(dep_paths)
+ # Exclude assets if recursive_resource_deps is set. The
+ # recursive_resource_deps arg is used to pull resources into the base
+ # module to workaround bugs accessing resources in isolated DFMs, but
+ # assets should be kept in the DFMs.
+ blocklist.append('android_assets')
+
+ return _DepsFromPathsWithFilters(dep_paths, blocklist, allowlist)
+
+
+def _DepsFromPathsWithFilters(dep_paths, blocklist=None, allowlist=None):
+ """Resolves all groups and trims dependency branches that we never want.
+
+ See _DepsFromPaths.
+
+ |blocklist| if passed, are the types of direct dependencies we do not care
+ about (i.e. tips of branches that we wish to prune).
+
+ |allowlist| if passed, are the only types of direct dependencies we care
+ about (i.e. we wish to prune all other branches that do not start from one of
+ these).
+ """
+ group_paths = DepPathsOfType('group', dep_paths)
+ config_paths = dep_paths
+ if group_paths:
+ config_paths = _ResolveGroups(dep_paths) + group_paths
+ configs = [GetDepConfig(p) for p in config_paths]
+ if blocklist:
+ configs = [c for c in configs if c['type'] not in blocklist]
+ if allowlist:
+ configs = [c for c in configs if c['type'] in allowlist]
+
+ return Deps([c['path'] for c in configs])
+
+
+def _ExtractSharedLibsFromRuntimeDeps(runtime_deps_file):
+ ret = []
+ with open(runtime_deps_file) as f:
+ for line in f:
+ line = line.rstrip()
+ if not line.endswith('.so'):
+ continue
+ # Only unstripped .so files are listed in runtime deps.
+ # Convert to the stripped .so by going up one directory.
+ ret.append(os.path.normpath(line.replace('lib.unstripped/', '')))
+ ret.reverse()
+ return ret
+
+
+def _CreateJavaLibrariesList(library_paths):
+ """Returns a java literal array with the "base" library names:
+ e.g. libfoo.so -> foo
+ """
+ names = ['"%s"' % os.path.basename(s)[3:-3] for s in library_paths]
+ return ('{%s}' % ','.join(sorted(set(names))))
+
+
+def _CreateJavaLocaleListFromAssets(assets, locale_paks):
+ """Returns a java literal array from a list of locale assets.
+
+ Args:
+ assets: A list of all APK asset paths in the form 'src:dst'
+ locale_paks: A list of asset paths that correponds to the locale pak
+ files of interest. Each |assets| entry will have its 'dst' part matched
+ against it to determine if they are part of the result.
+ Returns:
+ A string that is a Java source literal array listing the locale names
+ of the corresponding asset files, without directory or .pak suffix.
+ E.g. '{"en-GB", "en-US", "es-ES", "fr", ... }'
+ """
+ assets_paths = [a.split(':')[1] for a in assets]
+ locales = [os.path.basename(a)[:-4] for a in assets_paths if a in locale_paks]
+ return '{%s}' % ','.join('"%s"' % l for l in sorted(locales))
+
+
+def _AddJarMapping(jar_to_target, configs):
+ for config in configs:
+ jar = config.get('unprocessed_jar_path')
+ if jar:
+ jar_to_target[jar] = config['gn_target']
+ for jar in config.get('extra_classpath_jars', []):
+ jar_to_target[jar] = config['gn_target']
+
+
+def _CompareClasspathPriority(dep):
+ return 1 if dep.get('low_classpath_priority') else 0
+
+
+def main(argv):
+ parser = optparse.OptionParser()
+ build_utils.AddDepfileOption(parser)
+ parser.add_option('--build-config', help='Path to build_config output.')
+ parser.add_option(
+ '--type',
+ help='Type of this target (e.g. android_library).')
+ parser.add_option('--gn-target', help='GN label for this target')
+ parser.add_option(
+ '--deps-configs',
+ help='GN-list of dependent build_config files.')
+ parser.add_option(
+ '--annotation-processor-configs',
+ help='GN-list of build_config files for annotation processors.')
+
+ # android_resources options
+ parser.add_option('--srcjar', help='Path to target\'s resources srcjar.')
+ parser.add_option('--resources-zip', help='Path to target\'s resources zip.')
+ parser.add_option('--package-name',
+ help='Java package name for these resources.')
+ parser.add_option('--android-manifest',
+ help='Path to the root android manifest.')
+ parser.add_option('--merged-android-manifest',
+ help='Path to the merged android manifest.')
+ parser.add_option('--resource-dirs', action='append', default=[],
+ help='GYP-list of resource dirs')
+ parser.add_option(
+ '--res-sources-path',
+ help='Path to file containing a list of paths to resources.')
+ parser.add_option(
+ '--resource-overlay',
+ action='store_true',
+ help='Whether resources passed in via --resources-zip should override '
+ 'resources with the same name')
+ parser.add_option(
+ '--recursive-resource-deps',
+ action='store_true',
+ help='Whether deps should be walked recursively to find resource deps.')
+
+ # android_assets options
+ parser.add_option('--asset-sources', help='List of asset sources.')
+ parser.add_option('--asset-renaming-sources',
+ help='List of asset sources with custom destinations.')
+ parser.add_option('--asset-renaming-destinations',
+ help='List of asset custom destinations.')
+ parser.add_option('--disable-asset-compression', action='store_true',
+ help='Whether to disable asset compression.')
+ parser.add_option('--treat-as-locale-paks', action='store_true',
+ help='Consider the assets as locale paks in BuildConfig.java')
+
+ # java library options
+
+ parser.add_option('--public-deps-configs',
+ help='GN list of config files of deps which are exposed as '
+ 'part of the target\'s public API.')
+ parser.add_option(
+ '--ignore-dependency-public-deps',
+ action='store_true',
+ help='If true, \'public_deps\' will not be collected from the current '
+ 'target\'s direct deps.')
+ parser.add_option('--aar-path', help='Path to containing .aar file.')
+ parser.add_option('--device-jar-path', help='Path to .jar for dexing.')
+ parser.add_option('--host-jar-path', help='Path to .jar for java_binary.')
+ parser.add_option('--unprocessed-jar-path',
+ help='Path to the .jar to use for javac classpath purposes.')
+ parser.add_option(
+ '--interface-jar-path',
+ help='Path to the interface .jar to use for javac classpath purposes.')
+ parser.add_option('--is-prebuilt', action='store_true',
+ help='Whether the jar was compiled or pre-compiled.')
+ parser.add_option('--java-sources-file', help='Path to .sources file')
+ parser.add_option('--bundled-srcjars',
+ help='GYP-list of .srcjars that have been included in this java_library.')
+ parser.add_option('--supports-android', action='store_true',
+ help='Whether this library supports running on the Android platform.')
+ parser.add_option('--requires-android', action='store_true',
+ help='Whether this library requires running on the Android platform.')
+ parser.add_option('--bypass-platform-checks', action='store_true',
+ help='Bypass checks for support/require Android platform.')
+ parser.add_option('--extra-classpath-jars',
+ help='GYP-list of .jar files to include on the classpath when compiling, '
+ 'but not to include in the final binary.')
+ parser.add_option(
+ '--low-classpath-priority',
+ action='store_true',
+ help='Indicates that the library should be placed at the end of the '
+ 'classpath.')
+ parser.add_option(
+ '--mergeable-android-manifests',
+ help='GN-list of AndroidManifest.xml to include in manifest merging.')
+ parser.add_option('--gradle-treat-as-prebuilt', action='store_true',
+ help='Whether this library should be treated as a prebuilt library by '
+ 'generate_gradle.py.')
+ parser.add_option('--main-class',
+ help='Main class for java_binary or java_annotation_processor targets.')
+ parser.add_option('--java-resources-jar-path',
+ help='Path to JAR that contains java resources. Everything '
+ 'from this JAR except meta-inf/ content and .class files '
+ 'will be added to the final APK.')
+ parser.add_option(
+ '--non-chromium-code',
+ action='store_true',
+ help='True if a java library is not chromium code, used for lint.')
+
+ # android library options
+ parser.add_option('--dex-path', help='Path to target\'s dex output.')
+
+ # native library options
+ parser.add_option('--shared-libraries-runtime-deps',
+ help='Path to file containing runtime deps for shared '
+ 'libraries.')
+ parser.add_option(
+ '--loadable-modules',
+ action='append',
+ help='GN-list of native libraries for primary '
+ 'android-abi. Can be specified multiple times.',
+ default=[])
+ parser.add_option('--secondary-abi-shared-libraries-runtime-deps',
+ help='Path to file containing runtime deps for secondary '
+ 'abi shared libraries.')
+ parser.add_option(
+ '--secondary-abi-loadable-modules',
+ action='append',
+ help='GN-list of native libraries for secondary '
+ 'android-abi. Can be specified multiple times.',
+ default=[])
+ parser.add_option(
+ '--native-lib-placeholders',
+ action='append',
+ help='GN-list of native library placeholders to add.',
+ default=[])
+ parser.add_option(
+ '--secondary-native-lib-placeholders',
+ action='append',
+ help='GN-list of native library placeholders to add '
+ 'for the secondary android-abi.',
+ default=[])
+ parser.add_option('--uncompress-shared-libraries', default=False,
+ action='store_true',
+ help='Whether to store native libraries uncompressed')
+ parser.add_option(
+ '--library-always-compress',
+ help='The list of library files that we always compress.')
+ parser.add_option(
+ '--library-renames',
+ default=[],
+ help='The list of library files that we prepend crazy. to their names.')
+
+ # apk options
+ parser.add_option('--apk-path', help='Path to the target\'s apk output.')
+ parser.add_option('--incremental-apk-path',
+ help="Path to the target's incremental apk output.")
+ parser.add_option('--incremental-install-json-path',
+ help="Path to the target's generated incremental install "
+ "json.")
+ parser.add_option(
+ '--tested-apk-config',
+ help='Path to the build config of the tested apk (for an instrumentation '
+ 'test apk).')
+ parser.add_option(
+ '--proguard-enabled',
+ action='store_true',
+ help='Whether proguard is enabled for this apk or bundle module.')
+ parser.add_option(
+ '--proguard-configs',
+ help='GN-list of proguard flag files to use in final apk.')
+ parser.add_option(
+ '--proguard-mapping-path', help='Path to jar created by ProGuard step')
+
+ # apk options that are static library specific
+ parser.add_option(
+ '--static-library-dependent-configs',
+ help='GN list of .build_configs of targets that use this target as a '
+ 'static library.')
+
+ # options shared between android_resources and apk targets
+ parser.add_option('--r-text-path', help='Path to target\'s R.txt file.')
+
+ parser.add_option('--fail',
+ help='GN-list of error message lines to fail with.')
+
+ parser.add_option('--final-dex-path',
+ help='Path to final input classes.dex (or classes.zip) to '
+ 'use in final apk.')
+ parser.add_option('--res-size-info', help='Path to .ap_.info')
+ parser.add_option('--apk-proto-resources',
+ help='Path to resources compiled in protocol buffer format '
+ ' for this apk.')
+ parser.add_option(
+ '--module-pathmap-path',
+ help='Path to pathmap file for resource paths in a bundle module.')
+ parser.add_option(
+ '--base-allowlist-rtxt-path',
+ help='Path to R.txt file for the base resources allowlist.')
+ parser.add_option(
+ '--is-base-module',
+ action='store_true',
+ help='Specifies that this module is a base module for some app bundle.')
+
+ parser.add_option('--generate-markdown-format-doc', action='store_true',
+ help='Dump the Markdown .build_config format documentation '
+ 'then exit immediately.')
+
+ parser.add_option(
+ '--base-module-build-config',
+ help='Path to the base module\'s build config '
+ 'if this is a feature module.')
+
+ parser.add_option(
+ '--module-build-configs',
+ help='For bundles, the paths of all non-async module .build_configs '
+ 'for modules that are part of the bundle.')
+
+ parser.add_option('--version-name', help='Version name for this APK.')
+ parser.add_option('--version-code', help='Version code for this APK.')
+
+ options, args = parser.parse_args(argv)
+
+ if args:
+ parser.error('No positional arguments should be given.')
+
+ if options.generate_markdown_format_doc:
+ doc_lines = _ExtractMarkdownDocumentation(__doc__)
+ for line in doc_lines:
+ print(line)
+ return 0
+
+ if options.fail:
+ parser.error('\n'.join(build_utils.ParseGnList(options.fail)))
+
+ lib_options = ['unprocessed_jar_path', 'interface_jar_path']
+ device_lib_options = ['device_jar_path', 'dex_path']
+ required_options_map = {
+ 'android_apk': ['build_config'] + lib_options + device_lib_options,
+ 'android_app_bundle_module':
+ ['build_config', 'final_dex_path', 'res_size_info'] + lib_options +
+ device_lib_options,
+ 'android_assets': ['build_config'],
+ 'android_resources': ['build_config', 'resources_zip'],
+ 'dist_aar': ['build_config'],
+ 'dist_jar': ['build_config'],
+ 'group': ['build_config'],
+ 'java_annotation_processor': ['build_config', 'main_class'],
+ 'java_binary': ['build_config'],
+ 'java_library': ['build_config', 'host_jar_path'] + lib_options,
+ 'junit_binary': ['build_config'],
+ 'system_java_library': ['build_config', 'unprocessed_jar_path'],
+ 'android_app_bundle': ['build_config', 'module_build_configs'],
+ }
+ required_options = required_options_map.get(options.type)
+ if not required_options:
+ raise Exception('Unknown type: <%s>' % options.type)
+
+ build_utils.CheckOptions(options, parser, required_options)
+
+ if options.type != 'android_app_bundle_module':
+ if options.apk_proto_resources:
+ raise Exception('--apk-proto-resources can only be used with '
+ '--type=android_app_bundle_module')
+ if options.module_pathmap_path:
+ raise Exception('--module-pathmap-path can only be used with '
+ '--type=android_app_bundle_module')
+ if options.base_allowlist_rtxt_path:
+ raise Exception('--base-allowlist-rtxt-path can only be used with '
+ '--type=android_app_bundle_module')
+ if options.is_base_module:
+ raise Exception('--is-base-module can only be used with '
+ '--type=android_app_bundle_module')
+
+ is_apk_or_module_target = options.type in ('android_apk',
+ 'android_app_bundle_module')
+
+ if not is_apk_or_module_target:
+ if options.uncompress_shared_libraries:
+ raise Exception('--uncompressed-shared-libraries can only be used '
+ 'with --type=android_apk or '
+ '--type=android_app_bundle_module')
+ if options.library_always_compress:
+ raise Exception(
+ '--library-always-compress can only be used with --type=android_apk '
+ 'or --type=android_app_bundle_module')
+ if options.library_renames:
+ raise Exception(
+ '--library-renames can only be used with --type=android_apk or '
+ '--type=android_app_bundle_module')
+
+ if options.device_jar_path and not options.dex_path:
+ raise Exception('java_library that supports Android requires a dex path.')
+ if any(getattr(options, x) for x in lib_options):
+ for attr in lib_options:
+ if not getattr(options, attr):
+ raise('Expected %s to be set.' % attr)
+
+ if options.requires_android and not options.supports_android:
+ raise Exception(
+ '--supports-android is required when using --requires-android')
+
+ is_java_target = options.type in (
+ 'java_binary', 'junit_binary', 'java_annotation_processor',
+ 'java_library', 'android_apk', 'dist_aar', 'dist_jar',
+ 'system_java_library', 'android_app_bundle_module')
+
+ is_static_library_dex_provider_target = (
+ options.static_library_dependent_configs and options.proguard_enabled)
+ if is_static_library_dex_provider_target:
+ if options.type != 'android_apk':
+ raise Exception(
+ '--static-library-dependent-configs only supports --type=android_apk')
+ options.static_library_dependent_configs = build_utils.ParseGnList(
+ options.static_library_dependent_configs)
+ static_library_dependent_configs_by_path = {
+ p: GetDepConfig(p)
+ for p in options.static_library_dependent_configs
+ }
+
+ deps_configs_paths = build_utils.ParseGnList(options.deps_configs)
+ deps = _DepsFromPaths(deps_configs_paths,
+ options.type,
+ recursive_resource_deps=options.recursive_resource_deps)
+ processor_deps = _DepsFromPaths(
+ build_utils.ParseGnList(options.annotation_processor_configs or ''),
+ options.type, filter_root_targets=False)
+
+ all_inputs = (deps.AllConfigPaths() + processor_deps.AllConfigPaths() +
+ list(static_library_dependent_configs_by_path))
+
+ if options.recursive_resource_deps:
+ # Include java_library targets since changes to these targets can remove
+ # resource deps from the build, which would require rebuilding this target's
+ # build config file: crbug.com/1168655.
+ recursive_java_deps = _DepsFromPathsWithFilters(
+ GetAllDepsConfigsInOrder(deps_configs_paths),
+ allowlist=['java_library'])
+ all_inputs.extend(recursive_java_deps.AllConfigPaths())
+
+ direct_deps = deps.Direct()
+ system_library_deps = deps.Direct('system_java_library')
+ all_deps = deps.All()
+ all_library_deps = deps.All('java_library')
+ all_resources_deps = deps.All('android_resources')
+
+ if options.type == 'java_library':
+ java_library_deps = _DepsFromPathsWithFilters(
+ deps_configs_paths, allowlist=['android_resources'])
+ # for java libraries, we only care about resources that are directly
+ # reachable without going through another java_library.
+ all_resources_deps = java_library_deps.All('android_resources')
+ if options.type == 'android_resources' and options.recursive_resource_deps:
+ # android_resources targets that want recursive resource deps also need to
+ # collect package_names from all library deps. This ensures the R.java files
+ # for these libraries will get pulled in along with the resources.
+ android_resources_library_deps = _DepsFromPathsWithFilters(
+ deps_configs_paths, allowlist=['java_library']).All('java_library')
+ if is_apk_or_module_target:
+ # android_resources deps which had recursive_resource_deps set should not
+ # have the manifests from the recursively collected deps added to this
+ # module. This keeps the manifest declarations in the child DFMs, since they
+ # will have the Java implementations.
+ def ExcludeRecursiveResourcesDeps(config):
+ return not config.get('includes_recursive_resources', False)
+
+ extra_manifest_deps = [
+ GetDepConfig(p) for p in GetAllDepsConfigsInOrder(
+ deps_configs_paths, filter_func=ExcludeRecursiveResourcesDeps)
+ ]
+
+ base_module_build_config = None
+ if options.base_module_build_config:
+ with open(options.base_module_build_config, 'r') as f:
+ base_module_build_config = json.load(f)
+
+ # Initialize some common config.
+ # Any value that needs to be queryable by dependents must go within deps_info.
+ config = {
+ 'deps_info': {
+ 'name': os.path.basename(options.build_config),
+ 'path': options.build_config,
+ 'type': options.type,
+ 'gn_target': options.gn_target,
+ 'deps_configs': [d['path'] for d in direct_deps],
+ 'chromium_code': not options.non_chromium_code,
+ },
+ # Info needed only by generate_gradle.py.
+ 'gradle': {}
+ }
+ deps_info = config['deps_info']
+ gradle = config['gradle']
+
+ if options.type == 'android_apk' and options.tested_apk_config:
+ tested_apk_deps = Deps([options.tested_apk_config])
+ tested_apk_config = tested_apk_deps.Direct()[0]
+ gradle['apk_under_test'] = tested_apk_config['name']
+
+ if options.type == 'android_app_bundle_module':
+ deps_info['is_base_module'] = bool(options.is_base_module)
+
+ # Required for generating gradle files.
+ if options.type == 'java_library':
+ deps_info['is_prebuilt'] = bool(options.is_prebuilt)
+ deps_info['gradle_treat_as_prebuilt'] = options.gradle_treat_as_prebuilt
+
+ if options.android_manifest:
+ deps_info['android_manifest'] = options.android_manifest
+
+ if options.merged_android_manifest:
+ deps_info['merged_android_manifest'] = options.merged_android_manifest
+
+ if options.bundled_srcjars:
+ deps_info['bundled_srcjars'] = build_utils.ParseGnList(
+ options.bundled_srcjars)
+
+ if options.java_sources_file:
+ deps_info['java_sources_file'] = options.java_sources_file
+
+ if is_java_target:
+ if options.bundled_srcjars:
+ gradle['bundled_srcjars'] = deps_info['bundled_srcjars']
+
+ gradle['dependent_android_projects'] = []
+ gradle['dependent_java_projects'] = []
+ gradle['dependent_prebuilt_jars'] = deps.GradlePrebuiltJarPaths()
+
+ if options.main_class:
+ deps_info['main_class'] = options.main_class
+
+ for c in deps.GradleLibraryProjectDeps():
+ if c['requires_android']:
+ gradle['dependent_android_projects'].append(c['path'])
+ else:
+ gradle['dependent_java_projects'].append(c['path'])
+
+ if options.r_text_path:
+ deps_info['r_text_path'] = options.r_text_path
+
+ # TODO(tiborg): Remove creation of JNI info for type group and java_library
+ # once we can generate the JNI registration based on APK / module targets as
+ # opposed to groups and libraries.
+ if is_apk_or_module_target or options.type in (
+ 'group', 'java_library', 'junit_binary'):
+ deps_info['jni'] = {}
+ all_java_sources = [c['java_sources_file'] for c in all_library_deps
+ if 'java_sources_file' in c]
+ if options.java_sources_file:
+ all_java_sources.append(options.java_sources_file)
+
+ if options.apk_proto_resources:
+ deps_info['proto_resources_path'] = options.apk_proto_resources
+
+ deps_info['version_name'] = options.version_name
+ deps_info['version_code'] = options.version_code
+ if options.module_pathmap_path:
+ deps_info['module_pathmap_path'] = options.module_pathmap_path
+ else:
+ # Ensure there is an entry, even if it is empty, for modules
+ # that have not enabled resource path shortening. Otherwise
+ # build_utils.ExpandFileArgs fails.
+ deps_info['module_pathmap_path'] = ''
+
+ if options.base_allowlist_rtxt_path:
+ deps_info['base_allowlist_rtxt_path'] = options.base_allowlist_rtxt_path
+ else:
+ # Ensure there is an entry, even if it is empty, for modules
+ # that don't need such a allowlist.
+ deps_info['base_allowlist_rtxt_path'] = ''
+
+ if is_java_target:
+ deps_info['requires_android'] = bool(options.requires_android)
+ deps_info['supports_android'] = bool(options.supports_android)
+
+ if not options.bypass_platform_checks:
+ deps_require_android = (all_resources_deps +
+ [d['name'] for d in all_library_deps if d['requires_android']])
+ deps_not_support_android = (
+ [d['name'] for d in all_library_deps if not d['supports_android']])
+
+ if deps_require_android and not options.requires_android:
+ raise Exception('Some deps require building for the Android platform: '
+ + str(deps_require_android))
+
+ if deps_not_support_android and options.supports_android:
+ raise Exception('Not all deps support the Android platform: '
+ + str(deps_not_support_android))
+
+ if is_apk_or_module_target or options.type == 'dist_jar':
+ all_dex_files = [c['dex_path'] for c in all_library_deps]
+
+ if is_java_target:
+ # Classpath values filled in below (after applying tested_apk_config).
+ config['javac'] = {}
+ if options.aar_path:
+ deps_info['aar_path'] = options.aar_path
+ if options.unprocessed_jar_path:
+ deps_info['unprocessed_jar_path'] = options.unprocessed_jar_path
+ deps_info['interface_jar_path'] = options.interface_jar_path
+ if options.public_deps_configs:
+ deps_info['public_deps_configs'] = build_utils.ParseGnList(
+ options.public_deps_configs)
+ if options.device_jar_path:
+ deps_info['device_jar_path'] = options.device_jar_path
+ if options.host_jar_path:
+ deps_info['host_jar_path'] = options.host_jar_path
+ if options.dex_path:
+ deps_info['dex_path'] = options.dex_path
+ if is_apk_or_module_target:
+ all_dex_files.append(options.dex_path)
+ if options.low_classpath_priority:
+ deps_info['low_classpath_priority'] = True
+ if options.type == 'android_apk':
+ deps_info['apk_path'] = options.apk_path
+ deps_info['incremental_apk_path'] = options.incremental_apk_path
+ deps_info['incremental_install_json_path'] = (
+ options.incremental_install_json_path)
+
+ if options.type == 'android_assets':
+ all_asset_sources = []
+ if options.asset_renaming_sources:
+ all_asset_sources.extend(
+ build_utils.ParseGnList(options.asset_renaming_sources))
+ if options.asset_sources:
+ all_asset_sources.extend(build_utils.ParseGnList(options.asset_sources))
+
+ deps_info['assets'] = {
+ 'sources': all_asset_sources
+ }
+ if options.asset_renaming_destinations:
+ deps_info['assets']['outputs'] = (
+ build_utils.ParseGnList(options.asset_renaming_destinations))
+ if options.disable_asset_compression:
+ deps_info['assets']['disable_compression'] = True
+ if options.treat_as_locale_paks:
+ deps_info['assets']['treat_as_locale_paks'] = True
+
+ if options.type == 'android_resources':
+ deps_info['resources_zip'] = options.resources_zip
+ if options.resource_overlay:
+ deps_info['resource_overlay'] = True
+ if options.srcjar:
+ deps_info['srcjar'] = options.srcjar
+ if options.android_manifest:
+ manifest = AndroidManifest(options.android_manifest)
+ deps_info['package_name'] = manifest.GetPackageName()
+ if options.package_name:
+ deps_info['package_name'] = options.package_name
+ deps_info['res_sources_path'] = ''
+ if options.res_sources_path:
+ deps_info['res_sources_path'] = options.res_sources_path
+
+ if options.requires_android and options.type == 'java_library':
+ if options.package_name:
+ deps_info['package_name'] = options.package_name
+
+ if options.type in ('android_resources', 'android_apk', 'junit_binary',
+ 'dist_aar', 'android_app_bundle_module', 'java_library'):
+ dependency_zips = []
+ dependency_zip_overlays = []
+ for c in all_resources_deps:
+ if not c['resources_zip']:
+ continue
+
+ dependency_zips.append(c['resources_zip'])
+ if c.get('resource_overlay'):
+ dependency_zip_overlays.append(c['resources_zip'])
+
+ extra_package_names = []
+
+ if options.type != 'android_resources':
+ extra_package_names = [
+ c['package_name'] for c in all_resources_deps if 'package_name' in c
+ ]
+
+ # android_resources targets which specified recursive_resource_deps may
+ # have extra_package_names.
+ for resources_dep in all_resources_deps:
+ extra_package_names.extend(resources_dep['extra_package_names'])
+
+ # In final types (i.e. apks and modules) that create real R.java files,
+ # they must collect package names from java_libraries as well.
+ # https://crbug.com/1073476
+ if options.type != 'java_library':
+ extra_package_names.extend([
+ c['package_name'] for c in all_library_deps if 'package_name' in c
+ ])
+ elif options.recursive_resource_deps:
+ # Pull extra_package_names from library deps if recursive resource deps
+ # are required.
+ extra_package_names = [
+ c['package_name'] for c in android_resources_library_deps
+ if 'package_name' in c
+ ]
+ config['deps_info']['includes_recursive_resources'] = True
+
+ if options.type in ('dist_aar', 'java_library'):
+ r_text_files = [
+ c['r_text_path'] for c in all_resources_deps if 'r_text_path' in c
+ ]
+ deps_info['dependency_r_txt_files'] = r_text_files
+
+ # For feature modules, remove any resources that already exist in the base
+ # module.
+ if base_module_build_config:
+ dependency_zips = [
+ c for c in dependency_zips
+ if c not in base_module_build_config['deps_info']['dependency_zips']
+ ]
+ dependency_zip_overlays = [
+ c for c in dependency_zip_overlays if c not in
+ base_module_build_config['deps_info']['dependency_zip_overlays']
+ ]
+ extra_package_names = [
+ c for c in extra_package_names if c not in
+ base_module_build_config['deps_info']['extra_package_names']
+ ]
+
+ if options.type == 'android_apk' and options.tested_apk_config:
+ config['deps_info']['arsc_package_name'] = (
+ tested_apk_config['package_name'])
+ # We should not shadow the actual R.java files of the apk_under_test by
+ # creating new R.java files with the same package names in the tested apk.
+ extra_package_names = [
+ package for package in extra_package_names
+ if package not in tested_apk_config['extra_package_names']
+ ]
+ if options.res_size_info:
+ config['deps_info']['res_size_info'] = options.res_size_info
+
+ config['deps_info']['dependency_zips'] = dependency_zips
+ config['deps_info']['dependency_zip_overlays'] = dependency_zip_overlays
+ config['deps_info']['extra_package_names'] = extra_package_names
+
+ # These are .jars to add to javac classpath but not to runtime classpath.
+ extra_classpath_jars = build_utils.ParseGnList(options.extra_classpath_jars)
+ if extra_classpath_jars:
+ deps_info['extra_classpath_jars'] = extra_classpath_jars
+
+ mergeable_android_manifests = build_utils.ParseGnList(
+ options.mergeable_android_manifests)
+ if mergeable_android_manifests:
+ deps_info['mergeable_android_manifests'] = mergeable_android_manifests
+
+ extra_proguard_classpath_jars = []
+ proguard_configs = build_utils.ParseGnList(options.proguard_configs)
+ if proguard_configs:
+ # Make a copy of |proguard_configs| since it's mutated below.
+ deps_info['proguard_configs'] = list(proguard_configs)
+
+
+ if is_java_target:
+ if options.ignore_dependency_public_deps:
+ classpath_direct_deps = deps.Direct()
+ classpath_direct_library_deps = deps.Direct('java_library')
+ else:
+ classpath_direct_deps = deps.DirectAndChildPublicDeps()
+ classpath_direct_library_deps = deps.DirectAndChildPublicDeps(
+ 'java_library')
+
+ # The classpath used to compile this target when annotation processors are
+ # present.
+ javac_classpath = set(c['unprocessed_jar_path']
+ for c in classpath_direct_library_deps)
+ # The classpath used to compile this target when annotation processors are
+ # not present. These are also always used to know when a target needs to be
+ # rebuilt.
+ javac_interface_classpath = set(c['interface_jar_path']
+ for c in classpath_direct_library_deps)
+
+ # Preserve order of |all_library_deps|. Move low priority libraries to the
+ # end of the classpath.
+ all_library_deps_sorted_for_classpath = sorted(
+ all_library_deps[::-1], key=_CompareClasspathPriority)
+
+ # The classpath used for bytecode-rewritting.
+ javac_full_classpath = OrderedSet.fromkeys(
+ c['unprocessed_jar_path']
+ for c in all_library_deps_sorted_for_classpath)
+ # The classpath used for error prone.
+ javac_full_interface_classpath = OrderedSet.fromkeys(
+ c['interface_jar_path'] for c in all_library_deps_sorted_for_classpath)
+
+ # Adding base module to classpath to compile against its R.java file
+ if base_module_build_config:
+ javac_full_classpath.add(
+ base_module_build_config['deps_info']['unprocessed_jar_path'])
+ javac_full_interface_classpath.add(
+ base_module_build_config['deps_info']['interface_jar_path'])
+ # Turbine now compiles headers against only the direct classpath, so the
+ # base module's interface jar must be on the direct interface classpath.
+ javac_interface_classpath.add(
+ base_module_build_config['deps_info']['interface_jar_path'])
+
+ for dep in classpath_direct_deps:
+ if 'extra_classpath_jars' in dep:
+ javac_classpath.update(dep['extra_classpath_jars'])
+ javac_interface_classpath.update(dep['extra_classpath_jars'])
+ for dep in all_deps:
+ if 'extra_classpath_jars' in dep:
+ javac_full_classpath.update(dep['extra_classpath_jars'])
+ javac_full_interface_classpath.update(dep['extra_classpath_jars'])
+
+ # TODO(agrieve): Might be less confusing to fold these into bootclasspath.
+ # Deps to add to the compile-time classpath (but not the runtime classpath).
+ # These are jars specified by input_jars_paths that almost never change.
+ # Just add them directly to all the classpaths.
+ if options.extra_classpath_jars:
+ javac_classpath.update(extra_classpath_jars)
+ javac_interface_classpath.update(extra_classpath_jars)
+ javac_full_classpath.update(extra_classpath_jars)
+ javac_full_interface_classpath.update(extra_classpath_jars)
+
+ if is_java_target or options.type == 'android_app_bundle':
+ # The classpath to use to run this target (or as an input to ProGuard).
+ device_classpath = []
+ if is_java_target and options.device_jar_path:
+ device_classpath.append(options.device_jar_path)
+ device_classpath.extend(
+ c.get('device_jar_path') for c in all_library_deps
+ if c.get('device_jar_path'))
+ if options.type == 'android_app_bundle':
+ for d in deps.Direct('android_app_bundle_module'):
+ device_classpath.extend(c for c in d.get('device_classpath', [])
+ if c not in device_classpath)
+
+ if options.type in ('dist_jar', 'java_binary', 'junit_binary'):
+ # The classpath to use to run this target.
+ host_classpath = []
+ if options.host_jar_path:
+ host_classpath.append(options.host_jar_path)
+ host_classpath.extend(c['host_jar_path'] for c in all_library_deps)
+ deps_info['host_classpath'] = host_classpath
+
+ # We allow lint to be run on android_apk targets, so we collect lint
+ # artifacts for them.
+ # We allow lint to be run on android_app_bundle targets, so we need to
+ # collect lint artifacts for the android_app_bundle_module targets that the
+ # bundle includes. Different android_app_bundle targets may include different
+ # android_app_bundle_module targets, so the bundle needs to be able to
+ # de-duplicate these lint artifacts.
+ if options.type in ('android_app_bundle_module', 'android_apk'):
+ # Collect all sources and resources at the apk/bundle_module level.
+ lint_aars = set()
+ lint_srcjars = set()
+ lint_java_sources = set()
+ lint_resource_sources = set()
+ lint_resource_zips = set()
+
+ if options.java_sources_file:
+ lint_java_sources.add(options.java_sources_file)
+ if options.bundled_srcjars:
+ lint_srcjars.update(deps_info['bundled_srcjars'])
+ for c in all_library_deps:
+ if c['chromium_code'] and c['requires_android']:
+ if 'java_sources_file' in c:
+ lint_java_sources.add(c['java_sources_file'])
+ lint_srcjars.update(c['bundled_srcjars'])
+ if 'aar_path' in c:
+ lint_aars.add(c['aar_path'])
+
+ if options.res_sources_path:
+ lint_resource_sources.add(options.res_sources_path)
+ if options.resources_zip:
+ lint_resource_zips.add(options.resources_zip)
+ for c in all_resources_deps:
+ if c['chromium_code']:
+ # Prefer res_sources_path to resources_zips so that lint errors have
+ # real paths and to avoid needing to extract during lint.
+ if c['res_sources_path']:
+ lint_resource_sources.add(c['res_sources_path'])
+ else:
+ lint_resource_zips.add(c['resources_zip'])
+
+ deps_info['lint_aars'] = sorted(lint_aars)
+ deps_info['lint_srcjars'] = sorted(lint_srcjars)
+ deps_info['lint_java_sources'] = sorted(lint_java_sources)
+ deps_info['lint_resource_sources'] = sorted(lint_resource_sources)
+ deps_info['lint_resource_zips'] = sorted(lint_resource_zips)
+ deps_info['lint_extra_android_manifests'] = []
+
+ if options.type == 'android_apk':
+ assert options.android_manifest, 'Android APKs must define a manifest'
+ deps_info['lint_android_manifest'] = options.android_manifest
+
+ if options.type == 'android_app_bundle':
+ module_configs = [
+ GetDepConfig(c)
+ for c in build_utils.ParseGnList(options.module_build_configs)
+ ]
+ jni_all_source = set()
+ lint_aars = set()
+ lint_srcjars = set()
+ lint_java_sources = set()
+ lint_resource_sources = set()
+ lint_resource_zips = set()
+ lint_extra_android_manifests = set()
+ for c in module_configs:
+ if c['is_base_module']:
+ assert 'base_module_config' not in deps_info, (
+ 'Must have exactly 1 base module!')
+ deps_info['base_module_config'] = c['path']
+ # Use the base module's android manifest for linting.
+ deps_info['lint_android_manifest'] = c['android_manifest']
+ else:
+ lint_extra_android_manifests.add(c['android_manifest'])
+ jni_all_source.update(c['jni']['all_source'])
+ lint_aars.update(c['lint_aars'])
+ lint_srcjars.update(c['lint_srcjars'])
+ lint_java_sources.update(c['lint_java_sources'])
+ lint_resource_sources.update(c['lint_resource_sources'])
+ lint_resource_zips.update(c['lint_resource_zips'])
+ deps_info['jni'] = {'all_source': sorted(jni_all_source)}
+ deps_info['lint_aars'] = sorted(lint_aars)
+ deps_info['lint_srcjars'] = sorted(lint_srcjars)
+ deps_info['lint_java_sources'] = sorted(lint_java_sources)
+ deps_info['lint_resource_sources'] = sorted(lint_resource_sources)
+ deps_info['lint_resource_zips'] = sorted(lint_resource_zips)
+ deps_info['lint_extra_android_manifests'] = sorted(
+ lint_extra_android_manifests)
+
+ # Map configs to classpath entries that should be included in their final dex.
+ classpath_entries_by_owning_config = collections.defaultdict(list)
+ extra_main_r_text_files = []
+ if is_static_library_dex_provider_target:
+ # Map classpath entries to configs that include them in their classpath.
+ configs_by_classpath_entry = collections.defaultdict(list)
+ for config_path, dep_config in (sorted(
+ static_library_dependent_configs_by_path.items())):
+ # For bundles, only the jar path and jni sources of the base module
+ # are relevant for proguard. Should be updated when bundle feature
+ # modules support JNI.
+ base_config = dep_config
+ if dep_config['type'] == 'android_app_bundle':
+ base_config = GetDepConfig(dep_config['base_module_config'])
+ extra_main_r_text_files.append(base_config['r_text_path'])
+ proguard_configs.extend(dep_config['proguard_all_configs'])
+ extra_proguard_classpath_jars.extend(
+ dep_config['proguard_classpath_jars'])
+ all_java_sources.extend(base_config['jni']['all_source'])
+
+ # The srcjars containing the generated R.java files are excluded for APK
+ # targets the use static libraries, so we add them here to ensure the
+ # union of resource IDs are available in the static library APK.
+ for package in base_config['extra_package_names']:
+ if package not in extra_package_names:
+ extra_package_names.append(package)
+ for cp_entry in dep_config['device_classpath']:
+ configs_by_classpath_entry[cp_entry].append(config_path)
+
+ for cp_entry in device_classpath:
+ configs_by_classpath_entry[cp_entry].append(options.build_config)
+
+ for cp_entry, candidate_configs in configs_by_classpath_entry.items():
+ config_path = (candidate_configs[0]
+ if len(candidate_configs) == 1 else options.build_config)
+ classpath_entries_by_owning_config[config_path].append(cp_entry)
+ device_classpath.append(cp_entry)
+
+ device_classpath = sorted(set(device_classpath))
+
+ deps_info['static_library_proguard_mapping_output_paths'] = sorted([
+ d['proguard_mapping_path']
+ for d in static_library_dependent_configs_by_path.values()
+ ])
+ deps_info['static_library_dependent_classpath_configs'] = {
+ path: sorted(set(classpath))
+ for path, classpath in classpath_entries_by_owning_config.items()
+ }
+ deps_info['extra_main_r_text_files'] = sorted(extra_main_r_text_files)
+
+ if is_apk_or_module_target or options.type in ('group', 'java_library',
+ 'junit_binary'):
+ deps_info['jni']['all_source'] = sorted(set(all_java_sources))
+
+ system_jars = [c['unprocessed_jar_path'] for c in system_library_deps]
+ system_interface_jars = [c['interface_jar_path'] for c in system_library_deps]
+ if system_library_deps:
+ config['android'] = {}
+ config['android']['sdk_interface_jars'] = system_interface_jars
+ config['android']['sdk_jars'] = system_jars
+
+ if options.type in ('android_apk', 'dist_aar',
+ 'dist_jar', 'android_app_bundle_module', 'android_app_bundle'):
+ for c in all_deps:
+ proguard_configs.extend(c.get('proguard_configs', []))
+ extra_proguard_classpath_jars.extend(c.get('extra_classpath_jars', []))
+ if options.type == 'android_app_bundle':
+ for c in deps.Direct('android_app_bundle_module'):
+ proguard_configs.extend(p for p in c.get('proguard_configs', []))
+ if options.type == 'android_app_bundle':
+ for d in deps.Direct('android_app_bundle_module'):
+ extra_proguard_classpath_jars.extend(
+ c for c in d.get('proguard_classpath_jars', [])
+ if c not in extra_proguard_classpath_jars)
+
+ if options.type == 'android_app_bundle':
+ deps_proguard_enabled = []
+ deps_proguard_disabled = []
+ for d in deps.Direct('android_app_bundle_module'):
+ if not d['device_classpath']:
+ # We don't care about modules that have no Java code for proguarding.
+ continue
+ if d['proguard_enabled']:
+ deps_proguard_enabled.append(d['name'])
+ else:
+ deps_proguard_disabled.append(d['name'])
+ if deps_proguard_enabled and deps_proguard_disabled:
+ raise Exception('Deps %s have proguard enabled while deps %s have '
+ 'proguard disabled' % (deps_proguard_enabled,
+ deps_proguard_disabled))
+ deps_info['proguard_enabled'] = bool(options.proguard_enabled)
+
+ if options.proguard_mapping_path:
+ deps_info['proguard_mapping_path'] = options.proguard_mapping_path
+
+ # The java code for an instrumentation test apk is assembled differently for
+ # ProGuard vs. non-ProGuard.
+ #
+ # Without ProGuard: Each library's jar is dexed separately and then combined
+ # into a single classes.dex. A test apk will include all dex files not already
+ # present in the apk-under-test. At runtime all test code lives in the test
+ # apk, and the program code lives in the apk-under-test.
+ #
+ # With ProGuard: Each library's .jar file is fed into ProGuard, which outputs
+ # a single .jar, which is then dexed into a classes.dex. A test apk includes
+ # all jar files from the program and the tests because having them separate
+ # doesn't work with ProGuard's whole-program optimizations. Although the
+ # apk-under-test still has all of its code in its classes.dex, none of it is
+ # used at runtime because the copy of it within the test apk takes precidence.
+
+ if options.type == 'android_apk' and options.tested_apk_config:
+ if tested_apk_config['proguard_enabled']:
+ assert options.proguard_enabled, ('proguard must be enabled for '
+ 'instrumentation apks if it\'s enabled for the tested apk.')
+ # Mutating lists, so no need to explicitly re-assign to dict.
+ proguard_configs.extend(
+ p for p in tested_apk_config['proguard_all_configs'])
+ extra_proguard_classpath_jars.extend(
+ p for p in tested_apk_config['proguard_classpath_jars'])
+ tested_apk_config = GetDepConfig(options.tested_apk_config)
+ deps_info['proguard_under_test_mapping'] = (
+ tested_apk_config['proguard_mapping_path'])
+ elif options.proguard_enabled:
+ # Not sure why you'd want to proguard the test apk when the under-test apk
+ # is not proguarded, but it's easy enough to support.
+ deps_info['proguard_under_test_mapping'] = ''
+
+ # Add all tested classes to the test's classpath to ensure that the test's
+ # java code is a superset of the tested apk's java code
+ device_classpath_extended = list(device_classpath)
+ device_classpath_extended.extend(
+ p for p in tested_apk_config['device_classpath']
+ if p not in device_classpath)
+ # Include in the classpath classes that are added directly to the apk under
+ # test (those that are not a part of a java_library).
+ javac_classpath.add(tested_apk_config['unprocessed_jar_path'])
+ javac_interface_classpath.add(tested_apk_config['interface_jar_path'])
+ javac_full_classpath.add(tested_apk_config['unprocessed_jar_path'])
+ javac_full_interface_classpath.add(tested_apk_config['interface_jar_path'])
+ javac_full_classpath.update(tested_apk_config['javac_full_classpath'])
+ javac_full_interface_classpath.update(
+ tested_apk_config['javac_full_interface_classpath'])
+
+ # Exclude .jar files from the test apk that exist within the apk under test.
+ tested_apk_library_deps = tested_apk_deps.All('java_library')
+ tested_apk_dex_files = {c['dex_path'] for c in tested_apk_library_deps}
+ all_dex_files = [p for p in all_dex_files if p not in tested_apk_dex_files]
+ tested_apk_jar_files = set(tested_apk_config['device_classpath'])
+ device_classpath = [
+ p for p in device_classpath if p not in tested_apk_jar_files
+ ]
+
+ if options.type in ('android_apk', 'dist_aar', 'dist_jar',
+ 'android_app_bundle_module', 'android_app_bundle'):
+ deps_info['proguard_all_configs'] = sorted(set(proguard_configs))
+ deps_info['proguard_classpath_jars'] = sorted(
+ set(extra_proguard_classpath_jars))
+
+ # Dependencies for the final dex file of an apk.
+ if (is_apk_or_module_target or options.final_dex_path
+ or options.type == 'dist_jar'):
+ config['final_dex'] = {}
+ dex_config = config['final_dex']
+ dex_config['path'] = options.final_dex_path
+ if is_apk_or_module_target or options.type == 'dist_jar':
+ dex_config['all_dex_files'] = all_dex_files
+
+ if is_java_target:
+ config['javac']['classpath'] = sorted(javac_classpath)
+ config['javac']['interface_classpath'] = sorted(javac_interface_classpath)
+ # Direct() will be of type 'java_annotation_processor', and so not included
+ # in All('java_library').
+ # Annotation processors run as part of the build, so need host_jar_path.
+ config['javac']['processor_classpath'] = [
+ c['host_jar_path'] for c in processor_deps.Direct()
+ if c.get('host_jar_path')
+ ]
+ config['javac']['processor_classpath'] += [
+ c['host_jar_path'] for c in processor_deps.All('java_library')
+ ]
+ config['javac']['processor_classes'] = [
+ c['main_class'] for c in processor_deps.Direct()]
+ deps_info['javac_full_classpath'] = list(javac_full_classpath)
+ deps_info['javac_full_interface_classpath'] = list(
+ javac_full_interface_classpath)
+ elif options.type == 'android_app_bundle':
+ # bundles require javac_full_classpath to create .aab.jar.info and require
+ # javac_full_interface_classpath for lint.
+ javac_full_classpath = OrderedSet()
+ javac_full_interface_classpath = OrderedSet()
+ for d in deps.Direct('android_app_bundle_module'):
+ javac_full_classpath.update(d['javac_full_classpath'])
+ javac_full_interface_classpath.update(d['javac_full_interface_classpath'])
+ javac_full_classpath.add(d['unprocessed_jar_path'])
+ javac_full_interface_classpath.add(d['interface_jar_path'])
+ deps_info['javac_full_classpath'] = list(javac_full_classpath)
+ deps_info['javac_full_interface_classpath'] = list(
+ javac_full_interface_classpath)
+
+ if options.type in ('android_apk', 'dist_jar', 'android_app_bundle_module',
+ 'android_app_bundle'):
+ deps_info['device_classpath'] = device_classpath
+ if options.tested_apk_config:
+ deps_info['device_classpath_extended'] = device_classpath_extended
+
+ if options.type in ('android_apk', 'dist_jar'):
+ all_interface_jars = []
+ if options.interface_jar_path:
+ all_interface_jars.append(options.interface_jar_path)
+ all_interface_jars.extend(c['interface_jar_path'] for c in all_library_deps)
+
+ config['dist_jar'] = {
+ 'all_interface_jars': all_interface_jars,
+ }
+
+ if is_apk_or_module_target:
+ manifest = AndroidManifest(options.android_manifest)
+ deps_info['package_name'] = manifest.GetPackageName()
+ if not options.tested_apk_config and manifest.GetInstrumentationElements():
+ # This must then have instrumentation only for itself.
+ manifest.CheckInstrumentationElements(manifest.GetPackageName())
+
+ library_paths = []
+ java_libraries_list = None
+ if options.shared_libraries_runtime_deps:
+ library_paths = _ExtractSharedLibsFromRuntimeDeps(
+ options.shared_libraries_runtime_deps)
+ java_libraries_list = _CreateJavaLibrariesList(library_paths)
+ all_inputs.append(options.shared_libraries_runtime_deps)
+
+ secondary_abi_library_paths = []
+ if options.secondary_abi_shared_libraries_runtime_deps:
+ secondary_abi_library_paths = _ExtractSharedLibsFromRuntimeDeps(
+ options.secondary_abi_shared_libraries_runtime_deps)
+ all_inputs.append(options.secondary_abi_shared_libraries_runtime_deps)
+
+ native_library_placeholder_paths = build_utils.ParseGnList(
+ options.native_lib_placeholders)
+
+ secondary_native_library_placeholder_paths = build_utils.ParseGnList(
+ options.secondary_native_lib_placeholders)
+
+ loadable_modules = build_utils.ParseGnList(options.loadable_modules)
+ secondary_abi_loadable_modules = build_utils.ParseGnList(
+ options.secondary_abi_loadable_modules)
+
+ config['native'] = {
+ 'libraries':
+ library_paths,
+ 'native_library_placeholders':
+ native_library_placeholder_paths,
+ 'secondary_abi_libraries':
+ secondary_abi_library_paths,
+ 'secondary_native_library_placeholders':
+ secondary_native_library_placeholder_paths,
+ 'java_libraries_list':
+ java_libraries_list,
+ 'uncompress_shared_libraries':
+ options.uncompress_shared_libraries,
+ 'library_always_compress':
+ options.library_always_compress,
+ 'library_renames':
+ options.library_renames,
+ 'loadable_modules':
+ loadable_modules,
+ 'secondary_abi_loadable_modules':
+ secondary_abi_loadable_modules,
+ }
+ config['assets'], config['uncompressed_assets'], locale_paks = (
+ _MergeAssets(deps.All('android_assets')))
+
+ deps_info['locales_java_list'] = _CreateJavaLocaleListFromAssets(
+ config['uncompressed_assets'], locale_paks)
+
+ config['extra_android_manifests'] = []
+ for c in extra_manifest_deps:
+ config['extra_android_manifests'].extend(
+ c.get('mergeable_android_manifests', []))
+
+ # Collect java resources
+ java_resources_jars = [d['java_resources_jar'] for d in all_library_deps
+ if 'java_resources_jar' in d]
+ if options.tested_apk_config:
+ tested_apk_resource_jars = [d['java_resources_jar']
+ for d in tested_apk_library_deps
+ if 'java_resources_jar' in d]
+ java_resources_jars = [jar for jar in java_resources_jars
+ if jar not in tested_apk_resource_jars]
+ config['java_resources_jars'] = java_resources_jars
+
+ if options.java_resources_jar_path:
+ deps_info['java_resources_jar'] = options.java_resources_jar_path
+
+ # DYNAMIC FEATURE MODULES:
+ # Make sure that dependencies that exist on the base module
+ # are not duplicated on the feature module.
+ if base_module_build_config:
+ base = base_module_build_config
+ RemoveObjDups(config, base, 'deps_info', 'device_classpath')
+ RemoveObjDups(config, base, 'deps_info', 'javac_full_classpath')
+ RemoveObjDups(config, base, 'deps_info', 'javac_full_interface_classpath')
+ RemoveObjDups(config, base, 'deps_info', 'jni', 'all_source')
+ RemoveObjDups(config, base, 'final_dex', 'all_dex_files')
+ RemoveObjDups(config, base, 'extra_android_manifests')
+
+ if is_java_target:
+ jar_to_target = {}
+ _AddJarMapping(jar_to_target, [deps_info])
+ _AddJarMapping(jar_to_target, all_deps)
+ if base_module_build_config:
+ _AddJarMapping(jar_to_target, [base_module_build_config['deps_info']])
+ if options.tested_apk_config:
+ _AddJarMapping(jar_to_target, [tested_apk_config])
+ for jar, target in zip(tested_apk_config['javac_full_classpath'],
+ tested_apk_config['javac_full_classpath_targets']):
+ jar_to_target[jar] = target
+
+ # Used by bytecode_processor to give better error message when missing
+ # deps are found.
+ config['deps_info']['javac_full_classpath_targets'] = [
+ jar_to_target[x] for x in deps_info['javac_full_classpath']
+ ]
+
+ build_utils.WriteJson(config, options.build_config, only_if_changed=True)
+
+ if options.depfile:
+ build_utils.WriteDepfile(options.depfile, options.build_config,
+ sorted(set(all_inputs)))
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))