#!/usr/bin/env python
#
# 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)
    * [dist_jar](#target_dist_jar)
    * [dist_aar](#target_dist_aar)
    * [resource_rewriter](#target_resource_rewriter)
    * [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.

# Top-level `resources` dictionary:

This dictionary only appears for a few target types that can contain or
relate to Android resources (e.g. `android_resources` or `android_apk`):

* `resources['dependency_zips']`:
List of `deps_info['resources_zip']` entries for all `android_resources`
dependencies for the current target.

* `resource['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`.

* `resources['extra_r_text_files']`:
Always empty for `android_resources` types. Otherwise, the list of
`deps_info['r_text']` entries for all `android_resources` dependencies for
the current target. 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['resource_dirs']`:
List of paths to the source directories containing the resources for this
target. This key is optional, because some targets can refer to prebuilt
`.aar` archives.


* `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['resource_dirs']` 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 content of
    `deps_info['resource_dirs']` 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['r_text']`:
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']`. This is *always*
generated from the content of `deps_info['r_text']` by the
`build/android/gyp/process_resources.py` script.


## <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['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['jar_path']`:
Path to a file that is the result of processing
`deps_info['unprocessed_jar_path']` with various tools.

* `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`
tool on `deps_info['jar_path']`

* `deps_info['dex_path']`:
Path to the `.dex` file generated for this target, from `deps_info['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['owned_resource_dirs']`:
List of all resource directories belonging to all resource dependencies for
this target.

* `deps_info['owned_resource_zips']`:
List of all resource zip files belonging to all resource dependencies for this
target.

* `deps_info['owned_resource_srcjars']`:
List of all .srcjar files belonging to all resource dependencies for this
target.

* `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['java_runtime_classpath']`:
The classpath used when running a Java or Android binary. Essentially the
collection of all `deps_info['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['non_native_packed_relocations']`:
A string that is either "True" or "False" (why a string?). True to indicate
that this uses packed relocations that may not be supported by the target
Android system for this build (this generally requires the Chromium linker
to be used to load the native libraries).

* `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']['dependency_dex_files']`:
The list of paths to all `deps_info['dex_path']` entries for all library
dependencies for this APK.

* `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).

* `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['secondary_abi_java_libraries_list']`
The same list as `native['second_abi_libraries']` as a Java source string.

* `native['uncompress_shared_libraries']`
A boolean indicating whether native libraries are stored uncompressed in the
APK.

* `native['extra_shared_libraries']`
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.

* `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.

* `compressed_locales_java_list`
A string holding a Java source fragment that gives the list of locales stored
compressed in the `//assets/` directory. E.g. `"{\"am\","\ar\",\"en-US\"}"`.
Note that the files will be stored with the `.pak` extension (e.g.
`//assets/en-US.pak`).

* `uncompressed_locales_java_list`
A string holding a Java source fragment that gives the list of locales stored
uncompressed in the `//assets/stored-locales/` directory. These are used for
the System WebView feature only. Note that the files will be stored with the
`.pak` extension (e.g. `//assets/stored-locales/en-US.apk`).

* `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_all_extra_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_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="target_resource_rewriter">Target type `resource_rewriter`</a>:

The ResourceRewriter Java class is in charge of rewriting resource IDs at
runtime, for the benefit of the System WebView feature. This is a special
target type for it.

Its `.build_config` only keeps a list of dependencies in its
`deps_info['deps_configs']` key.

## <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['resource_packages']`
For `java_library` targets, this is the list of package names for all resource
dependencies for the current target. Order must match the one from
`javac['srcjars']`. For other target types, this key does not exist.

* `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`.

--------------- END_MARKDOWN ---------------------------------------------------
"""

import itertools
import json
import optparse
import os
import sys
import xml.dom.minidom

from util import build_utils

# Types that should never be used as a dependency of another build config.
_ROOT_TYPES = ('android_apk', 'java_binary',
               'java_annotation_processor', 'junit_binary', 'resource_rewriter')
# Types that should not allow code deps to pass through.
_RESOURCE_TYPES = ('android_assets', 'android_resources', 'system_java_library')


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 GetAllDepsConfigsInOrder(deps_config_paths):
  def GetDeps(path):
    return GetDepConfig(path)['deps_configs']
  return build_utils.GetSortedTransitiveDependencies(deps_config_paths, GetDeps)


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 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 AllConfigPaths(self):
    return self.all_deps_config_paths

  def RemoveNonDirectDep(self, path):
    if path in self.direct_deps_config_paths:
      raise Exception('Cannot remove direct dep.')
    self.all_deps_config_paths.remove(path)
    self.all_deps_configs.remove(GetDepConfig(path))

  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['jar_path'] not in ret:
            ret.append(config['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 itertools.izip_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.iteritems()]
    # Sort to ensure deterministic ordering.
    ret.sort()
    return ret

  return create_list(compressed), create_list(uncompressed), locale_paks


def _ResolveGroups(configs):
  """Returns a list of configs with all groups inlined."""
  ret = list(configs)
  while True:
    groups = DepsOfType('group', ret)
    if not groups:
      return ret
    for config in groups:
      index = ret.index(config)
      expanded_configs = [GetDepConfig(p) for p in config['deps_configs']]
      ret[index:index + 1] = expanded_configs


def _DepsFromPaths(dep_paths, target_type, filter_root_targets=True):
  """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.
  """
  configs = [GetDepConfig(p) for p in dep_paths]
  configs = _ResolveGroups(configs)
  # Don't allow root targets to be considered as a dep.
  if filter_root_targets:
    configs = [c for c in configs if c['type'] not in _ROOT_TYPES]

  # Don't allow java libraries to cross through assets/resources.
  if target_type in _RESOURCE_TYPES:
    configs = [c for c in configs if c['type'] in _RESOURCE_TYPES]
  return Deps([c['path'] for c in configs])


def _ExtractSharedLibsFromRuntimeDeps(runtime_deps_files):
  ret = []
  for path in runtime_deps_files:
    with open(path) 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
  """
  return ('{%s}' % ','.join(['"%s"' % s[3:-3] for s in library_paths]))


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 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(
      '--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.')
  parser.add_option(
      '--classpath-deps-configs',
      help='GN-list of build_config files for libraries to include as '
           'build-time-only classpath.')

  # 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('--r-text', help='Path to target\'s R.txt file.')
  parser.add_option('--package-name',
      help='Java package name for these resources.')
  parser.add_option('--android-manifest', help='Path to android manifest.')
  parser.add_option('--resource-dirs', action='append', default=[],
                    help='GYP-list of resource dirs')

  # 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('--jar-path', help='Path to target\'s jar output.')
  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('--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.')

  # 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('--secondary-abi-shared-libraries-runtime-deps',
                    help='Path to file containing runtime deps for secondary '
                         'abi shared libraries.')
  parser.add_option('--non-native-packed-relocations',
                    action='store_true', default=False,
                    help='Whether relocation packing was applied using the '
                         'Android relocation_packer tool.')
  parser.add_option('--uncompress-shared-libraries', default=False,
                    action='store_true',
                    help='Whether to store native libraries uncompressed')
  parser.add_option('--extra-shared-libraries',
                    help='GN-list of paths to extra native libraries stored '
                    'in the APK.')
  # 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.')
  parser.add_option('--proguard-configs',
      help='GN-list of proguard flag files to use in final apk.')
  parser.add_option('--proguard-output-jar-path',
      help='Path to jar created by ProGuard step')
  parser.add_option('--fail',
      help='GN-list of error message lines to fail with.')

  parser.add_option('--apk-proto-resources',
                    help='Path to resources compiled in protocol buffer format '
                         ' for this apk.')

  parser.add_option('--generate-markdown-format-doc', action='store_true',
                    help='Dump the Markdown .build_config format documentation '
                    'then exit immediately.')

  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)))

  jar_path_options = ['jar_path', 'unprocessed_jar_path', 'interface_jar_path']
  required_options_map = {
      'android_apk': ['build_config','dex_path'] + jar_path_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'] + jar_path_options,
      'junit_binary': ['build_config'],
      'resource_rewriter': ['build_config'],
      'system_java_library': ['build_config'],
  }
  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.apk_proto_resources:
    if options.type != 'android_apk':
      raise Exception('--apk-proto-resources can only be used with '
                      '--type=android_apk')

  if options.uncompress_shared_libraries:
    if options.type != 'android_apk':
      raise Exception('--uncompressed-shared-libraries can only be used '
                      'with --type=android_apk')

  if options.jar_path and options.supports_android and not options.dex_path:
    raise Exception('java_library that supports Android requires a dex path.')
  if any(getattr(options, x) for x in jar_path_options):
    for attr in jar_path_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')

  deps = _DepsFromPaths(
      build_utils.ParseGnList(options.deps_configs), options.type)
  processor_deps = _DepsFromPaths(
      build_utils.ParseGnList(options.annotation_processor_configs or ''),
      options.type, filter_root_targets=False)
  classpath_deps = _DepsFromPaths(
      build_utils.ParseGnList(options.classpath_deps_configs or ''),
      options.type)

  all_inputs = sorted(set(deps.AllConfigPaths() +
                          processor_deps.AllConfigPaths() +
                          classpath_deps.AllConfigPaths()))

  system_library_deps = deps.Direct('system_java_library')
  direct_library_deps = deps.Direct('java_library')
  all_library_deps = deps.All('java_library')
  all_resources_deps = deps.All('android_resources')

  # 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,
      'deps_configs': deps.direct_deps_config_paths
    },
    # 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_name = tested_apk_deps.Direct()[0]['name']
    tested_apk_resources_deps = tested_apk_deps.All('android_resources')
    gradle['apk_under_test'] = tested_apk_name
    all_resources_deps = [
        d for d in all_resources_deps if not d in tested_apk_resources_deps]

  # 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 is_java_target:
    if options.java_sources_file:
      deps_info['java_sources_file'] = options.java_sources_file
    if options.bundled_srcjars:
      gradle['bundled_srcjars'] = (
          build_utils.ParseGnList(options.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.type == 'android_apk':
    config['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)
    config['jni']['all_source'] = all_java_sources

    if options.apk_proto_resources:
      deps_info['proto_resources_path'] = options.apk_proto_resources

  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_java_target:
    # Classpath values filled in below (after applying tested_apk_config).
    config['javac'] = {}
    if options.jar_path:
      deps_info['jar_path'] = options.jar_path
      deps_info['unprocessed_jar_path'] = options.unprocessed_jar_path
      deps_info['interface_jar_path'] = options.interface_jar_path
    if options.dex_path:
      deps_info['dex_path'] = options.dex_path
    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)
      deps_info['non_native_packed_relocations'] = str(
          options.non_native_packed_relocations)

  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.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
    if options.r_text:
      deps_info['r_text'] = options.r_text

    deps_info['resources_dirs'] = []
    if options.resource_dirs:
      for gyp_list in options.resource_dirs:
        deps_info['resources_dirs'].extend(build_utils.ParseGnList(gyp_list))

  if options.requires_android and is_java_target:
    # Lint all resources that are not already linted by a dependent library.
    owned_resource_dirs = set()
    owned_resource_zips = set()
    owned_resource_srcjars = set()
    for c in all_resources_deps:
      # Always use resources_dirs in favour of resources_zips so that lint error
      # messages have paths that are closer to reality (and to avoid needing to
      # extract during lint).
      if c['resources_dirs']:
        owned_resource_dirs.update(c['resources_dirs'])
      else:
        owned_resource_zips.add(c['resources_zip'])
      srcjar = c.get('srcjar')
      if srcjar:
        owned_resource_srcjars.add(srcjar)

    for c in all_library_deps:
      if c['requires_android']:
        owned_resource_dirs.difference_update(c['owned_resources_dirs'])
        owned_resource_zips.difference_update(c['owned_resources_zips'])
        # Many .aar files include R.class files in them, as it makes it easier
        # for IDEs to resolve symbols. However, including them is not required
        # and not all prebuilts do. Rather than try to detect their presense,
        # just assume they are not there. The only consequence is redundant
        # compilation of the R.class.
        if not c['is_prebuilt']:
          owned_resource_srcjars.difference_update(c['owned_resource_srcjars'])
    deps_info['owned_resources_dirs'] = sorted(owned_resource_dirs)
    deps_info['owned_resources_zips'] = sorted(owned_resource_zips)
    deps_info['owned_resource_srcjars'] = sorted(owned_resource_srcjars)

    if options.type == 'java_library':
      # Used to strip out R.class for android_prebuilt()s.
      config['javac']['resource_packages'] = [
          c['package_name'] for c in all_resources_deps if 'package_name' in c]

  if options.type in (
      'android_resources', 'android_apk', 'junit_binary', 'resource_rewriter',
      'dist_aar'):
    config['resources'] = {}
    config['resources']['dependency_zips'] = [
        c['resources_zip'] for c in all_resources_deps]
    extra_package_names = []
    extra_r_text_files = []
    if options.type != 'android_resources':
      extra_package_names = [
          c['package_name'] for c in all_resources_deps if 'package_name' in c]
      extra_r_text_files = [
          c['r_text'] for c in all_resources_deps if 'r_text' in c]

    config['resources']['extra_package_names'] = extra_package_names
    config['resources']['extra_r_text_files'] = extra_r_text_files

  if options.type == 'android_apk':
    deps_dex_files = [c['dex_path'] for c in all_library_deps]

  if is_java_target:
    # The classpath used to compile this target when annotation processors are
    # present.
    javac_classpath = [
        c['unprocessed_jar_path'] for c in 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 = [
        c['interface_jar_path'] for c in direct_library_deps]
    # The classpath used for error prone.
    javac_full_interface_classpath = [
        c['interface_jar_path'] for c in all_library_deps]
    # The classpath used for bytecode-rewritting.
    javac_full_classpath = [
        c['unprocessed_jar_path'] for c in all_library_deps]
    # The classpath to use to run this target (or as an input to ProGuard).
    java_full_classpath = []
    if options.jar_path:
      java_full_classpath.append(options.jar_path)
    java_full_classpath.extend(c['jar_path'] for c in all_library_deps)

    # Deps to add to the compile-time classpath (but not the runtime classpath).
    # TODO(agrieve): Might be less confusing to fold these into bootclasspath.
    extra_jars = [c['unprocessed_jar_path']
                  for c in classpath_deps.Direct('java_library')]

    if options.extra_classpath_jars:
      # These are .jars to add to javac classpath but not to runtime classpath.
      extra_jars.extend(build_utils.ParseGnList(options.extra_classpath_jars))

    extra_jars = [p for p in extra_jars if p not in javac_classpath]
    javac_classpath.extend(extra_jars)
    javac_interface_classpath.extend(extra_jars)
    javac_full_interface_classpath.extend(
        p for p in extra_jars if p not in javac_full_classpath)
    javac_full_classpath.extend(
        p for p in extra_jars if p not in javac_full_classpath)
    if extra_jars:
      deps_info['extra_classpath_jars'] = extra_jars

  if options.proguard_configs:
    deps_info['proguard_configs'] = (
        build_utils.ParseGnList(options.proguard_configs))

  if options.type in ('android_apk', 'dist_aar', 'dist_jar'):
    all_configs = deps_info.get('proguard_configs', [])
    extra_jars = []
    for c in all_library_deps:
      all_configs.extend(
          p for p in c.get('proguard_configs', []) if p not in all_configs)
      extra_jars.extend(
          p for p in c.get('extra_classpath_jars', []) if p not in extra_jars)
    deps_info['proguard_all_configs'] = all_configs
    deps_info['proguard_all_extra_jars'] = extra_jars
    deps_info['proguard_enabled'] = options.proguard_enabled
    if options.proguard_output_jar_path:
      deps_info['proguard_output_jar_path'] = options.proguard_output_jar_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:
    tested_apk_config = GetDepConfig(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.
      all_configs.extend(p for p in tested_apk_config['proguard_all_configs']
                         if p not in all_configs)
      extra_jars.extend(p for p in tested_apk_config['proguard_all_extra_jars']
                        if p not in extra_jars)
      tested_apk_config = GetDepConfig(options.tested_apk_config)
      deps_info['proguard_under_test_mapping'] = (
          tested_apk_config['proguard_output_jar_path'] + '.mapping')
    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'] = ''

    expected_tested_package = tested_apk_config['package_name']
    AndroidManifest(options.android_manifest).CheckInstrumentationElements(
        expected_tested_package)

    # 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
    java_full_classpath.extend(
        p for p in tested_apk_config['java_runtime_classpath']
        if p not in java_full_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.append(tested_apk_config['unprocessed_jar_path'])
    javac_full_classpath.append(tested_apk_config['unprocessed_jar_path'])
    javac_interface_classpath.append(tested_apk_config['interface_jar_path'])
    javac_full_interface_classpath.append(
        tested_apk_config['interface_jar_path'])
    javac_full_interface_classpath.extend(
        p for p in tested_apk_config['javac_full_interface_classpath']
        if p not in javac_full_interface_classpath)
    javac_full_classpath.extend(
        p for p in tested_apk_config['javac_full_classpath']
        if p not in javac_full_classpath)

    # Exclude dex files from the test apk that exist within the apk under test.
    # TODO(agrieve): When proguard is enabled, this filtering logic happens
    #     within proguard_util.py. Move the logic for the proguard case into
    #     here as well.
    tested_apk_library_deps = tested_apk_deps.All('java_library')
    tested_apk_deps_dex_files = [c['dex_path'] for c in tested_apk_library_deps]
    deps_dex_files = [
        p for p in deps_dex_files if not p in tested_apk_deps_dex_files]

  # Dependencies for the final dex file of an apk.
  if options.type == 'android_apk':
    config['final_dex'] = {}
    dex_config = config['final_dex']
    dex_config['dependency_dex_files'] = deps_dex_files

  system_jars = [c['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
    gradle['bootclasspath'] = system_jars

  if is_java_target:
    config['javac']['bootclasspath'] = system_jars
    config['javac']['classpath'] = javac_classpath
    config['javac']['interface_classpath'] = javac_interface_classpath
    # Direct() will be of type 'java_annotation_processor'.
    config['javac']['processor_classpath'] = [
        c['jar_path'] for c in processor_deps.Direct() if c.get('jar_path')] + [
        c['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'] = javac_full_classpath
    deps_info['javac_full_interface_classpath'] = javac_full_interface_classpath

    if options.type in (
        'android_apk', 'dist_jar', 'java_binary', 'junit_binary'):
      deps_info['java_runtime_classpath'] = java_full_classpath

  if options.type in ('android_apk', 'dist_jar'):
    all_interface_jars = []
    if options.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 options.type == 'android_apk':
    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
    runtime_deps_files = build_utils.ParseGnList(
        options.shared_libraries_runtime_deps or '[]')
    if runtime_deps_files:
      library_paths = _ExtractSharedLibsFromRuntimeDeps(runtime_deps_files)
      java_libraries_list = _CreateJavaLibrariesList(library_paths)

    secondary_abi_library_paths = []
    secondary_abi_java_libraries_list = None
    secondary_abi_runtime_deps_files = build_utils.ParseGnList(
        options.secondary_abi_shared_libraries_runtime_deps or '[]')
    if secondary_abi_runtime_deps_files:
      secondary_abi_library_paths = _ExtractSharedLibsFromRuntimeDeps(
          secondary_abi_runtime_deps_files)
      secondary_abi_java_libraries_list = _CreateJavaLibrariesList(
          secondary_abi_library_paths)

    extra_shared_libraries = build_utils.ParseGnList(
        options.extra_shared_libraries)

    all_inputs.extend(runtime_deps_files)
    config['native'] = {
      'libraries': library_paths,
      'secondary_abi_libraries': secondary_abi_library_paths,
      'java_libraries_list': java_libraries_list,
      'secondary_abi_java_libraries_list': secondary_abi_java_libraries_list,
      'uncompress_shared_libraries': options.uncompress_shared_libraries,
      'extra_shared_libraries': extra_shared_libraries,
    }
    config['assets'], config['uncompressed_assets'], locale_paks = (
        _MergeAssets(deps.All('android_assets')))
    config['compressed_locales_java_list'] = _CreateJavaLocaleListFromAssets(
        config['assets'], locale_paks)
    config['uncompressed_locales_java_list'] = _CreateJavaLocaleListFromAssets(
        config['uncompressed_assets'], locale_paks)

    config['extra_android_manifests'] = filter(None, (
        d.get('android_manifest') for d in all_resources_deps))

    # 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

  build_utils.WriteJson(config, options.build_config, only_if_changed=True)

  if options.depfile:
    build_utils.WriteDepfile(options.depfile, options.build_config, all_inputs,
                             add_pydeps=False)  # pydeps listed in GN.


if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
