blob: 3abe651e5eca73789b17e4527c29d517a75b40bb [file] [log] [blame]
Ian Zernydcb172e2022-02-22 15:36:45 +01001#!/usr/bin/env python3
Ian Zerny5ffa58f2020-02-26 08:37:14 +01002# Copyright (c) 2020, 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
6import argparse
7import os
Christoffer Quist Adamsen3f21c2b2023-02-28 09:37:22 +01008import shutil
Ian Zerny5ffa58f2020-02-26 08:37:14 +01009import subprocess
10import sys
11import zipfile
12
Ian Zerny0e53ff12021-06-15 13:40:14 +020013import archive
Søren Gjesse1c8899c2023-11-23 12:06:17 +010014import gradle
Ian Zerny0e53ff12021-06-15 13:40:14 +020015import jdk
16import retrace
Ian Zerny5ffa58f2020-02-26 08:37:14 +010017import utils
18
19
20def make_parser():
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020021 parser = argparse.ArgumentParser(description='Compile a dump artifact.')
22 parser.add_argument('--summary',
23 help='List a summary of the contents of the dumps.',
24 default=False,
25 action='store_true')
26 parser.add_argument('-d',
27 '--dump',
28 help='Dump file or directory to compile',
29 default=None)
30 parser.add_argument('-o',
31 '--output',
32 help='File to output (defaults to out.jar in temp)',
33 default=None)
34 parser.add_argument(
35 '--temp',
36 help=
37 'Temp directory to extract the dump to, allows you to rerun the command'
38 ' more easily in the terminal with changes',
39 default=None)
40 parser.add_argument('-c',
41 '--compiler',
42 help='Compiler to use',
43 default=None)
44 parser.add_argument('--minify',
45 help='Force enable/disable minification'
46 ' (defaults to app proguard config)',
47 choices=['default', 'force-enable', 'force-disable'],
48 default='default')
49 parser.add_argument('--optimize',
50 help='Force enable/disable optimizations'
51 ' (defaults to app proguard config)',
52 choices=['default', 'force-enable', 'force-disable'],
53 default='default')
54 parser.add_argument('--shrink',
55 help='Force enable/disable shrinking'
56 ' (defaults to app proguard config)',
57 choices=['default', 'force-enable', 'force-disable'],
58 default='default')
59 parser.add_argument(
60 '-v',
61 '--version',
62 help='Compiler version to use (default read from dump version file).'
63 'Valid arguments are:'
64 ' "main" to run from your own tree,'
65 ' "source" to run from build classes directly,'
66 ' "X.Y.Z" to run a specific version, or'
67 ' <hash> to run that hash from main.',
68 default=None)
69 parser.add_argument('--r8-jar', help='Path to an R8 jar.', default=None)
70 parser.add_argument('--r8-flags',
71 '--r8_flags',
72 help='Additional option(s) for the compiler.')
73 parser.add_argument('--pg-conf',
74 '--pg_conf',
75 help='Keep rule file(s).',
76 action='append')
77 parser.add_argument('--override',
78 help='Do not override any extracted dump in temp-dir',
79 default=False,
80 action='store_true')
81 parser.add_argument(
82 '--nolib',
83 help='Use the non-lib distribution (default uses the lib distribution)',
84 default=False,
85 action='store_true')
86 parser.add_argument('--print-times',
87 help='Print timing information from r8',
88 default=False,
89 action='store_true')
90 parser.add_argument(
91 '--disable-assertions',
92 '--disable_assertions',
93 '-da',
94 help=
95 'Disable Java assertions when running the compiler (default enabled)',
96 default=False,
97 action='store_true')
Søren Gjessef8772cb2023-11-24 09:55:23 +010098 parser.add_argument(
99 '--enable-test-assertions',
100 '--enable_test_assertions',
101 help=
102 'Enable additional test assertions when running the compiler (default disabled)',
103 default=False,
104 action='store_true')
105 parser.add_argument(
106 '--java-opts',
107 '--java-opts',
108 '-J',
109 metavar='<JVM argument(s)>',
110 default=[],
111 action='append',
112 help='Additional options to pass to JVM invocation')
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200113 parser.add_argument('--classfile',
114 help='Run with classfile output',
115 default=False,
116 action='store_true')
117 parser.add_argument(
118 '--debug-agent',
119 help=
120 'Enable Java debug agent and suspend compilation (default disabled)',
121 default=False,
122 action='store_true')
123 parser.add_argument('--xmx',
124 help='Set JVM max heap size (-Xmx)',
125 default=None)
126 parser.add_argument('--threads',
127 help='Set the number of threads to use',
128 default=None)
129 parser.add_argument(
130 '--min-api',
131 help='Set min-api (default read from dump properties file)',
132 default=None)
133 parser.add_argument('--desugared-lib',
134 help='Set desugared-library (default set from dump)',
135 default=None)
136 parser.add_argument(
137 '--disable-desugared-lib',
138 help='Disable desugared-libary if it will be set from dump',
139 default=False,
140 action='store_true')
141 parser.add_argument('--loop',
142 help='Run the compilation in a loop',
143 default=False,
144 action='store_true')
145 parser.add_argument('--enable-missing-library-api-modeling',
146 help='Run with api modeling',
147 default=False,
148 action='store_true')
149 parser.add_argument('--android-platform-build',
150 help='Run as a platform build',
151 default=False,
152 action='store_true')
153 parser.add_argument('--compilation-mode',
154 '--compilation_mode',
155 help='Run compilation in specified mode',
156 choices=['debug', 'release'],
157 default=None)
Søren Gjesse1c8899c2023-11-23 12:06:17 +0100158 parser.add_argument(
Søren Gjesse95597812023-11-23 15:00:37 +0100159 '--ignore-features',
160 help="Don't split into features when features are present."
161 ' Instead include feature code in main app output.'
162 ' This is always the case when compiler is d8.',
163 default=False,
164 action='store_true')
165 parser.add_argument(
Søren Gjesse1c8899c2023-11-23 12:06:17 +0100166 '--no-build',
167 help="Don't build when using --version main",
168 default=False,
169 action='store_true')
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200170 return parser
171
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100172
173def error(msg):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200174 print(msg)
175 sys.exit(1)
176
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100177
178class Dump(object):
179
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200180 def __init__(self, directory):
181 self.directory = directory
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100182
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200183 def if_exists(self, name):
184 f = os.path.join(self.directory, name)
185 if os.path.exists(f):
186 return f
187 return None
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100188
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200189 def program_jar(self):
190 return self.if_exists('program.jar')
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100191
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200192 def feature_jars(self):
193 feature_jars = []
194 i = 1
195 while True:
196 feature_jar = self.if_exists('feature-%s.jar' % i)
197 if feature_jar:
198 feature_jars.append(feature_jar)
199 i = i + 1
200 else:
201 return feature_jars
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200202
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200203 def library_jar(self):
204 return self.if_exists('library.jar')
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100205
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200206 def classpath_jar(self):
207 return self.if_exists('classpath.jar')
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100208
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200209 def desugared_library_json(self):
210 return self.if_exists('desugared-library.json')
Clément Béradaae4ca2020-10-27 14:26:41 +0000211
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200212 def proguard_input_map(self):
213 if self.if_exists('proguard_input.config'):
214 print("Unimplemented: proguard_input configuration.")
Clément Béra64a3c4c2020-11-10 08:16:17 +0000215
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200216 def main_dex_list_resource(self):
217 return self.if_exists('main-dex-list.txt')
Clément Béra64a3c4c2020-11-10 08:16:17 +0000218
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200219 def main_dex_rules_resource(self):
220 return self.if_exists('main-dex-rules.txt')
Morten Krogh-Jespersen1e774252021-03-01 16:56:07 +0100221
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200222 def art_profile_resources(self):
223 art_profile_resources = []
224 while True:
225 current_art_profile_index = len(art_profile_resources) + 1
226 art_profile_resource = self.if_exists('art-profile-%s.txt' %
227 current_art_profile_index)
228 if art_profile_resource is None:
229 return art_profile_resources
230 art_profile_resources.append(art_profile_resource)
Christoffer Quist Adamsen819273a2023-03-02 15:20:45 +0100231
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200232 def startup_profile_resources(self):
233 startup_profile_resources = []
234 while True:
235 current_startup_profile_index = len(startup_profile_resources) + 1
236 startup_profile_resource = self.if_exists(
237 'startup-profile-%s.txt' % current_startup_profile_index)
238 if startup_profile_resource is None:
239 return startup_profile_resources
240 startup_profile_resources.append(startup_profile_resource)
Christoffer Quist Adamsencd7f7ec2022-08-26 13:39:11 +0200241
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200242 def build_properties_file(self):
243 return self.if_exists('build.properties')
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200244
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200245 def config_file(self):
246 return self.if_exists('proguard.config')
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100247
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200248 def version_file(self):
249 return self.if_exists('r8-version')
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100250
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200251 def version(self):
252 f = self.version_file()
253 if f:
254 return open(f).read().split(' ')[0]
255 return None
256
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100257
Ian Zerny0e53ff12021-06-15 13:40:14 +0200258def read_dump_from_args(args, temp):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200259 if args.dump is None:
260 error("A dump file or directory must be specified")
261 return read_dump(args.dump, temp, args.override)
262
Ian Zerny0e53ff12021-06-15 13:40:14 +0200263
264def read_dump(dump, temp, override=False):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200265 if os.path.isdir(dump):
266 return Dump(dump)
267 dump_file = zipfile.ZipFile(os.path.abspath(dump), 'r')
268 r8_version_file = os.path.join(temp, 'r8-version')
Christoffer Quist Adamsenbe6661d2023-08-24 11:01:12 +0200269
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200270 if override or not os.path.isfile(r8_version_file):
271 dump_file.extractall(temp)
272 if not os.path.isfile(r8_version_file):
273 error(
274 "Did not extract into %s. Either the zip file is invalid or the "
275 "dump is missing files" % temp)
276 return Dump(temp)
277
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100278
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200279def determine_build_properties(args, dump):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200280 build_properties = {}
281 build_properties_file = dump.build_properties_file()
282 if build_properties_file:
283 with open(build_properties_file) as f:
284 build_properties_contents = f.readlines()
285 for line in build_properties_contents:
286 stripped = line.strip()
287 if stripped:
288 pair = stripped.split('=')
289 build_properties[pair[0]] = pair[1]
290 if 'mode' not in build_properties:
291 build_properties['mode'] = 'release'
292 return build_properties
293
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200294
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100295def determine_version(args, dump):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200296 if args.version is None:
297 return dump.version()
298 return args.version
299
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100300
Søren Gjesse0f8d88b2021-09-28 15:15:54 +0200301def determine_compiler(args, build_properties):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200302 compilers = ['d8', 'r8', 'r8full', 'l8', 'l8d8', 'tracereferences']
303 compiler = args.compiler
304 if not compiler and 'tool' in build_properties:
305 compiler = build_properties.get('tool').lower()
306 if compiler == 'r8':
307 if not 'force-proguard-compatibility' in build_properties:
308 error(
309 "Unable to determine R8 compiler variant from build.properties."
310 " No value for 'force-proguard-compatibility'.")
311 if build_properties.get(
312 'force-proguard-compatibility').lower() == 'false':
313 compiler = compiler + 'full'
314 if compiler == 'TraceReferences':
315 compiler = build_properties.get('tool').lower()
316 if compiler not in compilers:
317 error("Unable to determine a compiler to use. Specified %s,"
318 " Valid options: %s" % (args.compiler, ', '.join(compilers)))
319 return compiler
320
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100321
Morten Krogh-Jespersendd12e782023-03-01 16:34:51 +0100322def determine_trace_references_commands(build_properties, output):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200323 trace_ref_consumer = build_properties.get('trace_references_consumer')
324 if trace_ref_consumer == 'com.android.tools.r8.tracereferences.TraceReferencesCheckConsumer':
325 return ["--check"]
326 else:
327 assert trace_ref_consumer == 'com.android.tools.r8.tracereferences.TraceReferencesKeepRules'
328 args = ['--allowobfuscation'
329 ] if build_properties.get('minification') == 'true' else []
330 args.extend(['--keep-rules', '--output', output])
331 return args
332
Morten Krogh-Jespersendd12e782023-03-01 16:34:51 +0100333
Christoffer Quist Adamsen7953d0a2023-02-27 12:08:33 +0100334def is_l8_compiler(compiler):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200335 return compiler.startswith('l8')
336
Christoffer Quist Adamsen7953d0a2023-02-27 12:08:33 +0100337
Christoffer Quist Adamsen3f21c2b2023-02-28 09:37:22 +0100338def is_r8_compiler(compiler):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200339 return compiler.startswith('r8')
340
Christoffer Quist Adamsen3f21c2b2023-02-28 09:37:22 +0100341
342def determine_config_files(args, dump, temp):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200343 if args.pg_conf:
344 config_files = []
345 for config_file in args.pg_conf:
346 dst = os.path.join(temp, 'proguard-%s.config' % len(config_files))
347 shutil.copyfile(config_file, dst)
348 config_files.append(dst)
349 return config_files
350 dump_config_file = dump.config_file()
351 if dump_config_file:
352 return [dump_config_file]
353 return []
354
Christoffer Quist Adamsen3f21c2b2023-02-28 09:37:22 +0100355
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100356def determine_output(args, temp):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200357 if (args.output):
358 return args.output
359 return os.path.join(temp, 'out.jar')
360
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100361
Ian Zerny77bdf5f2020-07-08 11:46:24 +0200362def determine_min_api(args, build_properties):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200363 if args.min_api:
364 return args.min_api
365 if 'min-api' in build_properties:
366 return build_properties.get('min-api')
Ian Zerny9ff31b72021-04-22 11:36:26 +0200367 return None
368
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200369
370def determine_residual_art_profile_output(art_profile, temp):
371 return os.path.join(temp, os.path.basename(art_profile)[:-4] + ".out.txt")
372
373
374def determine_desugared_lib_pg_conf_output(temp):
375 return os.path.join(temp, 'desugared-library-keep-rules.config')
376
377
378def determine_feature_output(feature_jar, temp):
Søren Gjesse95597812023-11-23 15:00:37 +0100379 return os.path.join(
380 args.output if args.output and os.path.isdir(args.output) else temp,
381 os.path.basename(feature_jar)[:-4] + ".out.jar")
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200382
383
384def determine_program_jar(args, dump):
385 if hasattr(args, 'program_jar') and args.program_jar:
386 return args.program_jar
387 return dump.program_jar()
388
389
390def determine_class_file(args, build_properties):
391 return args.classfile \
392 or build_properties.get('backend', 'dex').lower() == 'cf'
393
394
395def determine_android_platform_build(args, build_properties):
396 if args.android_platform_build:
397 return True
398 return build_properties.get('android-platform-build') == 'true'
399
400
401def determine_enable_missing_library_api_modeling(args, build_properties):
402 if args.enable_missing_library_api_modeling:
403 return True
404 return build_properties.get('enable-missing-library-api-modeling') == 'true'
405
406
407def determine_compilation_mode(args, build_properties):
408 if args.compilation_mode:
409 return args.compilation_mode
410 return build_properties.get('mode')
411
412
413def determine_properties(build_properties):
414 args = []
415 for key, value in build_properties.items():
416 # When writing dumps all system properties starting with com.android.tools.r8
417 # are written to the build.properties file in the format
418 # system-property-com.android.tools.r8.XXX=<value>
419 if key.startswith('system-property-'):
420 name = key[len('system-property-'):]
421 if name.endswith('dumpinputtofile') or name.endswith(
422 'dumpinputtodirectory'):
423 continue
424 if len(value) == 0:
425 args.append('-D' + name)
426 else:
427 args.append('-D' + name + '=' + value)
428 return args
429
430
431def download_distribution(version, args, temp):
432 nolib = args.nolib
433 if version == 'main':
Søren Gjesse1c8899c2023-11-23 12:06:17 +0100434 if not args.no_build:
435 gradle.RunGradle(
436 [utils.GRADLE_TASK_R8] if nolib else [utils.GRADLE_TASK_R8LIB]
437 )
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200438 return utils.R8_JAR if nolib else utils.R8LIB_JAR
439 if version == 'source':
440 return '%s:%s' % (utils.BUILD_JAVA_MAIN_DIR, utils.ALL_DEPS_JAR)
441 name = 'r8.jar' if nolib else 'r8lib.jar'
442 source = archive.GetUploadDestination(version, name, is_hash(version))
443 dest = os.path.join(temp, 'r8.jar')
444 utils.download_file_from_cloud_storage(source, dest)
445 return dest
446
447
448def clean_configs(files, args):
449 for file in files:
450 clean_config(file, args)
451
452
453def clean_config(file, args):
454 with open(file) as f:
455 lines = f.readlines()
456 minify = args.minify
457 optimize = args.optimize
458 shrink = args.shrink
459 with open(file, 'w') as f:
460 if minify == 'force-disable':
461 print('Adding config line: -dontobfuscate')
462 f.write('-dontobfuscate\n')
463 if optimize == 'force-disable':
464 print('Adding config line: -dontoptimize')
465 f.write('-dontoptimize\n')
466 if shrink == 'force-disable':
467 print('Adding config line: -dontshrink')
468 f.write('-dontshrink\n')
469 for line in lines:
470 if clean_config_line(line, minify, optimize, shrink):
471 print('Removing from config line: \n%s' % line)
472 else:
473 f.write(line)
474
475
476def clean_config_line(line, minify, optimize, shrink):
477 if line.lstrip().startswith('#'):
478 return False
479 if ('-injars' in line or '-libraryjars' in line or '-print' in line or
480 '-applymapping' in line):
481 return True
482 if minify == 'force-enable' and '-dontobfuscate' in line:
483 return True
484 if optimize == 'force-enable' and '-dontoptimize' in line:
485 return True
486 if shrink == 'force-enable' and '-dontshrink' in line:
487 return True
488 return False
489
490
491def prepare_r8_wrapper(dist, temp, jdkhome):
492 compile_wrapper_with_javac(
493 dist, temp, jdkhome,
494 os.path.join(
495 utils.REPO_ROOT,
496 'src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java')
497 )
498
499
500def prepare_d8_wrapper(dist, temp, jdkhome):
501 compile_wrapper_with_javac(
502 dist, temp, jdkhome,
503 os.path.join(
504 utils.REPO_ROOT,
505 'src/main/java/com/android/tools/r8/utils/CompileDumpD8.java'))
506
507
508def compile_wrapper_with_javac(dist, temp, jdkhome, path):
509 base_path = os.path.join(
510 utils.REPO_ROOT,
511 'src/main/java/com/android/tools/r8/utils/CompileDumpBase.java')
512 cmd = [
513 jdk.GetJavacExecutable(jdkhome),
514 path,
515 base_path,
516 '-d',
517 temp,
518 '-cp',
519 dist,
520 ]
521 utils.PrintCmd(cmd)
522 subprocess.check_output(cmd)
523
524
525def is_hash(version):
526 return len(version) == 40
527
528
529def run1(out, args, otherargs, jdkhome=None, worker_id=None):
530 jvmargs = []
531 compilerargs = []
532 for arg in otherargs:
533 if arg.startswith('-D'):
534 jvmargs.append(arg)
535 else:
536 compilerargs.append(arg)
537 with utils.TempDir() as temp:
538 if out:
539 temp = out
540 if not os.path.exists(temp):
541 os.makedirs(temp)
542 dump = read_dump_from_args(args, temp)
543 if not dump.program_jar():
544 error("Cannot compile dump with no program classes")
545 if not dump.library_jar():
546 print("WARNING: Unexpected lack of library classes in dump")
547 build_properties = determine_build_properties(args, dump)
548 version = determine_version(args, dump)
549 compiler = determine_compiler(args, build_properties)
550 config_files = determine_config_files(args, dump, temp)
551 out = determine_output(args, temp)
552 min_api = determine_min_api(args, build_properties)
553 classfile = determine_class_file(args, build_properties)
554 android_platform_build = determine_android_platform_build(
555 args, build_properties)
556 enable_missing_library_api_modeling = determine_enable_missing_library_api_modeling(
557 args, build_properties)
558 mode = determine_compilation_mode(args, build_properties)
559 jar = args.r8_jar if args.r8_jar else download_distribution(
560 version, args, temp)
561 if ':' not in jar and not os.path.exists(jar):
562 error("Distribution does not exist: " + jar)
563 cmd = [jdk.GetJavaExecutable(jdkhome)]
564 cmd.extend(jvmargs)
565 if args.debug_agent:
566 if not args.nolib:
567 print(
568 "WARNING: Running debugging agent on r8lib is questionable..."
569 )
570 cmd.append(
571 '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005'
572 )
573 if args.xmx:
574 cmd.append('-Xmx' + args.xmx)
575 if not args.disable_assertions:
576 cmd.append('-ea')
Søren Gjessef8772cb2023-11-24 09:55:23 +0100577 if args.enable_test_assertions:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200578 cmd.append('-Dcom.android.tools.r8.enableTestAssertions=1')
579 if args.print_times:
580 cmd.append('-Dcom.android.tools.r8.printtimes=1')
581 if args.r8_flags:
582 cmd.extend(args.r8_flags.split(' '))
583 if hasattr(args, 'properties'):
584 cmd.extend(args.properties)
585 cmd.extend(determine_properties(build_properties))
Søren Gjessef8772cb2023-11-24 09:55:23 +0100586 cmd.extend(args.java_opts)
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200587 cmd.extend(['-cp', '%s:%s' % (temp, jar)])
588 if compiler == 'd8':
589 prepare_d8_wrapper(jar, temp, jdkhome)
590 cmd.append('com.android.tools.r8.utils.CompileDumpD8')
591 if is_l8_compiler(compiler):
592 cmd.append('com.android.tools.r8.L8')
593 if compiler == 'tracereferences':
594 cmd.append('com.android.tools.r8.tracereferences.TraceReferences')
595 cmd.extend(
596 determine_trace_references_commands(build_properties, out))
597 if compiler.startswith('r8'):
598 prepare_r8_wrapper(jar, temp, jdkhome)
599 cmd.append('com.android.tools.r8.utils.CompileDumpCompatR8')
600 if compiler == 'r8':
601 cmd.append('--compat')
602 if compiler != 'tracereferences':
603 assert mode == 'debug' or mode == 'release'
604 cmd.append('--' + mode)
605 # For recompilation of dumps run_on_app_dumps pass in a program jar.
606 program_jar = determine_program_jar(args, dump)
607 if compiler != 'tracereferences':
608 cmd.append(program_jar)
609 cmd.extend(['--output', out])
610 else:
611 cmd.extend(['--source', program_jar])
612 for feature_jar in dump.feature_jars():
Søren Gjesse95597812023-11-23 15:00:37 +0100613 if not args.ignore_features and compiler != 'd8':
614 cmd.extend([
615 '--feature-jar', feature_jar,
616 determine_feature_output(feature_jar, temp)
617 ])
618 else:
619 cmd.append(feature_jar)
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200620 if dump.library_jar():
621 cmd.extend(['--lib', dump.library_jar()])
622 if dump.classpath_jar() and not is_l8_compiler(compiler):
623 cmd.extend([
624 '--target' if compiler == 'tracereferences' else '--classpath',
625 dump.classpath_jar()
626 ])
627 if dump.desugared_library_json() and not args.disable_desugared_lib:
628 cmd.extend(['--desugared-lib', dump.desugared_library_json()])
629 if not is_l8_compiler(compiler):
630 cmd.extend([
631 '--desugared-lib-pg-conf-output',
632 determine_desugared_lib_pg_conf_output(temp)
633 ])
634 if (is_r8_compiler(compiler) or compiler == 'l8') and config_files:
635 if hasattr(args,
636 'config_files_consumer') and args.config_files_consumer:
637 args.config_files_consumer(config_files)
638 else:
639 # If we get a dump from the wild we can't use -injars, -libraryjars or
640 # -print{mapping,usage}
641 clean_configs(config_files, args)
642 for config_file in config_files:
643 cmd.extend(['--pg-conf', config_file])
644 cmd.extend(['--pg-map-output', '%s.map' % out])
645 if dump.main_dex_list_resource():
646 cmd.extend(['--main-dex-list', dump.main_dex_list_resource()])
647 if dump.main_dex_rules_resource():
648 cmd.extend(['--main-dex-rules', dump.main_dex_rules_resource()])
649 for art_profile_resource in dump.art_profile_resources():
650 residual_art_profile_output = \
651 determine_residual_art_profile_output(art_profile_resource, temp)
652 cmd.extend([
653 '--art-profile', art_profile_resource,
654 residual_art_profile_output
655 ])
656 for startup_profile_resource in dump.startup_profile_resources():
657 cmd.extend(['--startup-profile', startup_profile_resource])
658 if min_api:
659 cmd.extend(['--min-api', min_api])
660 if classfile:
661 cmd.extend(['--classfile'])
662 if android_platform_build:
663 cmd.extend(['--android-platform-build'])
664 if enable_missing_library_api_modeling:
665 cmd.extend(['--enable-missing-library-api-modeling'])
666 if args.threads:
667 cmd.extend(['--threads', args.threads])
668 cmd.extend(compilerargs)
669 utils.PrintCmd(cmd, worker_id=worker_id)
670 try:
671 print(
672 subprocess.check_output(
673 cmd, stderr=subprocess.STDOUT).decode('utf-8'))
674 return 0
675 except subprocess.CalledProcessError as e:
676 if args.nolib \
677 or version == 'source' \
678 or not try_retrace_output(e, version, temp):
679 print(e.output.decode('UTF-8'))
680 return 1
681
682
683def try_retrace_output(e, version, temp):
Ian Zerny0e53ff12021-06-15 13:40:14 +0200684 try:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200685 stacktrace = os.path.join(temp, 'stacktrace')
686 open(stacktrace, 'w+').write(e.output.decode('UTF-8'))
687 print("=" * 80)
688 print(" RETRACED OUTPUT")
689 print("=" * 80)
690 retrace.run(get_map_file(version, temp),
691 stacktrace,
692 None,
693 no_r8lib=False)
694 return True
695 except Exception as e2:
696 print("Failed to retrace for version: %s" % version)
697 print(e2)
698 return False
699
700
701def get_map_file(version, temp):
702 if version == 'main':
703 return utils.R8LIB_MAP
704 download_path = archive.GetUploadDestination(version, 'r8lib.jar.map',
705 is_hash(version))
706 if utils.file_exists_on_cloud_storage(download_path):
707 map_path = os.path.join(temp, 'mapping.map')
708 utils.download_file_from_cloud_storage(download_path, map_path)
709 return map_path
710 else:
711 print('Could not find map file from argument: %s.' % version)
712 return None
713
714
715def summarize_dump_files(dumpfiles):
716 if len(dumpfiles) == 0:
717 error('Summary command expects a list of dumps to summarize')
718 for f in dumpfiles:
719 print(f + ':')
720 try:
721 with utils.TempDir() as temp:
722 dump = read_dump(f, temp)
723 summarize_dump(dump)
724 except IOError as e:
725 print("Error: " + str(e))
726 except zipfile.BadZipfile as e:
727 print("Error: " + str(e))
728
Ian Zerny0e53ff12021-06-15 13:40:14 +0200729
730def summarize_dump(dump):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200731 version = dump.version()
732 if not version:
733 print('No dump version info')
734 return
735 print('version=' + version)
736 props = dump.build_properties_file()
737 if props:
738 with open(props) as props_file:
739 print(props_file.read())
740 if dump.library_jar():
741 print('library.jar present')
742 if dump.classpath_jar():
743 print('classpath.jar present')
744 prog = dump.program_jar()
745 if prog:
746 print('program.jar content:')
747 summarize_jar(prog)
748
Ian Zerny0e53ff12021-06-15 13:40:14 +0200749
750def summarize_jar(jar):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200751 with zipfile.ZipFile(jar) as zip:
752 pkgs = {}
753 for info in zip.infolist():
754 if info.filename.endswith('.class'):
755 pkg, clazz = os.path.split(info.filename)
756 count = pkgs.get(pkg, 0)
757 pkgs[pkg] = count + 1
758 sorted = list(pkgs.keys())
759 sorted.sort()
760 for p in sorted:
761 print(' ' + p + ': ' + str(pkgs[p]))
762
Ian Zerny0e53ff12021-06-15 13:40:14 +0200763
Søren Gjesse7360f2b2020-08-10 09:13:35 +0200764def run(args, otherargs):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200765 if args.summary:
766 summarize_dump_files(otherargs)
767 elif args.loop:
768 count = 1
769 while True:
770 print('Iteration {:03d}'.format(count))
771 out = args.temp
772 if out:
773 out = os.path.join(out, '{:03d}'.format(count))
774 run1(out, args, otherargs)
775 count += 1
776 else:
777 run1(args.temp, args, otherargs)
778
Søren Gjesse7360f2b2020-08-10 09:13:35 +0200779
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100780if __name__ == '__main__':
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200781 (args, otherargs) = make_parser().parse_known_args(sys.argv[1:])
782 sys.exit(run(args, otherargs))