summaryrefslogtreecommitdiffstats
path: root/chromium/build/android/gyp
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-03-05 17:34:47 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-03-06 10:04:14 +0000
commiteaf1da4d961fbbda9455f9af3b23d1af777f43fa (patch)
tree95970599ecee31c4f7f940bc97ac98c61a3d0cad /chromium/build/android/gyp
parent38a9a29f4f9436cace7f0e7abf9c586057df8a4e (diff)
BASELINE: Update Chromium to 73.0.3683.64
Change-Id: I76517dc277ba4e16bfd7e098fda3d079656b3b9f Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/build/android/gyp')
-rwxr-xr-xchromium/build/android/gyp/apkbuilder.py298
-rwxr-xr-xchromium/build/android/gyp/assert_static_initializers.py117
-rw-r--r--chromium/build/android/gyp/assert_static_initializers.pydeps7
-rwxr-xr-xchromium/build/android/gyp/bundletool.py2
-rwxr-xr-xchromium/build/android/gyp/compile_resources.py2
-rwxr-xr-xchromium/build/android/gyp/create_app_bundle_minimal_apks.py46
-rw-r--r--chromium/build/android/gyp/create_app_bundle_minimal_apks.pydeps11
-rwxr-xr-xchromium/build/android/gyp/create_size_info_files.py167
-rw-r--r--chromium/build/android/gyp/create_size_info_files.pydeps (renamed from chromium/build/android/gyp/merge_jar_info_files.pydeps)4
-rwxr-xr-xchromium/build/android/gyp/javac.py24
-rwxr-xr-xchromium/build/android/gyp/merge_jar_info_files.py99
-rw-r--r--chromium/build/android/gyp/util/build_utils.py35
-rw-r--r--chromium/build/android/gyp/util/jar_info_utils.py17
-rwxr-xr-xchromium/build/android/gyp/write_build_config.py7
14 files changed, 508 insertions, 328 deletions
diff --git a/chromium/build/android/gyp/apkbuilder.py b/chromium/build/android/gyp/apkbuilder.py
index b5097aafb0c..9ffb137ec00 100755
--- a/chromium/build/android/gyp/apkbuilder.py
+++ b/chromium/build/android/gyp/apkbuilder.py
@@ -30,19 +30,18 @@ _NO_COMPRESS_EXTENSIONS = ('.jpg', '.jpeg', '.png', '.gif', '.wav', '.mp2',
def _ParseArgs(args):
parser = argparse.ArgumentParser()
build_utils.AddDepfileOption(parser)
- parser.add_argument('--assets',
- help='GYP-list of files to add as assets in the form '
- '"srcPath:zipPath", where ":zipPath" is optional.',
- default='[]')
- parser.add_argument('--java-resources',
- help='GYP-list of java_resources JARs to include.',
- default='[]')
+ parser.add_argument(
+ '--assets',
+ help='GYP-list of files to add as assets in the form '
+ '"srcPath:zipPath", where ":zipPath" is optional.')
+ parser.add_argument(
+ '--java-resources', help='GYP-list of java_resources JARs to include.')
parser.add_argument('--write-asset-list',
action='store_true',
help='Whether to create an assets/assets_list file.')
- parser.add_argument('--uncompressed-assets',
- help='Same as --assets, except disables compression.',
- default='[]')
+ parser.add_argument(
+ '--uncompressed-assets',
+ help='Same as --assets, except disables compression.')
parser.add_argument('--resource-apk',
help='An .ap_ file built using aapt',
required=True)
@@ -51,10 +50,6 @@ def _ParseArgs(args):
required=True)
parser.add_argument('--format', choices=['apk', 'bundle-module'],
default='apk', help='Specify output format.')
- parser.add_argument('--apk-pak-info-path',
- help='Path to the *.apk.pak.info file')
- parser.add_argument('--apk-res-info-path',
- help='Path to the *.apk.res.info file')
parser.add_argument('--dex-file',
help='Path to the classes.dex to use')
parser.add_argument('--uncompress-dex', action='store_true',
@@ -74,13 +69,13 @@ def _ParseArgs(args):
parser.add_argument('--secondary-android-abi',
help='The secondary Android architecture to use for'
'secondary native libraries')
- parser.add_argument('--native-lib-placeholders',
- help='GYP-list of native library placeholders to add.',
- default='[]')
- parser.add_argument('--secondary-native-lib-placeholders',
- help='GYP-list of native library placeholders to add '
- 'for the secondary ABI',
- default='[]')
+ parser.add_argument(
+ '--native-lib-placeholders',
+ help='GYP-list of native library placeholders to add.')
+ parser.add_argument(
+ '--secondary-native-lib-placeholders',
+ help='GYP-list of native library placeholders to add '
+ 'for the secondary ABI')
parser.add_argument('--uncompress-shared-libraries', default='False',
choices=['true', 'True', 'false', 'False'],
help='Whether to uncompress native shared libraries. Argument must be '
@@ -226,31 +221,12 @@ def _AddNativeLibraries(out_apk, native_libs, android_abi, uncompress):
compress=compress)
-def _MergeResInfoFiles(res_info_path, resource_apk):
- resource_apk_info_path = resource_apk + '.info'
- shutil.copy(resource_apk_info_path, res_info_path)
-
-
-def _FilterPakInfoPaths(assets):
- return [f.split(':')[0] + '.info' for f in assets if f.endswith('.pak')]
-
-
-def _MergePakInfoFiles(merged_path, pak_infos):
- info_lines = set()
- for pak_info_path in pak_infos:
- with open(pak_info_path, 'r') as src_info_file:
- info_lines.update(src_info_file.readlines())
- with open(merged_path, 'w') as merged_info_file:
- merged_info_file.writelines(sorted(info_lines))
-
-
def main(args):
args = build_utils.ExpandFileArgs(args)
options = _ParseArgs(args)
native_libs = sorted(options.native_libs)
- input_paths = [options.resource_apk, __file__]
# Include native libs in the depfile_deps since GN doesn't know about the
# dependencies when is_component_build=true.
depfile_deps = list(native_libs)
@@ -260,17 +236,6 @@ def main(args):
secondary_native_libs = sorted(options.secondary_native_libs)
depfile_deps += secondary_native_libs
- if options.dex_file:
- input_paths.append(options.dex_file)
-
- input_strings = [options.android_abi,
- options.native_lib_placeholders,
- options.secondary_native_lib_placeholders,
- str(options.uncompress_shared_libraries)]
-
- if options.secondary_android_abi:
- input_strings.append(options.secondary_android_abi)
-
if options.java_resources:
# Included via .build_config, so need to write it to depfile.
depfile_deps.extend(options.java_resources)
@@ -278,21 +243,9 @@ def main(args):
assets = _ExpandPaths(options.assets)
uncompressed_assets = _ExpandPaths(options.uncompressed_assets)
- if options.apk_pak_info_path:
- pak_infos = _FilterPakInfoPaths(
- options.assets + options.uncompressed_assets)
- depfile_deps.extend(pak_infos)
-
- for src_path, dest_path in itertools.chain(assets, uncompressed_assets):
- # Included via .build_config, so need to write it to depfile.
- depfile_deps.append(src_path)
- input_strings.append(dest_path)
-
- output_paths = [options.output_apk]
- if options.apk_pak_info_path:
- output_paths.append(options.apk_pak_info_path)
- if options.apk_res_info_path:
- output_paths.append(options.apk_res_info_path)
+ # Included via .build_config, so need to write it to depfile.
+ depfile_deps.extend(x[0] for x in assets)
+ depfile_deps.extend(x[0] for x in uncompressed_assets)
# Bundle modules have a structure similar to APKs, except that resources
# are compiled in protobuf format (instead of binary xml), and that some
@@ -314,119 +267,110 @@ def main(args):
apk_root_dir = ''
apk_dex_dir = ''
- def on_stale_md5():
- with tempfile.NamedTemporaryFile() as tmp_apk:
- tmp_file = tmp_apk.name
- with zipfile.ZipFile(options.resource_apk) as resource_apk, \
- zipfile.ZipFile(tmp_file, 'w', zipfile.ZIP_DEFLATED) as out_apk:
- def copy_resource(zipinfo, out_dir=''):
- compress = zipinfo.compress_type != zipfile.ZIP_STORED
- build_utils.AddToZipHermetic(out_apk, out_dir + zipinfo.filename,
- data=resource_apk.read(zipinfo.filename),
- compress=compress)
-
- # Make assets come before resources in order to maintain the same file
- # ordering as GYP / aapt. http://crbug.com/561862
- resource_infos = resource_apk.infolist()
-
- # 1. AndroidManifest.xml
- copy_resource(
- resource_apk.getinfo('AndroidManifest.xml'),
- out_dir=apk_manifest_dir)
-
- # 2. Assets
- if options.write_asset_list:
- data = _CreateAssetsList(
- itertools.chain(assets, uncompressed_assets))
- build_utils.AddToZipHermetic(out_apk, 'assets/assets_list', data=data)
-
- _AddAssets(out_apk, assets, disable_compression=False)
- _AddAssets(out_apk, uncompressed_assets, disable_compression=True)
-
- # 3. Dex files
- if options.dex_file and options.dex_file.endswith('.zip'):
- with zipfile.ZipFile(options.dex_file, 'r') as dex_zip:
- for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')):
- build_utils.AddToZipHermetic(out_apk, apk_dex_dir + dex,
- data=dex_zip.read(dex),
- compress=not options.uncompress_dex)
- elif options.dex_file:
- build_utils.AddToZipHermetic(out_apk, apk_dex_dir + 'classes.dex',
- src_path=options.dex_file,
- compress=not options.uncompress_dex)
-
- # 4. Native libraries.
- _AddNativeLibraries(out_apk,
- native_libs,
- options.android_abi,
+ # Targets generally do not depend on apks, so no need for only_if_changed.
+ with build_utils.AtomicOutput(options.output_apk, only_if_changed=False) as f:
+ with zipfile.ZipFile(options.resource_apk) as resource_apk, \
+ zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED) as out_apk:
+
+ def copy_resource(zipinfo, out_dir=''):
+ compress = zipinfo.compress_type != zipfile.ZIP_STORED
+ build_utils.AddToZipHermetic(
+ out_apk,
+ out_dir + zipinfo.filename,
+ data=resource_apk.read(zipinfo.filename),
+ compress=compress)
+
+ # Make assets come before resources in order to maintain the same file
+ # ordering as GYP / aapt. http://crbug.com/561862
+ resource_infos = resource_apk.infolist()
+
+ # 1. AndroidManifest.xml
+ copy_resource(
+ resource_apk.getinfo('AndroidManifest.xml'), out_dir=apk_manifest_dir)
+
+ # 2. Assets
+ if options.write_asset_list:
+ data = _CreateAssetsList(itertools.chain(assets, uncompressed_assets))
+ build_utils.AddToZipHermetic(out_apk, 'assets/assets_list', data=data)
+
+ _AddAssets(out_apk, assets, disable_compression=False)
+ _AddAssets(out_apk, uncompressed_assets, disable_compression=True)
+
+ # 3. Dex files
+ if options.dex_file and options.dex_file.endswith('.zip'):
+ with zipfile.ZipFile(options.dex_file, 'r') as dex_zip:
+ for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')):
+ build_utils.AddToZipHermetic(
+ out_apk,
+ apk_dex_dir + dex,
+ data=dex_zip.read(dex),
+ compress=not options.uncompress_dex)
+ elif options.dex_file:
+ build_utils.AddToZipHermetic(
+ out_apk,
+ apk_dex_dir + 'classes.dex',
+ src_path=options.dex_file,
+ compress=not options.uncompress_dex)
+
+ # 4. Native libraries.
+ _AddNativeLibraries(out_apk, native_libs, options.android_abi,
+ options.uncompress_shared_libraries)
+
+ if options.secondary_android_abi:
+ _AddNativeLibraries(out_apk, secondary_native_libs,
+ options.secondary_android_abi,
options.uncompress_shared_libraries)
- if options.secondary_android_abi:
- _AddNativeLibraries(out_apk,
- secondary_native_libs,
- options.secondary_android_abi,
- options.uncompress_shared_libraries)
-
- for name in sorted(options.native_lib_placeholders):
- # Note: Empty libs files are ignored by md5check (can cause issues
- # with stale builds when the only change is adding/removing
- # placeholders).
- apk_path = 'lib/%s/%s' % (options.android_abi, name)
- build_utils.AddToZipHermetic(out_apk, apk_path, data='')
-
- for name in sorted(options.secondary_native_lib_placeholders):
- # Note: Empty libs files are ignored by md5check (can cause issues
- # with stale builds when the only change is adding/removing
- # placeholders).
- apk_path = 'lib/%s/%s' % (options.secondary_android_abi, name)
- build_utils.AddToZipHermetic(out_apk, apk_path, data='')
-
- # 5. Resources
- for info in resource_infos:
- if info.filename != 'AndroidManifest.xml':
- copy_resource(info)
-
- # 6. Java resources that should be accessible via
- # Class.getResourceAsStream(), in particular parts of Emma jar.
- # Prebuilt jars may contain class files which we shouldn't include.
- for java_resource in options.java_resources:
- with zipfile.ZipFile(java_resource, 'r') as java_resource_jar:
- for apk_path in java_resource_jar.namelist():
- apk_path_lower = apk_path.lower()
-
- if apk_path_lower.startswith('meta-inf/'):
- continue
- if apk_path_lower.endswith('/'):
- continue
- if apk_path_lower.endswith('.class'):
- continue
-
- build_utils.AddToZipHermetic(
- out_apk, apk_root_dir + apk_path,
- data=java_resource_jar.read(apk_path))
-
- if options.apk_pak_info_path:
- _MergePakInfoFiles(options.apk_pak_info_path, pak_infos)
- if options.apk_res_info_path:
- _MergeResInfoFiles(options.apk_res_info_path, options.resource_apk)
-
- if options.format == 'apk':
- finalize_apk.FinalizeApk(options.apksigner_path, options.zipalign_path,
- tmp_file, options.output_apk,
- options.key_path, options.key_passwd,
- options.key_name)
- else:
- shutil.move(tmp_file, options.output_apk)
- tmp_apk.delete = False
-
- build_utils.CallAndWriteDepfileIfStale(
- on_stale_md5,
- options,
- input_paths=input_paths + depfile_deps,
- input_strings=input_strings,
- output_paths=output_paths,
- depfile_deps=depfile_deps,
- add_pydeps=False)
+ for name in sorted(options.native_lib_placeholders):
+ # Note: Empty libs files are ignored by md5check (can cause issues
+ # with stale builds when the only change is adding/removing
+ # placeholders).
+ apk_path = 'lib/%s/%s' % (options.android_abi, name)
+ build_utils.AddToZipHermetic(out_apk, apk_path, data='')
+
+ for name in sorted(options.secondary_native_lib_placeholders):
+ # Note: Empty libs files are ignored by md5check (can cause issues
+ # with stale builds when the only change is adding/removing
+ # placeholders).
+ apk_path = 'lib/%s/%s' % (options.secondary_android_abi, name)
+ build_utils.AddToZipHermetic(out_apk, apk_path, data='')
+
+ # 5. Resources
+ for info in resource_infos:
+ if info.filename != 'AndroidManifest.xml':
+ copy_resource(info)
+
+ # 6. Java resources that should be accessible via
+ # Class.getResourceAsStream(), in particular parts of Emma jar.
+ # Prebuilt jars may contain class files which we shouldn't include.
+ for java_resource in options.java_resources:
+ with zipfile.ZipFile(java_resource, 'r') as java_resource_jar:
+ for apk_path in java_resource_jar.namelist():
+ apk_path_lower = apk_path.lower()
+
+ if apk_path_lower.startswith('meta-inf/'):
+ continue
+ if apk_path_lower.endswith('/'):
+ continue
+ if apk_path_lower.endswith('.class'):
+ continue
+
+ build_utils.AddToZipHermetic(
+ out_apk,
+ apk_root_dir + apk_path,
+ data=java_resource_jar.read(apk_path))
+
+ if options.format == 'apk':
+ finalize_apk.FinalizeApk(options.apksigner_path, options.zipalign_path,
+ f.name, f.name, options.key_path,
+ options.key_passwd, options.key_name)
+
+ if options.depfile:
+ build_utils.WriteDepfile(
+ options.depfile,
+ options.output_apk,
+ inputs=depfile_deps,
+ add_pydeps=False)
if __name__ == '__main__':
diff --git a/chromium/build/android/gyp/assert_static_initializers.py b/chromium/build/android/gyp/assert_static_initializers.py
index 717861b77c9..019baface15 100755
--- a/chromium/build/android/gyp/assert_static_initializers.py
+++ b/chromium/build/android/gyp/assert_static_initializers.py
@@ -7,17 +7,116 @@
import argparse
import os
+import re
+import subprocess
import sys
-
-sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-import resource_sizes
+import tempfile
+import zipfile
from util import build_utils
+_DUMP_STATIC_INITIALIZERS_PATH = os.path.join(build_utils.DIR_SOURCE_ROOT,
+ 'tools', 'linux',
+ 'dump-static-initializers.py')
+
+
+def _RunReadelf(so_path, options, tool_prefix=''):
+ return subprocess.check_output([tool_prefix + 'readelf'] + options +
+ [so_path])
+
+
+def _ParseLibBuildId(so_path, tool_prefix):
+ """Returns the Build ID of the given native library."""
+ stdout = _RunReadelf(so_path, ['-n'], tool_prefix)
+ match = re.search(r'Build ID: (\w+)', stdout)
+ return match.group(1) if match else None
+
+
+def _VerifyLibBuildIdsMatch(tool_prefix, *so_files):
+ if len(set(_ParseLibBuildId(f, tool_prefix) for f in so_files)) > 1:
+ raise Exception('Found differing build ids in output directory and apk. '
+ 'Your output directory is likely stale.')
+
+
+def _GetStaticInitializers(so_path, tool_prefix):
+ output = subprocess.check_output(
+ [_DUMP_STATIC_INITIALIZERS_PATH, '-d', so_path, '-t', tool_prefix])
+ summary = re.search(r'Found \d+ static initializers in (\d+) files.', output)
+ return output.splitlines()[:-1], int(summary.group(1))
+
+
+def _PrintDumpSIsCount(apk_so_name, unzipped_so, out_dir, tool_prefix):
+ lib_name = os.path.basename(apk_so_name).replace('crazy.', '')
+ so_with_symbols_path = os.path.join(out_dir, 'lib.unstripped', lib_name)
+ if not os.path.exists(so_with_symbols_path):
+ raise Exception('Unstripped .so not found. Looked here: %s',
+ so_with_symbols_path)
+ _VerifyLibBuildIdsMatch(tool_prefix, unzipped_so, so_with_symbols_path)
+ sis, _ = _GetStaticInitializers(so_with_symbols_path, tool_prefix)
+ for si in sis:
+ print si
+
+
+# Mostly copied from //infra/scripts/legacy/scripts/slave/chromium/sizes.py.
+def _ReadInitArray(so_path, tool_prefix):
+ stdout = _RunReadelf(so_path, ['-SW'], tool_prefix)
+ # Matches: .ctors PROGBITS 000000000516add0 5169dd0 000010 00 WA 0 0 8
+ match = re.search(r'\.init_array.*$', stdout, re.MULTILINE)
+ if not match:
+ raise Exception('Did not find section: .init_array in:\n' + stdout)
+ size_str = re.split(r'\W+', match.group(0))[5]
+ return int(size_str, 16)
+
+
+def _CountStaticInitializers(so_path, tool_prefix):
+ # Find the number of files with at least one static initializer.
+ # First determine if we're 32 or 64 bit
+ stdout = _RunReadelf(so_path, ['-h'], tool_prefix)
+ elf_class_line = re.search('Class:.*$', stdout, re.MULTILINE).group(0)
+ elf_class = re.split(r'\W+', elf_class_line)[1]
+ if elf_class == 'ELF32':
+ word_size = 4
+ else:
+ word_size = 8
+
+ # Then find the number of files with global static initializers.
+ # NOTE: this is very implementation-specific and makes assumptions
+ # about how compiler and linker implement global static initializers.
+ init_array_size = _ReadInitArray(so_path, tool_prefix)
+ return init_array_size / word_size
+
+
+def _AnalyzeStaticInitializers(apk_filename, tool_prefix, dump_sis, out_dir,
+ ignored_libs):
+ # Static initializer counting mostly copies logic in
+ # infra/scripts/legacy/scripts/slave/chromium/sizes.py.
+ with zipfile.ZipFile(apk_filename) as z:
+ so_files = [
+ f for f in z.infolist() if f.filename.endswith('.so')
+ and f.file_size > 0 and os.path.basename(f.filename) not in ignored_libs
+ ]
+ # Skip checking static initializers for secondary abi libs. They will be
+ # checked by 32-bit bots. This avoids the complexity of finding 32 bit .so
+ # files in the output directory in 64 bit builds.
+ has_64 = any('64' in f.filename for f in so_files)
+ files_to_check = [f for f in so_files if not has_64 or '64' in f.filename]
+
+ si_count = 0
+ for f in files_to_check:
+ with tempfile.NamedTemporaryFile() as temp:
+ temp.write(z.read(f))
+ temp.flush()
+ si_count += _CountStaticInitializers(temp.name, tool_prefix)
+ if dump_sis:
+ # Print count and list of SIs reported by dump-static-initializers.py.
+ # Doesn't work well on all archs (particularly arm), which is why
+ # the readelf method is used for tracking SI counts.
+ _PrintDumpSIsCount(f.filename, temp.name, out_dir, tool_prefix)
+ return si_count
+
def main():
parser = argparse.ArgumentParser()
- build_utils.AddDepfileOption(parser)
parser.add_argument('--touch', help='File to touch upon success')
parser.add_argument('--tool-prefix', required=True,
help='Prefix for nm and friends')
@@ -30,8 +129,8 @@ def main():
#TODO(crbug.com/838414): add support for files included via loadable_modules.
ignored_libs = ['libarcore_sdk_c.so']
- si_count = resource_sizes.AnalyzeStaticInitializers(
- args.apk, args.tool_prefix, False, '.', ignored_libs)
+ si_count = _AnalyzeStaticInitializers(args.apk, args.tool_prefix, False, '.',
+ ignored_libs)
if si_count != args.expected_count:
print 'Expected {} static initializers, but found {}.'.format(
args.expected_count, si_count)
@@ -42,8 +141,8 @@ def main():
else:
print 'Dumping static initializers via dump-static-initializers.py:'
sys.stdout.flush()
- resource_sizes.AnalyzeStaticInitializers(
- args.apk, args.tool_prefix, True, '.', ignored_libs)
+ _AnalyzeStaticInitializers(args.apk, args.tool_prefix, True, '.',
+ ignored_libs)
print
print 'If the above list is not useful, consider listing them with:'
print ' //tools/binary_size/diagnose_bloat.py'
@@ -53,8 +152,6 @@ def main():
'static_initializers.md')
sys.exit(1)
- if args.depfile:
- build_utils.WriteDepfile(args.depfile, args.touch)
if args.touch:
open(args.touch, 'w')
diff --git a/chromium/build/android/gyp/assert_static_initializers.pydeps b/chromium/build/android/gyp/assert_static_initializers.pydeps
new file mode 100644
index 00000000000..e031668f467
--- /dev/null
+++ b/chromium/build/android/gyp/assert_static_initializers.pydeps
@@ -0,0 +1,7 @@
+# Generated by running:
+# build/print_python_deps.py --root build/android/gyp --output build/android/gyp/assert_static_initializers.pydeps build/android/gyp/assert_static_initializers.py
+../../gn_helpers.py
+assert_static_initializers.py
+util/__init__.py
+util/build_utils.py
+util/md5_check.py
diff --git a/chromium/build/android/gyp/bundletool.py b/chromium/build/android/gyp/bundletool.py
index 1709b936d98..3ac9cddec35 100755
--- a/chromium/build/android/gyp/bundletool.py
+++ b/chromium/build/android/gyp/bundletool.py
@@ -8,6 +8,7 @@
Bundletool is distributed as a versioned jar file. This script abstracts the
location and version of this jar file, as well as the JVM invokation."""
+import logging
import os
import subprocess
import sys
@@ -24,6 +25,7 @@ BUNDLETOOL_JAR_PATH = os.path.join(
def RunBundleTool(args):
args = ['java', '-jar', BUNDLETOOL_JAR_PATH] + args
+ logging.debug(' '.join(args))
subprocess.check_call(args)
if __name__ == '__main__':
diff --git a/chromium/build/android/gyp/compile_resources.py b/chromium/build/android/gyp/compile_resources.py
index 72ff6fe1f4f..15381e8efca 100755
--- a/chromium/build/android/gyp/compile_resources.py
+++ b/chromium/build/android/gyp/compile_resources.py
@@ -653,7 +653,7 @@ def _CreateResourceInfoFile(
lines.update(zip_info_file.readlines())
for dest, source in renamed_paths.iteritems():
lines.add('Rename:{},{}\n'.format(dest, source))
- with open(apk_info_path, 'w') as info_file:
+ with build_utils.AtomicOutput(apk_info_path) as info_file:
info_file.writelines(sorted(lines))
diff --git a/chromium/build/android/gyp/create_app_bundle_minimal_apks.py b/chromium/build/android/gyp/create_app_bundle_minimal_apks.py
new file mode 100755
index 00000000000..f01691e418f
--- /dev/null
+++ b/chromium/build/android/gyp/create_app_bundle_minimal_apks.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+#
+# Copyright 2019 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.
+
+"""Creates an .apks from an .aab with only English strings."""
+
+import argparse
+import os
+import sys
+
+sys.path.append(
+ os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)))
+from pylib.utils import app_bundle_utils
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument(
+ '--bundle', required=True, help='Path to input .aab file.')
+ parser.add_argument(
+ '--output', required=True, help='Path to output .apks file.')
+ parser.add_argument('--aapt2-path', required=True, help='Path to aapt2.')
+ parser.add_argument(
+ '--keystore-path', required=True, help='Path to keystore.')
+ parser.add_argument(
+ '--keystore-password', required=True, help='Keystore password.')
+ parser.add_argument(
+ '--keystore-name', required=True, help='Key name within keystore')
+
+ args = parser.parse_args()
+
+ app_bundle_utils.GenerateBundleApks(
+ args.bundle,
+ args.output,
+ args.aapt2_path,
+ args.keystore_path,
+ args.keystore_password,
+ args.keystore_name,
+ minimal=True,
+ check_for_noop=False)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/build/android/gyp/create_app_bundle_minimal_apks.pydeps b/chromium/build/android/gyp/create_app_bundle_minimal_apks.pydeps
new file mode 100644
index 00000000000..7cf09fdc174
--- /dev/null
+++ b/chromium/build/android/gyp/create_app_bundle_minimal_apks.pydeps
@@ -0,0 +1,11 @@
+# Generated by running:
+# build/print_python_deps.py --root build/android/gyp --output build/android/gyp/create_app_bundle_minimal_apks.pydeps build/android/gyp/create_app_bundle_minimal_apks.py
+../../gn_helpers.py
+../pylib/__init__.py
+../pylib/utils/__init__.py
+../pylib/utils/app_bundle_utils.py
+bundletool.py
+create_app_bundle_minimal_apks.py
+util/__init__.py
+util/build_utils.py
+util/md5_check.py
diff --git a/chromium/build/android/gyp/create_size_info_files.py b/chromium/build/android/gyp/create_size_info_files.py
new file mode 100755
index 00000000000..5b248e41956
--- /dev/null
+++ b/chromium/build/android/gyp/create_size_info_files.py
@@ -0,0 +1,167 @@
+#!/usr/bin/env python
+
+# 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.
+
+"""Creates size-info/*.info files used by SuperSize."""
+
+import argparse
+import os
+import sys
+import zipfile
+
+from util import build_utils
+from util import jar_info_utils
+from util import md5_check
+
+
+def _MergeResInfoFiles(res_info_path, info_paths):
+ # Concatenate them all.
+ # only_if_changed=False since no build rules depend on this as an input.
+ with build_utils.AtomicOutput(res_info_path, only_if_changed=False) as dst:
+ for p in info_paths:
+ with open(p) as src:
+ dst.write(src.read())
+
+
+def _PakInfoPathsForAssets(assets):
+ return [f.split(':')[0] + '.info' for f in assets if f.endswith('.pak')]
+
+
+def _MergePakInfoFiles(merged_path, pak_infos):
+ info_lines = set()
+ for pak_info_path in pak_infos:
+ with open(pak_info_path, 'r') as src_info_file:
+ info_lines.update(src_info_file.readlines())
+ # only_if_changed=False since no build rules depend on this as an input.
+ with build_utils.AtomicOutput(merged_path, only_if_changed=False) as f:
+ f.writelines(sorted(info_lines))
+
+
+def _FullJavaNameFromClassFilePath(path):
+ # Input: base/android/java/src/org/chromium/Foo.class
+ # Output: base.android.java.src.org.chromium.Foo
+ if not path.endswith('.class'):
+ return ''
+ path = os.path.splitext(path)[0]
+ parts = []
+ while path:
+ # Use split to be platform independent.
+ head, tail = os.path.split(path)
+ path = head
+ parts.append(tail)
+ parts.reverse() # Package comes first
+ return '.'.join(parts)
+
+
+def _MergeJarInfoFiles(output, inputs):
+ """Merge several .jar.info files to generate an .apk.jar.info.
+
+ Args:
+ output: output file path.
+ inputs: List of .info.jar or .jar files.
+ """
+ info_data = dict()
+ for path in inputs:
+ # android_java_prebuilt adds jar files in the src directory (relative to
+ # the output directory, usually ../../third_party/example.jar).
+ # android_aar_prebuilt collects jar files in the aar file and uses the
+ # java_prebuilt rule to generate gen/example/classes.jar files.
+ # We scan these prebuilt jars to parse each class path for the FQN. This
+ # allows us to later map these classes back to their respective src
+ # directories.
+ # TODO(agrieve): This should probably also check that the mtime of the .info
+ # is newer than that of the .jar, or change prebuilts to always output
+ # .info files so that they always exist (and change the depfile to
+ # depend directly on them).
+ if path.endswith('.info'):
+ info_data.update(jar_info_utils.ParseJarInfoFile(path))
+ else:
+ with zipfile.ZipFile(path) as zip_info:
+ for name in zip_info.namelist():
+ fully_qualified_name = _FullJavaNameFromClassFilePath(name)
+ if fully_qualified_name:
+ info_data[fully_qualified_name] = '{}/{}'.format(path, name)
+
+ # only_if_changed=False since no build rules depend on this as an input.
+ with build_utils.AtomicOutput(output, only_if_changed=False) as f:
+ jar_info_utils.WriteJarInfoFile(f, info_data)
+
+
+def _FindJarInputs(jar_paths):
+ ret = []
+ for jar_path in jar_paths:
+ jar_info_path = jar_path + '.info'
+ if os.path.exists(jar_info_path):
+ ret.append(jar_info_path)
+ else:
+ ret.append(jar_path)
+ return ret
+
+
+def main(args):
+ args = build_utils.ExpandFileArgs(args)
+ parser = argparse.ArgumentParser(description=__doc__)
+ build_utils.AddDepfileOption(parser)
+ parser.add_argument(
+ '--jar-info-path', required=True, help='Output .jar.info file')
+ parser.add_argument(
+ '--pak-info-path', required=True, help='Output .pak.info file')
+ parser.add_argument(
+ '--res-info-path', required=True, help='Output .res.info file')
+ parser.add_argument(
+ '--jar-files',
+ required=True,
+ action='append',
+ help='GN-list of .jar file paths')
+ parser.add_argument(
+ '--assets',
+ required=True,
+ action='append',
+ help='GN-list of files to add as assets in the form '
+ '"srcPath:zipPath", where ":zipPath" is optional.')
+ parser.add_argument(
+ '--uncompressed-assets',
+ required=True,
+ action='append',
+ help='Same as --assets, except disables compression.')
+ parser.add_argument(
+ '--resource-apk',
+ dest='resource_apks',
+ required=True,
+ action='append',
+ help='An .ap_ file built using aapt')
+
+ options = parser.parse_args(args)
+
+ options.jar_files = build_utils.ParseGnList(options.jar_files)
+ options.assets = build_utils.ParseGnList(options.assets)
+ options.uncompressed_assets = build_utils.ParseGnList(
+ options.uncompressed_assets)
+
+ jar_inputs = _FindJarInputs(set(options.jar_files))
+ pak_inputs = _PakInfoPathsForAssets(options.assets +
+ options.uncompressed_assets)
+ res_inputs = [p + '.info' for p in options.resource_apks]
+
+ # Don't bother re-running if no .info files have changed (saves ~250ms).
+ md5_check.CallAndRecordIfStale(
+ lambda: _MergeJarInfoFiles(options.jar_info_path, jar_inputs),
+ input_paths=jar_inputs,
+ output_paths=[options.jar_info_path])
+
+ # Always recreate these (just as fast as md5 checking them).
+ _MergePakInfoFiles(options.pak_info_path, pak_inputs)
+ _MergeResInfoFiles(options.res_info_path, res_inputs)
+
+ all_inputs = jar_inputs + pak_inputs + res_inputs
+ build_utils.WriteDepfile(
+ options.depfile,
+ options.jar_info_path,
+ inputs=all_inputs,
+ add_pydeps=False)
+
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/chromium/build/android/gyp/merge_jar_info_files.pydeps b/chromium/build/android/gyp/create_size_info_files.pydeps
index 710091c42fa..4ab7f94ea60 100644
--- a/chromium/build/android/gyp/merge_jar_info_files.pydeps
+++ b/chromium/build/android/gyp/create_size_info_files.pydeps
@@ -1,7 +1,7 @@
# Generated by running:
-# build/print_python_deps.py --root build/android/gyp --output build/android/gyp/merge_jar_info_files.pydeps build/android/gyp/merge_jar_info_files.py
+# build/print_python_deps.py --root build/android/gyp --output build/android/gyp/create_size_info_files.pydeps build/android/gyp/create_size_info_files.py
../../gn_helpers.py
-merge_jar_info_files.py
+create_size_info_files.py
util/__init__.py
util/build_utils.py
util/jar_info_utils.py
diff --git a/chromium/build/android/gyp/javac.py b/chromium/build/android/gyp/javac.py
index 8ad9bb7ebf0..e8ca89ab2fd 100755
--- a/chromium/build/android/gyp/javac.py
+++ b/chromium/build/android/gyp/javac.py
@@ -266,9 +266,6 @@ def _CreateInfoFile(java_files, jar_path, chromium_code, srcjar_files,
This maps fully qualified names for classes to either the java file that they
are defined in or the path of the srcjar that they came from.
-
- For apks this also produces a coalesced .apk.jar.info file combining all the
- .jar.info files of its transitive dependencies.
"""
output_path = jar_path + '.info'
logging.info('Start creating info file: %s', output_path)
@@ -290,7 +287,7 @@ def _CreateInfoFile(java_files, jar_path, chromium_code, srcjar_files,
all_info_data[fully_qualified_name] = java_file
logging.info('Writing info file: %s', output_path)
with build_utils.AtomicOutput(output_path) as f:
- jar_info_utils.WriteJarInfoFile(f.name, all_info_data, srcjar_files)
+ jar_info_utils.WriteJarInfoFile(f, all_info_data, srcjar_files)
logging.info('Completed info file: %s', output_path)
@@ -471,13 +468,6 @@ def _OnStaleMd5(changes, options, javac_cmd, java_files, classpath_inputs,
logging.info('Completed all steps in _OnStaleMd5')
-def _ParseAndFlattenGnLists(gn_lists):
- ret = []
- for arg in gn_lists:
- ret.extend(build_utils.ParseGnList(arg))
- return ret
-
-
def _ParseOptions(argv):
parser = optparse.OptionParser()
build_utils.AddDepfileOption(parser)
@@ -561,13 +551,13 @@ def _ParseOptions(argv):
options, args = parser.parse_args(argv)
build_utils.CheckOptions(options, parser, required=('jar_path',))
- options.bootclasspath = _ParseAndFlattenGnLists(options.bootclasspath)
- options.full_classpath = _ParseAndFlattenGnLists(options.full_classpath)
- options.interface_classpath = _ParseAndFlattenGnLists(
+ options.bootclasspath = build_utils.ParseGnList(options.bootclasspath)
+ options.full_classpath = build_utils.ParseGnList(options.full_classpath)
+ options.interface_classpath = build_utils.ParseGnList(
options.interface_classpath)
- options.processorpath = _ParseAndFlattenGnLists(options.processorpath)
- options.processors = _ParseAndFlattenGnLists(options.processors)
- options.java_srcjars = _ParseAndFlattenGnLists(options.java_srcjars)
+ options.processorpath = build_utils.ParseGnList(options.processorpath)
+ options.processors = build_utils.ParseGnList(options.processors)
+ options.java_srcjars = build_utils.ParseGnList(options.java_srcjars)
if options.java_version == '1.8' and options.bootclasspath:
# Android's boot jar doesn't contain all java 8 classes.
diff --git a/chromium/build/android/gyp/merge_jar_info_files.py b/chromium/build/android/gyp/merge_jar_info_files.py
deleted file mode 100755
index e6160f68469..00000000000
--- a/chromium/build/android/gyp/merge_jar_info_files.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/env python
-
-# 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.
-
-"""Merges .jar.info files into one for APKs."""
-
-import argparse
-import os
-import shutil
-import sys
-import tempfile
-import zipfile
-
-from util import build_utils
-from util import jar_info_utils
-
-
-def _FullJavaNameFromClassFilePath(path):
- # Input: base/android/java/src/org/chromium/Foo.class
- # Output: base.android.java.src.org.chromium.Foo
- if not path.endswith('.class'):
- return ''
- path = os.path.splitext(path)[0]
- parts = []
- while path:
- # Use split to be platform independent.
- head, tail = os.path.split(path)
- path = head
- parts.append(tail)
- parts.reverse() # Package comes first
- return '.'.join(parts)
-
-
-def _MergeInfoFiles(output, jar_paths):
- """Merge several .jar.info files to generate an .apk.jar.info.
-
- Args:
- output: output file path.
- jar_paths: List of .jar file paths for the target apk.
- """
- info_data = dict()
- for jar_path in jar_paths:
- # android_java_prebuilt adds jar files in the src directory (relative to
- # the output directory, usually ../../third_party/example.jar).
- # android_aar_prebuilt collects jar files in the aar file and uses the
- # java_prebuilt rule to generate gen/example/classes.jar files.
- # We scan these prebuilt jars to parse each class path for the FQN. This
- # allows us to later map these classes back to their respective src
- # directories.
- jar_info_path = jar_path + '.info'
- # TODO(agrieve): This should probably also check that the mtime of the .info
- # is newer than that of the .jar, or change prebuilts to always output
- # .info files so that they always exist (and change the depfile to
- # depend directly on them).
- if os.path.exists(jar_info_path):
- info_data.update(jar_info_utils.ParseJarInfoFile(jar_path + '.info'))
- else:
- with zipfile.ZipFile(jar_path) as zip_info:
- for path in zip_info.namelist():
- fully_qualified_name = _FullJavaNameFromClassFilePath(path)
- if fully_qualified_name:
- info_data[fully_qualified_name] = '{}/{}'.format(jar_path, path)
-
- jar_info_utils.WriteJarInfoFile(output, info_data)
-
-
-def main(args):
- args = build_utils.ExpandFileArgs(args)
- parser = argparse.ArgumentParser(description=__doc__)
- build_utils.AddDepfileOption(parser)
- parser.add_argument('--output', required=True,
- help='Output .apk.jar.info file')
- parser.add_argument('--apk-jar-file', required=True,
- help='Path to main .jar file for this APK.')
- parser.add_argument('--dep-jar-files', required=True,
- help='GN-list of dependent .jar file paths')
-
- options = parser.parse_args(args)
- options.dep_jar_files = build_utils.ParseGnList(options.dep_jar_files)
- jar_files = [ options.apk_jar_file ] + options.dep_jar_files
-
- def _OnStaleMd5():
- with tempfile.NamedTemporaryFile() as tmp_file:
- _MergeInfoFiles(tmp_file.name, jar_files)
- shutil.move(tmp_file.name, options.output)
- tmp_file.delete = False
-
- build_utils.CallAndWriteDepfileIfStale(
- _OnStaleMd5, options,
- input_paths=jar_files,
- output_paths=[options.output],
- depfile_deps=jar_files,
- add_pydeps=False)
-
-
-if __name__ == '__main__':
- main(sys.argv[1:])
diff --git a/chromium/build/android/gyp/util/build_utils.py b/chromium/build/android/gyp/util/build_utils.py
index b5fd17ae543..ad26224673e 100644
--- a/chromium/build/android/gyp/util/build_utils.py
+++ b/chromium/build/android/gyp/util/build_utils.py
@@ -83,24 +83,33 @@ def ReadBuildVars(path):
return dict(l.rstrip().split('=', 1) for l in f)
-def ParseGnList(gn_string):
- """Converts a command-line parameter into a list.
+def ParseGnList(value):
+ """Converts a "GN-list" command-line parameter into a list.
- If the input starts with a '[' it is assumed to be a GN-formatted list and
- it will be parsed accordingly. When empty an empty list will be returned.
- Otherwise, the parameter will be treated as a single raw string (not
- GN-formatted in that it's not assumed to have literal quotes that must be
- removed) and a list will be returned containing that string.
+ Conversions handled:
+ * None -> []
+ * '' -> []
+ * 'asdf' -> ['asdf']
+ * '["a", "b"]' -> ['a', 'b']
+ * ['["a", "b"]', 'c'] -> ['a', 'b', 'c'] (flattened list)
The common use for this behavior is in the Android build where things can
take lists of @FileArg references that are expanded via ExpandFileArgs.
"""
- if gn_string.startswith('['):
- parser = gn_helpers.GNValueParser(gn_string)
- return parser.ParseList()
- if len(gn_string):
- return [ gn_string ]
- return []
+ # Convert None to [].
+ if not value:
+ return []
+ # Convert a list of GN lists to a flattened list.
+ if isinstance(value, list):
+ ret = []
+ for arg in value:
+ ret.extend(ParseGnList(arg))
+ return ret
+ # Convert normal GN list.
+ if value.startswith('['):
+ return gn_helpers.GNValueParser(value).ParseList()
+ # Convert a single string value to a list.
+ return [value]
def CheckOptions(options, parser, required=None):
diff --git a/chromium/build/android/gyp/util/jar_info_utils.py b/chromium/build/android/gyp/util/jar_info_utils.py
index 987ee9dcf14..677e4e42616 100644
--- a/chromium/build/android/gyp/util/jar_info_utils.py
+++ b/chromium/build/android/gyp/util/jar_info_utils.py
@@ -32,21 +32,20 @@ def ParseJarInfoFile(info_path):
return info_data
-def WriteJarInfoFile(info_path, info_data, source_file_map=None):
+def WriteJarInfoFile(output_obj, info_data, source_file_map=None):
"""Generate a .jar.info file from a given dictionary.
Args:
- info_path: output file path.
+ output_obj: output file object.
info_data: a mapping of fully qualified Java class names to filepaths.
source_file_map: an optional mapping from java source file paths to the
corresponding source .srcjar. This is because info_data may contain the
path of Java source files that where extracted from an .srcjar into a
temporary location.
"""
- with open(info_path, 'w') as info_file:
- for fully_qualified_name, path in info_data.iteritems():
- if source_file_map and path in source_file_map:
- path = source_file_map[path]
- assert not path.startswith('/tmp'), (
- 'Java file path should not be in temp dir: {}'.format(path))
- info_file.write('{},{}\n'.format(fully_qualified_name, path))
+ for fully_qualified_name, path in sorted(info_data.iteritems()):
+ if source_file_map and path in source_file_map:
+ path = source_file_map[path]
+ assert not path.startswith('/tmp'), (
+ 'Java file path should not be in temp dir: {}'.format(path))
+ output_obj.write('{},{}\n'.format(fully_qualified_name, path))
diff --git a/chromium/build/android/gyp/write_build_config.py b/chromium/build/android/gyp/write_build_config.py
index 7427845ddd5..7050374f1ff 100755
--- a/chromium/build/android/gyp/write_build_config.py
+++ b/chromium/build/android/gyp/write_build_config.py
@@ -1417,6 +1417,13 @@ def main(argv):
c['main_class'] for c in processor_deps.Direct()]
deps_info['javac_full_classpath'] = javac_full_classpath
deps_info['javac_full_interface_classpath'] = javac_full_interface_classpath
+ elif options.type == 'android_app_bundle':
+ # bundles require javac_full_classpath to create .aab.jar.info.
+ javac_full_classpath = set()
+ for d in deps.Direct('android_app_bundle_module'):
+ javac_full_classpath.update(p for p in d['javac_full_classpath'])
+ javac_full_classpath.add(d['jar_path'])
+ deps_info['javac_full_classpath'] = sorted(javac_full_classpath)
if options.type in ('android_apk', 'dist_jar', 'java_binary', 'junit_binary',
'android_app_bundle_module', 'android_app_bundle'):