OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2015 The Chromium Authors. All rights reserved. | 3 # Copyright 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 import argparse | 7 import argparse |
8 import json | 8 import json |
9 import os | 9 import os |
10 import sys | 10 import sys |
11 import tempfile | 11 import tempfile |
12 | 12 |
13 from util import build_utils | 13 from util import build_utils |
14 | 14 |
15 sys.path.append(os.path.abspath(os.path.join( | 15 sys.path.append(os.path.abspath(os.path.join( |
16 os.path.dirname(__file__), os.pardir))) | 16 os.path.dirname(__file__), os.pardir))) |
17 from pylib import constants | 17 from pylib import constants |
18 | 18 |
19 | 19 |
20 def main(): | 20 def main(args): |
21 parser = argparse.ArgumentParser() | 21 parser = argparse.ArgumentParser() |
| 22 build_utils.AddDepfileOption(parser) |
22 parser.add_argument('--android-sdk-tools', required=True, | 23 parser.add_argument('--android-sdk-tools', required=True, |
23 help='Android sdk build tools directory.') | 24 help='Android sdk build tools directory.') |
24 parser.add_argument('--main-dex-rules-path', action='append', default=[], | 25 parser.add_argument('--main-dex-rules-path', action='append', default=[], |
25 dest='main_dex_rules_paths', | 26 dest='main_dex_rules_paths', |
26 help='A file containing a list of proguard rules to use ' | 27 help='A file containing a list of proguard rules to use ' |
27 'in determining the class to include in the ' | 28 'in determining the class to include in the ' |
28 'main dex.') | 29 'main dex.') |
29 parser.add_argument('--main-dex-list-path', required=True, | 30 parser.add_argument('--main-dex-list-path', required=True, |
30 help='The main dex list file to generate.') | 31 help='The main dex list file to generate.') |
31 parser.add_argument('--enabled-configurations', | 32 parser.add_argument('--enabled-configurations', |
32 help='The build configurations for which a main dex list' | 33 help='The build configurations for which a main dex list' |
33 ' should be generated.') | 34 ' should be generated.') |
34 parser.add_argument('--configuration-name', | 35 parser.add_argument('--configuration-name', |
35 help='The current build configuration.') | 36 help='The current build configuration.') |
36 parser.add_argument('--multidex-configuration-path', | 37 parser.add_argument('--multidex-configuration-path', |
37 help='A JSON file containing multidex build ' | 38 help='A JSON file containing multidex build ' |
38 'configuration.') | 39 'configuration.') |
39 parser.add_argument('paths', nargs='+', | 40 parser.add_argument('--inputs', |
| 41 help='JARs for which a main dex list should be ' |
| 42 'generated.') |
| 43 parser.add_argument('paths', nargs='*', default=[], |
40 help='JARs for which a main dex list should be ' | 44 help='JARs for which a main dex list should be ' |
41 'generated.') | 45 'generated.') |
42 | 46 |
43 args = parser.parse_args() | 47 args = parser.parse_args(build_utils.ExpandFileArgs(args)) |
44 | 48 |
45 if args.multidex_configuration_path: | 49 if args.multidex_configuration_path: |
46 with open(args.multidex_configuration_path) as multidex_config_file: | 50 with open(args.multidex_configuration_path) as multidex_config_file: |
47 multidex_config = json.loads(multidex_config_file.read()) | 51 multidex_config = json.loads(multidex_config_file.read()) |
48 | 52 |
49 if not multidex_config.get('enabled', False): | 53 if not multidex_config.get('enabled', False): |
50 return 0 | 54 return 0 |
51 | 55 |
52 with open(args.main_dex_list_path, 'w') as main_dex_list_file: | 56 if args.inputs: |
| 57 args.paths.extend(build_utils.ParseGypList(args.inputs)) |
53 | 58 |
54 shrinked_android_jar = os.path.abspath( | 59 shrinked_android_jar = os.path.abspath( |
55 os.path.join(args.android_sdk_tools, 'lib', 'shrinkedAndroid.jar')) | 60 os.path.join(args.android_sdk_tools, 'lib', 'shrinkedAndroid.jar')) |
56 dx_jar = os.path.abspath( | 61 dx_jar = os.path.abspath( |
57 os.path.join(args.android_sdk_tools, 'lib', 'dx.jar')) | 62 os.path.join(args.android_sdk_tools, 'lib', 'dx.jar')) |
58 paths_arg = ':'.join(args.paths) | 63 rules_file = os.path.abspath( |
59 rules_file = os.path.abspath( | 64 os.path.join(args.android_sdk_tools, 'mainDexClasses.rules')) |
60 os.path.join(args.android_sdk_tools, 'mainDexClasses.rules')) | |
61 | 65 |
62 with tempfile.NamedTemporaryFile(suffix='.jar') as temp_jar: | 66 proguard_cmd = [ |
63 proguard_cmd = [ | 67 constants.PROGUARD_SCRIPT_PATH, |
64 constants.PROGUARD_SCRIPT_PATH, | 68 '-forceprocessing', |
65 '-forceprocessing', | 69 '-dontwarn', '-dontoptimize', '-dontobfuscate', '-dontpreverify', |
66 '-dontwarn', '-dontoptimize', '-dontobfuscate', '-dontpreverify', | 70 '-libraryjars', shrinked_android_jar, |
67 '-injars', paths_arg, | 71 '-include', rules_file, |
68 '-outjars', temp_jar.name, | 72 ] |
69 '-libraryjars', shrinked_android_jar, | 73 for m in args.main_dex_rules_paths: |
70 '-include', rules_file, | 74 proguard_cmd.extend(['-include', m]) |
71 ] | |
72 for m in args.main_dex_rules_paths: | |
73 proguard_cmd.extend(['-include', m]) | |
74 | 75 |
75 main_dex_list = '' | 76 main_dex_list_cmd = [ |
76 try: | 77 'java', '-cp', dx_jar, |
77 build_utils.CheckOutput(proguard_cmd, print_stderr=False) | 78 'com.android.multidex.MainDexListBuilder', |
| 79 ] |
78 | 80 |
79 java_cmd = [ | 81 input_paths = list(args.paths) |
80 'java', '-cp', dx_jar, | 82 input_paths += [ |
81 'com.android.multidex.MainDexListBuilder', | 83 shrinked_android_jar, |
82 temp_jar.name, paths_arg | 84 dx_jar, |
83 ] | 85 rules_file, |
84 main_dex_list = build_utils.CheckOutput(java_cmd) | 86 ] |
85 except build_utils.CalledProcessError as e: | 87 input_paths += args.main_dex_rules_paths |
86 if 'output jar is empty' in e.output: | |
87 pass | |
88 elif "input doesn't contain any classes" in e.output: | |
89 pass | |
90 else: | |
91 raise | |
92 | 88 |
93 main_dex_list_file.write(main_dex_list) | 89 input_strings = [ |
| 90 proguard_cmd, |
| 91 main_dex_list_cmd, |
| 92 ] |
| 93 |
| 94 output_paths = [ |
| 95 args.main_dex_list_path, |
| 96 ] |
| 97 |
| 98 build_utils.CallAndWriteDepfileIfStale( |
| 99 lambda: _OnStaleMd5(proguard_cmd, main_dex_list_cmd, args.paths, |
| 100 args.main_dex_list_path), |
| 101 args, |
| 102 input_paths=input_paths, |
| 103 input_strings=input_strings, |
| 104 output_paths=output_paths) |
94 | 105 |
95 return 0 | 106 return 0 |
96 | 107 |
97 | 108 |
| 109 def _OnStaleMd5(proguard_cmd, main_dex_list_cmd, paths, main_dex_list_path): |
| 110 paths_arg = ':'.join(paths) |
| 111 main_dex_list = '' |
| 112 try: |
| 113 with tempfile.NamedTemporaryFile(suffix='.jar') as temp_jar: |
| 114 proguard_cmd += [ |
| 115 '-injars', paths_arg, |
| 116 '-outjars', temp_jar.name |
| 117 ] |
| 118 build_utils.CheckOutput(proguard_cmd, print_stderr=False) |
| 119 |
| 120 main_dex_list_cmd += [ |
| 121 temp_jar.name, paths_arg |
| 122 ] |
| 123 main_dex_list = build_utils.CheckOutput(main_dex_list_cmd) |
| 124 except build_utils.CalledProcessError as e: |
| 125 if 'output jar is empty' in e.output: |
| 126 pass |
| 127 elif "input doesn't contain any classes" in e.output: |
| 128 pass |
| 129 else: |
| 130 raise |
| 131 |
| 132 with open(main_dex_list_path, 'w') as main_dex_list_file: |
| 133 main_dex_list_file.write(main_dex_list) |
| 134 |
| 135 |
98 if __name__ == '__main__': | 136 if __name__ == '__main__': |
99 sys.exit(main()) | 137 sys.exit(main(sys.argv[1:])) |
100 | 138 |
OLD | NEW |