Commit 1fa1c441 authored by David 'Digit' Turner's avatar David 'Digit' Turner Committed by Commit Bot

android build: Split process_resources GN rule and script.

The process_resources() GN template and the associated
process_resources.py script are huge and difficult to understand
because they can be used to perform two slightly related
different things.

In preparation for a future CL that will introduce a new resource
compilation mode, this CL tries to clarify the situation by splitting
them into two sets of GN template + script:

   - prepare_resources() + prepare_resources.py, which are
     used to create .resources.zip archives of raw/uncompiled
     resources for resource related targets, as well as
     generating a corresponding R.txt and .srcjar(R.java)
     file.

     This corresponds to what process_resources() did when
     it was called from android_resources() and junit_binary().

     Note that this always generates non-final resource IDs,
     as well as a dummy onResourcesLoaded() method, necessary
     to compile, but not link, the ResourceRewriter class
     used to implement the system webview feature.

   - compile_resources() + compile_resources.py, which are used
     to compile all resource dependencies of a given binary
     (e.g. android_apk) into an intermediate .ap_ file.

     This corresponds to the behaviour of process_resources()
     when called from android_apk(). This generates final
     resource IDs by default, unless |shared_resources| or
     |shared_resources_whitelist| is used.

     Also, as a simplification, |shared_resources_whitelist|
     now implies |shared_resources|, except that it restrict
     the list of non-final resource IDs.

- Removed generate_constant_ids, since compile_resources()
  will always generate constant ids unless shared resources
  are being used. And prepare_resources() always generates
  non-constant IDs, as before the CL.

+ Add documentation for the prepare_resources() and
  compile_resources() internal GN rules, to make them
  a little less intimidating.

+ Removed |app_as_shared_lib|, since even before this CL all
  resources were generated with package ID 0x7f anyway, or
  fixed a compile_resources() time. Hence |shared_resources|
  did the exact same thing.

+ Improve --help output for prepare_resources.py and
  compile_resources.py by using option groups for inputs
  and outputs.

R=agrieve@chromium.org,yfriedman@chromium.org,estevenson@chromium.org,trevordixon@chromium.org

