blob: 94eae01db89af90dbf26ccaf2dbb9a88eb73d37d [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
Mads Ager418d1ca2017-05-22 09:35:49 +020011import sys
Tamas Kenezf2ee2a32017-06-21 10:30:20 +020012import time
Mads Ager418d1ca2017-05-22 09:35:49 +020013
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +010014import archive
15import as_utils
Søren Gjesse5ecb04a2017-06-13 09:44:32 +020016import gmail_data
Ian Zerny877c1862017-07-06 11:12:26 +020017import gmscore_data
Rico Wind1f4172c2018-09-06 16:29:03 +020018import golem
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
Morten Krogh-Jespersen1ba55f52020-04-24 12:49:17 +020028import tachiyomi_data
Mads Ager418d1ca2017-05-22 09:35:49 +020029
30TYPES = ['dex', 'deploy', 'proguarded']
Morten Krogh-Jespersen1ba55f52020-04-24 12:49:17 +020031APPS = [
32 'gmscore', 'nest', 'youtube', 'gmail', 'chrome', 'r8', 'iosched', 'tachiyomi']
Tamas Kenez63a51d02019-01-07 15:53:02 +010033COMPILERS = ['d8', 'r8']
34COMPILER_BUILDS = ['full', 'lib']
35
Rico Wind5fdec152018-12-17 09:16:14 +010036# We use this magic exit code to signal that the program OOM'ed
37OOM_EXIT_CODE = 42
Jinseong Jeon158a3f12019-02-08 01:40:59 -080038# According to Popen.returncode doc:
39# A negative value -N indicates that the child was terminated by signal N.
40TIMEOUT_KILL_CODE = -9
Mads Ager418d1ca2017-05-22 09:35:49 +020041
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +020042# Log file names
43FIND_MIN_XMX_FILE = 'find_min_xmx_results'
44FIND_MIN_XMX_DIR = 'find_min_xmx'
45
Tamas Kenez5b1c5852017-07-21 13:38:33 +020046def ParseOptions(argv):
Mads Ager418d1ca2017-05-22 09:35:49 +020047 result = optparse.OptionParser()
Søren Gjesse932881f2017-06-13 10:43:36 +020048 result.add_option('--compiler',
Rico Windb57bbc12018-09-20 19:23:32 +020049 help='The compiler to use',
Tamas Kenez5b1c5852017-07-21 13:38:33 +020050 choices=COMPILERS)
Tamas Kenez63a51d02019-01-07 15:53:02 +010051 result.add_option('--compiler-build',
52 help='Compiler build to use',
53 choices=COMPILER_BUILDS,
54 default='lib')
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +010055 result.add_option('--hash',
56 help='The version of D8/R8 to use')
Mads Ager418d1ca2017-05-22 09:35:49 +020057 result.add_option('--app',
Rico Windb57bbc12018-09-20 19:23:32 +020058 help='What app to run on',
Mads Ager418d1ca2017-05-22 09:35:49 +020059 choices=APPS)
Rico Windb57bbc12018-09-20 19:23:32 +020060 result.add_option('--run-all',
61 help='Compile all possible combinations',
62 default=False,
63 action='store_true')
Morten Krogh-Jespersenb7e1a182019-10-09 13:04:54 +020064 result.add_option('--expect-oom',
65 help='Expect that compilation will fail with an OOM',
66 default=False,
67 action='store_true')
Mads Ager418d1ca2017-05-22 09:35:49 +020068 result.add_option('--type',
Tamas Kenez3fdaabd2017-06-15 13:05:12 +020069 help='Default for R8: deploy, for D8: proguarded',
Mads Ager418d1ca2017-05-22 09:35:49 +020070 choices=TYPES)
71 result.add_option('--out',
Rico Windb57bbc12018-09-20 19:23:32 +020072 help='Where to place the output',
Rico Winde9485ba2018-10-01 07:04:16 +020073 default=utils.BUILD)
Mads Ager418d1ca2017-05-22 09:35:49 +020074 result.add_option('--no-build',
Rico Windb57bbc12018-09-20 19:23:32 +020075 help='Run without building first',
Mads Ager418d1ca2017-05-22 09:35:49 +020076 default=False,
77 action='store_true')
Morten Krogh-Jespersen322c2f12019-10-08 10:41:21 +020078 result.add_option('--max-memory',
79 help='The maximum memory in MB to run with',
80 type='int')
Rico Wind5fdec152018-12-17 09:16:14 +010081 result.add_option('--find-min-xmx',
82 help='Find the minimum amount of memory we can run in',
83 default=False,
84 action='store_true')
Morten Krogh-Jespersen04c7c302019-10-01 15:04:33 +020085 result.add_option('--find-min-xmx-min-memory',
86 help='Setting the minimum memory baseline to run in',
87 type='int')
88 result.add_option('--find-min-xmx-max-memory',
89 help='Setting the maximum memory baseline to run in',
90 type='int')
91 result.add_option('--find-min-xmx-range-size',
92 help='Setting the size of the acceptable memory range',
93 type='int',
94 default=32)
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +020095 result.add_option('--find-min-xmx-archive',
96 help='Archive find-min-xmx results on GCS',
97 default=False,
98 action='store_true')
Christoffer Quist Adamsen3bbb50e2020-05-19 15:00:00 +020099 result.add_option('--no-extra-pgconf', '--no_extra_pgconf',
100 help='Build without the following extra rules: ' +
101 '-printconfiguration, -printmapping, -printseeds, ' +
102 '-printusage',
103 default=False,
104 action='store_true')
Jinseong Jeon158a3f12019-02-08 01:40:59 -0800105 result.add_option('--timeout',
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200106 type='int',
Jinseong Jeon158a3f12019-02-08 01:40:59 -0800107 default=0,
108 help='Set timeout instead of waiting for OOM.')
Rico Wind1f4172c2018-09-06 16:29:03 +0200109 result.add_option('--golem',
Rico Windb57bbc12018-09-20 19:23:32 +0200110 help='Running on golem, do not build or download',
Rico Wind1f4172c2018-09-06 16:29:03 +0200111 default=False,
112 action='store_true')
Rico Wind139eece2018-09-25 09:42:09 +0200113 result.add_option('--ignore-java-version',
114 help='Do not check java version',
115 default=False,
116 action='store_true')
Mads Ager418d1ca2017-05-22 09:35:49 +0200117 result.add_option('--no-libraries',
Rico Windb57bbc12018-09-20 19:23:32 +0200118 help='Do not pass in libraries, even if they exist in conf',
Mads Ager418d1ca2017-05-22 09:35:49 +0200119 default=False,
120 action='store_true')
121 result.add_option('--no-debug',
122 help='Run without debug asserts.',
123 default=False,
124 action='store_true')
Ian Zerny016d6f62020-03-19 08:58:21 +0100125 result.add_option('--debug-agent',
126 help='Run with debug agent.',
127 default=False,
128 action='store_true')
Mads Ager418d1ca2017-05-22 09:35:49 +0200129 result.add_option('--version',
Rico Windb57bbc12018-09-20 19:23:32 +0200130 help='The version of the app to run')
Mads Ager418d1ca2017-05-22 09:35:49 +0200131 result.add_option('-k',
132 help='Override the default ProGuard keep rules')
Tamas Kenez139acc12017-06-14 17:14:58 +0200133 result.add_option('--compiler-flags',
134 help='Additional option(s) for the compiler. ' +
135 'If passing several options use a quoted string.')
Mads Ager418d1ca2017-05-22 09:35:49 +0200136 result.add_option('--r8-flags',
Tamas Kenez139acc12017-06-14 17:14:58 +0200137 help='Additional option(s) for the compiler. ' +
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200138 'Same as --compiler-flags, keeping it for backward'
139 ' compatibility. ' +
Mads Ager418d1ca2017-05-22 09:35:49 +0200140 'If passing several options use a quoted string.')
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200141 # TODO(tamaskenez) remove track-memory-to-file as soon as we updated golem
142 # to use --print-memoryuse instead
Mads Ager418d1ca2017-05-22 09:35:49 +0200143 result.add_option('--track-memory-to-file',
144 help='Track how much memory the jvm is using while ' +
145 ' compiling. Output to the specified file.')
146 result.add_option('--profile',
147 help='Profile R8 run.',
148 default=False,
149 action='store_true')
150 result.add_option('--dump-args-file',
151 help='Dump a file with the arguments for the specified ' +
152 'configuration. For use as a @<file> argument to perform ' +
153 'the run.')
Tamas Kenezf2ee2a32017-06-21 10:30:20 +0200154 result.add_option('--print-runtimeraw',
155 metavar='BENCHMARKNAME',
Tamas Kenez02bff032017-07-18 12:13:58 +0200156 help='Print the line \'<BENCHMARKNAME>(RunTimeRaw):' +
157 ' <elapsed> ms\' at the end where <elapsed> is' +
158 ' the elapsed time in milliseconds.')
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200159 result.add_option('--print-memoryuse',
160 metavar='BENCHMARKNAME',
Tamas Kenez02bff032017-07-18 12:13:58 +0200161 help='Print the line \'<BENCHMARKNAME>(MemoryUse):' +
162 ' <mem>\' at the end where <mem> is the peak' +
163 ' peak resident set size (VmHWM) in bytes.')
164 result.add_option('--print-dexsegments',
165 metavar='BENCHMARKNAME',
166 help='Print the sizes of individual dex segments as ' +
167 '\'<BENCHMARKNAME>-<segment>(CodeSize): <bytes>\'')
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200168 result.add_option('--track-time-in-memory',
169 help='Plot the times taken from memory starting point to '
170 'end-point with defined memory increment',
171 default=False,
172 action='store_true')
173 result.add_option('--track-time-in-memory-max',
174 help='Setting the maximum memory baseline to run in',
175 type='int')
176 result.add_option('--track-time-in-memory-min',
177 help='Setting the minimum memory baseline to run in',
178 type='int')
179 result.add_option('--track-time-in-memory-increment',
180 help='Setting the increment',
181 type='int',
182 default=32)
Søren Gjesse04a94332020-01-27 15:35:42 +0100183 result.add_option('--print-times',
184 help='Include timing',
185 default=False,
186 action='store_true')
Søren Gjesse943389f2020-03-13 10:40:25 +0100187 result.add_option('--cpu-list',
188 help='Run under \'taskset\' with these CPUs. See '
189 'the \'taskset\' -c option for the format')
Christoffer Quist Adamsend61d2a32020-06-02 07:41:10 +0200190 result.add_option('--quiet',
191 help='Disable compiler logging',
192 default=False,
193 action='store_true')
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +0100194 (options, args) = result.parse_args(argv)
195 assert not options.hash or options.no_build, (
196 'Argument --no-build is required when using --hash')
197 assert not options.hash or options.compiler_build == 'full', (
198 'Compiler build lib not yet supported with --hash')
199 return (options, args)
Mads Ager418d1ca2017-05-22 09:35:49 +0200200
Man Cao29b9ef12019-03-25 11:19:35 -0700201# Most apps have -printmapping, -printseeds, -printusage and
202# -printconfiguration in the Proguard configuration. However we don't
203# want to write these files in the locations specified.
204# Instead generate an auxiliary Proguard configuration placing these
205# output files together with the dex output.
Søren Gjesse3a5aed92017-06-14 15:36:02 +0200206def GenerateAdditionalProguardConfiguration(temp, outdir):
207 name = "output.config"
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200208 with open(os.path.join(temp, name), 'w') as f:
209 f.write('-printmapping ' + os.path.join(outdir, 'proguard.map') + "\n")
210 f.write('-printseeds ' + os.path.join(outdir, 'proguard.seeds') + "\n")
Søren Gjesse59459582018-04-06 10:12:45 +0200211 f.write('-printusage ' + os.path.join(outdir, 'proguard.usage') + "\n")
Man Cao29b9ef12019-03-25 11:19:35 -0700212 f.write('-printconfiguration ' + os.path.join(outdir, 'proguard.config') + "\n")
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200213 return os.path.abspath(f.name)
Søren Gjesse3a5aed92017-06-14 15:36:02 +0200214
Rico Wind3f9302b2018-09-21 08:53:09 +0200215# Please add bug number for disabled permutations and please explicitly
216# do Bug: #BUG in the commit message of disabling to ensure re-enabling
217DISABLED_PERMUTATIONS = [
Christoffer Quist Adamsen130394c2021-01-19 08:55:57 +0100218 # (app, version, type), e.g., ('gmail', '180826.15', 'deploy')
Rico Wind3f9302b2018-09-21 08:53:09 +0200219]
220
Rico Windb57bbc12018-09-20 19:23:32 +0200221def get_permutations():
222 data_providers = {
223 'gmscore': gmscore_data,
Christoffer Quist Adamsena2a58772018-10-03 09:47:46 +0200224 'nest': nest_data,
Rico Windb57bbc12018-09-20 19:23:32 +0200225 'youtube': youtube_data,
226 'chrome': chrome_data,
Morten Krogh-Jespersen04c7c302019-10-01 15:04:33 +0200227 'gmail': gmail_data,
Morten Krogh-Jespersencd6712c2019-10-09 13:09:47 +0200228 'r8': r8_data,
229 'iosched': iosched_data,
Morten Krogh-Jespersen1ba55f52020-04-24 12:49:17 +0200230 'tachiyomi': tachiyomi_data
Rico Windb57bbc12018-09-20 19:23:32 +0200231 }
232 # Check to ensure that we add all variants here.
233 assert len(APPS) == len(data_providers)
Christoffer Quist Adamsen147342c2021-01-20 11:50:17 +0100234 for app, data in data_providers.items():
Rico Windb57bbc12018-09-20 19:23:32 +0200235 for version in data.VERSIONS:
236 for type in data.VERSIONS[version]:
Rico Wind3f9302b2018-09-21 08:53:09 +0200237 if (app, version, type) not in DISABLED_PERMUTATIONS:
Tamas Keneza730a7e2018-12-10 15:02:28 +0100238 for use_r8lib in [False, True]:
239 yield app, version, type, use_r8lib
Rico Windb57bbc12018-09-20 19:23:32 +0200240
241def run_all(options, args):
242 # Args will be destroyed
243 assert len(args) == 0
Tamas Keneza730a7e2018-12-10 15:02:28 +0100244 for name, version, type, use_r8lib in get_permutations():
Rico Windb57bbc12018-09-20 19:23:32 +0200245 compiler = 'r8' if type == 'deploy' else 'd8'
Tamas Kenez63a51d02019-01-07 15:53:02 +0100246 compiler_build = 'lib' if use_r8lib else 'full'
247 print('Executing %s/%s with %s %s %s' % (compiler, compiler_build, name,
248 version, type))
Tamas Keneza730a7e2018-12-10 15:02:28 +0100249
Rico Windb57bbc12018-09-20 19:23:32 +0200250 fixed_options = copy.copy(options)
251 fixed_options.app = name
252 fixed_options.version = version
253 fixed_options.compiler = compiler
Tamas Kenez63a51d02019-01-07 15:53:02 +0100254 fixed_options.compiler_build = compiler_build
Rico Windb57bbc12018-09-20 19:23:32 +0200255 fixed_options.type = type
256 exit_code = run_with_options(fixed_options, [])
257 if exit_code != 0:
Tamas Kenez63a51d02019-01-07 15:53:02 +0100258 print('Failed %s %s %s with %s/%s' % (name, version, type, compiler,
259 compiler_build))
Rico Windb57bbc12018-09-20 19:23:32 +0200260 exit(exit_code)
261
Rico Wind5fdec152018-12-17 09:16:14 +0100262def find_min_xmx(options, args):
263 # Args will be destroyed
264 assert len(args) == 0
265 # If we can run in 128 MB then we are good (which we can for small examples
266 # or D8 on medium sized examples)
Morten Krogh-Jespersen04c7c302019-10-01 15:04:33 +0200267 if options.find_min_xmx_min_memory:
268 not_working = options.find_min_xmx_min_memory
269 elif options.compiler == 'd8':
270 not_working = 128
271 else:
272 not_working = 1024
273 if options.find_min_xmx_max_memory:
274 working = options.find_min_xmx_max_memory
275 else:
276 working = 1024 * 8
Rico Wind5fdec152018-12-17 09:16:14 +0100277 exit_code = 0
Morten Krogh-Jespersen70432842021-01-19 17:07:58 +0100278 range = int(options.find_min_xmx_range_size)
Morten Krogh-Jespersen04c7c302019-10-01 15:04:33 +0200279 while working - not_working > range:
Morten Krogh-Jespersen70432842021-01-19 17:07:58 +0100280 next_candidate = int(working - ((working - not_working)/2))
Rico Wind5fdec152018-12-17 09:16:14 +0100281 print('working: %s, non_working: %s, next_candidate: %s' %
282 (working, not_working, next_candidate))
283 extra_args = ['-Xmx%sM' % next_candidate]
Rico Wind5fdec152018-12-17 09:16:14 +0100284 t0 = time.time()
285 exit_code = run_with_options(options, [], extra_args)
286 t1 = time.time()
287 print('Running took: %s ms' % (1000.0 * (t1 - t0)))
Jinseong Jeon158a3f12019-02-08 01:40:59 -0800288 if exit_code != 0:
289 if exit_code not in [OOM_EXIT_CODE, TIMEOUT_KILL_CODE]:
290 print('Non OOM/Timeout error executing, exiting')
291 return 2
Rico Wind5fdec152018-12-17 09:16:14 +0100292 if exit_code == 0:
293 working = next_candidate
Jinseong Jeon158a3f12019-02-08 01:40:59 -0800294 elif exit_code == TIMEOUT_KILL_CODE:
295 print('Timeout. Continue to the next candidate.')
296 not_working = next_candidate
Rico Wind5fdec152018-12-17 09:16:14 +0100297 else:
298 assert exit_code == OOM_EXIT_CODE
299 not_working = next_candidate
300
Morten Krogh-Jespersen04c7c302019-10-01 15:04:33 +0200301 assert working - not_working <= range
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200302 found_range = 'Found range: %s - %s' % (not_working, working)
303 print(found_range)
304
305 if options.find_min_xmx_archive:
306 sha = utils.get_HEAD_sha1()
307 (version, _) = get_version_and_data(options)
308 destination = os.path.join(
309 utils.R8_TEST_RESULTS_BUCKET,
310 FIND_MIN_XMX_DIR,
311 sha,
312 options.compiler,
313 options.compiler_build,
314 options.app,
315 version,
316 get_type(options))
317 gs_destination = 'gs://%s' % destination
318 utils.archive_value(FIND_MIN_XMX_FILE, gs_destination, found_range + '\n')
319
Rico Wind5fdec152018-12-17 09:16:14 +0100320 return 0
321
Morten Krogh-Jespersenf2412302019-10-22 10:18:04 +0200322def print_min_xmx_ranges_for_hash(hash, compiler, compiler_build):
323 app_directory = os.path.join(
324 utils.R8_TEST_RESULTS_BUCKET,
325 FIND_MIN_XMX_DIR,
326 hash,
327 compiler,
328 compiler_build)
329 gs_base = 'gs://%s' % app_directory
330 for app in utils.ls_files_on_cloud_storage(gs_base).strip().split('\n'):
331 for version in utils.ls_files_on_cloud_storage(app).strip().split('\n'):
332 for type in utils.ls_files_on_cloud_storage(version).strip().split('\n'):
333 gs_location = '%s%s' % (type, FIND_MIN_XMX_FILE)
334 value = utils.cat_file_on_cloud_storage(gs_location, ignore_errors=True)
335 print('%s\n' % value)
336
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200337def track_time_in_memory(options, args):
338 # Args will be destroyed
339 assert len(args) == 0
340 if not options.track_time_in_memory_min:
341 raise Exception(
342 'You have to specify --track_time_in_memory_min when running with '
343 '--track-time-in-memory')
344 if not options.track_time_in_memory_max:
345 raise Exception(
346 'You have to specify --track_time_in_memory_max when running with '
347 '--track-time-in-memory')
348 if not options.track_time_in_memory_increment:
349 raise Exception(
350 'You have to specify --track_time_in_memory_increment when running '
351 'with --track-time-in-memory')
352 current = options.track_time_in_memory_min
353 print('Memory (KB)\tTime (ms)')
354 with utils.TempDir() as temp:
355 stdout = os.path.join(temp, 'stdout')
356 stdout_fd = open(stdout, 'w')
357 while current <= options.track_time_in_memory_max:
358 extra_args = ['-Xmx%sM' % current]
359 t0 = time.time()
360 exit_code = run_with_options(options, [], extra_args, stdout_fd, quiet=True)
361 t1 = time.time()
362 total = (1000.0 * (t1 - t0)) if exit_code == 0 else -1
363 print('%s\t%s' % (current, total))
364 current += options.track_time_in_memory_increment
365
366 return 0
367
Tamas Kenez5b1c5852017-07-21 13:38:33 +0200368def main(argv):
Tamas Kenez5b1c5852017-07-21 13:38:33 +0200369 (options, args) = ParseOptions(argv)
Morten Krogh-Jespersenb7e1a182019-10-09 13:04:54 +0200370 if options.expect_oom and not options.max_memory:
371 raise Exception(
372 'You should only use --expect-oom if also specifying --max-memory')
373 if options.expect_oom and options.timeout:
374 raise Exception(
375 'You should not use --timeout when also specifying --expect-oom')
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200376 if options.find_min_xmx and options.track_time_in_memory:
377 raise Exception(
378 'You cannot both find the min xmx and track time at the same time')
Rico Windb57bbc12018-09-20 19:23:32 +0200379 if options.run_all:
380 return run_all(options, args)
Rico Wind5fdec152018-12-17 09:16:14 +0100381 if options.find_min_xmx:
382 return find_min_xmx(options, args)
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200383 if options.track_time_in_memory:
384 return track_time_in_memory(options, args)
Christoffer Quist Adamsend61d2a32020-06-02 07:41:10 +0200385 exit_code = run_with_options(options, args, quiet=options.quiet)
Morten Krogh-Jespersenb7e1a182019-10-09 13:04:54 +0200386 if options.expect_oom:
387 exit_code = 0 if exit_code == OOM_EXIT_CODE else 1
388 return exit_code
Rico Windb57bbc12018-09-20 19:23:32 +0200389
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200390def get_version_and_data(options):
391 if options.app == 'gmscore':
392 version = options.version or 'v9'
393 data = gmscore_data
394 elif options.app == 'nest':
395 version = options.version or '20180926'
396 data = nest_data
397 elif options.app == 'youtube':
398 version = options.version or '12.22'
399 data = youtube_data
400 elif options.app == 'chrome':
401 version = options.version or '180917'
402 data = chrome_data
403 elif options.app == 'gmail':
404 version = options.version or '170604.16'
405 data = gmail_data
406 elif options.app == 'r8':
407 version = options.version or 'cf'
408 data = r8_data
Morten Krogh-Jespersencd6712c2019-10-09 13:09:47 +0200409 elif options.app == 'iosched':
410 version = options.version or '2019'
411 data = iosched_data
Morten Krogh-Jespersen1ba55f52020-04-24 12:49:17 +0200412 elif options.app == 'tachiyomi':
413 version = options.version or 'b15d2fe16864645055af6a745a62cc5566629798'
414 data = tachiyomi_data
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200415 else:
416 raise Exception("You need to specify '--app={}'".format('|'.join(APPS)))
417 return version, data
418
419def get_type(options):
420 if not options.type:
421 return 'deploy' if options.compiler == 'r8' else 'proguarded'
422 return options.type
423
Søren Gjesse94793ca2019-11-08 13:53:08 +0100424def has_injars_and_libraryjars(pgconfs):
425 # Check if there are -injars and -libraryjars in the configuration.
426 has_injars = False
427 has_libraryjars = False
428 for pgconf in pgconfs:
429 pgconf_dirname = os.path.abspath(os.path.dirname(pgconf))
430 with open(pgconf) as pgconf_file:
431 for line in pgconf_file:
432 trimmed = line.strip()
433 if trimmed.startswith('-injars'):
434 has_injars = True
435 elif trimmed.startswith('-libraryjars'):
436 has_libraryjars = True
437 if has_injars and has_libraryjars:
438 return True
439 return False
440
Søren Gjesse889e09d2019-11-07 16:33:51 +0100441def check_no_injars_and_no_libraryjars(pgconfs):
442 # Ensure that there are no -injars or -libraryjars in the configuration.
443 for pgconf in pgconfs:
444 pgconf_dirname = os.path.abspath(os.path.dirname(pgconf))
445 with open(pgconf) as pgconf_file:
446 for line in pgconf_file:
447 trimmed = line.strip()
448 if trimmed.startswith('-injars'):
449 raise Exception("Unexpected -injars found in " + pgconf)
450 elif trimmed.startswith('-libraryjars'):
451 raise Exception("Unexpected -libraryjars found in " + pgconf)
452
Morten Krogh-Jespersen94a9b102019-11-01 09:45:44 +0000453def run_with_options(options, args, extra_args=None, stdout=None, quiet=False):
454 if extra_args is None:
455 extra_args = []
Rico Windb57bbc12018-09-20 19:23:32 +0200456 app_provided_pg_conf = False;
Rico Windadd08132018-12-14 14:17:15 +0100457 # todo(121018500): remove when memory is under control
Rico Wind20602b72019-01-09 09:17:13 +0100458 if not any('-Xmx' in arg for arg in extra_args):
Morten Krogh-Jespersen322c2f12019-10-08 10:41:21 +0200459 if options.max_memory:
460 extra_args.append('-Xmx%sM' % options.max_memory)
461 else:
462 extra_args.append('-Xmx8G')
Rico Wind1f4172c2018-09-06 16:29:03 +0200463 if options.golem:
464 golem.link_third_party()
Rico Wind9bd3f5f2018-10-01 10:53:18 +0200465 options.out = os.getcwd()
Rico Windafdbbfd2019-02-22 09:32:07 +0100466 if not options.ignore_java_version:
467 utils.check_java_version()
468
Søren Gjesse04a94332020-01-27 15:35:42 +0100469 if options.print_times:
470 extra_args.append('-Dcom.android.tools.r8.printtimes=1')
471
Mads Ager418d1ca2017-05-22 09:35:49 +0200472 outdir = options.out
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200473 (version_id, data) = get_version_and_data(options)
474
Tamas Kenez5b1c5852017-07-21 13:38:33 +0200475 if options.compiler not in COMPILERS:
476 raise Exception("You need to specify '--compiler={}'"
477 .format('|'.join(COMPILERS)))
Mads Ager418d1ca2017-05-22 09:35:49 +0200478
Tamas Kenez63a51d02019-01-07 15:53:02 +0100479 if options.compiler_build not in COMPILER_BUILDS:
480 raise Exception("You need to specify '--compiler-build={}'"
481 .format('|'.join(COMPILER_BUILDS)))
482
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200483 if not version_id in data.VERSIONS.keys():
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200484 print('No version {} for application {}'
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200485 .format(version_id, options.app))
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200486 print('Valid versions are {}'.format(data.VERSIONS.keys()))
Mads Ager418d1ca2017-05-22 09:35:49 +0200487 return 1
488
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200489 version = data.VERSIONS[version_id]
Mads Ager418d1ca2017-05-22 09:35:49 +0200490
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200491 type = get_type(options)
Tamas Kenez3fdaabd2017-06-15 13:05:12 +0200492
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200493 if type not in version:
494 print('No type {} for version {}'.format(type, version))
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200495 print('Valid types are {}'.format(version.keys()))
Mads Ager418d1ca2017-05-22 09:35:49 +0200496 return 1
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200497 values = version[type]
Søren Gjesse94793ca2019-11-08 13:53:08 +0100498 inputs = []
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200499 # For R8 'deploy' the JAR is located using the Proguard configuration
Christoffer Quist Adamsena2a58772018-10-03 09:47:46 +0200500 # -injars option. For chrome and nest we don't have the injars in the
501 # proguard files.
Tamas Kenez63a51d02019-01-07 15:53:02 +0100502 if 'inputs' in values and (options.compiler != 'r8'
Morten Krogh-Jespersen0981b722019-10-09 10:00:33 +0200503 or type != 'deploy'
Christoffer Quist Adamsena2a58772018-10-03 09:47:46 +0200504 or options.app == 'chrome'
Morten Krogh-Jespersen04c7c302019-10-01 15:04:33 +0200505 or options.app == 'nest'
Morten Krogh-Jespersencd6712c2019-10-09 13:09:47 +0200506 or options.app == 'r8'
Morten Krogh-Jespersen1ba55f52020-04-24 12:49:17 +0200507 or options.app == 'iosched'
508 or options.app == 'tachiyomi'):
Mads Ager418d1ca2017-05-22 09:35:49 +0200509 inputs = values['inputs']
510
511 args.extend(['--output', outdir])
Ian Zerny877c1862017-07-06 11:12:26 +0200512 if 'min-api' in values:
513 args.extend(['--min-api', values['min-api']])
Søren Gjesse932881f2017-06-13 10:43:36 +0200514
Søren Gjesse8ae55eb2018-09-28 11:11:36 +0200515 if 'main-dex-list' in values:
516 args.extend(['--main-dex-list', values['main-dex-list']])
517
Søren Gjesse94793ca2019-11-08 13:53:08 +0100518 libraries = values['libraries'] if 'libraries' in values else []
Tamas Kenez63a51d02019-01-07 15:53:02 +0100519 if options.compiler == 'r8':
Søren Gjesse932881f2017-06-13 10:43:36 +0200520 if 'pgconf' in values and not options.k:
Søren Gjesse94793ca2019-11-08 13:53:08 +0100521 if has_injars_and_libraryjars(values['pgconf']):
522 sanitized_lib_path = os.path.join(
523 os.path.abspath(outdir), 'sanitized_lib.jar')
Søren Gjesse889e09d2019-11-07 16:33:51 +0100524 sanitized_pgconf_path = os.path.join(
525 os.path.abspath(outdir), 'sanitized.config')
526 SanitizeLibrariesInPgconf(
527 sanitized_lib_path, sanitized_pgconf_path, values['pgconf'])
Søren Gjesse94793ca2019-11-08 13:53:08 +0100528 libraries = [sanitized_lib_path]
Søren Gjesse889e09d2019-11-07 16:33:51 +0100529 args.extend(['--pg-conf', sanitized_pgconf_path])
Søren Gjesse94793ca2019-11-08 13:53:08 +0100530 else:
531 # -injars without -libraryjars or vice versa is not supported.
532 check_no_injars_and_no_libraryjars(values['pgconf'])
533 for pgconf in values['pgconf']:
534 args.extend(['--pg-conf', pgconf])
535 if 'sanitize_libraries' in values and values['sanitize_libraries']:
536 sanitized_lib_path = os.path.join(
537 os.path.abspath(outdir), 'sanitized_lib.jar')
538 SanitizeLibraries(
539 sanitized_lib_path, values['libraries'], values['inputs'])
540 libraries = [sanitized_lib_path]
541 inputs = values['inputs']
Søren Gjessecbeae782019-05-21 14:14:25 +0200542 app_provided_pg_conf = True
Søren Gjesse932881f2017-06-13 10:43:36 +0200543 if options.k:
544 args.extend(['--pg-conf', options.k])
Søren Gjessec801ecc2017-08-03 13:40:06 +0200545 if 'maindexrules' in values:
546 for rules in values['maindexrules']:
547 args.extend(['--main-dex-rules', rules])
Rico Wind79e4eb52018-12-13 13:00:49 +0100548 if 'allow-type-errors' in values:
549 extra_args.append('-Dcom.android.tools.r8.allowTypeErrors=1')
Christoffer Quist Adamsen57254f02020-05-18 15:43:58 +0200550 extra_args.append(
551 '-Dcom.android.tools.r8.disallowClassInlinerGracefulExit=1')
Søren Gjesse932881f2017-06-13 10:43:36 +0200552
Ian Zerny016d6f62020-03-19 08:58:21 +0100553 if options.debug_agent:
554 if not options.compiler_build == 'full':
555 print('WARNING: Running debugging agent on r8lib is questionable...')
556 extra_args.append(
557 '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005')
558
Søren Gjesse94793ca2019-11-08 13:53:08 +0100559 if not options.no_libraries:
560 for lib in libraries:
Mads Ager418d1ca2017-05-22 09:35:49 +0200561 args.extend(['--lib', lib])
562
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200563 if not outdir.endswith('.zip') and not outdir.endswith('.jar') \
564 and not os.path.exists(outdir):
Mads Ager418d1ca2017-05-22 09:35:49 +0200565 os.makedirs(outdir)
566
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +0100567 if options.hash:
568 # Download r8-<hash>.jar from
569 # https://storage.googleapis.com/r8-releases/raw/<hash>/.
570 download_path = archive.GetUploadDestination(options.hash, 'r8.jar', True)
571 assert utils.file_exists_on_cloud_storage(download_path), (
572 'Could not find r8.jar file from provided hash: %s' % options.hash)
573 destination = os.path.join(utils.LIBS, 'r8-' + options.hash + '.jar')
574 utils.download_file_from_cloud_storage(
575 download_path, destination, quiet=quiet)
576
Søren Gjesse8ae55eb2018-09-28 11:11:36 +0200577 # Additional flags for the compiler from the configuration file.
578 if 'flags' in values:
579 args.extend(values['flags'].split(' '))
Tamas Kenez63a51d02019-01-07 15:53:02 +0100580 if options.compiler == 'r8':
Søren Gjesse932881f2017-06-13 10:43:36 +0200581 if 'r8-flags' in values:
582 args.extend(values['r8-flags'].split(' '))
Tamas Kenez139acc12017-06-14 17:14:58 +0200583
Søren Gjesse8ae55eb2018-09-28 11:11:36 +0200584 # Additional flags for the compiler from the command line.
Tamas Kenez139acc12017-06-14 17:14:58 +0200585 if options.compiler_flags:
586 args.extend(options.compiler_flags.split(' '))
587 if options.r8_flags:
588 args.extend(options.r8_flags.split(' '))
Mads Ager418d1ca2017-05-22 09:35:49 +0200589
Christoffer Quist Adamsen287c1862020-05-20 15:51:12 +0200590 # Feature jars.
591 features = values['features'] if 'features' in values else []
592 for i, feature in enumerate(features, start=1):
593 feature_out = os.path.join(outdir, 'feature-%d.zip' % i)
594 for feature_jar in feature['inputs']:
595 args.extend(['--feature', feature_jar, feature_out])
596
Søren Gjesse94793ca2019-11-08 13:53:08 +0100597 args.extend(inputs)
Mads Ager418d1ca2017-05-22 09:35:49 +0200598
Tamas Kenezf2ee2a32017-06-21 10:30:20 +0200599 t0 = time.time()
Mads Ager418d1ca2017-05-22 09:35:49 +0200600 if options.dump_args_file:
601 with open(options.dump_args_file, 'w') as args_file:
602 args_file.writelines([arg + os.linesep for arg in args])
603 else:
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200604 with utils.TempDir() as temp:
605 if options.print_memoryuse and not options.track_memory_to_file:
606 options.track_memory_to_file = os.path.join(temp,
607 utils.MEMORY_USE_TMP_FILE)
Tamas Kenez63a51d02019-01-07 15:53:02 +0100608 if options.compiler == 'r8' and app_provided_pg_conf:
Mathias Ravdd6a6de2018-05-18 10:18:33 +0200609 # Ensure that output of -printmapping and -printseeds go to the output
610 # location and not where the app Proguard configuration places them.
611 if outdir.endswith('.zip') or outdir.endswith('.jar'):
612 pg_outdir = os.path.dirname(outdir)
613 else:
614 pg_outdir = outdir
Christoffer Quist Adamsen3bbb50e2020-05-19 15:00:00 +0200615 if not options.no_extra_pgconf:
616 additional_pg_conf = GenerateAdditionalProguardConfiguration(
617 temp, os.path.abspath(pg_outdir))
618 args.extend(['--pg-conf', additional_pg_conf])
Rico Wind1f4172c2018-09-06 16:29:03 +0200619 build = not options.no_build and not options.golem
Rico Wind5fdec152018-12-17 09:16:14 +0100620 stderr_path = os.path.join(temp, 'stderr')
621 with open(stderr_path, 'w') as stderr:
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +0100622 jar = None
623 main = None
Tamas Kenez63a51d02019-01-07 15:53:02 +0100624 if options.compiler_build == 'full':
625 tool = options.compiler
626 else:
627 assert(options.compiler_build == 'lib')
628 tool = 'r8lib-' + options.compiler
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +0100629 if options.hash:
630 jar = os.path.join(utils.LIBS, 'r8-' + options.hash + '.jar')
631 main = 'com.android.tools.r8.' + options.compiler.upper()
Tamas Kenez63a51d02019-01-07 15:53:02 +0100632 exit_code = toolhelper.run(tool, args,
Rico Wind5fdec152018-12-17 09:16:14 +0100633 build=build,
634 debug=not options.no_debug,
635 profile=options.profile,
636 track_memory_file=options.track_memory_to_file,
Jinseong Jeon158a3f12019-02-08 01:40:59 -0800637 extra_args=extra_args,
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200638 stdout=stdout,
Jinseong Jeon158a3f12019-02-08 01:40:59 -0800639 stderr=stderr,
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200640 timeout=options.timeout,
Søren Gjesse943389f2020-03-13 10:40:25 +0100641 quiet=quiet,
Morten Krogh-Jespersen0e4d7e22020-03-14 00:56:32 +0100642 cmd_prefix=[
Christoffer Quist Adamsen870fa462020-12-15 10:50:54 +0100643 'taskset', '-c', options.cpu_list] if options.cpu_list else [],
644 jar=jar,
645 main=main)
Christoffer Quist Adamsen21c66602018-08-09 16:22:54 +0200646 if exit_code != 0:
Rico Wind5fdec152018-12-17 09:16:14 +0100647 with open(stderr_path) as stderr:
648 stderr_text = stderr.read()
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200649 if not quiet:
650 print(stderr_text)
Rico Wind5fdec152018-12-17 09:16:14 +0100651 if 'java.lang.OutOfMemoryError' in stderr_text:
Morten Krogh-Jespersenae9557c2019-10-23 15:14:02 +0200652 if not quiet:
653 print('Failure was OOM')
Rico Wind5fdec152018-12-17 09:16:14 +0100654 return OOM_EXIT_CODE
655 return exit_code
Christoffer Quist Adamsen21c66602018-08-09 16:22:54 +0200656
Tamas Kenezfc34cd82017-07-13 12:43:57 +0200657 if options.print_memoryuse:
658 print('{}(MemoryUse): {}'
659 .format(options.print_memoryuse,
660 utils.grep_memoryuse(options.track_memory_to_file)))
Mads Ager418d1ca2017-05-22 09:35:49 +0200661
Tamas Kenezf2ee2a32017-06-21 10:30:20 +0200662 if options.print_runtimeraw:
663 print('{}(RunTimeRaw): {} ms'
664 .format(options.print_runtimeraw, 1000.0 * (time.time() - t0)))
665
Tamas Kenez02bff032017-07-18 12:13:58 +0200666 if options.print_dexsegments:
667 dex_files = glob(os.path.join(outdir, '*.dex'))
668 utils.print_dexsegments(options.print_dexsegments, dex_files)
Rico Windb57bbc12018-09-20 19:23:32 +0200669 return 0
Tamas Kenez02bff032017-07-18 12:13:58 +0200670
Mads Ager418d1ca2017-05-22 09:35:49 +0200671if __name__ == '__main__':
Tamas Kenez5b1c5852017-07-21 13:38:33 +0200672 sys.exit(main(sys.argv[1:]))