diff options
author | agrieve <agrieve@chromium.org> | 2015-11-23 14:07:23 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-23 22:08:11 +0000 |
commit | b37a3d86d55cb781acdaf4aa64c1ea4cadae3271 (patch) | |
tree | 910178da539abd68d4cb4b6acc40803364a1f75d | |
parent | a931efd5dc8d8783ce73a64fc641627866b6869d (diff) | |
download | chromium_src-b37a3d86d55cb781acdaf4aa64c1ea4cadae3271.zip chromium_src-b37a3d86d55cb781acdaf4aa64c1ea4cadae3271.tar.gz chromium_src-b37a3d86d55cb781acdaf4aa64c1ea4cadae3271.tar.bz2 |
Use hermetic timestamps in apkbuilder.py and refactor helper function
This makes it so that the command will always produce the same output
given the same inputs.
BUG=
Review URL: https://codereview.chromium.org/1452843002
Cr-Commit-Position: refs/heads/master@{#361198}
-rwxr-xr-x | build/android/gyp/apkbuilder.py | 51 | ||||
-rwxr-xr-x | build/android/gyp/java_cpp_enum.py | 2 | ||||
-rwxr-xr-x | build/android/gyp/java_google_api_keys.py | 10 | ||||
-rw-r--r-- | build/android/gyp/util/build_utils.py | 47 |
4 files changed, 67 insertions, 43 deletions
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py index 7e0ce23..1837fd6 100755 --- a/build/android/gyp/apkbuilder.py +++ b/build/android/gyp/apkbuilder.py @@ -92,16 +92,13 @@ def _AddAssets(apk, paths, disable_compression=False): """ # Group all uncompressed assets together in the hope that it will increase # locality of mmap'ed files. - for target_compress_type in (zipfile.ZIP_STORED, zipfile.ZIP_DEFLATED): + for target_compress in (False, True): for path in paths: src_path, dest_path = _SplitAssetPath(path) - compress_type = zipfile.ZIP_DEFLATED - if disable_compression or ( - os.path.splitext(src_path)[1] in _NO_COMPRESS_EXTENSIONS): - compress_type = zipfile.ZIP_STORED - - if target_compress_type == compress_type: + compress = not disable_compression and ( + os.path.splitext(src_path)[1] not in _NO_COMPRESS_EXTENSIONS) + if target_compress == compress: apk_path = 'assets/' + dest_path try: apk.getinfo(apk_path) @@ -109,7 +106,8 @@ def _AddAssets(apk, paths, disable_compression=False): raise Exception('Multiple targets specified the asset path: %s' % apk_path) except KeyError: - apk.write(src_path, apk_path, compress_type) + build_utils.AddToZipHermetic(apk, apk_path, src_path=src_path, + compress=compress) def main(args): @@ -148,36 +146,39 @@ def main(args): _AddAssets(apk, options.uncompressed_assets, disable_compression=True) for path in native_libs: basename = os.path.basename(path) - apk.write(path, 'lib/%s/%s' % (options.android_abi, basename)) + apk_path = 'lib/%s/%s' % (options.android_abi, basename) + build_utils.AddToZipHermetic(apk, apk_path, src_path=path) + for name in options.native_lib_placeholders: # Make it non-empty so that its checksum is non-zero and is not # ignored by md5_check. - apk.writestr('lib/%s/%s' % (options.android_abi, name), ':)', - zipfile.ZIP_STORED) - if options.dex_file: - if 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')): - apk.writestr(dex, dex_zip.read(dex)) - else: - apk.write(options.dex_file, 'classes.dex') + apk_path = 'lib/%s/%s.so' % (options.android_abi, name) + build_utils.AddToZipHermetic(apk, apk_path, data=':)') + + 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(apk, dex, data=dex_zip.read(dex)) + elif options.dex_file: + build_utils.AddToZipHermetic(apk, 'classes.dex', + src_path=options.dex_file) if options.emma_device_jar: # Add EMMA Java resources to APK. with zipfile.ZipFile(options.emma_device_jar, 'r') as emma_device_jar: - for emma_device_jar_entry in emma_device_jar.namelist(): - entry_name_lower = emma_device_jar_entry.lower() - if entry_name_lower.startswith('meta-inf/'): + for apk_path in emma_device_jar.namelist(): + apk_path_lower = apk_path.lower() + if apk_path_lower.startswith('meta-inf/'): continue - if entry_name_lower.endswith('/'): + if apk_path_lower.endswith('/'): continue - if entry_name_lower.endswith('.class'): + if apk_path_lower.endswith('.class'): continue - apk.writestr(emma_device_jar_entry, - emma_device_jar.read(emma_device_jar_entry)) + build_utils.AddToZipHermetic(apk, apk_path, + data=emma_device_jar.read(apk_path)) shutil.move(tmp_apk, options.output_apk) finally: diff --git a/build/android/gyp/java_cpp_enum.py b/build/android/gyp/java_cpp_enum.py index a82ebc2..9299bce 100755 --- a/build/android/gyp/java_cpp_enum.py +++ b/build/android/gyp/java_cpp_enum.py @@ -345,7 +345,7 @@ def DoMain(argv): with zipfile.ZipFile(options.srcjar, 'w', zipfile.ZIP_STORED) as srcjar: for output_path, data in DoGenerate(input_paths): - srcjar.writestr(build_utils.CreateHermeticZipInfo(output_path), data) + build_utils.AddToZipHermetic(srcjar, output_path, data=data) else: # TODO(agrieve): Delete this non-srcjar branch once GYP is gone. output_paths = [] diff --git a/build/android/gyp/java_google_api_keys.py b/build/android/gyp/java_google_api_keys.py index 95257d3..62c92cd 100755 --- a/build/android/gyp/java_google_api_keys.py +++ b/build/android/gyp/java_google_api_keys.py @@ -12,6 +12,8 @@ import string import sys import zipfile +from util import build_utils + sys.path.append( os.path.abspath(os.path.join(sys.path[0], '../../../google_apis'))) import google_api_keys @@ -23,8 +25,6 @@ from pylib import constants PACKAGE = 'org.chromium.chrome' CLASSNAME = 'GoogleAPIKeys' -HERMETIC_TIMESTAMP = (2001, 1, 1, 0, 0, 0) -HERMETIC_FILE_ATTR = (0644 << 16L) def GetScriptName(): @@ -84,10 +84,8 @@ def _DoWriteJarOutput(output_path, constant_definition): os.makedirs(folder) with zipfile.ZipFile(output_path, 'w') as srcjar: path = '%s/%s' % (PACKAGE.replace('.', '/'), CLASSNAME + '.java') - zipinfo = zipfile.ZipInfo(filename=path, - date_time=HERMETIC_TIMESTAMP) - zipinfo.external_attr = HERMETIC_FILE_ATTR - srcjar.writestr(zipinfo, GenerateOutput(constant_definition)) + data = GenerateOutput(constant_definition) + build_utils.AddToZipHermetic(srcjar, path, data=data) def _DoMain(argv): diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py index 94935d2..a8eb7c4 100644 --- a/build/android/gyp/util/build_utils.py +++ b/build/android/gyp/util/build_utils.py @@ -27,8 +27,8 @@ COLORAMA_ROOT = os.path.join(constants.DIR_SOURCE_ROOT, # aapt should ignore OWNERS files in addition the default ignore pattern. AAPT_IGNORE_PATTERN = ('!OWNERS:!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:' + '!CVS:!thumbs.db:!picasa.ini:!*~:!*.d.stamp') -HERMETIC_TIMESTAMP = (2001, 1, 1, 0, 0, 0) -HERMETIC_FILE_ATTR = (0644 << 16L) +_HERMETIC_TIMESTAMP = (2001, 1, 1, 0, 0, 0) +_HERMETIC_FILE_ATTR = (0644 << 16L) @contextlib.contextmanager @@ -224,12 +224,39 @@ def ExtractAll(zip_path, path=None, no_clobber=True, pattern=None, z.extract(name, path) -def CreateHermeticZipInfo(zip_path): - """Creates a ZipInfo with a zero'ed out timestamp.""" +def AddToZipHermetic(zip_file, zip_path, src_path=None, data=None, + compress=None): + """Adds a file to the given ZipFile with a hard-coded modified time. + + Args: + zip_file: ZipFile instance to add the file to. + zip_path: Destination path within the zip file. + src_path: Path of the source file. Mutually exclusive with |data|. + data: File data as a string. + compress: Whether to enable compression. Default is take from ZipFile + constructor. + """ + assert (src_path is None) != (data is None), ( + '|src_path| and |data| are mutually exclusive.') CheckZipPath(zip_path) - zipinfo = zipfile.ZipInfo(filename=zip_path, date_time=HERMETIC_TIMESTAMP) - zipinfo.external_attr = HERMETIC_FILE_ATTR - return zipinfo + zipinfo = zipfile.ZipInfo(filename=zip_path, date_time=_HERMETIC_TIMESTAMP) + zipinfo.external_attr = _HERMETIC_FILE_ATTR + + if src_path: + with file(src_path) as f: + data = f.read() + + # zipfile will deflate even when it makes the file bigger. To avoid + # growing files, disable compression at an arbitrary cut off point. + if len(data) < 16: + compress = False + + # None converts to ZIP_STORED, when passed explicitly rather than the + # default passed to the ZipFile constructor. + args = [] + if compress is not None: + args.append(zipfile.ZIP_DEFLATED if compress else zipfile.ZIP_STORED) + zip_file.writestr(zipinfo, data, *args) def DoZip(inputs, output, base_dir=None): @@ -250,9 +277,7 @@ def DoZip(inputs, output, base_dir=None): input_tuples.sort(key=lambda tup: tup[0]) with zipfile.ZipFile(output, 'w') as outfile: for zip_path, fs_path in input_tuples: - with file(fs_path) as f: - contents = f.read() - outfile.writestr(CreateHermeticZipInfo(zip_path), contents) + AddToZipHermetic(outfile, zip_path, src_path=fs_path) def ZipDir(output, base_dir): @@ -283,7 +308,7 @@ def MergeZips(output, inputs, exclude_patterns=None, path_transform=None): dst_name = path_transform(name, in_file) already_added = dst_name in added_names if not already_added and not MatchesGlob(dst_name, exclude_patterns): - out_zip.writestr(CreateHermeticZipInfo(dst_name), in_zip.read(name)) + AddToZipHermetic(out_zip, dst_name, data=in_zip.read(name)) added_names.add(dst_name) |