Bug: 820459
Change-Id: If05ac24a57c4dfa11f9ce43c30ab22e957b2765d
Reviewed-on: https://chromium-review.googlesource.com/957095
Commit-Queue: David Turner <digit@chromium.org>
Reviewed-by: default avataragrieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/master@{#543957}
parent f6520325
......@@ -4,16 +4,17 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Process Android resources to generate R.java, and prepare for packaging.
"""Compile Android resources into an intermediate APK.
This will crunch images with aapt2 and generate v14 compatible resources
(see generate_v14_compatible_resources.py).
This can also generate an R.txt, and an .srcjar file containing the proper
final R.java class for all resource packages the APK depends on.
This will crunch images with aapt2.
"""
import codecs
import argparse
import collections
import multiprocessing.pool
import optparse
import os
import re
import shutil
......@@ -23,9 +24,8 @@ import zipfile
from xml.etree import ElementTree
import generate_v14_compatible_resources
from util import build_utils
from util import resource_utils
_SOURCE_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(
__file__))))
......@@ -33,16 +33,6 @@ _SOURCE_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(
sys.path.insert(1, os.path.join(_SOURCE_ROOT, 'third_party'))
from jinja2 import Template # pylint: disable=F0401
_EMPTY_ANDROID_MANIFEST_PATH = os.path.join(
_SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml')
# Represents a line from a R.txt file.
TextSymbolsEntry = collections.namedtuple('RTextEntry',
('java_type', 'resource_type', 'name', 'value'))
# A variation of this lists also exists in:
# //base/android/java/src/org/chromium/base/LocaleUtils.java
_CHROME_TO_ANDROID_LOCALE_MAP = {
......@@ -69,378 +59,108 @@ _PNG_WEBP_BLACKLIST_PATTERN = re.compile('|'.join([
r'.*\.dd\.png']))
class _ResourceWhitelist(object):
def __init__(self, entries=None):
self._entries = None
if entries:
self._entries = set(self._Key(x) for x in entries)
def __contains__(self, entry):
return self._entries is None or self._Key(entry) in self._entries
@staticmethod
def _Key(entry):
# Whitelists should only care about the name of the resource rather than the
# resource ID (since the whitelist is from another compilation unit, the
# resource IDs may not match).
return (entry.java_type, entry.resource_type, entry.name)
def _ParseArgs(args):
"""Parses command line options.
Returns:
An options object as from optparse.OptionsParser.parse_args()
An options object as from argparse.ArgumentParser.parse_args()
"""
parser = optparse.OptionParser()
build_utils.AddDepfileOption(parser)
parser.add_option('--android-sdk-jar',
help='the path to android jar file.')
parser.add_option('--aapt-path',
help='path to the Android aapt tool')
parser.add_option('--non-constant-id', action='store_true')
parser.add_option('--android-manifest', help='AndroidManifest.xml path')
parser.add_option('--custom-package', help='Java package for R.java')
parser.add_option(
parser, input_opts, output_opts = resource_utils.ResourceArgsParser()
input_opts.add_argument('--android-manifest', required=True,
help='AndroidManifest.xml path')
input_opts.add_argument(
'--shared-resources',
action='store_true',
help='Make a resource package that can be loaded by a different'
'application at runtime to access the package\'s resources.')
parser.add_option(
'--app-as-shared-lib',
action='store_true',
help='Make a resource package that can be loaded as shared library.')
parser.add_option(
help='Make all resources in R.java non-final and allow the resource IDs '
'to be reset to a different package index when the apk is loaded by '
'another application at runtime.')
input_opts.add_argument(
'--shared-resources-whitelist',
help='An R.txt file acting as a whitelist for resources that should be '
'non-final and have their package ID changed at runtime in R.java. If no '
'whitelist is provided, then everything is whitelisted.')
parser.add_option('--resource-dirs',
default='[]',
help='Directories containing resources of this target.')
parser.add_option('--dependencies-res-zips',
help='Resources from dependents.')
parser.add_option('--resource-zip-out',
help='Path for output zipped resources.')
parser.add_option('--srcjar-out',
help='Path to srcjar to contain generated R.java.')
parser.add_option('--r-text-out',
help='Path to store the generated R.txt file.')
parser.add_option('--r-text-in',
help='Path to pre-existing R.txt for these resources. '
'Resource names from it will be used to generate R.java '
'instead of aapt-generated R.txt.')
parser.add_option('--proguard-file',
help='Path to proguard.txt generated file')
parser.add_option('--proguard-file-main-dex',
help='Path to proguard.txt generated file for main dex')
parser.add_option(
'--v14-skip',
action="store_true",
help='Do not generate nor verify v14 resources')
parser.add_option(
'--extra-res-packages',
help='Additional package names to generate R.java files for')
parser.add_option(
'--extra-r-text-files',
help='For each additional package, the R.txt file should contain a '
'list of resources to be included in the R.java file in the format '
'generated by aapt')
parser.add_option('--support-zh-hk', action='store_true',
help='Use zh-rTW resources for zh-rHK.')
parser.add_option('--stamp', help='File to touch on success')
parser.add_option('--debuggable',
action='store_true',
help='Whether to add android:debuggable="true"')
parser.add_option('--version-code', help='Version code for apk.')
parser.add_option('--version-name', help='Version name for apk.')
parser.add_option('--no-compress', help='disables compression for the '
'given comma separated list of extensions')
parser.add_option('--locale-whitelist',
default='[]',
help='GN list of languages to include. All other language '
'configs will be stripped out. List may include '
'a combination of Android locales or Chrome locales.')
parser.add_option('--apk-path',
help='Path to output (partial) apk.')
parser.add_option('--exclude-xxxhdpi', action='store_true',
help='Do not include xxxhdpi drawables.')
parser.add_option('--xxxhdpi-whitelist',
default='[]',
help='GN list of globs that say which xxxhdpi images to '
'include even when --exclude-xxxhdpi is set.')
parser.add_option('--png-to-webp', action='store_true',
help='Convert png files to webp format.')
parser.add_option('--webp-binary', default='',
help='Path to the cwebp binary.')
parser.add_option('--no-xml-namespaces',
action='store_true',
help='Whether to strip xml namespaces from processed xml '
'resources')
options, positional_args = parser.parse_args(args)
if positional_args:
parser.error('No positional arguments should be given.')
# Check that required options have been provided.
required_options = (
'android_sdk_jar',
'aapt_path',
'dependencies_res_zips',
)
build_utils.CheckOptions(options, parser, required=required_options)
options.resource_dirs = build_utils.ParseGnList(options.resource_dirs)
options.dependencies_res_zips = (
build_utils.ParseGnList(options.dependencies_res_zips))
'non-final and have their package ID changed at runtime in R.java. '
'Implies and overrides --shared-resources.')
options.locale_whitelist = build_utils.ParseGnList(options.locale_whitelist)
options.xxxhdpi_whitelist = build_utils.ParseGnList(options.xxxhdpi_whitelist)
input_opts.add_argument('--support-zh-hk', action='store_true',
help='Use zh-rTW resources for zh-rHK.')
# Don't use [] as default value since some script explicitly pass "".
if options.extra_res_packages:
options.extra_res_packages = (
build_utils.ParseGnList(options.extra_res_packages))
else:
options.extra_res_packages = []
input_opts.add_argument('--debuggable',
action='store_true',
help='Whether to add android:debuggable="true"')
if options.extra_r_text_files:
options.extra_r_text_files = (
build_utils.ParseGnList(options.extra_r_text_files))
else:
options.extra_r_text_files = []
input_opts.add_argument('--version-code', help='Version code for apk.')
input_opts.add_argument('--version-name', help='Version name for apk.')
return options
input_opts.add_argument(
'--no-compress',
help='disables compression for the given comma-separated list of '
'extensions')
input_opts.add_argument(
'--locale-whitelist',
default='[]',
help='GN list of languages to include. All other language configs will '
'be stripped out. List may include a combination of Android locales '
'or Chrome locales.')
def _CreateRJavaFiles(srcjar_dir, main_r_txt_file, packages, r_txt_files,
shared_resources, non_constant_id, whitelist_r_txt_file, is_apk):
assert len(packages) == len(r_txt_files), 'Need one R.txt file per package'
input_opts.add_argument('--exclude-xxxhdpi', action='store_true',
help='Do not include xxxhdpi drawables.')
# Map of (resource_type, name) -> Entry.
# Contains the correct values for resources.
all_resources = {}
for entry in _ParseTextSymbolsFile(main_r_txt_file):
entry = entry._replace(value=_FixPackageIds(entry.value))
all_resources[(entry.resource_type, entry.name)] = entry
input_opts.add_argument(
'--xxxhdpi-whitelist',
default='[]',
help='GN list of globs that say which xxxhdpi images to include even '
'when --exclude-xxxhdpi is set.')
input_opts.add_argument('--png-to-webp', action='store_true',
help='Convert png files to webp format.')
input_opts.add_argument('--webp-binary', default='',
help='Path to the cwebp binary.')
input_opts.add_argument('--no-xml-namespaces',
action='store_true',
help='Whether to strip xml namespaces from processed '
'xml resources')
output_opts.add_argument('--apk-path', required=True,
help='Path to output (partial) apk.')
output_opts.add_argument('--srcjar-out',
help='Path to srcjar to contain generated R.java.')
output_opts.add_argument('--r-text-out',
help='Path to store the generated R.txt file.')
output_opts.add_argument('--proguard-file',
help='Path to proguard.txt generated file')
output_opts.add_argument(
'--proguard-file-main-dex',
help='Path to proguard.txt generated file for main dex')
options = parser.parse_args(args)
resource_utils.HandleCommonOptions(options)
options.locale_whitelist = build_utils.ParseGnList(options.locale_whitelist)
options.xxxhdpi_whitelist = build_utils.ParseGnList(options.xxxhdpi_whitelist)
return options
if whitelist_r_txt_file:
whitelisted_resources = _ResourceWhitelist(
_ParseTextSymbolsFile(whitelist_r_txt_file))
else:
whitelisted_resources = _ResourceWhitelist()
# Map of package_name->resource_type->entry
resources_by_package = (
collections.defaultdict(lambda: collections.defaultdict(list)))
# Build the R.java files using each package's R.txt file, but replacing
# each entry's placeholder value with correct values from all_resources.
for package, r_txt_file in zip(packages, r_txt_files):
if package in resources_by_package:
raise Exception(('Package name "%s" appeared twice. All '
'android_resources() targets must use unique package '
'names, or no package name at all.') % package)
resources_by_type = resources_by_package[package]
# The sub-R.txt files have the wrong values at this point. Read them to
# figure out which entries belong to them, but use the values from the
# main R.txt file.
for entry in _ParseTextSymbolsFile(r_txt_file):
entry = all_resources.get((entry.resource_type, entry.name))
# For most cases missing entry here is an error. It means that some
# library claims to have or depend on a resource that isn't included into
# the APK. There is one notable exception: Google Play Services (GMS).
# GMS is shipped as a bunch of AARs. One of them - basement - contains
# R.txt with ids of all resources, but most of the resources are in the
# other AARs. However, all other AARs reference their resources via
# basement's R.java so the latter must contain all ids that are in its
# R.txt. Most targets depend on only a subset of GMS AARs so some
# resources are missing, which is okay because the code that references
# them is missing too. We can't get an id for a resource that isn't here
# so the only solution is to skip the resource entry entirely.
#
# We can verify that all entries referenced in the code were generated
# correctly by running Proguard on the APK: it will report missing
# fields.
if entry:
resources_by_type[entry.resource_type].append(entry)
for package, resources_by_type in resources_by_package.iteritems():
package_r_java_dir = os.path.join(srcjar_dir, *package.split('.'))
build_utils.MakeDirectory(package_r_java_dir)
package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
java_file_contents = _CreateRJavaFile(package, resources_by_type,
shared_resources, non_constant_id, whitelisted_resources, is_apk)
with open(package_r_java_path, 'w') as f:
f.write(java_file_contents)
def _ParseTextSymbolsFile(path):
"""Given an R.txt file, returns a list of TextSymbolsEntry."""
ret = []
with open(path) as f:
for line in f:
m = re.match(r'(int(?:\[\])?) (\w+) (\w+) (.+)$', line)
if not m:
raise Exception('Unexpected line in R.txt: %s' % line)
java_type, resource_type, name, value = m.groups()
ret.append(TextSymbolsEntry(java_type, resource_type, name, value))
return ret
def _FixPackageIds(resource_value):
# Resource IDs for resources belonging to regular APKs have their first byte
# as 0x7f (package id). However with webview, since it is not a regular apk
# but used as a shared library, aapt is passed the --shared-resources flag
# which changes some of the package ids to 0x02 and 0x00. This function just
# normalises all package ids to 0x7f, which the generated code in R.java
# changes to the correct package id at runtime.
# resource_value is a string with either, a single value '0x12345678', or an
# array of values like '{ 0xfedcba98, 0x01234567, 0x56789abc }'
return re.sub(r'0x(?!01)\d\d', r'0x7f', resource_value)
def _CreateRJavaFile(package, resources_by_type, shared_resources,
non_constant_id, whitelisted_resources, is_apk):
"""Generates the contents of a R.java file."""
final_resources_by_type = collections.defaultdict(list)
non_final_resources_by_type = collections.defaultdict(list)
if shared_resources or non_constant_id:
for res_type, resources in resources_by_type.iteritems():
for entry in resources:
# Entries in stylable that are not int[] are not actually resource ids
# but constants. If we are creating an apk there is no reason for them
# to be non-final. However for libraries, they may be clobbered later on
# and thus should remain non-final. This is regardless of the
# whitelisting rules (since they are not actually resources).
if entry.resource_type == 'styleable' and entry.java_type != 'int[]':
if is_apk:
final_resources_by_type[res_type].append(entry)
else:
non_final_resources_by_type[res_type].append(entry)
elif entry in whitelisted_resources:
non_final_resources_by_type[res_type].append(entry)
else:
final_resources_by_type[res_type].append(entry)
else:
final_resources_by_type = resources_by_type
# Keep these assignments all on one line to make diffing against regular
# aapt-generated files easier.
create_id = ('{{ e.resource_type }}.{{ e.name }} ^= packageIdTransform;')
# Here we diverge from what aapt does. Because we have so many
# resources, the onResourcesLoaded method was exceeding the 64KB limit that
# Java imposes. For this reason we split onResourcesLoaded into different
# methods for each resource type.
template = Template("""/* AUTO-GENERATED FILE. DO NOT MODIFY. */
package {{ package }};
public final class R {
private static boolean sResourcesDidLoad;
{% for resource_type in resource_types %}
public static final class {{ resource_type }} {
{% for e in final_resources[resource_type] %}
public static final {{ e.java_type }} {{ e.name }} = {{ e.value }};
{% endfor %}
{% for e in non_final_resources[resource_type] %}
public static {{ e.java_type }} {{ e.name }} = {{ e.value }};
{% endfor %}
}
{% endfor %}
{% if shared_resources %}
public static void transfromArray(int[] array, int packageIdTransform) {
for (int i=0; i < array.length; i++) {
if ((array[i] >>> 24) == 0x7f) {
array[i] ^= packageIdTransform;
}
}
}
public static void onResourcesLoaded(int packageId) {
assert !sResourcesDidLoad;
sResourcesDidLoad = true;
int packageIdTransform = (packageId ^ 0x7f) << 24;
{% for resource_type in resource_types %}
onResourcesLoaded{{ resource_type|title }}(packageIdTransform);
{% for e in non_final_resources[resource_type] %}
{% if e.java_type == 'int[]' %}
transfromArray({{ e.resource_type }}.{{ e.name }}, packageIdTransform);
{% endif %}
{% endfor %}
{% endfor %}
}
{% for res_type in resource_types %}
private static void onResourcesLoaded{{ res_type|title }} (
int packageIdTransform) {
{% for e in non_final_resources[res_type] %}
{% if res_type != 'styleable' and e.java_type != 'int[]' %}
""" + create_id + """
{% endif %}
{% endfor %}
}
{% endfor %}
{% endif %}
}
""", trim_blocks=True, lstrip_blocks=True)
return template.render(package=package,
resource_types=sorted(resources_by_type),
shared_resources=shared_resources,
final_resources=final_resources_by_type,
non_final_resources=non_final_resources_by_type)
def _GenerateGlobs(pattern):
# This function processes the aapt ignore assets pattern into a list of globs
# to be used to exclude files on the python side. It removes the '!', which is
# used by aapt to mean 'not chatty' so it does not output if the file is
# ignored (we dont output anyways, so it is not required). This function does
# not handle the <dir> and <file> prefixes used by aapt and are assumed not to
# be included in the pattern string.
return pattern.replace('!', '').split(':')
def _ZipResources(resource_dirs, zip_path, ignore_pattern):
# Python zipfile does not provide a way to replace a file (it just writes
# another file with the same name). So, first collect all the files to put
# in the zip (with proper overriding), and then zip them.
# ignore_pattern is a string of ':' delimited list of globs used to ignore
# files that should not be part of the final resource zip.
files_to_zip = dict()
globs = _GenerateGlobs(ignore_pattern)
for d in resource_dirs:
for root, _, files in os.walk(d):
for f in files:
archive_path = f
parent_dir = os.path.relpath(root, d)
if parent_dir != '.':
archive_path = os.path.join(parent_dir, f)
path = os.path.join(root, f)
if build_utils.MatchesGlob(archive_path, globs):
continue
files_to_zip[archive_path] = path
build_utils.DoZip(files_to_zip.iteritems(), zip_path)
def _SortZip(original_path, sorted_path):
"""Generate new zip archive by sorting all files in the original by name."""
with zipfile.ZipFile(sorted_path, 'w') as sorted_zip, \
zipfile.ZipFile(original_path, 'r') as original_zip:
for info in sorted(original_zip.infolist(), key=lambda i: i.filename):
sorted_zip.writestr(info, original_zip.read(info))
def _DuplicateZhResources(resource_dirs):
"""Duplicate Taiwanese resources into Hong-Kong specific directory."""
for resource_dir in resource_dirs:
# We use zh-TW resources for zh-HK (if we have zh-TW resources).
for path in build_utils.IterFiles(resource_dir):
......@@ -449,10 +169,6 @@ def _DuplicateZhResources(resource_dirs):
build_utils.MakeDirectory(os.path.dirname(hk_path))
shutil.copyfile(path, hk_path)
def _ExtractPackageFromManifest(manifest_path):
doc = ElementTree.parse(manifest_path)
return doc.getroot().get('package')
def _ToAaptLocales(locale_whitelist, support_zh_hk):
"""Converts the list of Chrome locales to aapt config locales."""
......@@ -504,6 +220,14 @@ def _MoveImagesToNonMdpiFolders(res_root):
def _CreateLinkApkArgs(options):
"""Create command-line arguments list to invoke 'aapt2 link'.
Args:
options: The command-line options tuple.
Returns:
A list of strings corresponding to the command-line invokation for
the command, matching the arguments from |options|.
"""
link_command = [
options.aapt_path + '2',
'link',
......@@ -539,6 +263,14 @@ def _CreateLinkApkArgs(options):
def _ExtractVersionFromSdk(aapt_path, sdk_path):
"""Extract version code and name from Android SDK .jar file.
Args:
aapt_path: Path to 'aapt' build tool.
sdk_path: Path to SDK-specific android.jar file.
Returns:
A (version_code, version_name) pair of strings.
"""
output = subprocess.check_output([aapt_path, 'dump', 'badging', sdk_path])
version_code = re.search(r"versionCode='(.*?)'", output).group(1)
version_name = re.search(r"versionName='(.*?)'", output).group(1)
......@@ -546,6 +278,18 @@ def _ExtractVersionFromSdk(aapt_path, sdk_path):
def _FixManifest(options, temp_dir):
"""Fix the APK's AndroidManifest.xml.
This adds any missing namespaces for 'android' and 'tools', and
sets certains elements like 'platformBuildVersionCode' or
'android:debuggable' depending on the content of |options|.
Args:
options: The command-line arguments tuple.
temp_dir: A temporary directory where the fixed manifest will be written to.
Returns:
Path to the fixed manifest within |temp_dir|.
"""
debug_manifest_path = os.path.join(temp_dir, 'AndroidManifest.xml')
_ANDROID_NAMESPACE = 'http://schemas.android.com/apk/res/android'
_TOOLS_NAMESPACE = 'http://schemas.android.com/tools'
......@@ -581,6 +325,7 @@ def _ResourceNameFromPath(path):
def _CreateKeepPredicate(resource_dirs, exclude_xxxhdpi, xxxhdpi_whitelist):
"""Return a predicate lambda to determine which resource files to keep."""
if not exclude_xxxhdpi:
# Do not extract dotfiles (e.g. ".gitkeep"). aapt ignores them anyways.
return lambda path: os.path.basename(path)[0] != '.'
......@@ -650,6 +395,18 @@ def _CompileDeps(aapt_path, dep_subdirs, temp_dir):
def _PackageApk(options, dep_subdirs, temp_dir, gen_dir, r_txt_path):
"""Compile resources with aapt2 and generate intermediate .ap_ file.
Args:
options: The command-line options tuple. E.g. the generated apk
will be written to |options.apk_path|.
dep_subdirs: The list of directories where dependency resource zips
were extracted (its content will be altered by this function).
temp_dir: A temporary directory.
gen_dir: Another temp directory where some intermediate files are
generated.
r_txt_path: The path where the R.txt file will written to.
"""
_DuplicateZhResources(dep_subdirs)
keep_predicate = _CreateKeepPredicate(
......@@ -668,6 +425,7 @@ def _PackageApk(options, dep_subdirs, temp_dir, gen_dir, r_txt_path):
link_command = _CreateLinkApkArgs(options)
link_command += ['--output-text-symbols', r_txt_path]
# TODO(digit): Is this below actually required for R.txt generation?
link_command += ['--java', gen_dir]
fixed_manifest = _FixManifest(options, temp_dir)
......@@ -683,126 +441,70 @@ def _PackageApk(options, dep_subdirs, temp_dir, gen_dir, r_txt_path):
link_command, print_stdout=False, print_stderr=False)
# _PackageLibrary uses aapt rather than aapt2 because aapt2 compile does not
# support outputting an R.txt file.
def _PackageLibrary(options, dep_subdirs, temp_dir, gen_dir):
v14_dir = os.path.join(temp_dir, 'v14')
build_utils.MakeDirectory(v14_dir)
# Generate R.java. This R.java contains non-final constants and is used only
# while compiling the library jar (e.g. chromium_content.jar). When building
# an apk, a new R.java file with the correct resource -> ID mappings will be
# generated by merging the resources from all libraries and the main apk
# project.
package_command = [options.aapt_path,
'package',
'-m',
'-M', _EMPTY_ANDROID_MANIFEST_PATH,
'--no-crunch',
'--auto-add-overlay',
'--no-version-vectors',
'-I', options.android_sdk_jar,
'--output-text-symbols', gen_dir,
'-J', gen_dir, # Required for R.txt generation.
'--ignore-assets', build_utils.AAPT_IGNORE_PATTERN]
# Adding all dependencies as sources is necessary for @type/foo references
# to symbols within dependencies to resolve. However, it has the side-effect
# that all Java symbols from dependencies are copied into the new R.java.
# E.g.: It enables an arguably incorrect usage of
# "mypackage.R.id.lib_symbol" where "libpackage.R.id.lib_symbol" would be
# more correct. This is just how Android works.
for d in dep_subdirs:
package_command += ['-S', d]
input_resource_dirs = options.resource_dirs
for d in input_resource_dirs:
package_command += ['-S', d]
if not options.v14_skip:
for resource_dir in input_resource_dirs:
generate_v14_compatible_resources.GenerateV14Resources(
resource_dir,
v14_dir)
# This is the list of directories with resources to put in the final .zip
zip_resource_dirs = input_resource_dirs + [v14_dir]
if options.resource_zip_out:
_ZipResources(zip_resource_dirs, options.resource_zip_out,
build_utils.AAPT_IGNORE_PATTERN)
# Only creates an R.txt
build_utils.CheckOutput(
package_command, print_stdout=False, print_stderr=False)
def _WriteFinalRTxtFile(options, aapt_r_txt_path):
"""Determine final R.txt and return its location.
def _CreateRTxtAndSrcJar(options, r_txt_path, srcjar_dir):
# When an empty res/ directory is passed, aapt does not write an R.txt.
if not os.path.exists(r_txt_path):
build_utils.Touch(r_txt_path)
This handles --r-text-in and --r-text-out options at the same time.
Args:
options: The command-line options tuple.
aapt_r_txt_path: The path to the R.txt generated by aapt.
Returns:
Path to the final R.txt file.
"""
if options.r_text_in:
r_txt_path = options.r_text_in
packages = list(options.extra_res_packages)
r_txt_files = list(options.extra_r_text_files)
cur_package = options.custom_package
if not options.custom_package and options.android_manifest:
cur_package = _ExtractPackageFromManifest(options.android_manifest)
# Don't create a .java file for the current resource target when:
# - no package name was provided (either by manifest or build rules),
# - there was already a dependent android_resources() with the same
# package (occurs mostly when an apk target and resources target share
# an AndroidManifest.xml)
if cur_package and cur_package not in packages:
packages.append(cur_package)
r_txt_files.append(r_txt_path)
if packages:
shared_resources = options.shared_resources or options.app_as_shared_lib
_CreateRJavaFiles(srcjar_dir, r_txt_path, packages, r_txt_files,
shared_resources, options.non_constant_id,
options.shared_resources_whitelist, bool(options.apk_path))
if options.srcjar_out:
build_utils.ZipDir(options.srcjar_out, srcjar_dir)
r_txt_file = options.r_text_in
else:
# When an empty res/ directory is passed, aapt does not write an R.txt.
r_txt_file = aapt_r_txt_path
if not os.path.exists(r_txt_file):
build_utils.Touch(r_txt_file)
if options.r_text_out:
shutil.copyfile(r_txt_path, options.r_text_out)
shutil.copyfile(r_txt_file, options.r_text_out)
def _ExtractDeps(dep_zips, deps_dir):
dep_subdirs = []
for z in dep_zips:
subdir = os.path.join(deps_dir, os.path.basename(z))
if os.path.exists(subdir):
raise Exception('Resource zip name conflict: ' + os.path.basename(z))
build_utils.ExtractAll(z, path=subdir)
dep_subdirs.append(subdir)
return dep_subdirs
return r_txt_file
def _OnStaleMd5(options):
with build_utils.TempDir() as temp_dir:
deps_dir = os.path.join(temp_dir, 'deps')
build_utils.MakeDirectory(deps_dir)
gen_dir = os.path.join(temp_dir, 'gen')
build_utils.MakeDirectory(gen_dir)
r_txt_path = os.path.join(gen_dir, 'R.txt')
srcjar_dir = os.path.join(temp_dir, 'java')
dep_subdirs = _ExtractDeps(options.dependencies_res_zips, deps_dir)
if options.apk_path:
_PackageApk(options, dep_subdirs, temp_dir, gen_dir, r_txt_path)
else:
_PackageLibrary(options, dep_subdirs, temp_dir, gen_dir)
_CreateRTxtAndSrcJar(options, r_txt_path, srcjar_dir)
with resource_utils.BuildContext() as build:
dep_subdirs = resource_utils.ExtractDeps(options.dependencies_res_zips,
build.deps_dir)
_PackageApk(options, dep_subdirs, build.temp_dir, build.gen_dir,
build.r_txt_path)
r_txt_path = _WriteFinalRTxtFile(options, build.r_txt_path)
package = resource_utils.ExtractPackageFromManifest(
options.android_manifest)
# If --shared-resources-whitelist is used, the all resources listed in
# the corresponding R.txt file will be non-final, and an onResourcesLoaded()
# will be generated to adjust them at runtime.
#
# Otherwise, if --shared-resources is used, the all resources will be
# non-final, and an onResourcesLoaded() method will be generated too.
#
# Otherwise, all resources will be final, and no method will be generated.
#
rjava_build_options = resource_utils.RJavaBuildOptions()
if options.shared_resources_whitelist:
rjava_build_options.ExportSomeResources(
options.shared_resources_whitelist)
rjava_build_options.GenerateOnResourcesLoaded()
elif options.shared_resources:
rjava_build_options.ExportAllResources()
rjava_build_options.GenerateOnResourcesLoaded()
resource_utils.CreateRJavaFiles(
build.srcjar_dir, package, r_txt_path,
options.extra_res_packages,
options.extra_r_text_files,
rjava_build_options)
if options.srcjar_out:
build_utils.ZipDir(options.srcjar_out, build.srcjar_dir)
def main(args):
......@@ -813,7 +515,6 @@ def main(args):
# appears first in the depfile.
possible_output_paths = [
options.apk_path,
options.resource_zip_out,
options.r_text_out,
options.srcjar_out,
options.proguard_file,
......@@ -824,11 +525,7 @@ def main(args):
# List python deps in input_strings rather than input_paths since the contents
# of them does not change what gets written to the depsfile.
input_strings = options.extra_res_packages + [
options.app_as_shared_lib,
options.custom_package,
options.non_constant_id,
options.shared_resources,
options.v14_skip,
options.exclude_xxxhdpi,
options.xxxhdpi_whitelist,
str(options.debuggable),
......@@ -837,8 +534,7 @@ def main(args):
str(options.no_xml_namespaces),
]
if options.apk_path:
input_strings.extend(_CreateLinkApkArgs(options))
input_strings.extend(_CreateLinkApkArgs(options))
possible_input_paths = [
options.aapt_path,
......@@ -853,31 +549,12 @@ def main(args):
if options.webp_binary:
input_paths.append(options.webp_binary)
# Resource files aren't explicitly listed in GN. Listing them in the depfile
# ensures the target will be marked stale when resource files are removed.
depfile_deps = []
resource_names = []
for resource_dir in options.resource_dirs:
for resource_file in build_utils.FindInDirectory(resource_dir, '*'):
# Don't list the empty .keep file in depfile. Since it doesn't end up
# included in the .zip, it can lead to -w 'dupbuild=err' ninja errors
# if ever moved.
if not resource_file.endswith(os.path.join('empty', '.keep')):
input_paths.append(resource_file)
depfile_deps.append(resource_file)
resource_names.append(os.path.relpath(resource_file, resource_dir))
# Resource filenames matter to the output, so add them to strings as well.
# This matters if a file is renamed but not changed (http://crbug.com/597126).
input_strings.extend(sorted(resource_names))
build_utils.CallAndWriteDepfileIfStale(
lambda: _OnStaleMd5(options),
options,
input_paths=input_paths,
input_strings=input_strings,
output_paths=output_paths,
depfile_deps=depfile_deps)
output_paths=output_paths)
if __name__ == '__main__':
......
#!/usr/bin/env python
#
# Copyright (c) 2012 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.
"""Process Android resource directories to generate .resources.zip, R.txt and
.srcjar files."""
import argparse
import collections
import os
import re
import shutil
import sys
import generate_v14_compatible_resources
from util import build_utils
from util import resource_utils
def _ParseArgs(args):
"""Parses command line options.
Returns:
An options object as from argparse.ArgumentParser.parse_args()
"""
parser, input_opts, output_opts = resource_utils.ResourceArgsParser()
input_opts.add_argument('--resource-dirs',
default='[]',
help='A list of input directories containing resources '
'for this target.')
input_opts.add_argument(
'--shared-resources',
action='store_true',
help='Make resources shareable by generating an onResourcesLoaded() '
'method in the R.java source file.')
input_opts.add_argument('--custom-package',
help='Optional Java package for main R.java.')
input_opts.add_argument(
'--android-manifest',
help='Optional AndroidManifest.xml path. Only used to extract a package '
'name for R.java if a --custom-package is not provided.')
output_opts.add_argument(
'--resource-zip-out',
help='Path to a zip archive containing all resources from '
'--resource-dirs, merged into a single directory tree. This will '
'also include auto-generated v14-compatible resources unless '
'--v14-skip is used.')
output_opts.add_argument('--srcjar-out',
help='Path to .srcjar to contain the generated R.java.')
output_opts.add_argument('--r-text-out',
help='Path to store the generated R.txt file.')
input_opts.add_argument(
'--v14-skip',
action="store_true",
help='Do not generate nor verify v14 resources.')
options = parser.parse_args(args)
resource_utils.HandleCommonOptions(options)
options.resource_dirs = build_utils.ParseGnList(options.resource_dirs)
return options
def _GenerateGlobs(pattern):
# This function processes the aapt ignore assets pattern into a list of globs
# to be used to exclude files on the python side. It removes the '!', which is
# used by aapt to mean 'not chatty' so it does not output if the file is
# ignored (we dont output anyways, so it is not required). This function does
# not handle the <dir> and <file> prefixes used by aapt and are assumed not to
# be included in the pattern string.
return pattern.replace('!', '').split(':')
def _ZipResources(resource_dirs, zip_path, ignore_pattern):
# Python zipfile does not provide a way to replace a file (it just writes
# another file with the same name). So, first collect all the files to put
# in the zip (with proper overriding), and then zip them.
# ignore_pattern is a string of ':' delimited list of globs used to ignore
# files that should not be part of the final resource zip.
files_to_zip = dict()
globs = _GenerateGlobs(ignore_pattern)
for d in resource_dirs:
for root, _, files in os.walk(d):
for f in files:
archive_path = f
parent_dir = os.path.relpath(root, d)
if parent_dir != '.':
archive_path = os.path.join(parent_dir, f)
path = os.path.join(root, f)
if build_utils.MatchesGlob(archive_path, globs):
continue
files_to_zip[archive_path] = path
build_utils.DoZip(files_to_zip.iteritems(), zip_path)
def _GenerateRTxt(options, dep_subdirs, gen_dir):
"""Generate R.txt file.
Args:
options: The command-line options tuple.
dep_subdirs: List of directories containing extracted dependency resources.
gen_dir: Locates where the aapt-generated files will go. In particular
the output file is always generated as |{gen_dir}/R.txt|.
"""
# NOTE: This uses aapt rather than aapt2 because 'aapt2 compile' does not
# support the --output-text-symbols option yet (https://crbug.com/820460).
package_command = [options.aapt_path,
'package',
'-m',
'-M', resource_utils.EMPTY_ANDROID_MANIFEST_PATH,
'--no-crunch',
'--auto-add-overlay',
'--no-version-vectors',
'-I', options.android_sdk_jar,
'--output-text-symbols', gen_dir,
'-J', gen_dir, # Required for R.txt generation.
'--ignore-assets', build_utils.AAPT_IGNORE_PATTERN]
# Adding all dependencies as sources is necessary for @type/foo references
# to symbols within dependencies to resolve. However, it has the side-effect
# that all Java symbols from dependencies are copied into the new R.java.
# E.g.: It enables an arguably incorrect usage of
# "mypackage.R.id.lib_symbol" where "libpackage.R.id.lib_symbol" would be
# more correct. This is just how Android works.
for d in dep_subdirs:
package_command += ['-S', d]
for d in options.resource_dirs:
package_command += ['-S', d]
# Only creates an R.txt
build_utils.CheckOutput(
package_command, print_stdout=False, print_stderr=False)
def _GenerateResourcesZip(output_resource_zip, input_resource_dirs,
v14_skip, temp_dir):
"""Generate a .resources.zip file fron a list of input resource dirs.
Args:
output_resource_zip: Path to the output .resources.zip file.
input_resource_dirs: A list of input resource directories.
v14_skip: If False, then v14-compatible resource will also be
generated in |{temp_dir}/v14| and added to the final zip.
temp_dir: Path to temporary directory.
"""
if not v14_skip:
# Generate v14-compatible resources in temp_dir.
v14_dir = os.path.join(temp_dir, 'v14')
build_utils.MakeDirectory(v14_dir)
for resource_dir in input_resource_dirs:
generate_v14_compatible_resources.GenerateV14Resources(
resource_dir,
v14_dir)
input_resource_dirs.append(v14_dir)
_ZipResources(input_resource_dirs, output_resource_zip,
build_utils.AAPT_IGNORE_PATTERN)
def _OnStaleMd5(options):
with resource_utils.BuildContext() as build:
if options.r_text_in:
r_txt_path = options.r_text_in
else:
# Extract dependencies to resolve @foo/type references into
# dependent packages.
dep_subdirs = resource_utils.ExtractDeps(options.dependencies_res_zips,
build.deps_dir)
_GenerateRTxt(options, dep_subdirs, build.gen_dir)
r_txt_path = build.r_txt_path
# 'aapt' doesn't generate any R.txt file if res/ was empty.
if not os.path.exists(r_txt_path):
build_utils.Touch(r_txt_path)
if options.r_text_out:
shutil.copyfile(r_txt_path, options.r_text_out)
if options.srcjar_out:
package = options.custom_package
if not package and options.android_manifest:
package = resource_utils.ExtractPackageFromManifest(
options.android_manifest)
# Don't create a .java file for the current resource target when no
# package name was provided (either by manifest or build rules).
if package:
# All resource IDs should be non-final here, but the
# onResourcesLoaded() method should only be generated if
# --shared-resources is used.
rjava_build_options = resource_utils.RJavaBuildOptions()
rjava_build_options.ExportAllResources()
rjava_build_options.ExportAllStyleables()
if options.shared_resources:
rjava_build_options.GenerateOnResourcesLoaded()
resource_utils.CreateRJavaFiles(
build.srcjar_dir, package, r_txt_path,
options.extra_res_packages,
options.extra_r_text_files,
rjava_build_options)
build_utils.ZipDir(options.srcjar_out, build.srcjar_dir)
if options.resource_zip_out:
_GenerateResourcesZip(options.resource_zip_out, options.resource_dirs,
options.v14_skip, build.temp_dir)
def main(args):
args = build_utils.ExpandFileArgs(args)
options = _ParseArgs(args)
# Order of these must match order specified in GN so that the correct one
# appears first in the depfile.
possible_output_paths = [
options.resource_zip_out,
options.r_text_out,
options.srcjar_out,
]
output_paths = [x for x in possible_output_paths if x]
# List python deps in input_strings rather than input_paths since the contents
# of them does not change what gets written to the depsfile.
input_strings = options.extra_res_packages + [
options.custom_package,
options.shared_resources,
options.v14_skip,
]
possible_input_paths = [
options.aapt_path,
options.android_manifest,
options.android_sdk_jar,
]
input_paths = [x for x in possible_input_paths if x]
input_paths.extend(options.dependencies_res_zips)
input_paths.extend(options.extra_r_text_files)
# Resource files aren't explicitly listed in GN. Listing them in the depfile
# ensures the target will be marked stale when resource files are removed.
depfile_deps = []
resource_names = []
for resource_dir in options.resource_dirs:
for resource_file in build_utils.FindInDirectory(resource_dir, '*'):
# Don't list the empty .keep file in depfile. Since it doesn't end up
# included in the .zip, it can lead to -w 'dupbuild=err' ninja errors
# if ever moved.
if not resource_file.endswith(os.path.join('empty', '.keep')):
input_paths.append(resource_file)
depfile_deps.append(resource_file)
resource_names.append(os.path.relpath(resource_file, resource_dir))
# Resource filenames matter to the output, so add them to strings as well.
# This matters if a file is renamed but not changed (http://crbug.com/597126).
input_strings.extend(sorted(resource_names))
build_utils.CallAndWriteDepfileIfStale(
lambda: _OnStaleMd5(options),
options,
input_paths=input_paths,
input_strings=input_strings,
output_paths=output_paths,
depfile_deps=depfile_deps)
if __name__ == '__main__':
main(sys.argv[1:])
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import argparse
import collections
import contextlib
import os
import re
import shutil
import sys
import tempfile
from xml.etree import ElementTree
import util.build_utils as build_utils
_SOURCE_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(
os.path.dirname(__file__)))))
# Import jinja2 from third_party/jinja2
sys.path.insert(1, os.path.join(_SOURCE_ROOT, 'third_party'))
from jinja2 import Template # pylint: disable=F0401
EMPTY_ANDROID_MANIFEST_PATH = os.path.join(
_SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml')
# Represents a line from a R.txt file.
_TextSymbolEntry = collections.namedtuple('RTextEntry',
('java_type', 'resource_type', 'name', 'value'))
def _ParseTextSymbolsFile(path, fix_package_ids=False):
"""Given an R.txt file, returns a list of _TextSymbolEntry.
Args:
path: Input file path.
fix_package_ids: if True, all packaged IDs read from the file
will be fixed to 0x7f.
Returns:
A list of _TextSymbolEntry instances.
Raises:
Exception: An unexpected line was detected in the input.
"""
ret = []
with open(path) as f:
for line in f:
m = re.match(r'(int(?:\[\])?) (\w+) (\w+) (.+)$', line)
if not m:
raise Exception('Unexpected line in R.txt: %s' % line)
java_type, resource_type, name, value = m.groups()
if fix_package_ids:
value = _FixPackageIds(value)
ret.append(_TextSymbolEntry(java_type, resource_type, name, value))
return ret
def _FixPackageIds(resource_value):
# Resource IDs for resources belonging to regular APKs have their first byte
# as 0x7f (package id). However with webview, since it is not a regular apk
# but used as a shared library, aapt is passed the --shared-resources flag
# which changes some of the package ids to 0x02 and 0x00. This function just
# normalises all package ids to 0x7f, which the generated code in R.java
# changes to the correct package id at runtime.
# resource_value is a string with either, a single value '0x12345678', or an
# array of values like '{ 0xfedcba98, 0x01234567, 0x56789abc }'
return re.sub(r'0x(?!01)\d\d', r'0x7f', resource_value)
def _GetRTxtResourceNames(r_txt_path):
"""Parse an R.txt file and extract the set of resource names from it."""
result = set()
for entry in _ParseTextSymbolsFile(r_txt_path):
result.add(entry.name)
return result
class RJavaBuildOptions:
"""A class used to model the various ways to build an R.java file.
This is used to control which resource ID variables will be final or
non-final, and whether an onResourcesLoaded() method will be generated
to adjust the non-final ones, when the corresponding library is loaded
at runtime.
Note that by default, all resources are final, and there is no
method generated, which corresponds to calling ExportNoResources().
"""
def __init__(self):
self.has_constant_ids = True
self.resources_whitelist = None
self.has_on_resources_loaded = False
self.export_const_styleable = False
def ExportNoResources(self):
"""Make all resource IDs final, and don't generate a method."""
self.has_constant_ids = True
self.resources_whitelist = None
self.has_on_resources_loaded = False
self.export_const_styleable = False
def ExportAllResources(self):
"""Make all resource IDs non-final in the R.java file."""
self.has_constant_ids = False
self.resources_whitelist = None
def ExportSomeResources(self, r_txt_file_path):
"""Only select specific resource IDs to be non-final.
Args:
r_txt_file_path: The path to an R.txt file. All resources named
int it will be non-final in the generated R.java file, all others
will be final.
"""
self.has_constant_ids = True
self.resources_whitelist = _GetRTxtResourceNames(r_txt_file_path)
def ExportAllStyleables(self):
"""Make all styleable constants non-final, even non-resources ones.
Resources that are styleable but not of int[] type are not actually
resource IDs but constants. By default they are always final. Call this
method to make them non-final anyway in the final R.java file.
"""
self.export_const_styleable = True
def GenerateOnResourcesLoaded(self):
"""Generate an onResourcesLoaded() method.
This Java method will be called at runtime by the framework when
the corresponding library (which includes the R.java source file)
will be loaded at runtime. This corresponds to the --shared-resources
or --app-as-shared-lib flags of 'aapt package'.
"""
self.has_on_resources_loaded = True
def _IsResourceFinal(self, entry):
"""Determines whether a resource should be final or not.
Args:
entry: A _TextSymbolEntry instance.
Returns:
True iff the corresponding entry should be final.
"""
if entry.resource_type == 'styleable' and entry.java_type != 'int[]':
# A styleable constant may be exported as non-final after all.
return not self.export_const_styleable
elif not self.has_constant_ids:
# Every resource is non-final
return False
elif not self.resources_whitelist:
# No whitelist means all IDs are non-final.
return True
else:
# Otherwise, only those in the
return entry.name not in self.resources_whitelist
def CreateRJavaFiles(srcjar_dir, package, main_r_txt_file,
extra_res_packages, extra_r_txt_files,
rjava_build_options):
"""Create all R.java files for a set of packages and R.txt files.
Args:
srcjar_dir: The top-level output directory for the generated files.
package: Top-level package name.
main_r_txt_file: The main R.txt file containing the valid values
of _all_ resource IDs.
extra_res_packages: A list of extra package names.
extra_r_txt_files: A list of extra R.txt files. One per item in
|extra_res_packages|. Note that all resource IDs in them will be ignored,
|and replaced by the values extracted from |main_r_txt_file|.
rjava_build_options: An RJavaBuildOptions instance that controls how
exactly the R.java file is generated.
Raises:
Exception if a package name appears several times in |extra_res_packages|
"""
assert len(extra_res_packages) == len(extra_r_txt_files), \
'Need one R.txt file per package'
packages = list(extra_res_packages)
r_txt_files = list(extra_r_txt_files)
if package not in packages:
# Sometimes, an apk target and a resources target share the same
# AndroidManifest.xml and thus |package| will already be in |packages|.
packages.append(package)
r_txt_files.append(main_r_txt_file)
# Map of (resource_type, name) -> Entry.
# Contains the correct values for resources.
all_resources = {}
for entry in _ParseTextSymbolsFile(main_r_txt_file, fix_package_ids=True):
all_resources[(entry.resource_type, entry.name)] = entry
# Map of package_name->resource_type->entry
resources_by_package = (
collections.defaultdict(lambda: collections.defaultdict(list)))
# Build the R.java files using each package's R.txt file, but replacing
# each entry's placeholder value with correct values from all_resources.
for package, r_txt_file in zip(packages, r_txt_files):
if package in resources_by_package:
raise Exception(('Package name "%s" appeared twice. All '
'android_resources() targets must use unique package '
'names, or no package name at all.') % package)
resources_by_type = resources_by_package[package]
# The sub-R.txt files have the wrong values at this point. Read them to
# figure out which entries belong to them, but use the values from the
# main R.txt file.
for entry in _ParseTextSymbolsFile(r_txt_file):
entry = all_resources.get((entry.resource_type, entry.name))
# For most cases missing entry here is an error. It means that some
# library claims to have or depend on a resource that isn't included into
# the APK. There is one notable exception: Google Play Services (GMS).
# GMS is shipped as a bunch of AARs. One of them - basement - contains
# R.txt with ids of all resources, but most of the resources are in the
# other AARs. However, all other AARs reference their resources via
# basement's R.java so the latter must contain all ids that are in its
# R.txt. Most targets depend on only a subset of GMS AARs so some
# resources are missing, which is okay because the code that references
# them is missing too. We can't get an id for a resource that isn't here
# so the only solution is to skip the resource entry entirely.
#
# We can verify that all entries referenced in the code were generated
# correctly by running Proguard on the APK: it will report missing
# fields.
if entry:
resources_by_type[entry.resource_type].append(entry)
for package, resources_by_type in resources_by_package.iteritems():
_CreateRJavaSourceFile(srcjar_dir, package, resources_by_type,
rjava_build_options)
def _CreateRJavaSourceFile(srcjar_dir, package, resources_by_type,
rjava_build_options):
"""Generates an R.java source file."""
package_r_java_dir = os.path.join(srcjar_dir, *package.split('.'))
build_utils.MakeDirectory(package_r_java_dir)
package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
java_file_contents = _RenderRJavaSource(package, resources_by_type,
rjava_build_options)
with open(package_r_java_path, 'w') as f:
f.write(java_file_contents)
def _RenderRJavaSource(package, resources_by_type, rjava_build_options):
"""Render an R.java source file. See _CreateRJaveSourceFile for args info."""
final_resources_by_type = collections.defaultdict(list)
non_final_resources_by_type = collections.defaultdict(list)
for res_type, resources in resources_by_type.iteritems():
for entry in resources:
# Entries in stylable that are not int[] are not actually resource ids
# but constants.
if rjava_build_options._IsResourceFinal(entry):
final_resources_by_type[res_type].append(entry)
else:
non_final_resources_by_type[res_type].append(entry)
# Keep these assignments all on one line to make diffing against regular
# aapt-generated files easier.
create_id = ('{{ e.resource_type }}.{{ e.name }} ^= packageIdTransform;')
# Here we diverge from what aapt does. Because we have so many
# resources, the onResourcesLoaded method was exceeding the 64KB limit that
# Java imposes. For this reason we split onResourcesLoaded into different
# methods for each resource type.
template = Template("""/* AUTO-GENERATED FILE. DO NOT MODIFY. */
package {{ package }};
public final class R {
private static boolean sResourcesDidLoad;
{% for resource_type in resource_types %}
public static final class {{ resource_type }} {
{% for e in final_resources[resource_type] %}
public static final {{ e.java_type }} {{ e.name }} = {{ e.value }};
{% endfor %}
{% for e in non_final_resources[resource_type] %}
public static {{ e.java_type }} {{ e.name }} = {{ e.value }};
{% endfor %}
}
{% endfor %}
{% if has_on_resources_loaded %}
public static void transfromArray(int[] array, int packageIdTransform) {
for (int i=0; i < array.length; i++) {
if ((array[i] >>> 24) == 0x7f) {
array[i] ^= packageIdTransform;
}
}
}
public static void onResourcesLoaded(int packageId) {
assert !sResourcesDidLoad;
sResourcesDidLoad = true;
int packageIdTransform = (packageId ^ 0x7f) << 24;
{% for resource_type in resource_types %}
onResourcesLoaded{{ resource_type|title }}(packageIdTransform);
{% for e in non_final_resources[resource_type] %}
{% if e.java_type == 'int[]' %}
transfromArray({{ e.resource_type }}.{{ e.name }}, packageIdTransform);
{% endif %}
{% endfor %}
{% endfor %}
}
{% for res_type in resource_types %}
private static void onResourcesLoaded{{ res_type|title }} (
int packageIdTransform) {
{% for e in non_final_resources[res_type] %}
{% if res_type != 'styleable' and e.java_type != 'int[]' %}
""" + create_id + """
{% endif %}
{% endfor %}
}
{% endfor %}
{% endif %}
}
""", trim_blocks=True, lstrip_blocks=True)
return template.render(
package=package,
resource_types=sorted(resources_by_type),
has_on_resources_loaded=rjava_build_options.has_on_resources_loaded,
final_resources=final_resources_by_type,
non_final_resources=non_final_resources_by_type)
def ExtractPackageFromManifest(manifest_path):
"""Extract package name from Android manifest file."""
doc = ElementTree.parse(manifest_path)
return doc.getroot().get('package')
def ExtractDeps(dep_zips, deps_dir):
"""Extract a list of resource dependency zip files.
Args:
dep_zips: A list of zip file paths, each one will be extracted to
a subdirectory of |deps_dir|, named after the zip file (e.g.
'/some/path/foo.zip' -> '{deps_dir}/foo/').
deps_dir: Top-level extraction directory.
Returns:
The list of all sub-directory paths, relative to |deps_dir|.
Raises:
Exception: If a sub-directory already exists with the same name before
extraction.
"""
dep_subdirs = []
for z in dep_zips:
subdir = os.path.join(deps_dir, os.path.basename(z))
if os.path.exists(subdir):
raise Exception('Resource zip name conflict: ' + os.path.basename(z))
build_utils.ExtractAll(z, path=subdir)
dep_subdirs.append(subdir)
return dep_subdirs
class _ResourceBuildContext(object):
"""A temporary directory for packaging and compiling Android resources."""
def __init__(self):
"""Initialized the context."""
# The top-level temporary directory.
self.temp_dir = tempfile.mkdtemp()
# A location to store resources extracted form dependency zip files.
self.deps_dir = os.path.join(self.temp_dir, 'deps')
os.mkdir(self.deps_dir)
# A location to place aapt-generated files.
self.gen_dir = os.path.join(self.temp_dir, 'gen')
os.mkdir(self.gen_dir)
# Location of the generated R.txt file.
self.r_txt_path = os.path.join(self.gen_dir, 'R.txt')
# A location to place generated R.java files.
self.srcjar_dir = os.path.join(self.temp_dir, 'java')
os.mkdir(self.srcjar_dir)
def Close(self):
"""Close the context and destroy all temporary files."""
shutil.rmtree(self.temp_dir)
@contextlib.contextmanager
def BuildContext():
"""Generator for a _ResourceBuildContext instance."""
try:
context = _ResourceBuildContext()
yield context
finally:
context.Close()
def ResourceArgsParser():
"""Create an argparse.ArgumentParser instance with common argument groups.
Returns:
A tuple of (parser, in_group, out_group) corresponding to the parser
instance, and the input and output argument groups for it, respectively.
"""
parser = argparse.ArgumentParser(description=__doc__)
input_opts = parser.add_argument_group('Input options')
output_opts = parser.add_argument_group('Output options')
build_utils.AddDepfileOption(output_opts)
input_opts.add_argument('--android-sdk-jar', required=True,
help='Path to the android.jar file.')
input_opts.add_argument('--aapt-path', required=True,
help='Path to the Android aapt tool')
input_opts.add_argument('--dependencies-res-zips', required=True,
help='Resources zip archives from dependents. Required to '
'resolve @type/foo references into dependent '
'libraries.')
input_opts.add_argument(
'--r-text-in',
help='Path to pre-existing R.txt. Its resource IDs override those found '
'in the aapt-generated R.txt when generating R.java.')
input_opts.add_argument(
'--extra-res-packages',
help='Additional package names to generate R.java files for.')
input_opts.add_argument(
'--extra-r-text-files',
help='For each additional package, the R.txt file should contain a '
'list of resources to be included in the R.java file in the format '
'generated by aapt.')
return (parser, input_opts, output_opts)
def HandleCommonOptions(options):
"""Handle common command-line options after parsing.
Args:
options: the result of parse_args() on the parser returned by
ResourceArgsParser(). This function updates a few common fields.
"""
options.dependencies_res_zips = (
build_utils.ParseGnList(options.dependencies_res_zips))
# Don't use [] as default value since some script explicitly pass "".
if options.extra_res_packages:
options.extra_res_packages = (
build_utils.ParseGnList(options.extra_res_packages))
else:
options.extra_res_packages = []
if options.extra_r_text_files:
options.extra_r_text_files = (
build_utils.ParseGnList(options.extra_r_text_files))
else:
options.extra_r_text_files = []
......@@ -1449,22 +1449,65 @@ if (enable_java_templates) {
}
}
template("process_resources") {
_process_resources_target_name = target_name
# This template is used to parse a set of resource directories and
# create the R.txt, .srcjar and .resources.zip for it.
#
# Input variables:
# deps: Specifies the input dependencies for this target.
#
# build_config: Path to the .build_config file corresponding to the target.
#
# resource_dirs:
# List of directories containing Android resources, layout should be
# similar to what aapt -S <dir> expects.
#
# generated_resource_dirs: (optional)
# List of directories containing generated resources.
#
# generated_resource_files: (optional)
# If generated_resources_dirs is not empty, must list all the files
# within these directories (the directory must appear at the start of
# the file path).
#
# custom_package: (optional)
# Package name for the generated R.java source file. Optional if
# android_manifest is not provided.
#
# android_manifest: (optional)
# If custom_package is not provided, path to an AndroidManifest.xml file
# that is only used to extract a package name out of it.
#
# r_text_in_path: (optional)
# Path to an input R.txt file to use to generate the R.java file.
# The default is to use 'aapt' to generate the file from the content
# of the resource directories.
#
# alternative_android_sdk_jar: Alternative android.jar to use.
# TODO(digit): Not sure this is needed here.
#
# shared_resources: (optional)
# If true, generate an R.java file that uses non-final resource ID
# variables and an onResourcesLoaded() method.
#
# v14_skip: (optional)
# If true, skip generation of v14 compatible resources.
# (see generate_v14_compatible_resources.py for details).
#
# Output variables:
# zip_path: (optional)
# Path to a .resources.zip that will simply contain all the
# input resources, collected in a single archive.
#
# r_text_out_path: (optional): Path for the generated R.txt file.
#
# srcjar_path: (optional) Path to a generated .srcjar containing the
# generated R.java source file.
#
template("prepare_resources") {
if (defined(invoker.srcjar_path)) {
_srcjar_path = invoker.srcjar_path
}
if (defined(invoker.output)) {
_packaged_resources_path = invoker.output
}
if (defined(invoker.post_process_script)) {
_process_resources_target_name = "${target_name}__intermediate"
_packaged_resources_path =
get_path_info(_packaged_resources_path, "dir") + "/" +
get_path_info(_packaged_resources_path, "name") + ".intermediate.ap_"
_srcjar_path = "${_srcjar_path}.intermediate.srcjar"
}
action(_process_resources_target_name) {
action(target_name) {
set_sources_assignment_filter([])
forward_variables_from(invoker,
[
......@@ -1472,9 +1515,9 @@ if (enable_java_templates) {
"testonly",
"visibility",
])
script = "//build/android/gyp/process_resources.py"
script = "//build/android/gyp/prepare_resources.py"
depfile = "$target_gen_dir/${invoker.target_name}_1.d"
depfile = "$target_gen_dir/${invoker.target_name}.d"
outputs = []
_all_resource_dirs = []
sources = []
......@@ -1507,7 +1550,6 @@ if (enable_java_templates) {
}
inputs = [
android_default_aapt_path,
invoker.build_config,
_android_aapt_path,
_android_sdk_jar,
......@@ -1541,6 +1583,184 @@ if (enable_java_templates) {
args += [ "--resource-dirs=$_rebased_all_resource_dirs" ]
}
if (defined(invoker.zip_path)) {
outputs += [ invoker.zip_path ]
args += [
"--resource-zip-out",
rebase_path(invoker.zip_path, root_build_dir),
]
}
if (defined(invoker.r_text_out_path)) {
outputs += [ invoker.r_text_out_path ]
args += [
"--r-text-out",
rebase_path(invoker.r_text_out_path, root_build_dir),
]
}
if (defined(_srcjar_path)) {
outputs += [ _srcjar_path ]
args += [
"--srcjar-out",
rebase_path(_srcjar_path, root_build_dir),
]
}
if (defined(invoker.r_text_in_path)) {
_r_text_in_path = invoker.r_text_in_path
inputs += [ _r_text_in_path ]
args += [
"--r-text-in",
rebase_path(_r_text_in_path, root_build_dir),
]
}
if (defined(invoker.custom_package)) {
args += [
"--custom-package",
invoker.custom_package,
]
}
if (defined(invoker.shared_resources) && invoker.shared_resources) {
args += [ "--shared-resources" ]
}
if (defined(invoker.v14_skip) && invoker.v14_skip) {
args += [ "--v14-skip" ]
}
}
}
# A template that is used to compile all resources needed by a binary
# (e.g. an android_apk or a junit_binary) into an intermediate .ar_
# archive. It can also generate an associated .srcjar that contains the
# final R.java sources for all resource packages the binary depends on.
#
# Input variables:
# deps: Specifies the input dependencies for this target.
#
# build_config: Path to the .build_config file corresponding to the target.
#
# android_manifest: Path to root manifest for the binary.
#
# version_code: (optional)
#
# version_name: (optional)
#
# alternative_android_sdk_jar: Alternative system android.jar to use.
#
# shared_resources: (optional)
# If true, make all variables in each generated R.java file non-final,
# and provide an onResourcesLoaded() method that can be used to reset
# their package index at load time. Useful when the APK corresponds to
# a library that is loaded at runtime, like system_webview_apk or
# monochrome_apk.
#
# shared_resources_whitelist: (optional)
# Path to an R.txt file. If provided, acts similar to shared_resources
# except that it restricts the list of non-final resource variables
# to the list from the input R.txt file. Overrides shared_resources
# when both are specified.
#
# support_zh_hk: (optional)
# If true, support zh-HK in Chrome on Android by using the resources
# from zh-TW. See https://crbug.com/780847.
#
# aapt_locale_whitelist: (optional)
# Restrict compiled locale-dependent resources to a specific whitelist.
# NOTE: This is a list of Chromium locale names, not Android ones.
#
# exclude_xxxhdpi: (optional)
#
# xxxhdpi_whitelist: (optional)
#
# no_xml_namespaces: (optional)
#
# png_to_webp: (optional)
# If true, convert all PNG resources (except 9-patch files) to WebP.
#
# post_process_script: (optional)
#
#
# Output variables:
# output: Path to a zip file containing the compiled resources.
#
# r_text_out_path: (optional):
# Path for the corresponding generated R.txt file.
#
# srcjar_path: (optional)
# Path to a generated .srcjar containing the generated R.java sources
# for all dependent resource libraries.
#
# proguard_file: (optional)
# Path to proguard configuration file for this apk target.
#
# proguard_file_main_dex: (optional)
#
#
template("compile_resources") {
_compile_resources_target_name = target_name
_compiled_resources_path = invoker.output
if (defined(invoker.srcjar_path)) {
_srcjar_path = invoker.srcjar_path
}
if (defined(invoker.post_process_script)) {
_compile_resources_target_name = "${target_name}__intermediate"
_compiled_resources_path =
get_path_info(_compiled_resources_path, "dir") + "/" +
get_path_info(_compiled_resources_path, "name") + ".intermediate.ap_"
_srcjar_path = "${_srcjar_path}.intermediate.srcjar"
}
action(_compile_resources_target_name) {
set_sources_assignment_filter([])
forward_variables_from(invoker,
[
"deps",
"testonly",
"visibility",
])
script = "//build/android/gyp/compile_resources.py"
depfile = "$target_gen_dir/${invoker.target_name}_1.d"
outputs = []
_android_aapt_path = android_default_aapt_path
_android_sdk_jar = android_sdk_jar
if (defined(invoker.alternative_android_sdk_jar)) {
_android_sdk_jar = invoker.alternative_android_sdk_jar
}
inputs = [
invoker.build_config,
_android_aapt_path,
_android_sdk_jar,
]
_rebased_build_config = rebase_path(invoker.build_config, root_build_dir)
args = [
"--depfile",
rebase_path(depfile, root_build_dir),
"--android-sdk-jar",
rebase_path(_android_sdk_jar, root_build_dir),
"--aapt-path",
rebase_path(_android_aapt_path, root_build_dir),
"--dependencies-res-zips=@FileArg($_rebased_build_config:resources:dependency_zips)",
"--extra-res-packages=@FileArg($_rebased_build_config:resources:extra_package_names)",
"--extra-r-text-files=@FileArg($_rebased_build_config:resources:extra_r_text_files)",
]
inputs += [ invoker.android_manifest ]
args += [
"--android-manifest",
rebase_path(invoker.android_manifest, root_build_dir),
]
if (defined(invoker.shared_resources_whitelist)) {
inputs += [ invoker.shared_resources_whitelist ]
args += [
......@@ -1565,11 +1785,11 @@ if (enable_java_templates) {
invoker.version_name,
]
}
if (defined(_packaged_resources_path)) {
outputs += [ _packaged_resources_path ]
if (defined(_compiled_resources_path)) {
outputs += [ _compiled_resources_path ]
args += [
"--apk-path",
rebase_path(_packaged_resources_path, root_build_dir),
rebase_path(_compiled_resources_path, root_build_dir),
]
}
......@@ -1579,14 +1799,6 @@ if (enable_java_templates) {
args += [ "--debuggable" ]
}
if (defined(invoker.zip_path)) {
outputs += [ invoker.zip_path ]
args += [
"--resource-zip-out",
rebase_path(invoker.zip_path, root_build_dir),
]
}
if (defined(invoker.r_text_out_path)) {
outputs += [ invoker.r_text_out_path ]
args += [
......@@ -1603,20 +1815,6 @@ if (enable_java_templates) {
]
}
if (defined(invoker.r_text_in_path)) {
_r_text_in_path = invoker.r_text_in_path
inputs += [ _r_text_in_path ]
args += [
"--r-text-in",
rebase_path(_r_text_in_path, root_build_dir),
]
}
if (!defined(invoker.generate_constant_ids) ||
!invoker.generate_constant_ids) {
args += [ "--non-constant-id" ]
}
if (defined(invoker.custom_package)) {
args += [
"--custom-package",
......@@ -1624,18 +1822,10 @@ if (enable_java_templates) {
]
}
if (defined(invoker.v14_skip) && invoker.v14_skip) {
args += [ "--v14-skip" ]
}
if (defined(invoker.shared_resources) && invoker.shared_resources) {
args += [ "--shared-resources" ]
}
if (defined(invoker.app_as_shared_lib) && invoker.app_as_shared_lib) {
args += [ "--app-as-shared-lib" ]
}
if (defined(invoker.proguard_file)) {
outputs += [ invoker.proguard_file ]
args += [
......@@ -1690,7 +1880,7 @@ if (enable_java_templates) {
"--depfile",
rebase_path(depfile, root_build_dir),
"--apk-path",
rebase_path(_packaged_resources_path, root_build_dir),
rebase_path(_compiled_resources_path, root_build_dir),
"--output",
rebase_path(invoker.output, root_build_dir),
"--srcjar-in",
......@@ -1708,14 +1898,14 @@ if (enable_java_templates) {
}
inputs = [
_srcjar_path,
_packaged_resources_path,
_compiled_resources_path,
]
outputs = [
invoker.output,
invoker.srcjar_path,
]
public_deps = [
":${_process_resources_target_name}",
":${_compile_resources_target_name}",
]
}
}
......@@ -1764,14 +1954,14 @@ if (enable_java_templates) {
invoker.output_apk_path,
]
_rebased_packaged_resources_path =
_rebased_compiled_resources_path =
rebase_path(invoker.packaged_resources_path, root_build_dir)
_rebased_packaged_apk_path =
rebase_path(invoker.output_apk_path, root_build_dir)
args = [
"--depfile",
rebase_path(depfile, root_build_dir),
"--resource-apk=$_rebased_packaged_resources_path",
"--resource-apk=$_rebased_compiled_resources_path",
"--output-apk=$_rebased_packaged_apk_path",
]
if (defined(invoker.assets_build_config)) {
......@@ -1936,27 +2126,23 @@ if (enable_java_templates) {
invoker.native_libs_even_when_incremental
}
_incremental_packaged_resources_path = "${_base_path}_incremental.ap_"
_incremental_compiled_resources_path = "${_base_path}_incremental.ap_"
_packaged_apk_path = "${_base_path}_unsigned.apk"
_incremental_packaged_apk_path = "${_base_path}_incremental_unsigned.apk"
_shared_resources =
defined(invoker.shared_resources) && invoker.shared_resources
assert(_shared_resources || true) # Mark as used.
_app_as_shared_lib =
defined(invoker.app_as_shared_lib) && invoker.app_as_shared_lib
assert(_app_as_shared_lib || true) # Mark as used.
assert(!(_shared_resources && _app_as_shared_lib))
_keystore_path = invoker.keystore_path
_keystore_name = invoker.keystore_name
_keystore_password = invoker.keystore_password
_incremental_package_resources_target_name =
"${target_name}_incremental__package_resources"
_incremental_compile_resources_target_name =
"${target_name}_incremental__compile_resources"
_incremental_android_manifest =
get_label_info(_incremental_package_resources_target_name,
get_label_info(_incremental_compile_resources_target_name,
"target_gen_dir") + "/AndroidManifest.xml"
action(_incremental_package_resources_target_name) {
action(_incremental_compile_resources_target_name) {
deps = _incremental_deps
script =
"//build/android/incremental_install/generate_android_manifest.py"
......@@ -1970,7 +2156,7 @@ if (enable_java_templates) {
# Output the non-compiled manifest for easy debugging (as opposed to
# generating to a temp file).
_incremental_android_manifest,
_incremental_packaged_resources_path,
_incremental_compiled_resources_path,
]
_android_sdk_jar = android_sdk_jar
......@@ -1985,7 +2171,7 @@ if (enable_java_templates) {
"--in-apk",
rebase_path(invoker.packaged_resources_path, root_build_dir),
"--out-apk",
rebase_path(_incremental_packaged_resources_path, root_build_dir),
rebase_path(_incremental_compiled_resources_path, root_build_dir),
"--aapt-path",
rebase_path(android_default_aapt_path, root_build_dir),
"--android-sdk-jar",
......@@ -2036,7 +2222,7 @@ if (enable_java_templates) {
}
_dex_target = "//build/android/incremental_install:bootstrap_java__dex"
deps = _incremental_deps + [
":${_incremental_package_resources_target_name}",
":${_incremental_compile_resources_target_name}",
_dex_target,
]
......@@ -2055,7 +2241,7 @@ if (enable_java_templates) {
}
output_apk_path = _incremental_packaged_apk_path
packaged_resources_path = _incremental_packaged_resources_path
packaged_resources_path = _incremental_compiled_resources_path
}
finalize_apk(target_name) {
......
......@@ -723,8 +723,6 @@ if (enable_java_templates) {
# false. (see build/android/gyp/generate_v14_compatible_resources.py)
# shared_resources: If true make a resource package that can be loaded by a
# different application at runtime to access the package's resources.
# app_as_shared_lib: If true make a resource package that can be loaded as
# both shared_resources and normal application.
# r_text_file: (optional) path to pre-generated R.txt to be used when
# generating R.java instead of resource-based aapt-generated one.
# create_srcjar: If false, does not create an R.java file. Needed only for
......@@ -792,17 +790,15 @@ if (enable_java_templates) {
}
}
process_resources(target_name) {
prepare_resources(target_name) {
forward_variables_from(invoker,
[
"app_as_shared_lib",
"android_manifest",
"custom_package",
"deps",
"generated_resource_dirs",
"generated_resource_files",
"resource_dirs",
"shared_resources",
"v14_skip",
])
if (!defined(deps)) {
......@@ -1151,8 +1147,8 @@ if (enable_java_templates) {
_deps += invoker.deps
}
_process_resources_target = "${target_name}__process_resources"
process_resources(_process_resources_target) {
_prepare_resources_target = "${target_name}__prepare_resources"
prepare_resources(_prepare_resources_target) {
deps = _deps + [ ":$_build_config_target_name" ]
build_config = _build_config
srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
......@@ -1182,7 +1178,7 @@ if (enable_java_templates) {
srcjar_deps = []
}
srcjar_deps += [
":$_process_resources_target",
":$_prepare_resources_target",
# This dep is required for any targets that depend on //base:base_java.
"//base:base_build_config_gen",
......@@ -2014,12 +2010,11 @@ if (enable_java_templates) {
"$_base_path.resources.main-dex-proguard.txt"
}
_generated_proguard_config = "$_base_path.resources.proguard.txt"
_process_resources_target = "${_template_name}__process_resources"
process_resources(_process_resources_target) {
_compile_resources_target = "${_template_name}__compile_resources"
compile_resources(_compile_resources_target) {
forward_variables_from(invoker,
[
"alternative_android_sdk_jar",
"app_as_shared_lib",
"shared_resources",
"support_zh_hk",
"aapt_locale_whitelist",
......@@ -2036,7 +2031,6 @@ if (enable_java_templates) {
}
srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
r_text_out_path = "${target_gen_dir}/${target_name}_R.txt"
generate_constant_ids = true
proguard_file = _generated_proguard_config
if (_enable_multidex) {
proguard_file_main_dex = _generated_proguard_main_dex_config
......@@ -2056,13 +2050,13 @@ if (enable_java_templates) {
get_label_info(invoker.shared_resources_whitelist_target, "name")
shared_resources_whitelist =
"${_whitelist_gen_dir}/${_whitelist_target_name}" +
"__process_resources_R.txt"
"__compile_resources_R.txt"
deps += [
"${invoker.shared_resources_whitelist_target}__process_resources",
"${invoker.shared_resources_whitelist_target}__compile_resources",
]
}
}
_srcjar_deps += [ ":$_process_resources_target" ]
_srcjar_deps += [ ":$_compile_resources_target" ]
if (_native_libs_deps != []) {
_enable_chromium_linker_tests = false
......@@ -2240,7 +2234,7 @@ if (enable_java_templates) {
])
deps = _deps + [
":$_build_config_target",
":$_process_resources_target",
":$_compile_resources_target",
":$_java_target",
]
inputs = [
......@@ -2298,7 +2292,7 @@ if (enable_java_templates) {
if (_enable_multidex) {
extra_main_dex_proguard_config = _generated_proguard_main_dex_config
deps += [ ":$_process_resources_target" ]
deps += [ ":$_compile_resources_target" ]
}
# All deps are already included in _dex_sources when proguard is used.
......@@ -2426,7 +2420,7 @@ if (enable_java_templates) {
incremental_deps = _deps + [
":$_merge_manifest_target",
":$_build_config_target",
":$_process_resources_target",
":$_compile_resources_target",
]
# This target generates the input file _all_resources_zip_path.
......@@ -2434,7 +2428,7 @@ if (enable_java_templates) {
":$_merge_manifest_target",
":$_build_config_target",
":$_final_dex_target_name",
":$_process_resources_target",
":$_compile_resources_target",
]
if (_native_libs_deps != [] ||
......
......@@ -112,7 +112,6 @@ template("monochrome_public_apk_tmpl") {
}
alternative_android_sdk_jar = webview_framework_jar
app_as_shared_lib = true
use_chromium_linker = false
requires_sdk_api_level_23 = true
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment