Reland: Actually use --extra-r-text-files in process_resources.py
Originally landed in crrev.com/1104703003 Reverted in crrev.com/1129103002 due to breaking GN APKs with no resouces. This now handles the case where aapt doesn't generate an R.txt (no resources) by creating an empty R.txt. Generate extra packages' R.java files only containing the resources listed in their R.txt files. This significantly reduces the number of DEX field IDs taken up by resources. BUG=480036 R=cjhopman,yfriedman Review URL: https://codereview.chromium.org/1136653002 Cr-Original-Commit-Position: refs/heads/master@{#329219} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: 4b5d0300e3fa2a382ac3c1c157247a82583d7ed0
This commit is contained in:
Родитель
3cb436415f
Коммит
f2b9b229e1
|
@ -22,6 +22,10 @@ import generate_v14_compatible_resources
|
|||
|
||||
from util import build_utils
|
||||
|
||||
# Import jinja2 from third_party/jinja2
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '../../../third_party'))
|
||||
from jinja2 import Template # pylint: disable=F0401
|
||||
|
||||
|
||||
def ParseArgs(args):
|
||||
"""Parses command line options.
|
||||
|
@ -57,6 +61,8 @@ def ParseArgs(args):
|
|||
help='directory to hold generated R.java.')
|
||||
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 R.txt file generated by appt.')
|
||||
|
||||
parser.add_option('--proguard-file',
|
||||
help='Path to proguard.txt generated file')
|
||||
|
@ -71,13 +77,16 @@ def ParseArgs(args):
|
|||
parser.add_option(
|
||||
'--extra-res-packages',
|
||||
help='Additional package names to generate R.java files for')
|
||||
# TODO(cjhopman): Actually use --extra-r-text-files. We currently include all
|
||||
# the resources in all R.java files for a particular apk.
|
||||
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(
|
||||
'--include-all-resources',
|
||||
action='store_true',
|
||||
help='Include every resource ID in every generated R.java file '
|
||||
'(ignoring R.txt).')
|
||||
|
||||
parser.add_option(
|
||||
'--all-resources-zip-out',
|
||||
|
@ -108,24 +117,104 @@ def ParseArgs(args):
|
|||
return options
|
||||
|
||||
|
||||
def CreateExtraRJavaFiles(r_dir, extra_packages):
|
||||
java_files = build_utils.FindInDirectory(r_dir, "R.java")
|
||||
if len(java_files) != 1:
|
||||
return
|
||||
r_java_file = java_files[0]
|
||||
r_java_contents = codecs.open(r_java_file, encoding='utf-8').read()
|
||||
def CreateExtraRJavaFiles(
|
||||
r_dir, extra_packages, extra_r_text_files, shared_resources, include_all):
|
||||
if include_all:
|
||||
java_files = build_utils.FindInDirectory(r_dir, "R.java")
|
||||
if len(java_files) != 1:
|
||||
return
|
||||
r_java_file = java_files[0]
|
||||
r_java_contents = codecs.open(r_java_file, encoding='utf-8').read()
|
||||
|
||||
for package in extra_packages:
|
||||
package_r_java_dir = os.path.join(r_dir, *package.split('.'))
|
||||
build_utils.MakeDirectory(package_r_java_dir)
|
||||
package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
|
||||
new_r_java = re.sub(r'package [.\w]*;', u'package %s;' % package,
|
||||
r_java_contents)
|
||||
codecs.open(package_r_java_path, 'w', encoding='utf-8').write(new_r_java)
|
||||
# TODO(cjhopman): These extra package's R.java files should be filtered to
|
||||
# only contain the resources listed in their R.txt files. At this point, we
|
||||
# have already compiled those other libraries, so doing this would only
|
||||
# affect how the code in this .apk target could refer to the resources.
|
||||
for package in extra_packages:
|
||||
package_r_java_dir = os.path.join(r_dir, *package.split('.'))
|
||||
build_utils.MakeDirectory(package_r_java_dir)
|
||||
package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
|
||||
new_r_java = re.sub(r'package [.\w]*;', u'package %s;' % package,
|
||||
r_java_contents)
|
||||
codecs.open(package_r_java_path, 'w', encoding='utf-8').write(new_r_java)
|
||||
else:
|
||||
if len(extra_packages) != len(extra_r_text_files):
|
||||
raise Exception('Need one R.txt file per extra package')
|
||||
|
||||
all_resources = {}
|
||||
r_txt_file = os.path.join(r_dir, 'R.txt')
|
||||
if not os.path.exists(r_txt_file):
|
||||
return
|
||||
with open(r_txt_file) 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()
|
||||
all_resources[(resource_type, name)] = (java_type, value)
|
||||
|
||||
for package, r_text_file in zip(extra_packages, extra_r_text_files):
|
||||
if os.path.exists(r_text_file):
|
||||
package_r_java_dir = os.path.join(r_dir, *package.split('.'))
|
||||
build_utils.MakeDirectory(package_r_java_dir)
|
||||
package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
|
||||
CreateExtraRJavaFile(
|
||||
package, package_r_java_path, r_text_file, all_resources,
|
||||
shared_resources)
|
||||
|
||||
|
||||
def CreateExtraRJavaFile(
|
||||
package, r_java_path, r_text_file, all_resources, shared_resources):
|
||||
resources = {}
|
||||
with open(r_text_file) 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)
|
||||
resource_type, name = m.groups()
|
||||
java_type, value = all_resources[(resource_type, name)]
|
||||
if resource_type not in resources:
|
||||
resources[resource_type] = []
|
||||
resources[resource_type].append((name, java_type, value))
|
||||
|
||||
template = Template("""/* AUTO-GENERATED FILE. DO NOT MODIFY. */
|
||||
|
||||
package {{ package }};
|
||||
|
||||
public final class R {
|
||||
{% for resource_type in resources %}
|
||||
public static final class {{ resource_type }} {
|
||||
{% for name, java_type, value in resources[resource_type] %}
|
||||
{% if shared_resources %}
|
||||
public static {{ java_type }} {{ name }} = {{ value }};
|
||||
{% else %}
|
||||
public static final {{ java_type }} {{ name }} = {{ value }};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% if shared_resources %}
|
||||
public static void onResourcesLoaded(int packageId) {
|
||||
{% for resource_type in resources %}
|
||||
{% for name, java_type, value in resources[resource_type] %}
|
||||
{% if java_type == 'int[]' %}
|
||||
for(int i = 0; i < {{ resource_type }}.{{ name }}.length; ++i) {
|
||||
{{ resource_type }}.{{ name }}[i] =
|
||||
({{ resource_type }}.{{ name }}[i] & 0x00ffffff)
|
||||
| (packageId << 24);
|
||||
}
|
||||
{% else %}
|
||||
{{ resource_type }}.{{ name }} =
|
||||
({{ resource_type }}.{{ name }} & 0x00ffffff)
|
||||
| (packageId << 24);
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
}
|
||||
{% endif %}
|
||||
}
|
||||
""", trim_blocks=True, lstrip_blocks=True)
|
||||
|
||||
output = template.render(package=package, resources=resources,
|
||||
shared_resources=shared_resources)
|
||||
with open(r_java_path, 'w') as f:
|
||||
f.write(output)
|
||||
|
||||
|
||||
def CrunchDirectory(aapt, input_dir, output_dir):
|
||||
|
@ -280,7 +369,10 @@ def main():
|
|||
if options.extra_res_packages:
|
||||
CreateExtraRJavaFiles(
|
||||
gen_dir,
|
||||
build_utils.ParseGypList(options.extra_res_packages))
|
||||
build_utils.ParseGypList(options.extra_res_packages),
|
||||
build_utils.ParseGypList(options.extra_r_text_files),
|
||||
options.shared_resources,
|
||||
options.include_all_resources)
|
||||
|
||||
# This is the list of directories with resources to put in the final .zip
|
||||
# file. The order of these is important so that crunched/v14 resources
|
||||
|
@ -310,6 +402,13 @@ def main():
|
|||
else:
|
||||
build_utils.ZipDir(options.srcjar_out, gen_dir)
|
||||
|
||||
if options.r_text_out:
|
||||
r_text_path = os.path.join(gen_dir, 'R.txt')
|
||||
if os.path.exists(r_text_path):
|
||||
shutil.copyfile(r_text_path, options.r_text_out)
|
||||
else:
|
||||
open(options.r_text_out, 'w').close()
|
||||
|
||||
if options.depfile:
|
||||
input_files += build_utils.GetPythonDependencies()
|
||||
build_utils.WriteDepfile(options.depfile, input_files)
|
||||
|
|
|
@ -100,6 +100,7 @@ def main(argv):
|
|||
# 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.')
|
||||
|
@ -237,18 +238,26 @@ def main(argv):
|
|||
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
|
||||
|
||||
if options.type == 'android_resources' or options.type == 'android_apk':
|
||||
config['resources'] = {}
|
||||
config['resources']['dependency_zips'] = [
|
||||
c['resources_zip'] for c in all_resources_deps]
|
||||
config['resources']['extra_package_names'] = []
|
||||
config['resources']['extra_r_text_files'] = []
|
||||
|
||||
if options.type == 'android_apk':
|
||||
config['resources']['extra_package_names'] = [
|
||||
c['package_name'] for c in all_resources_deps if 'package_name' in c]
|
||||
config['resources']['extra_r_text_files'] = [
|
||||
c['r_text'] for c in all_resources_deps if 'r_text' in c]
|
||||
|
||||
if options.type in ['android_apk', 'deps_dex']:
|
||||
deps_dex_files = [c['dex_path'] for c in all_library_deps]
|
||||
|
|
|
@ -323,6 +323,12 @@ template("write_build_config") {
|
|||
invoker.custom_package,
|
||||
]
|
||||
}
|
||||
if (defined(invoker.r_text)) {
|
||||
args += [
|
||||
"--r-text",
|
||||
rebase_path(invoker.r_text, root_build_dir),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (is_apk) {
|
||||
|
@ -1005,6 +1011,7 @@ template("process_resources") {
|
|||
|
||||
zip_path = invoker.zip_path
|
||||
srcjar_path = invoker.srcjar_path
|
||||
r_text_path = invoker.r_text_path
|
||||
build_config = invoker.build_config
|
||||
resource_dirs = invoker.resource_dirs
|
||||
android_manifest = invoker.android_manifest
|
||||
|
@ -1022,6 +1029,7 @@ template("process_resources") {
|
|||
depfile,
|
||||
zip_path,
|
||||
srcjar_path,
|
||||
r_text_path,
|
||||
]
|
||||
|
||||
sources_build_rel = exec_script("//build/android/gyp/find.py",
|
||||
|
@ -1050,8 +1058,11 @@ template("process_resources") {
|
|||
rebase_path(srcjar_path, root_build_dir),
|
||||
"--resource-zip-out",
|
||||
rebase_path(zip_path, root_build_dir),
|
||||
"--r-text-out",
|
||||
rebase_path(r_text_path, root_build_dir),
|
||||
"--dependencies-res-zips=@FileArg($rebase_build_config:resources:dependency_zips)",
|
||||
"--extra-res-packages=@FileArg($rebase_build_config:resources:extra_package_names)",
|
||||
"--extra-r-text-files=@FileArg($rebase_build_config:resources:extra_r_text_files)",
|
||||
]
|
||||
|
||||
if (non_constant_id) {
|
||||
|
@ -1073,6 +1084,11 @@ template("process_resources") {
|
|||
args += [ "--shared-resources" ]
|
||||
}
|
||||
|
||||
if (defined(invoker.include_all_resources) &&
|
||||
invoker.include_all_resources) {
|
||||
args += [ "--include-all-resources" ]
|
||||
}
|
||||
|
||||
if (defined(invoker.all_resources_zip_path)) {
|
||||
all_resources_zip = invoker.all_resources_zip_path
|
||||
outputs += [ all_resources_zip ]
|
||||
|
|
|
@ -530,6 +530,7 @@ template("jinja_template_resources") {
|
|||
# shared_resources: If true make a resource package that can be loaded by a
|
||||
# different application at runtime to access the package's resources.
|
||||
#
|
||||
|
||||
# Example
|
||||
# android_resources("foo_resources") {
|
||||
# deps = [":foo_strings_grd"]
|
||||
|
@ -548,12 +549,14 @@ template("android_resources") {
|
|||
base_path = "$target_gen_dir/$target_name"
|
||||
zip_path = base_path + ".resources.zip"
|
||||
srcjar_path = base_path + ".srcjar"
|
||||
r_text_path = base_path + "_R.txt"
|
||||
build_config = base_path + ".build_config"
|
||||
|
||||
write_build_config("${target_name}__build_config") {
|
||||
type = "android_resources"
|
||||
resources_zip = zip_path
|
||||
srcjar = srcjar_path
|
||||
r_text = r_text_path
|
||||
if (defined(invoker.deps)) {
|
||||
deps = invoker.deps
|
||||
}
|
||||
|
@ -1163,6 +1166,8 @@ template("android_java_prebuilt") {
|
|||
# also be included in the apk.
|
||||
# apk_under_test: For an instrumentation test apk, this is the target of the
|
||||
# tested apk.
|
||||
# include_all_resources - If true include all resource IDs in all generated
|
||||
# R.java files.
|
||||
# testonly: Marks this target as "test-only".
|
||||
#
|
||||
# DEPRECATED_java_in_dir: Directory containing java files. All .java files in
|
||||
|
@ -1306,11 +1311,16 @@ template("android_apk") {
|
|||
final_deps += [ ":${_template_name}__process_resources" ]
|
||||
process_resources("${_template_name}__process_resources") {
|
||||
srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
|
||||
r_text_path = "${target_gen_dir}/${target_name}_R.txt"
|
||||
android_manifest = _android_manifest
|
||||
resource_dirs = [ "//build/android/ant/empty/res" ]
|
||||
zip_path = resources_zip_path
|
||||
generate_constant_ids = true
|
||||
build_config = _build_config
|
||||
|
||||
if (defined(invoker.include_all_resources)) {
|
||||
include_all_resources = invoker.include_all_resources
|
||||
}
|
||||
}
|
||||
_srcjar_deps += [ ":${_template_name}__process_resources" ]
|
||||
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
# application at runtime to access the package's resources.
|
||||
# R_package - A custom Java package to generate the resource file R.java in.
|
||||
# By default, the package given in AndroidManifest.xml will be used.
|
||||
# include_all_resources - Set to 1 to include all resource IDs in all generated
|
||||
# R.java files.
|
||||
# use_chromium_linker - Enable the content dynamic linker that allows sharing the
|
||||
# RELRO section of the native libraries between the different processes.
|
||||
# load_library_from_zip_file - When using the dynamic linker, load the library
|
||||
|
@ -78,6 +80,7 @@
|
|||
'jar_name': 'chromium_apk_<(_target_name).jar',
|
||||
'resource_dir%':'<(DEPTH)/build/android/ant/empty/res',
|
||||
'R_package%':'',
|
||||
'include_all_resources%': 0,
|
||||
'additional_R_text_files': [],
|
||||
'dependencies_res_zip_paths': [],
|
||||
'additional_res_packages': [],
|
||||
|
@ -610,6 +613,12 @@
|
|||
['shared_resources == 1', {
|
||||
'process_resources_options+': ['--shared-resources']
|
||||
}],
|
||||
['R_package != ""', {
|
||||
'process_resources_options+': ['--custom-package', '<(R_package)']
|
||||
}],
|
||||
['include_all_resources == 1', {
|
||||
'process_resources_options+': ['--include-all-resources']
|
||||
}]
|
||||
],
|
||||
},
|
||||
'inputs': [
|
||||
|
|
Загрузка…
Ссылка в новой задаче