blob: f81e64cc56878c79ae576c70f7505f99d5f7f629 [file] [log] [blame]
Ian Zerny37097652019-04-11 13:13:27 +02001#!/usr/bin/env python
2# Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
3# for details. All rights reserved. Use of this source code is governed by a
4# BSD-style license that can be found in the LICENSE file.
5
6# Run R8 on a simple Hello World program
7# Report Golem-compatible RunTimeRaw values:
8#
9# <NAME>-Total(RunTimeRaw): <time> ms
10#
11# where <NAME> is Hello{,Dex}{,Large}{,NoOpt}
12
13import argparse
14import os
15import subprocess
16import sys
17import time
18import zipfile
19
20import golem
21import jdk
Ian Zerny859dd892020-07-03 11:19:03 +020022import proguard
Ian Zerny37097652019-04-11 13:13:27 +020023import utils
24
25HELLO_JAR = os.path.join(utils.BUILD, 'test', 'examples', 'hello.jar')
26
27EXTRA_INPUTS = [
28 os.path.join(utils.THIRD_PARTY, 'sample_libraries', lib) for lib in [
29 'animal-sniffer-annotations-1.17.jar',
30 'annotations-13.0.jar',
31 'checker-compat-qual-2.5.2.jar',
32 'collections-28.0.0.jar',
33 'common-1.1.1.jar',
34 'commons-collections4-4.3.jar',
35 'commons-compress-1.18.jar',
36 'commons-lang3-3.8.1.jar',
37 'commons-math3-3.6.1.jar',
38 'constraint-layout-solver-1.1.3.jar',
39 'converter-gson-2.5.0.jar',
40 'dagger-2.22.1.jar',
41 'error_prone_annotations-2.2.0.jar',
42 'failureaccess-1.0.1.jar',
43 'gson-2.8.2.jar',
44 'guava-27.1-android.jar',
45 'j2objc-annotations-1.1.jar',
46 'javax.inject-1.jar',
47 'jsr305-3.0.2.jar',
48 'kotlin-stdlib-1.3.21.jar',
49 'kotlin-stdlib-common-1.3.21.jar',
50 'kotlin-stdlib-jdk7-1.3.21.jar',
51 'listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar',
52 'okhttp-3.14.0.jar',
53 'okio-1.17.2.jar',
54 'play-services-ads-17.2.0-javadoc.jar',
55 'play-services-ads-base-17.2.0-javadoc.jar',
56 'play-services-ads-lite-17.2.0-javadoc.jar',
57 'play-services-analytics-16.0.8-javadoc.jar',
58 'play-services-analytics-impl-16.0.8-javadoc.jar',
59 'play-services-base-16.1.0-javadoc.jar',
60 'play-services-basement-16.2.0-javadoc.jar',
61 'play-services-cast-16.1.2-javadoc.jar',
62 'play-services-drive-16.1.0-javadoc.jar',
63 'play-services-fitness-16.0.1-javadoc.jar',
64 'play-services-games-17.0.0-javadoc.jar',
65 'play-services-gass-17.2.0-javadoc.jar',
66 'play-services-gcm-16.1.0-javadoc.jar',
67 'play-services-iid-16.0.1-javadoc.jar',
68 'play-services-measurement-16.4.0-javadoc.jar',
69 'play-services-measurement-api-16.4.0-javadoc.jar',
70 'play-services-measurement-base-16.4.0-javadoc.jar',
71 'play-services-measurement-impl-16.4.0-javadoc.jar',
72 'play-services-measurement-sdk-16.4.0-javadoc.jar',
73 'play-services-measurement-sdk-api-16.4.0-javadoc.jar',
74 'play-services-tagmanager-v4-impl-16.0.8-javadoc.jar',
75 'play-services-vision-17.0.2-javadoc.jar',
76 'play-services-vision-common-17.0.2-javadoc.jar',
77 'protobuf-lite-3.0.1.jar',
78 'reactive-streams-1.0.2.jar',
79 'retrofit-2.5.0.jar',
80 'rxjava-2.2.8.jar',
81 'support-annotations-28.0.0.jar',
82 ]
83]
84
85EXTRA_KEEP_RULES = ['-dontwarn java.lang.ClassValue']
86
87def parse_arguments():
88 parser = argparse.ArgumentParser(
89 description = 'Compile a hello world example program')
90 parser.add_argument('--tool',
Ian Zerny859dd892020-07-03 11:19:03 +020091 choices = ['d8', 'r8'] + proguard.getVersions(),
Ian Zerny37097652019-04-11 13:13:27 +020092 required = True,
93 help = 'Compiler tool to use.')
94 parser.add_argument('--output-mode',
95 choices = ['dex', 'cf'],
96 required = True,
97 help = 'Output mode to compile to.')
98 parser.add_argument('--golem',
99 help = 'Running on golem, link in third_party resources.',
100 default = False,
101 action = 'store_true')
102 parser.add_argument('--large',
103 help = 'Add many additional program inputs.',
104 default = False,
105 action = 'store_true')
106 parser.add_argument('--noopt',
107 help = 'Disable most optimizations/processing.',
108 default = False,
109 action = 'store_true')
110 parser.add_argument('--print-memoryuse',
111 help = 'Prints the line \'<NAME>-Total(MemoryUse):'
112 ' <mem>\' at the end where <mem> is the peak'
113 ' peak resident set size (VmHWM) in bytes.',
114 default = False,
115 action = 'store_true')
116 parser.add_argument('--output',
117 help = 'Output directory to keep the generated files')
118 return parser.parse_args()
119
120def GetConfRules(extra, noopt):
121 rules = ['-keep class hello.Hello { void main(java.lang.String[]); }']
122 if len(extra) > 0:
123 rules.extend(EXTRA_KEEP_RULES)
124 if noopt:
125 rules.extend([
126 '-dontoptimize',
127 '-dontshrink',
128 '-dontobfuscate',
129 '-keepattributes *',
130 ])
131 return rules
132
133def GetCompilerPrefix(tool, mode, output, input, lib, extra, noopt):
134 return [
135 jdk.GetJavaExecutable(),
136 '-jar', utils.R8_JAR if tool == 'r8' else utils.D8_JAR,
137 '--output', output,
138 '--lib', lib,
139 '--debug' if noopt else '--release',
140 input,
141 ] + ([] if mode == 'cf' else ['--min-api', '21']) + extra
142
143def Compile(tool, output_mode, lib, extra, output_dir, noopt, temp_dir):
144 output = os.path.join(output_dir, 'out.zip')
145 if tool == 'd8':
146 if output_mode != 'dex':
147 raise ValueError('Invalid output mode for D8')
Ian Zerny92545362019-05-06 10:46:55 +0200148 classpath = []
149 for cp_entry in extra:
150 classpath.extend(['--classpath', cp_entry])
Ian Zerny37097652019-04-11 13:13:27 +0200151 return [
Ian Zerny92545362019-05-06 10:46:55 +0200152 GetCompilerPrefix(
153 tool, output_mode, output, HELLO_JAR, lib, classpath, noopt)
Ian Zerny37097652019-04-11 13:13:27 +0200154 ]
155 # The compilation is either R8 or PG.
156 # Write keep rules to a temporary file.
157 rules = GetConfRules(extra, noopt)
158 rules_file = os.path.join(temp_dir, 'rules.conf')
159 open(rules_file, 'w').write('\n'.join(rules))
160 if tool == 'r8':
161 cmd = GetCompilerPrefix(
162 tool, output_mode, output, HELLO_JAR, lib, extra, noopt)
163 cmd.extend(['--pg-conf', rules_file])
164 if output_mode == 'cf':
165 cmd.append('--classfile')
166 return [cmd]
Ian Zerny859dd892020-07-03 11:19:03 +0200167 if proguard.isValidVersion(tool):
Ian Zerny37097652019-04-11 13:13:27 +0200168 # Build PG invokation with additional rules to silence warnings.
169 pg_out = output if output_mode == 'cf' \
170 else os.path.join(output_dir, 'pgout.zip')
Ian Zerny859dd892020-07-03 11:19:03 +0200171 cmds = [proguard.getCmd([
Ian Zerny37097652019-04-11 13:13:27 +0200172 '-injars', ':'.join([HELLO_JAR] + extra),
173 '-libraryjars', lib,
174 '-outjars', pg_out,
175 '-dontwarn **',
176 '@' + rules_file
Ian Zerny859dd892020-07-03 11:19:03 +0200177 ], version=tool)]
Ian Zerny37097652019-04-11 13:13:27 +0200178 if output_mode == 'dex':
179 cmds.append(
180 GetCompilerPrefix('d8', 'dex', output, pg_out, lib, [], noopt))
181 return cmds
182 raise ValueError('Unknown tool: ' + tool)
183
184def ProcessInput(input, tmp_dir):
185 if not input.endswith('.aar'):
186 return input
187 out_dir = os.path.join(tmp_dir, input)
188 os.makedirs(out_dir)
189 zip = zipfile.ZipFile(input, 'r')
190 zip.extractall(out_dir)
191 zip.close()
192 return os.path.join(out_dir, 'classes.jar')
193
194def Main():
195 args = parse_arguments()
196 if args.golem:
197 golem.link_third_party()
198 utils.check_java_version()
199
200 with utils.TempDir() as temp_dir:
201 cmd_prefix = []
202 output_dir = args.output if args.output else temp_dir
203 temp_dir = os.path.join(args.output, 'tmp') if args.output else temp_dir
204
205 track_memory_file = None
206 if args.print_memoryuse:
207 track_memory_file = os.path.join(output_dir, utils.MEMORY_USE_TMP_FILE)
208 cmd_prefix.extend(['tools/track_memory.sh', track_memory_file])
209
Ian Zerny08ad2c32019-04-11 13:30:32 +0200210 name = 'CompileHelloExample'
Ian Zerny37097652019-04-11 13:13:27 +0200211
212 tool = args.tool
213 output_mode = args.output_mode
214 lib = None
215 if output_mode == 'dex':
216 name += 'Dex'
217 lib = utils.get_android_jar(28)
218 else:
219 lib = utils.RT_JAR
220
221 extra = []
222 if args.large:
223 name += 'Large'
224 extra = EXTRA_INPUTS
225
226 if args.noopt:
227 name += 'NoOpt'
228
229 cmds = Compile(
230 tool,
231 output_mode,
232 lib,
233 extra,
234 output_dir,
235 args.noopt,
236 temp_dir,
237 )
238
239 t0 = time.time()
240 for cmd in cmds:
241 fullcmd = cmd_prefix + cmd
242 utils.PrintCmd(fullcmd)
Ian Zerny678683a2019-05-07 11:28:23 +0200243 subprocess.check_output(fullcmd)
Ian Zerny37097652019-04-11 13:13:27 +0200244 dt = time.time() - t0
245
246 if args.print_memoryuse:
247 print('{}(MemoryUse): {}'
248 .format(name, utils.grep_memoryuse(track_memory_file)))
249
250 print('{}(RunTimeRaw): {} ms'
251 .format(name, 1000.0 * dt))
252
253if __name__ == '__main__':
254 sys.exit(Main())