blob: a0542d4d22230e894b382557fe0ac24ca4991cf7 [file] [log] [blame]
Morten Krogh-Jespersen45abed92021-01-18 22:07:41 +01001#!/usr/bin/env python3
Mads Ager418d1ca2017-05-22 09:35:49 +02002# Copyright (c) 2017, 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
Tamas Kenezfc34cd82017-07-13 12:43:57 +02006from __future__ import print_function
Tamas Kenez02bff032017-07-18 12:13:58 +02007from glob import glob
Rico Windb57bbc12018-09-20 19:23:32 +02008import copy
Mads Ager418d1ca2017-05-22 09:35:49 +02009import optparse
10import os
Søren Gjesse80e00482021-04-06 13:17:35 +020011import shutil
Mads Ager418d1ca2017-05-22 09:35:49 +020012import sys
Tamas Kenezf2ee2a32017-06-21 10:30:20 +020013import time
Mads Ager418d1ca2017-05-22 09:35:49 +020014
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +010015import archive
Morten Krogh-Jespersen89e19012021-10-05 09:55:01 +020016import gradle
Søren Gjesse5ecb04a2017-06-13 09:44:32 +020017import gmail_data
Ian Zerny877c1862017-07-06 11:12:26 +020018import gmscore_data
Christoffer Quist Adamsena2a58772018-10-03 09:47:46 +020019import nest_data
Søren Gjesse889e09d2019-11-07 16:33:51 +010020from sanitize_libraries import SanitizeLibraries, SanitizeLibrariesInPgconf
Mathias Ravdd6a6de2018-05-18 10:18:33 +020021import toolhelper
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +010022import update_prebuilds_in_android
Ian Zerny877c1862017-07-06 11:12:26 +020023import utils
24import youtube_data
Rico Wind86bfc832018-09-18 07:48:21 +020025import chrome_data
Morten Krogh-Jespersen04c7c302019-10-01 15:04:33 +020026import r8_data
Morten Krogh-Jespersencd6712c2019-10-09 13:09:47 +020027import iosched_data
Mads Ager418d1ca2017-05-22 09:35:49 +020028
29TYPES = ['dex', 'deploy', 'proguarded']
Morten Krogh-Jespersen1ba55f52020-04-24 12:49:17 +020030APPS = [
Rico Windf35d1fa2021-09-10 12:50:15 +020031 'gmscore', 'nest', 'youtube', 'gmail', 'chrome', 'r8', 'iosched']
Tamas Kenez63a51d02019-01-07 15:53:02 +010032COMPILERS = ['d8', 'r8']
33COMPILER_BUILDS = ['full', 'lib']
34
Rico Wind5fdec152018-12-17 09:16:14 +010035# We use this magic exit code to signal that the program OOM'ed
36OOM_EXIT_CODE = 42
Jinseong Jeon158a3f12019-02-08 01:40:59 -080037# According to Popen.returncode doc:
38# A negative value -N indicates that the child was terminated by signal N.
39TIMEOUT_KILL_CODE = -9
Mads Ager418d1ca2017-05-22 09:35:49 +020040
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +020041# Log file names
42FIND_MIN_XMX_FILE = 'find_min_xmx_results'
43FIND_MIN_XMX_DIR = 'find_min_xmx'
44
Tamas Kenez5b1c5852017-07-21 13:38:33 +020045def ParseOptions(argv):
Mads Ager418d1ca2017-05-22 09:35:49 +020046 result = optparse.OptionParser()
Søren Gjesse932881f2017-06-13 10:43:36 +020047 result.add_option('--compiler',
Rico Windb57bbc12018-09-20 19:23:32 +020048 help='The compiler to use',
Tamas Kenez5b1c5852017-07-21 13:38:33 +020049 choices=COMPILERS)
Tamas Kenez63a51d02019-01-07 15:53:02 +010050 result.add_option('--compiler-build',
51 help='Compiler build to use',
52 choices=COMPILER_BUILDS,
53 default='lib')
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +010054 result.add_option('--hash',
55 help='The version of D8/R8 to use')
Mads Ager418d1ca2017-05-22 09:35:49 +020056 result.add_option('--app',
Rico Windb57bbc12018-09-20 19:23:32 +020057 help='What app to run on',
Mads Ager418d1ca2017-05-22 09:35:49 +020058 choices=APPS)
Rico Windb57bbc12018-09-20 19:23:32 +020059 result.add_option('--run-all',
60 help='Compile all possible combinations',
61 default=False,
62 action='store_true')
Morten Krogh-Jespersenb7e1a182019-10-09 13:04:54 +020063 result.add_option('--expect-oom',
64 help='Expect that compilation will fail with an OOM',
65 default=False,
66 action='store_true')
Mads Ager418d1ca2017-05-22 09:35:49 +020067 result.add_option('--type',
Tamas Kenez3fdaabd2017-06-15 13:05:12 +020068 help='Default for R8: deploy, for D8: proguarded',
Mads Ager418d1ca2017-05-22 09:35:49 +020069 choices=TYPES)
70 result.add_option('--out',
Rico Windb57bbc12018-09-20 19:23:32 +020071 help='Where to place the output',
Rico Winde9485ba2018-10-01 07:04:16 +020072 default=utils.BUILD)
Mads Ager418d1ca2017-05-22 09:35:49 +020073 result.add_option('--no-build',
Rico Windb57bbc12018-09-20 19:23:32 +020074 help='Run without building first',
Mads Ager418d1ca2017-05-22 09:35:49 +020075 default=False,
76 action='store_true')
Morten Krogh-Jespersen322c2f12019-10-08 10:41:21 +020077 result.add_option('--max-memory',
78 help='The maximum memory in MB to run with',
79 type='int')
Rico Wind5fdec152018-12-17 09:16:14 +010080 result.add_option('--find-min-xmx',
81 help='Find the minimum amount of memory we can run in',
82 default=False,
83 action='store_true')
Morten Krogh-Jespersen04c7c302019-10-01 15:04:33 +020084 result.add_option('--find-min-xmx-min-memory',
85 help='Setting the minimum memory baseline to run in',
86 type='int')
87 result.add_option('--find-min-xmx-max-memory',
88 help='Setting the maximum memory baseline to run in',
89 type='int')
90 result.add_option('--find-min-xmx-range-size',
91 help='Setting the size of the acceptable memory range',
92 type='int',
93 default=32)
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +020094 result.add_option('--find-min-xmx-archive',
95 help='Archive find-min-xmx results on GCS',
96 default=False,
97 action='store_true')
Christoffer Quist Adamsen3bbb50e2020-05-19 15:00:00 +020098 result.add_option('--no-extra-pgconf', '--no_extra_pgconf',
99 help='Build without the following extra rules: ' +
100 '-printconfiguration, -printmapping, -printseeds, ' +
101 '-printusage',
102 default=False,
103 action='store_true')
Jinseong Jeon158a3f12019-02-08 01:40:59 -0800104 result.add_option('--timeout',
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200105 type='int',
Jinseong Jeon158a3f12019-02-08 01:40:59 -0800106 default=0,
107 help='Set timeout instead of waiting for OOM.')
Rico Wind139eece2018-09-25 09:42:09 +0200108 result.add_option('--ignore-java-version',
109 help='Do not check java version',
110 default=False,
111 action='store_true')
Mads Ager418d1ca2017-05-22 09:35:49 +0200112 result.add_option('--no-libraries',
Rico Windb57bbc12018-09-20 19:23:32 +0200113 help='Do not pass in libraries, even if they exist in conf',
Mads Ager418d1ca2017-05-22 09:35:49 +0200114 default=False,
115 action='store_true')
116 result.add_option('--no-debug',
117 help='Run without debug asserts.',
118 default=False,
119 action='store_true')
Ian Zerny016d6f62020-03-19 08:58:21 +0100120 result.add_option('--debug-agent',
121 help='Run with debug agent.',
122 default=False,
123 action='store_true')
Mads Ager418d1ca2017-05-22 09:35:49 +0200124 result.add_option('--version',
Rico Windb57bbc12018-09-20 19:23:32 +0200125 help='The version of the app to run')
Mads Ager418d1ca2017-05-22 09:35:49 +0200126 result.add_option('-k',
127 help='Override the default ProGuard keep rules')
Tamas Kenez139acc12017-06-14 17:14:58 +0200128 result.add_option('--compiler-flags',
129 help='Additional option(s) for the compiler. ' +
130 'If passing several options use a quoted string.')
Mads Ager418d1ca2017-05-22 09:35:49 +0200131 result.add_option('--r8-flags',
Tamas Kenez139acc12017-06-14 17:14:58 +0200132 help='Additional option(s) for the compiler. ' +
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200133 'Same as --compiler-flags, keeping it for backward'
134 ' compatibility. ' +
Mads Ager418d1ca2017-05-22 09:35:49 +0200135 'If passing several options use a quoted string.')
136 result.add_option('--track-memory-to-file',
137 help='Track how much memory the jvm is using while ' +
138 ' compiling. Output to the specified file.')
139 result.add_option('--profile',
140 help='Profile R8 run.',
141 default=False,
142 action='store_true')
143 result.add_option('--dump-args-file',
144 help='Dump a file with the arguments for the specified ' +
145 'configuration. For use as a @<file> argument to perform ' +
146 'the run.')
Tamas Kenezf2ee2a32017-06-21 10:30:20 +0200147 result.add_option('--print-runtimeraw',
148 metavar='BENCHMARKNAME',
Tamas Kenez02bff032017-07-18 12:13:58 +0200149 help='Print the line \'<BENCHMARKNAME>(RunTimeRaw):' +
150 ' <elapsed> ms\' at the end where <elapsed> is' +
151 ' the elapsed time in milliseconds.')
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200152 result.add_option('--print-memoryuse',
153 metavar='BENCHMARKNAME',
Tamas Kenez02bff032017-07-18 12:13:58 +0200154 help='Print the line \'<BENCHMARKNAME>(MemoryUse):' +
155 ' <mem>\' at the end where <mem> is the peak' +
156 ' peak resident set size (VmHWM) in bytes.')
157 result.add_option('--print-dexsegments',
158 metavar='BENCHMARKNAME',
159 help='Print the sizes of individual dex segments as ' +
160 '\'<BENCHMARKNAME>-<segment>(CodeSize): <bytes>\'')
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200161 result.add_option('--track-time-in-memory',
162 help='Plot the times taken from memory starting point to '
163 'end-point with defined memory increment',
164 default=False,
165 action='store_true')
166 result.add_option('--track-time-in-memory-max',
167 help='Setting the maximum memory baseline to run in',
168 type='int')
169 result.add_option('--track-time-in-memory-min',
170 help='Setting the minimum memory baseline to run in',
171 type='int')
172 result.add_option('--track-time-in-memory-increment',
173 help='Setting the increment',
174 type='int',
175 default=32)
Søren Gjesse04a94332020-01-27 15:35:42 +0100176 result.add_option('--print-times',
177 help='Include timing',
178 default=False,
179 action='store_true')
Søren Gjesse943389f2020-03-13 10:40:25 +0100180 result.add_option('--cpu-list',
181 help='Run under \'taskset\' with these CPUs. See '
182 'the \'taskset\' -c option for the format')
Christoffer Quist Adamsend61d2a32020-06-02 07:41:10 +0200183 result.add_option('--quiet',
184 help='Disable compiler logging',
185 default=False,
186 action='store_true')
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +0100187 (options, args) = result.parse_args(argv)
188 assert not options.hash or options.no_build, (
189 'Argument --no-build is required when using --hash')
190 assert not options.hash or options.compiler_build == 'full', (
191 'Compiler build lib not yet supported with --hash')
192 return (options, args)
Mads Ager418d1ca2017-05-22 09:35:49 +0200193
Man Cao29b9ef12019-03-25 11:19:35 -0700194# Most apps have -printmapping, -printseeds, -printusage and
195# -printconfiguration in the Proguard configuration. However we don't
196# want to write these files in the locations specified.
197# Instead generate an auxiliary Proguard configuration placing these
198# output files together with the dex output.
Søren Gjesse3a5aed92017-06-14 15:36:02 +0200199def GenerateAdditionalProguardConfiguration(temp, outdir):
200 name = "output.config"
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200201 with open(os.path.join(temp, name), 'w') as f:
202 f.write('-printmapping ' + os.path.join(outdir, 'proguard.map') + "\n")
203 f.write('-printseeds ' + os.path.join(outdir, 'proguard.seeds') + "\n")
Søren Gjesse59459582018-04-06 10:12:45 +0200204 f.write('-printusage ' + os.path.join(outdir, 'proguard.usage') + "\n")
Man Cao29b9ef12019-03-25 11:19:35 -0700205 f.write('-printconfiguration ' + os.path.join(outdir, 'proguard.config') + "\n")
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200206 return os.path.abspath(f.name)
Søren Gjesse3a5aed92017-06-14 15:36:02 +0200207
Rico Wind3f9302b2018-09-21 08:53:09 +0200208# Please add bug number for disabled permutations and please explicitly
209# do Bug: #BUG in the commit message of disabling to ensure re-enabling
210DISABLED_PERMUTATIONS = [
Christoffer Quist Adamsen130394c2021-01-19 08:55:57 +0100211 # (app, version, type), e.g., ('gmail', '180826.15', 'deploy')
Rico Wind3f9302b2018-09-21 08:53:09 +0200212]
213
Rico Windb57bbc12018-09-20 19:23:32 +0200214def get_permutations():
215 data_providers = {
216 'gmscore': gmscore_data,
Christoffer Quist Adamsena2a58772018-10-03 09:47:46 +0200217 'nest': nest_data,
Rico Windb57bbc12018-09-20 19:23:32 +0200218 'youtube': youtube_data,
219 'chrome': chrome_data,
Morten Krogh-Jespersen04c7c302019-10-01 15:04:33 +0200220 'gmail': gmail_data,
Morten Krogh-Jespersencd6712c2019-10-09 13:09:47 +0200221 'r8': r8_data,
222 'iosched': iosched_data,
Rico Windb57bbc12018-09-20 19:23:32 +0200223 }
224 # Check to ensure that we add all variants here.
225 assert len(APPS) == len(data_providers)
Christoffer Quist Adamsen147342c2021-01-20 11:50:17 +0100226 for app, data in data_providers.items():
Rico Windb57bbc12018-09-20 19:23:32 +0200227 for version in data.VERSIONS:
228 for type in data.VERSIONS[version]:
Rico Wind3f9302b2018-09-21 08:53:09 +0200229 if (app, version, type) not in DISABLED_PERMUTATIONS:
Tamas Keneza730a7e2018-12-10 15:02:28 +0100230 for use_r8lib in [False, True]:
231 yield app, version, type, use_r8lib
Rico Windb57bbc12018-09-20 19:23:32 +0200232
233def run_all(options, args):
234 # Args will be destroyed
235 assert len(args) == 0
Tamas Keneza730a7e2018-12-10 15:02:28 +0100236 for name, version, type, use_r8lib in get_permutations():
Rico Windb57bbc12018-09-20 19:23:32 +0200237 compiler = 'r8' if type == 'deploy' else 'd8'
Tamas Kenez63a51d02019-01-07 15:53:02 +0100238 compiler_build = 'lib' if use_r8lib else 'full'
239 print('Executing %s/%s with %s %s %s' % (compiler, compiler_build, name,
240 version, type))
Tamas Keneza730a7e2018-12-10 15:02:28 +0100241
Rico Windb57bbc12018-09-20 19:23:32 +0200242 fixed_options = copy.copy(options)
243 fixed_options.app = name
244 fixed_options.version = version
245 fixed_options.compiler = compiler
Tamas Kenez63a51d02019-01-07 15:53:02 +0100246 fixed_options.compiler_build = compiler_build
Rico Windb57bbc12018-09-20 19:23:32 +0200247 fixed_options.type = type
248 exit_code = run_with_options(fixed_options, [])
249 if exit_code != 0:
Tamas Kenez63a51d02019-01-07 15:53:02 +0100250 print('Failed %s %s %s with %s/%s' % (name, version, type, compiler,
251 compiler_build))
Rico Windb57bbc12018-09-20 19:23:32 +0200252 exit(exit_code)
253
Rico Wind5fdec152018-12-17 09:16:14 +0100254def find_min_xmx(options, args):
255 # Args will be destroyed
256 assert len(args) == 0
257 # If we can run in 128 MB then we are good (which we can for small examples
258 # or D8 on medium sized examples)
Morten Krogh-Jespersen04c7c302019-10-01 15:04:33 +0200259 if options.find_min_xmx_min_memory:
260 not_working = options.find_min_xmx_min_memory
261 elif options.compiler == 'd8':
262 not_working = 128
263 else:
264 not_working = 1024
265 if options.find_min_xmx_max_memory:
266 working = options.find_min_xmx_max_memory
267 else:
268 working = 1024 * 8
Rico Wind5fdec152018-12-17 09:16:14 +0100269 exit_code = 0
Morten Krogh-Jespersen70432842021-01-19 17:07:58 +0100270 range = int(options.find_min_xmx_range_size)
Morten Krogh-Jespersen04c7c302019-10-01 15:04:33 +0200271 while working - not_working > range:
Morten Krogh-Jespersen70432842021-01-19 17:07:58 +0100272 next_candidate = int(working - ((working - not_working)/2))
Rico Wind5fdec152018-12-17 09:16:14 +0100273 print('working: %s, non_working: %s, next_candidate: %s' %
274 (working, not_working, next_candidate))
275 extra_args = ['-Xmx%sM' % next_candidate]
Rico Wind5fdec152018-12-17 09:16:14 +0100276 t0 = time.time()
277 exit_code = run_with_options(options, [], extra_args)
278 t1 = time.time()
279 print('Running took: %s ms' % (1000.0 * (t1 - t0)))
Jinseong Jeon158a3f12019-02-08 01:40:59 -0800280 if exit_code != 0:
281 if exit_code not in [OOM_EXIT_CODE, TIMEOUT_KILL_CODE]:
282 print('Non OOM/Timeout error executing, exiting')
283 return 2
Rico Wind5fdec152018-12-17 09:16:14 +0100284 if exit_code == 0:
285 working = next_candidate
Jinseong Jeon158a3f12019-02-08 01:40:59 -0800286 elif exit_code == TIMEOUT_KILL_CODE:
287 print('Timeout. Continue to the next candidate.')
288 not_working = next_candidate
Rico Wind5fdec152018-12-17 09:16:14 +0100289 else:
290 assert exit_code == OOM_EXIT_CODE
291 not_working = next_candidate
292
Morten Krogh-Jespersen04c7c302019-10-01 15:04:33 +0200293 assert working - not_working <= range
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200294 found_range = 'Found range: %s - %s' % (not_working, working)
295 print(found_range)
296
297 if options.find_min_xmx_archive:
298 sha = utils.get_HEAD_sha1()
299 (version, _) = get_version_and_data(options)
300 destination = os.path.join(
301 utils.R8_TEST_RESULTS_BUCKET,
302 FIND_MIN_XMX_DIR,
303 sha,
304 options.compiler,
305 options.compiler_build,
306 options.app,
307 version,
308 get_type(options))
309 gs_destination = 'gs://%s' % destination
310 utils.archive_value(FIND_MIN_XMX_FILE, gs_destination, found_range + '\n')
311
Rico Wind5fdec152018-12-17 09:16:14 +0100312 return 0
313
Morten Krogh-Jespersenf2412302019-10-22 10:18:04 +0200314def print_min_xmx_ranges_for_hash(hash, compiler, compiler_build):
315 app_directory = os.path.join(
316 utils.R8_TEST_RESULTS_BUCKET,
317 FIND_MIN_XMX_DIR,
318 hash,
319 compiler,
320 compiler_build)
321 gs_base = 'gs://%s' % app_directory
322 for app in utils.ls_files_on_cloud_storage(gs_base).strip().split('\n'):
323 for version in utils.ls_files_on_cloud_storage(app).strip().split('\n'):
324 for type in utils.ls_files_on_cloud_storage(version).strip().split('\n'):
325 gs_location = '%s%s' % (type, FIND_MIN_XMX_FILE)
326 value = utils.cat_file_on_cloud_storage(gs_location, ignore_errors=True)
327 print('%s\n' % value)
328
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200329def track_time_in_memory(options, args):
330 # Args will be destroyed
331 assert len(args) == 0
332 if not options.track_time_in_memory_min:
333 raise Exception(
334 'You have to specify --track_time_in_memory_min when running with '
335 '--track-time-in-memory')
336 if not options.track_time_in_memory_max:
337 raise Exception(
338 'You have to specify --track_time_in_memory_max when running with '
339 '--track-time-in-memory')
340 if not options.track_time_in_memory_increment:
341 raise Exception(
342 'You have to specify --track_time_in_memory_increment when running '
343 'with --track-time-in-memory')
344 current = options.track_time_in_memory_min
345 print('Memory (KB)\tTime (ms)')
346 with utils.TempDir() as temp:
347 stdout = os.path.join(temp, 'stdout')
348 stdout_fd = open(stdout, 'w')
349 while current <= options.track_time_in_memory_max:
350 extra_args = ['-Xmx%sM' % current]
351 t0 = time.time()
352 exit_code = run_with_options(options, [], extra_args, stdout_fd, quiet=True)
353 t1 = time.time()
354 total = (1000.0 * (t1 - t0)) if exit_code == 0 else -1
355 print('%s\t%s' % (current, total))
356 current += options.track_time_in_memory_increment
357
358 return 0
359
Tamas Kenez5b1c5852017-07-21 13:38:33 +0200360def main(argv):
Tamas Kenez5b1c5852017-07-21 13:38:33 +0200361 (options, args) = ParseOptions(argv)
Morten Krogh-Jespersenb7e1a182019-10-09 13:04:54 +0200362 if options.expect_oom and not options.max_memory:
363 raise Exception(
364 'You should only use --expect-oom if also specifying --max-memory')
365 if options.expect_oom and options.timeout:
366 raise Exception(
367 'You should not use --timeout when also specifying --expect-oom')
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200368 if options.find_min_xmx and options.track_time_in_memory:
369 raise Exception(
370 'You cannot both find the min xmx and track time at the same time')
Rico Windb57bbc12018-09-20 19:23:32 +0200371 if options.run_all:
372 return run_all(options, args)
Rico Wind5fdec152018-12-17 09:16:14 +0100373 if options.find_min_xmx:
374 return find_min_xmx(options, args)
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200375 if options.track_time_in_memory:
376 return track_time_in_memory(options, args)
Christoffer Quist Adamsend61d2a32020-06-02 07:41:10 +0200377 exit_code = run_with_options(options, args, quiet=options.quiet)
Morten Krogh-Jespersenb7e1a182019-10-09 13:04:54 +0200378 if options.expect_oom:
379 exit_code = 0 if exit_code == OOM_EXIT_CODE else 1
380 return exit_code
Rico Windb57bbc12018-09-20 19:23:32 +0200381
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200382def get_version_and_data(options):
383 if options.app == 'gmscore':
Christoffer Quist Adamsen6b668e82021-05-04 09:31:44 +0200384 version = options.version or gmscore_data.LATEST_VERSION
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200385 data = gmscore_data
386 elif options.app == 'nest':
387 version = options.version or '20180926'
388 data = nest_data
389 elif options.app == 'youtube':
Christoffer Quist Adamsen4380de32021-04-23 06:24:31 +0200390 version = options.version or youtube_data.LATEST_VERSION
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200391 data = youtube_data
392 elif options.app == 'chrome':
393 version = options.version or '180917'
394 data = chrome_data
395 elif options.app == 'gmail':
396 version = options.version or '170604.16'
397 data = gmail_data
398 elif options.app == 'r8':
399 version = options.version or 'cf'
400 data = r8_data
Morten Krogh-Jespersencd6712c2019-10-09 13:09:47 +0200401 elif options.app == 'iosched':
402 version = options.version or '2019'
403 data = iosched_data
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200404 else:
405 raise Exception("You need to specify '--app={}'".format('|'.join(APPS)))
406 return version, data
407
408def get_type(options):
409 if not options.type:
410 return 'deploy' if options.compiler == 'r8' else 'proguarded'
411 return options.type
412
Søren Gjesse94793ca2019-11-08 13:53:08 +0100413def has_injars_and_libraryjars(pgconfs):
414 # Check if there are -injars and -libraryjars in the configuration.
415 has_injars = False
416 has_libraryjars = False
417 for pgconf in pgconfs:
418 pgconf_dirname = os.path.abspath(os.path.dirname(pgconf))
419 with open(pgconf) as pgconf_file:
420 for line in pgconf_file:
421 trimmed = line.strip()
422 if trimmed.startswith('-injars'):
423 has_injars = True
424 elif trimmed.startswith('-libraryjars'):
425 has_libraryjars = True
426 if has_injars and has_libraryjars:
427 return True
428 return False
429
Søren Gjesse889e09d2019-11-07 16:33:51 +0100430def check_no_injars_and_no_libraryjars(pgconfs):
431 # Ensure that there are no -injars or -libraryjars in the configuration.
432 for pgconf in pgconfs:
433 pgconf_dirname = os.path.abspath(os.path.dirname(pgconf))
434 with open(pgconf) as pgconf_file:
435 for line in pgconf_file:
436 trimmed = line.strip()
437 if trimmed.startswith('-injars'):
438 raise Exception("Unexpected -injars found in " + pgconf)
439 elif trimmed.startswith('-libraryjars'):
440 raise Exception("Unexpected -libraryjars found in " + pgconf)
441
Søren Gjesse80e00482021-04-06 13:17:35 +0200442def should_build(options):
Morten Krogh-Jespersen254805e2022-06-03 09:32:42 +0200443 return not options.no_build
Søren Gjesse80e00482021-04-06 13:17:35 +0200444
Christoffer Quist Adamsen7ff14092021-04-15 11:48:12 +0200445def build_desugared_library_dex(
446 options,
447 quiet,
448 temp,
449 android_java8_libs,
450 desugared_lib_pg_conf,
451 inputs,
452 outdir):
453 if not inputs:
454 raise Exception(
455 "If 'android_java8_libs' is specified the inputs must be explicit"
456 + "(not defined using '-injars' in Proguard configuration files)")
Søren Gjesse80e00482021-04-06 13:17:35 +0200457 if outdir.endswith('.zip') or outdir.endswith('.jar'):
Christoffer Quist Adamsen7ff14092021-04-15 11:48:12 +0200458 raise Exception(
459 "If 'android_java8_libs' is specified the output must be a directory")
Søren Gjesse80e00482021-04-06 13:17:35 +0200460
461 jar = None
462 main = None
463 if options.hash:
464 jar = os.path.join(utils.LIBS, 'r8-' + options.hash + '.jar')
Christoffer Quist Adamsen7ff14092021-04-15 11:48:12 +0200465 main = 'com.android.tools.r8.R8'
Søren Gjesse80e00482021-04-06 13:17:35 +0200466
Christoffer Quist Adamsen7ff14092021-04-15 11:48:12 +0200467 # Determine the l8 tool.
Søren Gjesse80e00482021-04-06 13:17:35 +0200468 assert(options.compiler_build in ['full', 'lib'])
469 lib_prefix = 'r8lib-' if options.compiler_build == 'lib' else ''
Christoffer Quist Adamsen7ff14092021-04-15 11:48:12 +0200470 tool = lib_prefix + 'l8'
Søren Gjesse80e00482021-04-06 13:17:35 +0200471
Christoffer Quist Adamsen7ff14092021-04-15 11:48:12 +0200472 # Prepare out directory.
Søren Gjesse80e00482021-04-06 13:17:35 +0200473 android_java8_libs_output = os.path.join(temp, 'android_java8_libs')
474 os.makedirs(android_java8_libs_output)
Christoffer Quist Adamsen7ff14092021-04-15 11:48:12 +0200475
476 # Prepare arguments for L8.
Søren Gjesse80e00482021-04-06 13:17:35 +0200477 args = [
Christoffer Quist Adamsen7ff14092021-04-15 11:48:12 +0200478 '--desugared-lib', android_java8_libs['config'],
479 '--lib', android_java8_libs['library'],
Søren Gjesse80e00482021-04-06 13:17:35 +0200480 '--output', android_java8_libs_output,
Christoffer Quist Adamsen7ff14092021-04-15 11:48:12 +0200481 '--pg-conf', desugared_lib_pg_conf,
482 '--release',
Søren Gjesse80e00482021-04-06 13:17:35 +0200483 ]
Christoffer Quist Adamsen7ff14092021-04-15 11:48:12 +0200484 if 'pgconf' in android_java8_libs:
485 for pgconf in android_java8_libs['pgconf']:
486 args.extend(['--pg-conf', pgconf])
487 args.extend(android_java8_libs['program'])
488
489 # Run L8.
490 exit_code = toolhelper.run(
491 tool, args,
Søren Gjesse80e00482021-04-06 13:17:35 +0200492 build=should_build(options),
493 debug=not options.no_debug,
494 quiet=quiet,
495 jar=jar,
496 main=main)
Christoffer Quist Adamsen7ff14092021-04-15 11:48:12 +0200497
Søren Gjesse80e00482021-04-06 13:17:35 +0200498 # Copy the desugared library DEX to the output.
Christoffer Quist Adamsen7ff14092021-04-15 11:48:12 +0200499 dex_file_name = (
500 'classes' + str(len(glob(os.path.join(outdir, '*.dex'))) + 1) + '.dex')
Søren Gjesse80e00482021-04-06 13:17:35 +0200501 shutil.copyfile(
502 os.path.join(android_java8_libs_output, 'classes.dex'),
503 os.path.join(outdir, dex_file_name))
504
Morten Krogh-Jespersen94a9b102019-11-01 09:45:44 +0000505def run_with_options(options, args, extra_args=None, stdout=None, quiet=False):
506 if extra_args is None:
507 extra_args = []
Rico Windb57bbc12018-09-20 19:23:32 +0200508 app_provided_pg_conf = False;
Rico Windadd08132018-12-14 14:17:15 +0100509 # todo(121018500): remove when memory is under control
Rico Wind20602b72019-01-09 09:17:13 +0100510 if not any('-Xmx' in arg for arg in extra_args):
Morten Krogh-Jespersen322c2f12019-10-08 10:41:21 +0200511 if options.max_memory:
512 extra_args.append('-Xmx%sM' % options.max_memory)
513 else:
514 extra_args.append('-Xmx8G')
Rico Windafdbbfd2019-02-22 09:32:07 +0100515 if not options.ignore_java_version:
516 utils.check_java_version()
517
Søren Gjesse04a94332020-01-27 15:35:42 +0100518 if options.print_times:
519 extra_args.append('-Dcom.android.tools.r8.printtimes=1')
520
Morten Krogh-Jespersena565f012021-07-13 13:27:41 +0200521 if not options.no_debug:
522 extra_args.append('-Dcom.android.tools.r8.enableTestAssertions=1')
523
Mads Ager418d1ca2017-05-22 09:35:49 +0200524 outdir = options.out
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200525 (version_id, data) = get_version_and_data(options)
526
Tamas Kenez5b1c5852017-07-21 13:38:33 +0200527 if options.compiler not in COMPILERS:
528 raise Exception("You need to specify '--compiler={}'"
529 .format('|'.join(COMPILERS)))
Mads Ager418d1ca2017-05-22 09:35:49 +0200530
Tamas Kenez63a51d02019-01-07 15:53:02 +0100531 if options.compiler_build not in COMPILER_BUILDS:
532 raise Exception("You need to specify '--compiler-build={}'"
533 .format('|'.join(COMPILER_BUILDS)))
534
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200535 if not version_id in data.VERSIONS.keys():
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200536 print('No version {} for application {}'
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200537 .format(version_id, options.app))
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200538 print('Valid versions are {}'.format(data.VERSIONS.keys()))
Mads Ager418d1ca2017-05-22 09:35:49 +0200539 return 1
540
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200541 version = data.VERSIONS[version_id]
Mads Ager418d1ca2017-05-22 09:35:49 +0200542
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200543 type = get_type(options)
Tamas Kenez3fdaabd2017-06-15 13:05:12 +0200544
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200545 if type not in version:
546 print('No type {} for version {}'.format(type, version))
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200547 print('Valid types are {}'.format(version.keys()))
Mads Ager418d1ca2017-05-22 09:35:49 +0200548 return 1
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200549 values = version[type]
Mads Ager418d1ca2017-05-22 09:35:49 +0200550
551 args.extend(['--output', outdir])
Ian Zerny877c1862017-07-06 11:12:26 +0200552 if 'min-api' in values:
553 args.extend(['--min-api', values['min-api']])
Søren Gjesse932881f2017-06-13 10:43:36 +0200554
Søren Gjesse8ae55eb2018-09-28 11:11:36 +0200555 if 'main-dex-list' in values:
556 args.extend(['--main-dex-list', values['main-dex-list']])
557
Christoffer Quist Adamsene7273022021-04-12 07:42:07 +0200558 inputs = values['inputs']
Søren Gjesse94793ca2019-11-08 13:53:08 +0100559 libraries = values['libraries'] if 'libraries' in values else []
Christoffer Quist Adamsene7273022021-04-12 07:42:07 +0200560
Tamas Kenez63a51d02019-01-07 15:53:02 +0100561 if options.compiler == 'r8':
Søren Gjesse932881f2017-06-13 10:43:36 +0200562 if 'pgconf' in values and not options.k:
Søren Gjesse94793ca2019-11-08 13:53:08 +0100563 if has_injars_and_libraryjars(values['pgconf']):
564 sanitized_lib_path = os.path.join(
565 os.path.abspath(outdir), 'sanitized_lib.jar')
Søren Gjesse889e09d2019-11-07 16:33:51 +0100566 sanitized_pgconf_path = os.path.join(
567 os.path.abspath(outdir), 'sanitized.config')
568 SanitizeLibrariesInPgconf(
569 sanitized_lib_path, sanitized_pgconf_path, values['pgconf'])
Søren Gjesse94793ca2019-11-08 13:53:08 +0100570 libraries = [sanitized_lib_path]
Søren Gjesse889e09d2019-11-07 16:33:51 +0100571 args.extend(['--pg-conf', sanitized_pgconf_path])
Christoffer Quist Adamsene7273022021-04-12 07:42:07 +0200572 inputs = []
Søren Gjesse94793ca2019-11-08 13:53:08 +0100573 else:
574 # -injars without -libraryjars or vice versa is not supported.
575 check_no_injars_and_no_libraryjars(values['pgconf'])
576 for pgconf in values['pgconf']:
577 args.extend(['--pg-conf', pgconf])
578 if 'sanitize_libraries' in values and values['sanitize_libraries']:
579 sanitized_lib_path = os.path.join(
580 os.path.abspath(outdir), 'sanitized_lib.jar')
581 SanitizeLibraries(
582 sanitized_lib_path, values['libraries'], values['inputs'])
583 libraries = [sanitized_lib_path]
Søren Gjessecbeae782019-05-21 14:14:25 +0200584 app_provided_pg_conf = True
Rico Wind51f0bb22021-09-09 09:57:42 +0200585 if 'pgconf_extra' in values:
586 extra_conf = os.path.join(os.path.abspath(outdir), 'pgconf_extra')
587 with open(extra_conf, 'w') as extra_f:
588 extra_f.write(values['pgconf_extra'])
589 args.extend(['--pg-conf', extra_conf])
Søren Gjesse932881f2017-06-13 10:43:36 +0200590 if options.k:
591 args.extend(['--pg-conf', options.k])
Søren Gjessec801ecc2017-08-03 13:40:06 +0200592 if 'maindexrules' in values:
593 for rules in values['maindexrules']:
594 args.extend(['--main-dex-rules', rules])
Rico Wind79e4eb52018-12-13 13:00:49 +0100595 if 'allow-type-errors' in values:
596 extra_args.append('-Dcom.android.tools.r8.allowTypeErrors=1')
Christoffer Quist Adamsen57254f02020-05-18 15:43:58 +0200597 extra_args.append(
598 '-Dcom.android.tools.r8.disallowClassInlinerGracefulExit=1')
Christoffer Quist Adamsen62fcc152022-06-03 14:01:35 +0200599 if 'system-properties' in values:
600 for system_property in values['system-properties']:
601 extra_args.append(system_property)
Søren Gjesse932881f2017-06-13 10:43:36 +0200602
Ian Zerny016d6f62020-03-19 08:58:21 +0100603 if options.debug_agent:
604 if not options.compiler_build == 'full':
605 print('WARNING: Running debugging agent on r8lib is questionable...')
606 extra_args.append(
607 '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005')
608
Søren Gjesse94793ca2019-11-08 13:53:08 +0100609 if not options.no_libraries:
610 for lib in libraries:
Mads Ager418d1ca2017-05-22 09:35:49 +0200611 args.extend(['--lib', lib])
612
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200613 if not outdir.endswith('.zip') and not outdir.endswith('.jar') \
614 and not os.path.exists(outdir):
Mads Ager418d1ca2017-05-22 09:35:49 +0200615 os.makedirs(outdir)
616
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +0100617 if options.hash:
618 # Download r8-<hash>.jar from
619 # https://storage.googleapis.com/r8-releases/raw/<hash>/.
620 download_path = archive.GetUploadDestination(options.hash, 'r8.jar', True)
621 assert utils.file_exists_on_cloud_storage(download_path), (
622 'Could not find r8.jar file from provided hash: %s' % options.hash)
623 destination = os.path.join(utils.LIBS, 'r8-' + options.hash + '.jar')
624 utils.download_file_from_cloud_storage(
625 download_path, destination, quiet=quiet)
626
Søren Gjesse8ae55eb2018-09-28 11:11:36 +0200627 # Additional flags for the compiler from the configuration file.
628 if 'flags' in values:
629 args.extend(values['flags'].split(' '))
Tamas Kenez63a51d02019-01-07 15:53:02 +0100630 if options.compiler == 'r8':
Søren Gjesse932881f2017-06-13 10:43:36 +0200631 if 'r8-flags' in values:
632 args.extend(values['r8-flags'].split(' '))
Tamas Kenez139acc12017-06-14 17:14:58 +0200633
Søren Gjesse8ae55eb2018-09-28 11:11:36 +0200634 # Additional flags for the compiler from the command line.
Tamas Kenez139acc12017-06-14 17:14:58 +0200635 if options.compiler_flags:
636 args.extend(options.compiler_flags.split(' '))
637 if options.r8_flags:
638 args.extend(options.r8_flags.split(' '))
Mads Ager418d1ca2017-05-22 09:35:49 +0200639
Christoffer Quist Adamsen287c1862020-05-20 15:51:12 +0200640 # Feature jars.
641 features = values['features'] if 'features' in values else []
642 for i, feature in enumerate(features, start=1):
643 feature_out = os.path.join(outdir, 'feature-%d.zip' % i)
644 for feature_jar in feature['inputs']:
645 args.extend(['--feature', feature_jar, feature_out])
646
Søren Gjesse94793ca2019-11-08 13:53:08 +0100647 args.extend(inputs)
Mads Ager418d1ca2017-05-22 09:35:49 +0200648
Morten Krogh-Jespersen89e19012021-10-05 09:55:01 +0200649 t0 = None
Mads Ager418d1ca2017-05-22 09:35:49 +0200650 if options.dump_args_file:
651 with open(options.dump_args_file, 'w') as args_file:
652 args_file.writelines([arg + os.linesep for arg in args])
653 else:
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200654 with utils.TempDir() as temp:
655 if options.print_memoryuse and not options.track_memory_to_file:
656 options.track_memory_to_file = os.path.join(temp,
657 utils.MEMORY_USE_TMP_FILE)
Tamas Kenez63a51d02019-01-07 15:53:02 +0100658 if options.compiler == 'r8' and app_provided_pg_conf:
Mathias Ravdd6a6de2018-05-18 10:18:33 +0200659 # Ensure that output of -printmapping and -printseeds go to the output
660 # location and not where the app Proguard configuration places them.
661 if outdir.endswith('.zip') or outdir.endswith('.jar'):
662 pg_outdir = os.path.dirname(outdir)
663 else:
664 pg_outdir = outdir
Christoffer Quist Adamsen3bbb50e2020-05-19 15:00:00 +0200665 if not options.no_extra_pgconf:
666 additional_pg_conf = GenerateAdditionalProguardConfiguration(
667 temp, os.path.abspath(pg_outdir))
668 args.extend(['--pg-conf', additional_pg_conf])
Christoffer Quist Adamsen7ff14092021-04-15 11:48:12 +0200669
670 android_java8_libs = values.get('android_java8_libs')
671 if android_java8_libs:
672 desugared_lib_pg_conf = os.path.join(
673 temp, 'desugared-lib-pg-conf.txt')
674 args.extend(['--desugared-lib', android_java8_libs['config']])
675 args.extend(
676 ['--desugared-lib-pg-conf-output', desugared_lib_pg_conf])
677
Rico Wind5fdec152018-12-17 09:16:14 +0100678 stderr_path = os.path.join(temp, 'stderr')
679 with open(stderr_path, 'w') as stderr:
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +0100680 jar = None
681 main = None
Tamas Kenez63a51d02019-01-07 15:53:02 +0100682 if options.compiler_build == 'full':
683 tool = options.compiler
684 else:
685 assert(options.compiler_build == 'lib')
686 tool = 'r8lib-' + options.compiler
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +0100687 if options.hash:
688 jar = os.path.join(utils.LIBS, 'r8-' + options.hash + '.jar')
689 main = 'com.android.tools.r8.' + options.compiler.upper()
Morten Krogh-Jespersen89e19012021-10-05 09:55:01 +0200690 if should_build(options):
691 gradle.RunGradle(['r8lib' if tool.startswith('r8lib') else 'r8'])
692 t0 = time.time()
Tamas Kenez63a51d02019-01-07 15:53:02 +0100693 exit_code = toolhelper.run(tool, args,
Morten Krogh-Jespersen89e19012021-10-05 09:55:01 +0200694 build=False,
Rico Wind5fdec152018-12-17 09:16:14 +0100695 debug=not options.no_debug,
696 profile=options.profile,
697 track_memory_file=options.track_memory_to_file,
Jinseong Jeon158a3f12019-02-08 01:40:59 -0800698 extra_args=extra_args,
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200699 stdout=stdout,
Jinseong Jeon158a3f12019-02-08 01:40:59 -0800700 stderr=stderr,
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200701 timeout=options.timeout,
Søren Gjesse943389f2020-03-13 10:40:25 +0100702 quiet=quiet,
Morten Krogh-Jespersen0e4d7e22020-03-14 00:56:32 +0100703 cmd_prefix=[
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +0100704 'taskset', '-c', options.cpu_list] if options.cpu_list else [],
705 jar=jar,
706 main=main)
Christoffer Quist Adamsen21c66602018-08-09 16:22:54 +0200707 if exit_code != 0:
Rico Wind5fdec152018-12-17 09:16:14 +0100708 with open(stderr_path) as stderr:
709 stderr_text = stderr.read()
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200710 if not quiet:
711 print(stderr_text)
Rico Wind5fdec152018-12-17 09:16:14 +0100712 if 'java.lang.OutOfMemoryError' in stderr_text:
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200713 if not quiet:
714 print('Failure was OOM')
Rico Wind5fdec152018-12-17 09:16:14 +0100715 return OOM_EXIT_CODE
716 return exit_code
Christoffer Quist Adamsen21c66602018-08-09 16:22:54 +0200717
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200718 if options.print_memoryuse:
719 print('{}(MemoryUse): {}'
720 .format(options.print_memoryuse,
721 utils.grep_memoryuse(options.track_memory_to_file)))
Mads Ager418d1ca2017-05-22 09:35:49 +0200722
Christoffer Quist Adamsen7ff14092021-04-15 11:48:12 +0200723 if android_java8_libs:
724 build_desugared_library_dex(
725 options, quiet, temp, android_java8_libs,
726 desugared_lib_pg_conf, inputs, outdir)
Søren Gjesse80e00482021-04-06 13:17:35 +0200727
728
Tamas Kenezf2ee2a32017-06-21 10:30:20 +0200729 if options.print_runtimeraw:
730 print('{}(RunTimeRaw): {} ms'
731 .format(options.print_runtimeraw, 1000.0 * (time.time() - t0)))
732
Tamas Kenez02bff032017-07-18 12:13:58 +0200733 if options.print_dexsegments:
734 dex_files = glob(os.path.join(outdir, '*.dex'))
735 utils.print_dexsegments(options.print_dexsegments, dex_files)
Morten Krogh-Jespersen254805e2022-06-03 09:32:42 +0200736 print('{}-Total(CodeSize): {}'.format(
737 options.print_dexsegments, compute_size_of_dex_files(dex_files)))
Rico Windb57bbc12018-09-20 19:23:32 +0200738 return 0
Tamas Kenez02bff032017-07-18 12:13:58 +0200739
Morten Krogh-Jespersenf4a8f762021-12-22 12:31:21 +0100740def compute_size_of_dex_files(dex_files):
741 dex_size = 0
742 for dex_file in dex_files:
743 dex_size += os.path.getsize(dex_file)
744 return dex_size
745
Mads Ager418d1ca2017-05-22 09:35:49 +0200746if __name__ == '__main__':
Tamas Kenez5b1c5852017-07-21 13:38:33 +0200747 sys.exit(main(sys.argv[1:]))