| 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 """Returns (src, dest) given an asset path in the form src[:dest].""" | 78 """Returns (src, dest) given an asset path in the form src[:dest].""" |
| 79 path_parts = path.split(':') | 79 path_parts = path.split(':') |
| 80 src_path = path_parts[0] | 80 src_path = path_parts[0] |
| 81 if len(path_parts) > 1: | 81 if len(path_parts) > 1: |
| 82 dest_path = path_parts[1] | 82 dest_path = path_parts[1] |
| 83 else: | 83 else: |
| 84 dest_path = os.path.basename(src_path) | 84 dest_path = os.path.basename(src_path) |
| 85 return src_path, dest_path | 85 return src_path, dest_path |
| 86 | 86 |
| 87 | 87 |
| 88 def _AddAssets(apk, paths, disable_compression=False): | 88 def _ExpandPaths(paths): |
| 89 """Converts src:dst into tuples and enumerates files within directories. |
| 90 |
| 91 Args: |
| 92 paths: Paths in the form "src_path:dest_path" |
| 93 |
| 94 Returns: |
| 95 A list of (src_path, dest_path) tuples sorted by dest_path (for stable |
| 96 ordering within output .apk). |
| 97 """ |
| 98 ret = [] |
| 99 for path in paths: |
| 100 src_path, dest_path = _SplitAssetPath(path) |
| 101 if os.path.isdir(src_path): |
| 102 for f in build_utils.FindInDirectory(src_path, '*'): |
| 103 ret.append((f, os.path.join(dest_path, f[len(src_path) + 1:]))) |
| 104 else: |
| 105 ret.append((src_path, dest_path)) |
| 106 ret.sort(key=lambda t:t[1]) |
| 107 return ret |
| 108 |
| 109 |
| 110 def _AddAssets(apk, path_tuples, disable_compression=False): |
| 89 """Adds the given paths to the apk. | 111 """Adds the given paths to the apk. |
| 90 | 112 |
| 91 Args: | 113 Args: |
| 92 apk: ZipFile to write to. | 114 apk: ZipFile to write to. |
| 93 paths: List of paths (with optional :zipPath suffix) to add. | 115 paths: List of paths (with optional :zipPath suffix) to add. |
| 94 disable_compression: Whether to disable compression. | 116 disable_compression: Whether to disable compression. |
| 95 """ | 117 """ |
| 96 # Group all uncompressed assets together in the hope that it will increase | 118 # Group all uncompressed assets together in the hope that it will increase |
| 97 # locality of mmap'ed files. | 119 # locality of mmap'ed files. |
| 98 for target_compress in (False, True): | 120 for target_compress in (False, True): |
| 99 for path in paths: | 121 for src_path, dest_path in path_tuples: |
| 100 src_path, dest_path = _SplitAssetPath(path) | |
| 101 | 122 |
| 102 compress = not disable_compression and ( | 123 compress = not disable_compression and ( |
| 103 os.path.splitext(src_path)[1] not in _NO_COMPRESS_EXTENSIONS) | 124 os.path.splitext(src_path)[1] not in _NO_COMPRESS_EXTENSIONS) |
| 104 if target_compress == compress: | 125 if target_compress == compress: |
| 105 apk_path = 'assets/' + dest_path | 126 apk_path = 'assets/' + dest_path |
| 106 try: | 127 try: |
| 107 apk.getinfo(apk_path) | 128 apk.getinfo(apk_path) |
| 108 # Should never happen since write_build_config.py handles merging. | 129 # Should never happen since write_build_config.py handles merging. |
| 109 raise Exception('Multiple targets specified the asset path: %s' % | 130 raise Exception('Multiple targets specified the asset path: %s' % |
| 110 apk_path) | 131 apk_path) |
| 111 except KeyError: | 132 except KeyError: |
| 112 build_utils.AddToZipHermetic(apk, apk_path, src_path=src_path, | 133 build_utils.AddToZipHermetic(apk, apk_path, src_path=src_path, |
| 113 compress=compress) | 134 compress=compress) |
| 114 | 135 |
| 115 | 136 |
| 116 def _CreateAssetsList(paths): | 137 def _CreateAssetsList(path_tuples): |
| 117 """Returns a newline-separated list of asset paths for the given paths.""" | 138 """Returns a newline-separated list of asset paths for the given paths.""" |
| 118 return '\n'.join(_SplitAssetPath(p)[1] for p in sorted(paths)) + '\n' | 139 dests = sorted(t[1] for t in path_tuples) |
| 140 return '\n'.join(dests) + '\n' |
| 119 | 141 |
| 120 | 142 |
| 121 def main(args): | 143 def main(args): |
| 122 args = build_utils.ExpandFileArgs(args) | 144 args = build_utils.ExpandFileArgs(args) |
| 123 options = _ParseArgs(args) | 145 options = _ParseArgs(args) |
| 124 | 146 |
| 125 native_libs = sorted(options.native_libs) | 147 native_libs = sorted(options.native_libs) |
| 126 | 148 |
| 127 input_paths = [options.resource_apk, __file__] + native_libs | 149 input_paths = [options.resource_apk, __file__] + native_libs |
| 128 if options.dex_file: | 150 if options.dex_file: |
| 129 input_paths.append(options.dex_file) | 151 input_paths.append(options.dex_file) |
| 130 | 152 |
| 131 if options.emma_device_jar: | 153 if options.emma_device_jar: |
| 132 input_paths.append(options.emma_device_jar) | 154 input_paths.append(options.emma_device_jar) |
| 133 | 155 |
| 134 input_strings = [options.android_abi, options.native_lib_placeholders] | 156 input_strings = [options.android_abi, options.native_lib_placeholders] |
| 135 | 157 |
| 136 for path in itertools.chain(options.assets, options.uncompressed_assets): | 158 _assets = _ExpandPaths(options.assets) |
| 137 src_path, dest_path = _SplitAssetPath(path) | 159 _uncompressed_assets = _ExpandPaths(options.uncompressed_assets) |
| 160 |
| 161 for src_path, dest_path in itertools.chain(_assets, _uncompressed_assets): |
| 138 input_paths.append(src_path) | 162 input_paths.append(src_path) |
| 139 input_strings.append(dest_path) | 163 input_strings.append(dest_path) |
| 140 | 164 |
| 141 def on_stale_md5(): | 165 def on_stale_md5(): |
| 142 tmp_apk = options.output_apk + '.tmp' | 166 tmp_apk = options.output_apk + '.tmp' |
| 143 try: | 167 try: |
| 144 # TODO(agrieve): It would be more efficient to combine this step | 168 # TODO(agrieve): It would be more efficient to combine this step |
| 145 # with finalize_apk(), which sometimes aligns and uncompresses the | 169 # with finalize_apk(), which sometimes aligns and uncompresses the |
| 146 # native libraries. | 170 # native libraries. |
| 147 with zipfile.ZipFile(options.resource_apk) as resource_apk, \ | 171 with zipfile.ZipFile(options.resource_apk) as resource_apk, \ |
| 148 zipfile.ZipFile(tmp_apk, 'w', zipfile.ZIP_DEFLATED) as out_apk: | 172 zipfile.ZipFile(tmp_apk, 'w', zipfile.ZIP_DEFLATED) as out_apk: |
| 149 def copy_resource(zipinfo): | 173 def copy_resource(zipinfo): |
| 150 compress = zipinfo.compress_type != zipfile.ZIP_STORED | 174 compress = zipinfo.compress_type != zipfile.ZIP_STORED |
| 151 build_utils.AddToZipHermetic(out_apk, zipinfo.filename, | 175 build_utils.AddToZipHermetic(out_apk, zipinfo.filename, |
| 152 data=resource_apk.read(zipinfo.filename), | 176 data=resource_apk.read(zipinfo.filename), |
| 153 compress=compress) | 177 compress=compress) |
| 154 | 178 |
| 155 # Make assets come before resources in order to maintain the same file | 179 # Make assets come before resources in order to maintain the same file |
| 156 # ordering as GYP / aapt. http://crbug.com/561862 | 180 # ordering as GYP / aapt. http://crbug.com/561862 |
| 157 resource_infos = resource_apk.infolist() | 181 resource_infos = resource_apk.infolist() |
| 158 | 182 |
| 159 # 1. AndroidManifest.xml | 183 # 1. AndroidManifest.xml |
| 160 assert resource_infos[0].filename == 'AndroidManifest.xml' | 184 assert resource_infos[0].filename == 'AndroidManifest.xml' |
| 161 copy_resource(resource_infos[0]) | 185 copy_resource(resource_infos[0]) |
| 162 | 186 |
| 163 # 2. Assets | 187 # 2. Assets |
| 164 if options.write_asset_list: | 188 if options.write_asset_list: |
| 165 data = _CreateAssetsList( | 189 data = _CreateAssetsList( |
| 166 itertools.chain(options.assets, options.uncompressed_assets)) | 190 itertools.chain(_assets, _uncompressed_assets)) |
| 167 build_utils.AddToZipHermetic(out_apk, 'assets/assets_list', data=data) | 191 build_utils.AddToZipHermetic(out_apk, 'assets/assets_list', data=data) |
| 168 | 192 |
| 169 _AddAssets(out_apk, options.assets, disable_compression=False) | 193 _AddAssets(out_apk, _assets, disable_compression=False) |
| 170 _AddAssets(out_apk, options.uncompressed_assets, | 194 _AddAssets(out_apk, _uncompressed_assets, disable_compression=True) |
| 171 disable_compression=True) | |
| 172 | 195 |
| 173 # 3. Resources | 196 # 3. Resources |
| 174 for info in resource_infos[1:]: | 197 for info in resource_infos[1:]: |
| 175 copy_resource(info) | 198 copy_resource(info) |
| 176 | 199 |
| 177 # 4. Dex files | 200 # 4. Dex files |
| 178 if options.dex_file and options.dex_file.endswith('.zip'): | 201 if options.dex_file and options.dex_file.endswith('.zip'): |
| 179 with zipfile.ZipFile(options.dex_file, 'r') as dex_zip: | 202 with zipfile.ZipFile(options.dex_file, 'r') as dex_zip: |
| 180 for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')): | 203 for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')): |
| 181 build_utils.AddToZipHermetic(out_apk, dex, data=dex_zip.read(dex)) | 204 build_utils.AddToZipHermetic(out_apk, dex, data=dex_zip.read(dex)) |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 build_utils.CallAndWriteDepfileIfStale( | 245 build_utils.CallAndWriteDepfileIfStale( |
| 223 on_stale_md5, | 246 on_stale_md5, |
| 224 options, | 247 options, |
| 225 input_paths=input_paths, | 248 input_paths=input_paths, |
| 226 input_strings=input_strings, | 249 input_strings=input_strings, |
| 227 output_paths=[options.output_apk]) | 250 output_paths=[options.output_apk]) |
| 228 | 251 |
| 229 | 252 |
| 230 if __name__ == '__main__': | 253 if __name__ == '__main__': |
| 231 main(sys.argv[1:]) | 254 main(sys.argv[1:]) |
| OLD | NEW |