Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright 2013 The Chromium Authors. All rights reserved. | 3 # Copyright 2013 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 import json | |
| 7 import logging | 8 import logging |
| 8 import optparse | 9 import optparse |
| 9 import os | 10 import os |
| 10 import sys | 11 import sys |
| 11 import tempfile | 12 import tempfile |
| 12 import zipfile | 13 import zipfile |
| 13 | 14 |
| 14 from util import build_utils | 15 from util import build_utils |
| 15 | 16 |
| 16 | 17 |
| 17 def _CreateCombinedMainDexList(main_dex_list_paths): | |
| 18 main_dex_list = [] | |
| 19 for m in main_dex_list_paths: | |
| 20 with open(m) as main_dex_list_file: | |
| 21 main_dex_list.extend(l for l in main_dex_list_file if l) | |
| 22 return '\n'.join(main_dex_list) | |
| 23 | |
| 24 | |
| 25 def _RemoveUnwantedFilesFromZip(dex_path): | 18 def _RemoveUnwantedFilesFromZip(dex_path): |
| 26 iz = zipfile.ZipFile(dex_path, 'r') | 19 iz = zipfile.ZipFile(dex_path, 'r') |
| 27 tmp_dex_path = '%s.tmp.zip' % dex_path | 20 tmp_dex_path = '%s.tmp.zip' % dex_path |
| 28 oz = zipfile.ZipFile(tmp_dex_path, 'w', zipfile.ZIP_DEFLATED) | 21 oz = zipfile.ZipFile(tmp_dex_path, 'w', zipfile.ZIP_DEFLATED) |
| 29 for i in iz.namelist(): | 22 for i in iz.namelist(): |
| 30 if i.endswith('.dex'): | 23 if i.endswith('.dex'): |
| 31 oz.writestr(i, iz.read(i)) | 24 oz.writestr(i, iz.read(i)) |
| 32 os.remove(dex_path) | 25 os.remove(dex_path) |
| 33 os.rename(tmp_dex_path, dex_path) | 26 os.rename(tmp_dex_path, dex_path) |
| 34 | 27 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 49 help='The build CONFIGURATION_NAME.') | 42 help='The build CONFIGURATION_NAME.') |
| 50 parser.add_option('--proguard-enabled', | 43 parser.add_option('--proguard-enabled', |
| 51 help='"true" if proguard is enabled.') | 44 help='"true" if proguard is enabled.') |
| 52 parser.add_option('--debug-build-proguard-enabled', | 45 parser.add_option('--debug-build-proguard-enabled', |
| 53 help='"true" if proguard is enabled for debug build.') | 46 help='"true" if proguard is enabled for debug build.') |
| 54 parser.add_option('--proguard-enabled-input-path', | 47 parser.add_option('--proguard-enabled-input-path', |
| 55 help=('Path to dex in Release mode when proguard ' | 48 help=('Path to dex in Release mode when proguard ' |
| 56 'is enabled.')) | 49 'is enabled.')) |
| 57 parser.add_option('--no-locals', | 50 parser.add_option('--no-locals', |
| 58 help='Exclude locals list from the dex file.') | 51 help='Exclude locals list from the dex file.') |
| 59 parser.add_option('--multi-dex', default=False, action='store_true', | |
| 60 help='Create multiple dex files.') | |
| 61 parser.add_option('--incremental', | 52 parser.add_option('--incremental', |
| 62 action='store_true', | 53 action='store_true', |
| 63 help='Enable incremental builds when possible.') | 54 help='Enable incremental builds when possible.') |
| 64 parser.add_option('--inputs', help='A list of additional input paths.') | 55 parser.add_option('--inputs', help='A list of additional input paths.') |
| 65 parser.add_option('--excluded-paths', | 56 parser.add_option('--excluded-paths', |
| 66 help='A list of paths to exclude from the dex file.') | 57 help='A list of paths to exclude from the dex file.') |
| 67 parser.add_option('--main-dex-list-paths', | 58 parser.add_option('--main-dex-list-path', |
| 68 help='A list of paths containing a list of the classes to ' | 59 help='A file containing a list of the classes to ' |
| 69 'include in the main dex.') | 60 'include in the main dex.') |
| 61 parser.add_option('--multidex-configuration-path', | |
| 62 help='A JSON file containing multidex build configuration.') | |
| 70 | 63 |
| 71 options, paths = parser.parse_args(args) | 64 options, paths = parser.parse_args(args) |
| 72 | 65 |
| 73 required_options = ('android_sdk_tools',) | 66 required_options = ('android_sdk_tools',) |
| 74 build_utils.CheckOptions(options, parser, required=required_options) | 67 build_utils.CheckOptions(options, parser, required=required_options) |
| 75 | 68 |
| 76 if options.multi_dex and not options.main_dex_list_paths: | 69 options.multi_dex = False |
| 77 logging.warning('--multi-dex is unused without --main-dex-list-paths') | 70 if options.multidex_configuration_path: |
| 71 with open(options.multidex_configuration_path) as multidex_config_file: | |
| 72 multidex_config = json.loads(multidex_config_file.read()) | |
| 73 options.multi_dex = multidex_config.get('enabled', False) | |
| 74 multidex_libs = multidex_config.get('libs', []) | |
| 75 else: | |
| 78 options.multi_dex = False | 76 options.multi_dex = False |
|
Yaron
2015/11/11 02:06:38
Redundant?
jbudorick
2015/11/12 20:33:40
It was. This logic got shuffled around once libs w
| |
| 79 elif options.main_dex_list_paths and not options.multi_dex: | |
| 80 logging.warning('--main-dex-list-paths is unused without --multi-dex') | |
| 81 | 77 |
| 82 if options.main_dex_list_paths: | 78 if options.multi_dex and not options.main_dex_list_path: |
| 83 options.main_dex_list_paths = build_utils.ParseGypList( | 79 logging.warning('multidex cannot be enabled without --main-dex-list-path') |
| 84 options.main_dex_list_paths) | 80 options.multi_dex = False |
| 81 elif options.main_dex_list_path and not options.multi_dex: | |
| 82 logging.warning('--main-dex-list-path is unused if multidex is not enabled') | |
| 83 elif options.multi_dex: | |
| 84 paths.extend(multidex_libs) | |
| 85 | |
| 85 if options.inputs: | 86 if options.inputs: |
| 86 options.inputs = build_utils.ParseGypList(options.inputs) | 87 options.inputs = build_utils.ParseGypList(options.inputs) |
| 87 if options.excluded_paths: | 88 if options.excluded_paths: |
| 88 options.excluded_paths = build_utils.ParseGypList(options.excluded_paths) | 89 options.excluded_paths = build_utils.ParseGypList(options.excluded_paths) |
| 89 | 90 |
| 90 return options, paths | 91 return options, paths |
| 91 | 92 |
| 92 | 93 |
| 93 def _AllSubpathsAreClassFiles(paths, changes): | 94 def _AllSubpathsAreClassFiles(paths, changes): |
| 94 for path in paths: | 95 for path in paths: |
| 95 if any(not p.endswith('.class') for p in changes.IterChangedSubpaths(path)): | 96 if any(not p.endswith('.class') for p in changes.IterChangedSubpaths(path)): |
| 96 return False | 97 return False |
| 97 return True | 98 return True |
| 98 | 99 |
| 99 | 100 |
| 100 def _RunDx(changes, options, dex_cmd, paths): | 101 def _RunDx(changes, options, dex_cmd, paths): |
| 101 with build_utils.TempDir() as classes_temp_dir: | 102 with build_utils.TempDir() as classes_temp_dir: |
| 102 # --multi-dex is incompatible with --incremental. | 103 # --multi-dex is incompatible with --incremental. |
| 103 if options.multi_dex: | 104 if options.multi_dex: |
| 104 combined_main_dex_list = tempfile.NamedTemporaryFile(suffix='.txt') | 105 dex_cmd.append('--main-dex-list=%s' % options.main_dex_list_path) |
| 105 combined_main_dex_list.write( | |
| 106 _CreateCombinedMainDexList(options.main_dex_list_paths)) | |
| 107 combined_main_dex_list.flush() | |
| 108 dex_cmd.append('--main-dex-list=%s' % combined_main_dex_list.name) | |
| 109 else: | 106 else: |
| 110 # Use --incremental when .class files are added or modified (never when | 107 # Use --incremental when .class files are added or modified (never when |
| 111 # removed). | 108 # removed). |
| 112 # --incremental tells dx to merge all newly dex'ed .class files with | 109 # --incremental tells dx to merge all newly dex'ed .class files with |
| 113 # what that already exist in the output dex file (existing classes are | 110 # what that already exist in the output dex file (existing classes are |
| 114 # replaced). | 111 # replaced). |
| 115 if options.incremental and changes.AddedOrModifiedOnly(): | 112 if options.incremental and changes.AddedOrModifiedOnly(): |
| 116 changed_inputs = set(changes.IterChangedPaths()) | 113 changed_inputs = set(changes.IterChangedPaths()) |
| 117 changed_paths = [p for p in paths if p in changed_inputs] | 114 changed_paths = [p for p in paths if p in changed_inputs] |
| 118 if not changed_paths: | 115 if not changed_paths: |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 dx_binary = os.path.join(options.android_sdk_tools, 'dx') | 163 dx_binary = os.path.join(options.android_sdk_tools, 'dx') |
| 167 # See http://crbug.com/272064 for context on --force-jumbo. | 164 # See http://crbug.com/272064 for context on --force-jumbo. |
| 168 # See https://github.com/android/platform_dalvik/commit/dd140a22d for | 165 # See https://github.com/android/platform_dalvik/commit/dd140a22d for |
| 169 # --num-threads. | 166 # --num-threads. |
| 170 dex_cmd = [dx_binary, '--num-threads=8', '--dex', '--force-jumbo', | 167 dex_cmd = [dx_binary, '--num-threads=8', '--dex', '--force-jumbo', |
| 171 '--output', options.dex_path] | 168 '--output', options.dex_path] |
| 172 if options.no_locals != '0': | 169 if options.no_locals != '0': |
| 173 dex_cmd.append('--no-locals') | 170 dex_cmd.append('--no-locals') |
| 174 | 171 |
| 175 if options.multi_dex: | 172 if options.multi_dex: |
| 176 input_paths.extend(options.main_dex_list_paths) | 173 input_paths.append(options.main_dex_list_path) |
| 177 dex_cmd += [ | 174 dex_cmd += [ |
| 178 '--multi-dex', | 175 '--multi-dex', |
| 179 '--minimal-main-dex', | 176 '--minimal-main-dex', |
| 180 ] | 177 ] |
| 181 | 178 |
| 182 output_paths = [ | 179 output_paths = [ |
| 183 options.dex_path, | 180 options.dex_path, |
| 184 options.dex_path + '.inputs', | 181 options.dex_path + '.inputs', |
| 185 ] | 182 ] |
| 186 | 183 |
| 187 # An escape hatch to be able to check if incremental dexing is causing | 184 # An escape hatch to be able to check if incremental dexing is causing |
| 188 # problems. | 185 # problems. |
| 189 force = int(os.environ.get('DISABLE_INCREMENTAL_DX', 0)) | 186 force = int(os.environ.get('DISABLE_INCREMENTAL_DX', 0)) |
| 190 | 187 |
| 191 build_utils.CallAndWriteDepfileIfStale( | 188 build_utils.CallAndWriteDepfileIfStale( |
| 192 lambda changes: _OnStaleMd5(changes, options, dex_cmd, paths), | 189 lambda changes: _OnStaleMd5(changes, options, dex_cmd, paths), |
| 193 options, | 190 options, |
| 194 input_paths=input_paths, | 191 input_paths=input_paths, |
| 195 input_strings=dex_cmd, | 192 input_strings=dex_cmd, |
| 196 output_paths=output_paths, | 193 output_paths=output_paths, |
| 197 force=force, | 194 force=force, |
| 198 pass_changes=True) | 195 pass_changes=True) |
| 199 | 196 |
| 200 | 197 |
| 201 if __name__ == '__main__': | 198 if __name__ == '__main__': |
| 202 sys.exit(main(sys.argv[1:])) | 199 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |