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:
cullinan 2015-05-11 12:11:29 -07:00 коммит произвёл Commit bot
Родитель 3cb436415f
Коммит f2b9b229e1
5 изменённых файлов: 163 добавлений и 20 удалений

Просмотреть файл

@ -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': [