Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright (c) 2015 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """Adds the code parts to a resource APK.""" | 7 """Adds the code parts to a resource APK.""" |
| 8 | 8 |
| 9 import argparse | 9 import argparse |
| 10 import itertools | 10 import itertools |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 """Returns (src, dest) given an asset path in the form src[:dest].""" | 73 """Returns (src, dest) given an asset path in the form src[:dest].""" |
| 74 path_parts = path.split(':') | 74 path_parts = path.split(':') |
| 75 src_path = path_parts[0] | 75 src_path = path_parts[0] |
| 76 if len(path_parts) > 1: | 76 if len(path_parts) > 1: |
| 77 dest_path = path_parts[1] | 77 dest_path = path_parts[1] |
| 78 else: | 78 else: |
| 79 dest_path = os.path.basename(src_path) | 79 dest_path = os.path.basename(src_path) |
| 80 return src_path, dest_path | 80 return src_path, dest_path |
| 81 | 81 |
| 82 | 82 |
| 83 def _AddAssets(apk, paths, disable_compression=False): | 83 def _ExpandPaths(paths): |
| 84 """Converts src:dst into tuples and enumerates files within directories. | |
| 85 | |
| 86 Args: | |
| 87 paths: Paths in the form "src_path:dest_path" | |
| 88 | |
| 89 Returns: | |
| 90 A list of (src_path, dest_path) tuples sorted by dest_path (for stable | |
| 91 ordering within output .apk). | |
| 92 """ | |
| 93 ret = [] | |
| 94 for path in paths: | |
| 95 src_path, dest_path = _SplitAssetPath(path) | |
| 96 if os.path.isdir(src_path): | |
| 97 for f in build_utils.FindInDirectory(src_path, '*'): | |
| 98 ret.append((f, os.path.join(dest_path, f[len(src_path) + 1:]))) | |
|
pkotwicz
2015/11/17 19:34:25
I think that using os.path.basename() would be cle
agrieve
2015/11/21 01:47:26
It's not adding the past path component, but rathe
| |
| 99 else: | |
| 100 ret.append((src_path, dest_path)) | |
| 101 ret.sort(key=lambda t:t[1]) | |
| 102 return ret | |
| 103 | |
| 104 | |
| 105 def _AddAssets(apk, path_tuples, disable_compression=False): | |
| 84 """Adds the given paths to the apk. | 106 """Adds the given paths to the apk. |
| 85 | 107 |
| 86 Args: | 108 Args: |
| 87 apk: ZipFile to write to. | 109 apk: ZipFile to write to. |
| 88 paths: List of paths (with optional :zipPath suffix) to add. | 110 paths: List of paths (with optional :zipPath suffix) to add. |
| 89 disable_compression: Whether to disable compression. | 111 disable_compression: Whether to disable compression. |
| 90 """ | 112 """ |
| 91 # Group all uncompressed assets together in the hope that it will increase | 113 # Group all uncompressed assets together in the hope that it will increase |
| 92 # locality of mmap'ed files. | 114 # locality of mmap'ed files. |
| 93 for target_compress in (False, True): | 115 for target_compress in (False, True): |
| 94 for path in paths: | 116 for src_path, dest_path in path_tuples: |
| 95 src_path, dest_path = _SplitAssetPath(path) | |
| 96 | 117 |
| 97 compress = not disable_compression and ( | 118 compress = not disable_compression and ( |
| 98 os.path.splitext(src_path)[1] not in _NO_COMPRESS_EXTENSIONS) | 119 os.path.splitext(src_path)[1] not in _NO_COMPRESS_EXTENSIONS) |
| 99 if target_compress == compress: | 120 if target_compress == compress: |
| 100 apk_path = 'assets/' + dest_path | 121 apk_path = 'assets/' + dest_path |
| 101 try: | 122 try: |
| 102 apk.getinfo(apk_path) | 123 apk.getinfo(apk_path) |
| 103 # Should never happen since write_build_config.py handles merging. | 124 # Should never happen since write_build_config.py handles merging. |
| 104 raise Exception('Multiple targets specified the asset path: %s' % | 125 raise Exception('Multiple targets specified the asset path: %s' % |
| 105 apk_path) | 126 apk_path) |
| 106 except KeyError: | 127 except KeyError: |
| 107 build_utils.AddToZipHermetic(apk, apk_path, src_path=src_path, | 128 build_utils.AddToZipHermetic(apk, apk_path, src_path=src_path, |
| 108 compress=compress) | 129 compress=compress) |
| 109 | 130 |
| 110 | 131 |
| 111 def _CreateAssetsList(paths): | 132 def _CreateAssetsList(path_tuples): |
| 112 """Returns a newline-separated list of asset paths for the given paths.""" | 133 """Returns a newline-separated list of asset paths for the given paths.""" |
| 113 return '\n'.join(_SplitAssetPath(p)[1] for p in sorted(paths)) + '\n' | 134 dests = sorted(t[1] for t in path_tuples) |
| 135 return '\n'.join(dests) + '\n' | |
| 114 | 136 |
| 115 | 137 |
| 116 def main(args): | 138 def main(args): |
| 117 args = build_utils.ExpandFileArgs(args) | 139 args = build_utils.ExpandFileArgs(args) |
| 118 options = _ParseArgs(args) | 140 options = _ParseArgs(args) |
| 119 | 141 |
| 120 native_libs = [] | 142 native_libs = [] |
| 121 if options.native_libs_dir: | 143 if options.native_libs_dir: |
| 122 native_libs = _ListSubPaths(options.native_libs_dir) | 144 native_libs = _ListSubPaths(options.native_libs_dir) |
| 123 | 145 |
| 124 input_paths = [options.resource_apk, __file__] + native_libs | 146 input_paths = [options.resource_apk, __file__] + native_libs |
| 125 if options.dex_file: | 147 if options.dex_file: |
| 126 input_paths.append(options.dex_file) | 148 input_paths.append(options.dex_file) |
| 127 | 149 |
| 128 input_strings = [options.create_placeholder_lib, options.android_abi] | 150 input_strings = [options.create_placeholder_lib, options.android_abi] |
| 129 | 151 |
| 130 for path in itertools.chain(options.assets, options.uncompressed_assets): | 152 _assets = _ExpandPaths(options.assets) |
| 131 src_path, dest_path = _SplitAssetPath(path) | 153 _uncompressed_assets = _ExpandPaths(options.uncompressed_assets) |
| 154 | |
| 155 for src_path, dest_path in itertools.chain(_assets, _uncompressed_assets): | |
| 132 input_paths.append(src_path) | 156 input_paths.append(src_path) |
| 133 input_strings.append(dest_path) | 157 input_strings.append(dest_path) |
| 134 | 158 |
| 135 def on_stale_md5(): | 159 def on_stale_md5(): |
| 136 tmp_apk = options.output_apk + '.tmp' | 160 tmp_apk = options.output_apk + '.tmp' |
| 137 try: | 161 try: |
| 138 # Use a temp file to avoid creating an output if anything goes wrong. | 162 # Use a temp file to avoid creating an output if anything goes wrong. |
| 139 shutil.copyfile(options.resource_apk, tmp_apk) | 163 shutil.copyfile(options.resource_apk, tmp_apk) |
| 140 | 164 |
| 141 # TODO(agrieve): It would be more efficient to combine this step | 165 # TODO(agrieve): It would be more efficient to combine this step |
| 142 # with finalize_apk(), which sometimes aligns and uncompresses the | 166 # with finalize_apk(), which sometimes aligns and uncompresses the |
| 143 # native libraries. | 167 # native libraries. |
| 144 with zipfile.ZipFile(tmp_apk, 'a', zipfile.ZIP_DEFLATED) as apk: | 168 with zipfile.ZipFile(tmp_apk, 'a', zipfile.ZIP_DEFLATED) as apk: |
| 145 if options.write_asset_list: | 169 if options.write_asset_list: |
| 146 data = _CreateAssetsList( | 170 data = _CreateAssetsList( |
| 147 itertools.chain(options.assets, options.uncompressed_assets)) | 171 itertools.chain(_assets, _uncompressed_assets)) |
| 148 build_utils.AddToZipHermetic(apk, 'assets/assets_list', data=data) | 172 build_utils.AddToZipHermetic(apk, 'assets/assets_list', data=data) |
| 149 | 173 |
| 150 _AddAssets(apk, options.assets, disable_compression=False) | 174 _AddAssets(apk, _assets, disable_compression=False) |
| 151 _AddAssets(apk, options.uncompressed_assets, disable_compression=True) | 175 _AddAssets(apk, _uncompressed_assets, disable_compression=True) |
| 152 | 176 |
| 153 for path in native_libs: | 177 for path in native_libs: |
| 154 basename = os.path.basename(path) | 178 basename = os.path.basename(path) |
| 155 apk_path = 'lib/%s/%s' % (options.android_abi, basename) | 179 apk_path = 'lib/%s/%s' % (options.android_abi, basename) |
| 156 build_utils.AddToZipHermetic(apk, apk_path, src_path=path) | 180 build_utils.AddToZipHermetic(apk, apk_path, src_path=path) |
| 157 if options.create_placeholder_lib: | 181 if options.create_placeholder_lib: |
| 158 # Make it non-empty so that its checksum is non-zero and is not | 182 # Make it non-empty so that its checksum is non-zero and is not |
| 159 # ignored by md5_check. | 183 # ignored by md5_check. |
| 160 apk_path = 'lib/%s/libplaceholder.so' % options.android_abi | 184 apk_path = 'lib/%s/libplaceholder.so' % options.android_abi |
| 161 build_utils.AddToZipHermetic(apk, apk_path, data=':)') | 185 build_utils.AddToZipHermetic(apk, apk_path, data=':)') |
| 162 if options.dex_file: | 186 if options.dex_file: |
| 163 build_utils.AddToZipHermetic(apk, 'classes.dex', | 187 build_utils.AddToZipHermetic(apk, 'classes.dex', |
| 164 src_path=options.dex_file) | 188 src_path=options.dex_file) |
| 165 | 189 |
| 166 shutil.move(tmp_apk, options.output_apk) | 190 shutil.move(tmp_apk, options.output_apk) |
| 167 finally: | 191 finally: |
| 168 if os.path.exists(tmp_apk): | 192 if os.path.exists(tmp_apk): |
| 169 os.unlink(tmp_apk) | 193 os.unlink(tmp_apk) |
| 170 | 194 |
| 171 build_utils.CallAndWriteDepfileIfStale( | 195 build_utils.CallAndWriteDepfileIfStale( |
| 172 on_stale_md5, | 196 on_stale_md5, |
| 173 options, | 197 options, |
| 174 input_paths=input_paths, | 198 input_paths=input_paths, |
| 175 input_strings=input_strings, | 199 input_strings=input_strings, |
| 176 output_paths=[options.output_apk]) | 200 output_paths=[options.output_apk]) |
| 177 | 201 |
| 178 | 202 |
| 179 if __name__ == '__main__': | 203 if __name__ == '__main__': |
| 180 main(sys.argv[1:]) | 204 main(sys.argv[1:]) |
| OLD | NEW |