| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """ Merges a 64-bit and a 32-bit APK into a single APK | 6 """ Merges a 64-bit and a 32-bit APK into a single APK |
| 7 | 7 |
| 8 This script is used to merge two APKs which have only 32-bit or 64-bit | 8 This script is used to merge two APKs which have only 32-bit or 64-bit |
| 9 binaries respectively into a APK that has both 32-bit and 64-bit binaries | 9 binaries respectively into a APK that has both 32-bit and 64-bit binaries |
| 10 for 64-bit Android platform. | 10 for 64-bit Android platform. |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 ' unexpected files: %s' % pprint.pformat(unexpected_file_set)) | 112 ' unexpected files: %s' % pprint.pformat(unexpected_file_set)) |
| 113 if missing_file_set: | 113 if missing_file_set: |
| 114 errors.append(' missing files: %s' % pprint.pformat(missing_file_set)) | 114 errors.append(' missing files: %s' % pprint.pformat(missing_file_set)) |
| 115 if duplicate_file_set: | 115 if duplicate_file_set: |
| 116 errors.append(' duplicate files: %s' % pprint.pformat(duplicate_file_set)) | 116 errors.append(' duplicate files: %s' % pprint.pformat(duplicate_file_set)) |
| 117 | 117 |
| 118 if errors: | 118 if errors: |
| 119 raise ApkMergeFailure( | 119 raise ApkMergeFailure( |
| 120 "Files don't match expectations:\n%s" % '\n'.join(errors)) | 120 "Files don't match expectations:\n%s" % '\n'.join(errors)) |
| 121 | 121 |
| 122 def AddDiffFiles(diff_files, tmp_dir_32, tmp_apk, expected_files, | 122 |
| 123 def AddDiffFiles(diff_files, tmp_dir_32, out_zip, expected_files, |
| 123 component_build, uncompress_shared_libraries): | 124 component_build, uncompress_shared_libraries): |
| 124 """ Insert files only present in 32-bit APK into 64-bit APK (tmp_apk). """ | 125 """ Insert files only present in 32-bit APK into 64-bit APK (tmp_apk). """ |
| 125 old_dir = os.getcwd() | 126 for diff_file in diff_files: |
| 126 # Move into 32-bit directory to make sure the files we insert have correct | 127 if component_build and diff_file.endswith('.so'): |
| 127 # relative paths. | 128 compress = not uncompress_shared_libraries |
| 128 os.chdir(tmp_dir_32) | 129 else: |
| 129 try: | 130 compress = expected_files[os.path.basename(diff_file)] |
| 130 for diff_file in diff_files: | 131 build_utils.AddToZipHermetic(out_zip, |
| 131 if component_build and diff_file.endswith('.so'): | 132 diff_file, |
| 132 extra_flags = [] | 133 os.path.join(tmp_dir_32, diff_file), |
| 133 if uncompress_shared_libraries: | 134 compress=compress) |
| 134 extra_flags = ['-0'] | |
| 135 else: | |
| 136 extra_flags = expected_files[os.path.basename(diff_file)] | |
| 137 build_utils.CheckOutput( | |
| 138 [ | |
| 139 'zip', '-r', '-X', '--no-dir-entries', tmp_apk, diff_file | |
| 140 ] + extra_flags) | |
| 141 except build_utils.CalledProcessError as e: | |
| 142 raise ApkMergeFailure( | |
| 143 'Failed to add file %s to APK: %s' % (diff_file, e.output)) | |
| 144 finally: | |
| 145 # Move out of 32-bit directory when done | |
| 146 os.chdir(old_dir) | |
| 147 | |
| 148 | |
| 149 def RemoveMetafiles(tmp_apk): | |
| 150 """ Remove all meta info to avoid certificate clashes """ | |
| 151 try: | |
| 152 build_utils.CheckOutput(['zip', '-d', tmp_apk, 'META-INF/*']) | |
| 153 except build_utils.CalledProcessError as e: | |
| 154 raise ApkMergeFailure('Failed to delete Meta folder: ' + e.output) | |
| 155 | 135 |
| 156 | 136 |
| 157 def SignAndAlignApk(tmp_apk, signed_tmp_apk, new_apk, zipalign_path, | 137 def SignAndAlignApk(tmp_apk, signed_tmp_apk, new_apk, zipalign_path, |
| 158 keystore_path, key_name, key_password, | 138 keystore_path, key_name, key_password, |
| 159 page_align_shared_libraries): | 139 page_align_shared_libraries): |
| 160 try: | 140 try: |
| 161 finalize_apk.JarSigner( | 141 finalize_apk.JarSigner( |
| 162 keystore_path, | 142 keystore_path, |
| 163 key_name, | 143 key_name, |
| 164 key_password, | 144 key_password, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 187 ret = 'mips64' | 167 ret = 'mips64' |
| 188 elif abi == 'x86': | 168 elif abi == 'x86': |
| 189 ret = 'x86_64' | 169 ret = 'x86_64' |
| 190 else: | 170 else: |
| 191 raise ApkMergeFailure('Unsupported abi ' + abi) | 171 raise ApkMergeFailure('Unsupported abi ' + abi) |
| 192 if ret == '': | 172 if ret == '': |
| 193 raise ApkMergeFailure('Failed to find secondary abi') | 173 raise ApkMergeFailure('Failed to find secondary abi') |
| 194 return ret | 174 return ret |
| 195 | 175 |
| 196 def MergeApk(args, tmp_apk, tmp_dir_32, tmp_dir_64): | 176 def MergeApk(args, tmp_apk, tmp_dir_32, tmp_dir_64): |
| 197 # Expected files to copy from 32- to 64-bit APK together with an extra flag | 177 # Expected files to copy from 32- to 64-bit APK together with whether to |
| 198 # setting the compression level of the file | 178 # compress within the .apk. |
| 199 expected_files = {'snapshot_blob_32.bin': ['-0']} | 179 expected_files = {'snapshot_blob_32.bin': False} |
| 200 if args.shared_library: | 180 if args.shared_library: |
| 201 expected_files[args.shared_library] = [] | 181 expected_files[args.shared_library] = not args.uncompress_shared_libraries |
| 202 | |
| 203 if args.debug: | 182 if args.debug: |
| 204 expected_files['gdbserver'] = [] | 183 expected_files['gdbserver'] = True |
| 205 if args.uncompress_shared_libraries and args.shared_library: | |
| 206 expected_files[args.shared_library] += ['-0'] | |
| 207 | |
| 208 shutil.copyfile(args.apk_64bit, tmp_apk) | |
| 209 | 184 |
| 210 # need to unpack APKs to compare their contents | 185 # need to unpack APKs to compare their contents |
| 211 UnpackApk(args.apk_64bit, tmp_dir_64) | 186 UnpackApk(args.apk_64bit, tmp_dir_64) |
| 212 UnpackApk(args.apk_32bit, tmp_dir_32) | 187 UnpackApk(args.apk_32bit, tmp_dir_32) |
| 213 | 188 |
| 214 ignores = ['META-INF', 'AndroidManifest.xml'] | 189 ignores = ['META-INF', 'AndroidManifest.xml'] |
| 215 if args.ignore_classes_dex: | 190 if args.ignore_classes_dex: |
| 216 ignores += ['classes.dex', 'classes2.dex'] | 191 ignores += ['classes.dex', 'classes2.dex'] |
| 217 if args.debug: | 192 if args.debug: |
| 218 # see http://crbug.com/648720 | 193 # see http://crbug.com/648720 |
| 219 ignores += ['webview_licenses.notice'] | 194 ignores += ['webview_licenses.notice'] |
| 220 | 195 |
| 221 dcmp = filecmp.dircmp( | 196 dcmp = filecmp.dircmp( |
| 222 tmp_dir_64, | 197 tmp_dir_64, |
| 223 tmp_dir_32, | 198 tmp_dir_32, |
| 224 ignore=ignores) | 199 ignore=ignores) |
| 225 | 200 |
| 226 diff_files = GetDiffFiles(dcmp, tmp_dir_32) | 201 diff_files = GetDiffFiles(dcmp, tmp_dir_32) |
| 227 | 202 |
| 228 # Check that diff_files match exactly those files we want to insert into | 203 # Check that diff_files match exactly those files we want to insert into |
| 229 # the 64-bit APK. | 204 # the 64-bit APK. |
| 230 CheckFilesExpected(diff_files, expected_files, args.component_build) | 205 CheckFilesExpected(diff_files, expected_files, args.component_build) |
| 231 | 206 |
| 232 RemoveMetafiles(tmp_apk) | 207 with zipfile.ZipFile(tmp_apk, 'w') as out_zip: |
| 233 | 208 build_utils.MergeZips(out_zip, [args.apk_64bit], |
| 234 AddDiffFiles(diff_files, tmp_dir_32, tmp_apk, expected_files, | 209 exclude_patterns=['META-INF/*']) |
| 235 args.component_build, args.uncompress_shared_libraries) | 210 AddDiffFiles(diff_files, tmp_dir_32, out_zip, expected_files, |
| 211 args.component_build, args.uncompress_shared_libraries) |
| 236 | 212 |
| 237 | 213 |
| 238 def main(): | 214 def main(): |
| 239 parser = argparse.ArgumentParser( | 215 parser = argparse.ArgumentParser( |
| 240 description='Merge a 32-bit APK into a 64-bit APK') | 216 description='Merge a 32-bit APK into a 64-bit APK') |
| 241 # Using type=os.path.abspath converts file paths to absolute paths so that | 217 # Using type=os.path.abspath converts file paths to absolute paths so that |
| 242 # we can change working directory without affecting these paths | 218 # we can change working directory without affecting these paths |
| 243 parser.add_argument('--apk_32bit', required=True, type=os.path.abspath) | 219 parser.add_argument('--apk_32bit', required=True, type=os.path.abspath) |
| 244 parser.add_argument('--apk_64bit', required=True, type=os.path.abspath) | 220 parser.add_argument('--apk_64bit', required=True, type=os.path.abspath) |
| 245 parser.add_argument('--out_apk', required=True, type=os.path.abspath) | 221 parser.add_argument('--out_apk', required=True, type=os.path.abspath) |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 except ApkMergeFailure as e: | 256 except ApkMergeFailure as e: |
| 281 print e | 257 print e |
| 282 return 1 | 258 return 1 |
| 283 finally: | 259 finally: |
| 284 shutil.rmtree(tmp_dir) | 260 shutil.rmtree(tmp_dir) |
| 285 return 0 | 261 return 0 |
| 286 | 262 |
| 287 | 263 |
| 288 if __name__ == '__main__': | 264 if __name__ == '__main__': |
| 289 sys.exit(main()) | 265 sys.exit(main()) |
| OLD | NEW |