Index: build/android/gyp/dex.py |
diff --git a/build/android/gyp/dex.py b/build/android/gyp/dex.py |
index c26d23a61166627dba6c0acddd189301dd35c18a..8b1d75d83436975490de7fc553e782f9743ee3c1 100755 |
--- a/build/android/gyp/dex.py |
+++ b/build/android/gyp/dex.py |
@@ -4,33 +4,88 @@ |
# Use of this source code is governed by a BSD-style license that can be |
# found in the LICENSE file. |
+import itertools |
import optparse |
import os |
import sys |
+import tempfile |
+import zipfile |
from util import build_utils |
from util import md5_check |
+def _GenerateMainDexListFile(main_dex_list_file, paths, options): |
+ proguard_binary = os.path.abspath( |
+ os.path.join(options.android_sdk_tools, os.pardir, os.pardir, 'tools', |
+ 'proguard', 'bin', 'proguard.sh')) |
+ shrinked_android_jar = os.path.join( |
+ options.android_sdk_tools, 'lib', 'shrinkedAndroid.jar') |
+ dx_jar = os.path.join( |
+ options.android_sdk_tools, 'lib', 'dx.jar') |
+ paths_arg = ':'.join(paths) |
+ rules_file = os.path.abspath(os.path.join( |
+ options.android_sdk_tools, 'mainDexClasses.rules')) |
+ |
+ with tempfile.NamedTemporaryFile(suffix='.jar') as temp_jar: |
+ proguard_cmd = [ |
+ proguard_binary, |
+ '-forceprocessing', |
+ '-dontwarn', '-dontoptimize', '-dontobfuscate', '-dontpreverify', |
+ '-injars', paths_arg, |
+ '-outjars', temp_jar.name, |
+ '-libraryjars', shrinked_android_jar, |
+ '-include', rules_file, |
+ ] |
+ proguard_cmd += list(itertools.chain( |
+ ['-include', m] for m in options.main_dex_rules_files)) |
+ build_utils.CheckOutput(proguard_cmd) |
+ |
+ java_cmd = ['java', '-cp', dx_jar, |
+ 'com.android.multidex.MainDexListBuilder', |
+ temp_jar.name, paths_arg] |
+ main_dex_list = build_utils.CheckOutput(java_cmd) |
+ main_dex_list_file.write(main_dex_list) |
+ main_dex_list_file.flush() |
+ |
+ |
def DoDex(options, paths): |
dx_binary = os.path.join(options.android_sdk_tools, 'dx') |
# See http://crbug.com/272064 for context on --force-jumbo. |
- dex_cmd = [dx_binary, '--dex', '--force-jumbo', '--output', options.dex_path] |
+ dex_cmd = [dx_binary, '--dex', '--force-jumbo'] |
if options.no_locals != '0': |
dex_cmd.append('--no-locals') |
- |
- dex_cmd += paths |
- |
- record_path = '%s.md5.stamp' % options.dex_path |
- md5_check.CallAndRecordIfStale( |
- lambda: build_utils.CheckOutput(dex_cmd, print_stderr=False), |
- record_path=record_path, |
- input_paths=paths, |
- input_strings=dex_cmd, |
- force=not os.path.exists(options.dex_path)) |
- build_utils.WriteJson( |
- [os.path.relpath(p, options.output_directory) for p in paths], |
- options.dex_path + '.inputs') |
+ with tempfile.NamedTemporaryFile() as main_dex_list_file: |
+ if options.multi_dex: |
+ _GenerateMainDexListFile(main_dex_list_file, paths, options) |
+ |
+ dex_cmd.append('--multi-dex') |
+ dex_cmd.append('--minimal-main-dex') |
+ dex_cmd.append('--main-dex-list=%s' % main_dex_list_file.name) |
+ |
+ dex_cmd += ['--output', options.dex_path] |
+ dex_cmd += paths |
+ |
+ record_path = '%s.md5.stamp' % options.dex_path |
+ md5_check.CallAndRecordIfStale( |
+ lambda: build_utils.CheckOutput(dex_cmd, print_stderr=False), |
+ record_path=record_path, |
+ input_paths=paths, |
+ input_strings=dex_cmd, |
+ force=not os.path.exists(options.dex_path)) |
+ build_utils.WriteJson( |
+ [os.path.relpath(p, options.output_directory) for p in paths], |
+ options.dex_path + '.inputs') |
+ |
+ if options.multi_dex and options.dex_path.endswith('.zip'): |
+ iz = zipfile.ZipFile(options.dex_path, 'r') |
+ tmp_dex_path = '%s.tmp.zip' % options.dex_path |
+ oz = zipfile.ZipFile(tmp_dex_path, 'w', zipfile.ZIP_DEFLATED) |
+ for i in iz.namelist(): |
+ if i.endswith('.dex'): |
+ oz.writestr(i, iz.read(i)) |
+ os.remove(options.dex_path) |
+ os.rename(tmp_dex_path, options.dex_path) |
def main(): |
@@ -54,9 +109,18 @@ def main(): |
'is enabled.')) |
parser.add_option('--no-locals', |
help='Exclude locals list from the dex file.') |
+ parser.add_option('--multi-dex', default=False, action='store_true', |
+ help='Create multiple dex files.') |
parser.add_option('--inputs', help='A list of additional input paths.') |
parser.add_option('--excluded-paths', |
help='A list of paths to exclude from the dex file.') |
+ parser.add_option('--main-dex-rules-file', |
+ action='append', |
+ default=[], |
+ dest='main_dex_rules_files', |
+ help='A file containing a list of proguard rules to use ' |
+ 'in determining the classes to include in the ' |
+ 'main dex.') |
options, paths = parser.parse_args(args) |