blob: 60f50ace741c04331aa008580f88250c8fca669d [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
14import jdk
15import retrace
Ian Zerny5ffa58f2020-02-26 08:37:14 +010016import utils
17
18
19def make_parser():
20 parser = argparse.ArgumentParser(description = 'Compile a dump artifact.')
21 parser.add_argument(
Ian Zerny0e53ff12021-06-15 13:40:14 +020022 '--summary',
23 help='List a summary of the contents of the dumps.',
24 default=False,
25 action='store_true')
26 parser.add_argument(
Ian Zerny5ffa58f2020-02-26 08:37:14 +010027 '-d',
28 '--dump',
Christoffer Quist Adamsend84a6f02020-05-16 12:29:35 +020029 help='Dump file or directory to compile',
Ian Zerny5ffa58f2020-02-26 08:37:14 +010030 default=None)
31 parser.add_argument(
Søren Gjesseaee909b2023-09-22 17:16:12 +020032 '-o',
33 '--output',
34 help='File to output (defaults to out.jar in temp)',
35 default=None)
36 parser.add_argument(
Rico Wind9ed87b92020-03-06 12:37:18 +010037 '--temp',
38 help='Temp directory to extract the dump to, allows you to rerun the command'
39 ' more easily in the terminal with changes',
40 default=None)
41 parser.add_argument(
Ian Zerny5ffa58f2020-02-26 08:37:14 +010042 '-c',
43 '--compiler',
Rico Windf73f18d2020-03-03 09:28:54 +010044 help='Compiler to use',
Ian Zerny5ffa58f2020-02-26 08:37:14 +010045 default=None)
46 parser.add_argument(
Christoffer Quist Adamsenf86fc0b2021-12-10 12:39:36 +010047 '--minify',
48 help='Force enable/disable minification'
49 ' (defaults to app proguard config)',
50 choices=['default', 'force-enable', 'force-disable'],
51 default='default')
52 parser.add_argument(
53 '--optimize',
54 help='Force enable/disable optimizations'
55 ' (defaults to app proguard config)',
56 choices=['default', 'force-enable', 'force-disable'],
57 default='default')
58 parser.add_argument(
59 '--shrink',
60 help='Force enable/disable shrinking'
61 ' (defaults to app proguard config)',
62 choices=['default', 'force-enable', 'force-disable'],
63 default='default')
64 parser.add_argument(
Ian Zerny5ffa58f2020-02-26 08:37:14 +010065 '-v',
66 '--version',
67 help='Compiler version to use (default read from dump version file).'
68 'Valid arguments are:'
Rico Wind1b52acf2021-03-21 12:36:55 +010069 ' "main" to run from your own tree,'
Morten Krogh-Jespersen51db2b02020-11-11 12:49:26 +010070 ' "source" to run from build classes directly,'
Ian Zerny5ffa58f2020-02-26 08:37:14 +010071 ' "X.Y.Z" to run a specific version, or'
Rico Wind1b52acf2021-03-21 12:36:55 +010072 ' <hash> to run that hash from main.',
Ian Zerny5ffa58f2020-02-26 08:37:14 +010073 default=None)
74 parser.add_argument(
Morten Krogh-Jespersend8bceb52020-03-06 12:56:48 +010075 '--r8-jar',
76 help='Path to an R8 jar.',
77 default=None)
78 parser.add_argument(
Christoffer Quist Adamsen2f48f3f2021-10-14 17:25:03 +020079 '--r8-flags', '--r8_flags',
80 help='Additional option(s) for the compiler.')
81 parser.add_argument(
Christoffer Quist Adamsen3f21c2b2023-02-28 09:37:22 +010082 '--pg-conf', '--pg_conf',
83 help='Keep rule file(s).',
84 action='append')
85 parser.add_argument(
Morten Krogh-Jespersen1fbfd592021-11-26 13:41:32 +010086 '--override',
Morten Krogh-Jespersen9206a662020-11-23 08:47:06 +010087 help='Do not override any extracted dump in temp-dir',
88 default=False,
89 action='store_true')
90 parser.add_argument(
Ian Zerny5ffa58f2020-02-26 08:37:14 +010091 '--nolib',
92 help='Use the non-lib distribution (default uses the lib distribution)',
93 default=False,
94 action='store_true')
95 parser.add_argument(
Morten Krogh-Jespersen6c702402021-06-21 12:29:48 +020096 '--print-times',
Rico Wind28653642020-03-31 13:59:07 +020097 help='Print timing information from r8',
98 default=False,
99 action='store_true')
100 parser.add_argument(
Christoffer Quist Adamsen08da5e52023-09-22 09:37:37 +0200101 '--disable-assertions', '--disable_assertions', '-da',
102 help='Disable Java assertions when running the compiler (default enabled)',
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100103 default=False,
104 action='store_true')
105 parser.add_argument(
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100106 '--classfile',
107 help='Run with classfile output',
108 default=False,
109 action='store_true')
110 parser.add_argument(
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100111 '--debug-agent',
112 help='Enable Java debug agent and suspend compilation (default disabled)',
113 default=False,
114 action='store_true')
Ian Zerny77bdf5f2020-07-08 11:46:24 +0200115 parser.add_argument(
116 '--xmx',
117 help='Set JVM max heap size (-Xmx)',
118 default=None)
119 parser.add_argument(
120 '--threads',
121 help='Set the number of threads to use',
122 default=None)
123 parser.add_argument(
124 '--min-api',
125 help='Set min-api (default read from dump properties file)',
126 default=None)
Søren Gjesse7360f2b2020-08-10 09:13:35 +0200127 parser.add_argument(
Clément Béradaae4ca2020-10-27 14:26:41 +0000128 '--desugared-lib',
129 help='Set desugared-library (default set from dump)',
130 default=None)
131 parser.add_argument(
Morten Krogh-Jespersend86a81b2020-11-13 12:33:26 +0100132 '--disable-desugared-lib',
133 help='Disable desugared-libary if it will be set from dump',
134 default=False,
135 action='store_true'
136 )
137 parser.add_argument(
Søren Gjesse7360f2b2020-08-10 09:13:35 +0200138 '--loop',
139 help='Run the compilation in a loop',
140 default=False,
141 action='store_true')
Morten Krogh-Jespersen9e201ea2022-06-14 12:41:50 +0200142 parser.add_argument(
143 '--enable-missing-library-api-modeling',
144 help='Run with api modeling',
145 default=False,
146 action='store_true')
147 parser.add_argument(
148 '--android-platform-build',
149 help='Run as a platform build',
150 default=False,
151 action='store_true')
Morten Krogh-Jespersenaa2f9ec2022-07-04 13:10:17 +0200152 parser.add_argument(
153 '--compilation-mode', '--compilation_mode',
154 help='Run compilation in specified mode',
155 choices=['debug', 'release'],
156 default=None)
Ian Zernydfc36892023-08-25 14:11:57 +0200157 parser.add_argument(
158 '--new-gradle',
159 help='Use the new gradle build (defaults to old build)',
160 default=False,
161 action='store_true')
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100162 return parser
163
164def error(msg):
Rico Wind3d369b42021-01-12 10:26:24 +0100165 print(msg)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100166 sys.exit(1)
167
168class Dump(object):
169
170 def __init__(self, directory):
171 self.directory = directory
172
173 def if_exists(self, name):
174 f = os.path.join(self.directory, name)
175 if os.path.exists(f):
176 return f
177 return None
178
179 def program_jar(self):
180 return self.if_exists('program.jar')
181
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200182 def feature_jars(self):
183 feature_jars = []
184 i = 1
185 while True:
186 feature_jar = self.if_exists('feature-%s.jar' % i)
187 if feature_jar:
188 feature_jars.append(feature_jar)
189 i = i + 1
190 else:
191 return feature_jars
192
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100193 def library_jar(self):
194 return self.if_exists('library.jar')
195
196 def classpath_jar(self):
197 return self.if_exists('classpath.jar')
198
Clément Béradaae4ca2020-10-27 14:26:41 +0000199 def desugared_library_json(self):
200 return self.if_exists('desugared-library.json')
201
Clément Béra64a3c4c2020-11-10 08:16:17 +0000202 def proguard_input_map(self):
203 if self.if_exists('proguard_input.config'):
Rico Wind3d369b42021-01-12 10:26:24 +0100204 print("Unimplemented: proguard_input configuration.")
Clément Béra64a3c4c2020-11-10 08:16:17 +0000205
Morten Krogh-Jespersen1e774252021-03-01 16:56:07 +0100206 def main_dex_list_resource(self):
Christoffer Quist Adamsencd7f7ec2022-08-26 13:39:11 +0200207 return self.if_exists('main-dex-list.txt')
Clément Béra64a3c4c2020-11-10 08:16:17 +0000208
Morten Krogh-Jespersen1e774252021-03-01 16:56:07 +0100209 def main_dex_rules_resource(self):
210 return self.if_exists('main-dex-rules.txt')
211
Christoffer Quist Adamsen819273a2023-03-02 15:20:45 +0100212 def art_profile_resources(self):
213 art_profile_resources = []
214 while True:
215 current_art_profile_index = len(art_profile_resources) + 1
216 art_profile_resource = self.if_exists(
217 'art-profile-%s.txt' % current_art_profile_index)
218 if art_profile_resource is None:
219 return art_profile_resources
220 art_profile_resources.append(art_profile_resource)
221
Christoffer Quist Adamsencd7f7ec2022-08-26 13:39:11 +0200222 def startup_profile_resources(self):
223 startup_profile_resources = []
224 while True:
225 current_startup_profile_index = len(startup_profile_resources) + 1
226 startup_profile_resource = self.if_exists(
227 'startup-profile-%s.txt' % current_startup_profile_index)
228 if startup_profile_resource is None:
229 return startup_profile_resources
230 startup_profile_resources.append(startup_profile_resource)
231
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200232 def build_properties_file(self):
233 return self.if_exists('build.properties')
234
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100235 def config_file(self):
236 return self.if_exists('proguard.config')
237
238 def version_file(self):
239 return self.if_exists('r8-version')
240
241 def version(self):
242 f = self.version_file()
243 if f:
244 return open(f).read().split(' ')[0]
245 return None
246
Ian Zerny0e53ff12021-06-15 13:40:14 +0200247def read_dump_from_args(args, temp):
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100248 if args.dump is None:
Christoffer Quist Adamsend84a6f02020-05-16 12:29:35 +0200249 error("A dump file or directory must be specified")
Ian Zerny674099e2021-06-15 13:44:37 +0200250 return read_dump(args.dump, temp, args.override)
Ian Zerny0e53ff12021-06-15 13:40:14 +0200251
252def read_dump(dump, temp, override=False):
253 if os.path.isdir(dump):
254 return Dump(dump)
255 dump_file = zipfile.ZipFile(os.path.abspath(dump), 'r')
Christoffer Quist Adamsenbe6661d2023-08-24 11:01:12 +0200256 r8_version_file = os.path.join(temp, 'r8-version')
257
258 if override or not os.path.isfile(r8_version_file):
259 dump_file.extractall(temp)
260 if not os.path.isfile(r8_version_file):
261 error("Did not extract into %s. Either the zip file is invalid or the "
262 "dump is missing files" % temp)
263 return Dump(temp)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100264
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200265def determine_build_properties(args, dump):
266 build_properties = {}
267 build_properties_file = dump.build_properties_file()
268 if build_properties_file:
269 with open(build_properties_file) as f:
270 build_properties_contents = f.readlines()
271 for line in build_properties_contents:
272 stripped = line.strip()
273 if stripped:
274 pair = stripped.split('=')
275 build_properties[pair[0]] = pair[1]
Rico Windcfe1b2a2023-03-03 08:11:39 +0100276 if 'mode' not in build_properties:
277 build_properties['mode'] = 'release'
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200278 return build_properties
279
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100280def determine_version(args, dump):
281 if args.version is None:
282 return dump.version()
283 return args.version
284
Søren Gjesse0f8d88b2021-09-28 15:15:54 +0200285def determine_compiler(args, build_properties):
Morten Krogh-Jespersendd12e782023-03-01 16:34:51 +0100286 compilers = ['d8', 'r8', 'r8full', 'l8', 'l8d8', 'tracereferences']
Søren Gjesse0f8d88b2021-09-28 15:15:54 +0200287 compiler = args.compiler
288 if not compiler and 'tool' in build_properties:
289 compiler = build_properties.get('tool').lower()
Morten Krogh-Jespersendd12e782023-03-01 16:34:51 +0100290 if compiler == 'r8':
Søren Gjesse0f8d88b2021-09-28 15:15:54 +0200291 if not 'force-proguard-compatibility' in build_properties:
292 error("Unable to determine R8 compiler variant from build.properties."
293 " No value for 'force-proguard-compatibility'.")
294 if build_properties.get('force-proguard-compatibility').lower() == 'false':
295 compiler = compiler + 'full'
Morten Krogh-Jespersendd12e782023-03-01 16:34:51 +0100296 if compiler == 'TraceReferences':
297 compiler = build_properties.get('tool').lower()
Søren Gjesse0f8d88b2021-09-28 15:15:54 +0200298 if compiler not in compilers:
Rico Windf73f18d2020-03-03 09:28:54 +0100299 error("Unable to determine a compiler to use. Specified %s,"
300 " Valid options: %s" % (args.compiler, ', '.join(compilers)))
Søren Gjesse0f8d88b2021-09-28 15:15:54 +0200301 return compiler
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100302
Morten Krogh-Jespersendd12e782023-03-01 16:34:51 +0100303def determine_trace_references_commands(build_properties, output):
304 trace_ref_consumer = build_properties.get('trace_references_consumer')
305 if trace_ref_consumer == 'com.android.tools.r8.tracereferences.TraceReferencesCheckConsumer':
306 return ["--check"]
307 else:
308 assert trace_ref_consumer == 'com.android.tools.r8.tracereferences.TraceReferencesKeepRules'
309 args = ['--allowobfuscation'] if build_properties.get('minification') == 'true' else []
310 args.extend(['--keep-rules', '--output', output])
311 return args
312
Christoffer Quist Adamsen7953d0a2023-02-27 12:08:33 +0100313def is_l8_compiler(compiler):
314 return compiler.startswith('l8')
315
Christoffer Quist Adamsen3f21c2b2023-02-28 09:37:22 +0100316def is_r8_compiler(compiler):
317 return compiler.startswith('r8')
318
319def determine_config_files(args, dump, temp):
320 if args.pg_conf:
321 config_files = []
322 for config_file in args.pg_conf:
323 dst = os.path.join(temp, 'proguard-%s.config' % len(config_files))
324 shutil.copyfile(config_file, dst)
325 config_files.append(dst)
326 return config_files
327 dump_config_file = dump.config_file()
328 if dump_config_file:
329 return [dump_config_file]
330 return []
331
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100332def determine_output(args, temp):
Søren Gjesseaee909b2023-09-22 17:16:12 +0200333 if (args.output):
334 return args.output
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100335 return os.path.join(temp, 'out.jar')
336
Ian Zerny77bdf5f2020-07-08 11:46:24 +0200337def determine_min_api(args, build_properties):
338 if args.min_api:
339 return args.min_api
340 if 'min-api' in build_properties:
341 return build_properties.get('min-api')
342 return None
343
Christoffer Quist Adamsen819273a2023-03-02 15:20:45 +0100344def determine_residual_art_profile_output(art_profile, temp):
345 return os.path.join(temp, os.path.basename(art_profile)[:-4] + ".out.txt")
346
Christoffer Quist Adamsen3f21c2b2023-02-28 09:37:22 +0100347def determine_desugared_lib_pg_conf_output(temp):
348 return os.path.join(temp, 'desugared-library-keep-rules.config')
349
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200350def determine_feature_output(feature_jar, temp):
351 return os.path.join(temp, os.path.basename(feature_jar)[:-4] + ".out.jar")
352
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100353def determine_program_jar(args, dump):
354 if hasattr(args, 'program_jar') and args.program_jar:
355 return args.program_jar
356 return dump.program_jar()
357
358def determine_class_file(args, build_properties):
Christoffer Quist Adamsen0a3c16e2023-02-15 14:34:44 +0100359 return args.classfile \
360 or build_properties.get('backend', 'dex').lower() == 'cf'
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100361
Morten Krogh-Jespersen9e201ea2022-06-14 12:41:50 +0200362def determine_android_platform_build(args, build_properties):
363 if args.android_platform_build:
Morten Krogh-Jespersen9e201ea2022-06-14 12:41:50 +0200364 return True
Morten Krogh-Jespersenaa2f9ec2022-07-04 13:10:17 +0200365 return build_properties.get('android-platform-build') == 'true'
Morten Krogh-Jespersen9e201ea2022-06-14 12:41:50 +0200366
367def determine_enable_missing_library_api_modeling(args, build_properties):
368 if args.enable_missing_library_api_modeling:
Morten Krogh-Jespersen9e201ea2022-06-14 12:41:50 +0200369 return True
Morten Krogh-Jespersenaa2f9ec2022-07-04 13:10:17 +0200370 return build_properties.get('enable-missing-library-api-modeling') == 'true'
371
372def determine_compilation_mode(args, build_properties):
373 if args.compilation_mode:
374 return args.compilation_mode
375 return build_properties.get('mode')
Morten Krogh-Jespersen9e201ea2022-06-14 12:41:50 +0200376
Søren Gjesse1768e252021-10-06 12:50:36 +0200377def determine_properties(build_properties):
378 args = []
379 for key, value in build_properties.items():
380 # When writing dumps all system properties starting with com.android.tools.r8
381 # are written to the build.properties file in the format
382 # system-property-com.android.tools.r8.XXX=<value>
383 if key.startswith('system-property-'):
384 name = key[len('system-property-'):]
385 if name.endswith('dumpinputtofile') or name.endswith('dumpinputtodirectory'):
386 continue
387 if len(value) == 0:
388 args.append('-D' + name)
389 else:
390 args.append('-D' + name + '=' + value)
391 return args
392
Ian Zernydfc36892023-08-25 14:11:57 +0200393def download_distribution(version, args, temp):
394 nolib = args.nolib
Rico Wind1b52acf2021-03-21 12:36:55 +0100395 if version == 'main':
Ian Zernydfc36892023-08-25 14:11:57 +0200396 if args.new_gradle:
397 return "%s:%s" % (
398 "d8_r8/main/build/libs/deps.jar",
399 "d8_r8/main/build/libs/r8.jar")
400 else:
401 return utils.R8_JAR if nolib else utils.R8LIB_JAR
Morten Krogh-Jespersen51db2b02020-11-11 12:49:26 +0100402 if version == 'source':
403 return '%s:%s' % (utils.BUILD_JAVA_MAIN_DIR, utils.ALL_DEPS_JAR)
Ian Zerny171c6a62022-04-04 14:25:30 +0200404 name = 'r8.jar' if nolib else 'r8lib.jar'
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100405 source = archive.GetUploadDestination(version, name, is_hash(version))
406 dest = os.path.join(temp, 'r8.jar')
407 utils.download_file_from_cloud_storage(source, dest)
408 return dest
409
Christoffer Quist Adamsen3f21c2b2023-02-28 09:37:22 +0100410def clean_configs(files, args):
411 for file in files:
412 clean_config(file, args)
Rico Windc9e52f72021-08-19 08:30:26 +0200413
Christoffer Quist Adamsenf86fc0b2021-12-10 12:39:36 +0100414def clean_config(file, args):
Rico Windc9e52f72021-08-19 08:30:26 +0200415 with open(file) as f:
416 lines = f.readlines()
Christoffer Quist Adamsenf86fc0b2021-12-10 12:39:36 +0100417 minify = args.minify
418 optimize = args.optimize
419 shrink = args.shrink
Rico Windc9e52f72021-08-19 08:30:26 +0200420 with open(file, 'w') as f:
Christoffer Quist Adamsenf86fc0b2021-12-10 12:39:36 +0100421 if minify == 'force-disable':
422 print('Adding config line: -dontobfuscate')
423 f.write('-dontobfuscate\n')
424 if optimize == 'force-disable':
425 print('Adding config line: -dontoptimize')
426 f.write('-dontoptimize\n')
427 if shrink == 'force-disable':
428 print('Adding config line: -dontshrink')
429 f.write('-dontshrink\n')
Rico Windc9e52f72021-08-19 08:30:26 +0200430 for line in lines:
Christoffer Quist Adamsenf86fc0b2021-12-10 12:39:36 +0100431 if clean_config_line(line, minify, optimize, shrink):
Rico Windc9e52f72021-08-19 08:30:26 +0200432 print('Removing from config line: \n%s' % line)
Christoffer Quist Adamsenf86fc0b2021-12-10 12:39:36 +0100433 else:
434 f.write(line)
Rico Windc9e52f72021-08-19 08:30:26 +0200435
Christoffer Quist Adamsenf86fc0b2021-12-10 12:39:36 +0100436def clean_config_line(line, minify, optimize, shrink):
Søren Gjessea5dc7ed2023-03-20 13:25:38 +0100437 if line.lstrip().startswith('#'):
438 return False
Christoffer Quist Adamsenf86fc0b2021-12-10 12:39:36 +0100439 if ('-injars' in line or '-libraryjars' in line or
Christoffer Quist Adamsen3f21c2b2023-02-28 09:37:22 +0100440 '-print' in line or '-applymapping' in line):
Christoffer Quist Adamsenf86fc0b2021-12-10 12:39:36 +0100441 return True
442 if minify == 'force-enable' and '-dontobfuscate' in line:
443 return True
444 if optimize == 'force-enable' and '-dontoptimize' in line:
445 return True
446 if shrink == 'force-enable' and '-dontshrink' in line:
447 return True
448 return False
Rico Windc9e52f72021-08-19 08:30:26 +0200449
Morten Krogh-Jespersen327e76d2022-06-23 09:31:13 +0200450def prepare_r8_wrapper(dist, temp, jdkhome):
Christoffer Quist Adamsen819273a2023-03-02 15:20:45 +0100451 compile_wrapper_with_javac(
Morten Krogh-Jespersen327e76d2022-06-23 09:31:13 +0200452 dist,
453 temp,
454 jdkhome,
455 os.path.join(
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100456 utils.REPO_ROOT,
Morten Krogh-Jespersen327e76d2022-06-23 09:31:13 +0200457 'src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java'))
458
459def prepare_d8_wrapper(dist, temp, jdkhome):
Christoffer Quist Adamsen819273a2023-03-02 15:20:45 +0100460 compile_wrapper_with_javac(
Morten Krogh-Jespersen327e76d2022-06-23 09:31:13 +0200461 dist,
462 temp,
463 jdkhome,
464 os.path.join(
465 utils.REPO_ROOT,
466 'src/main/java/com/android/tools/r8/utils/CompileDumpD8.java'))
467
Christoffer Quist Adamsen819273a2023-03-02 15:20:45 +0100468def compile_wrapper_with_javac(dist, temp, jdkhome, path):
469 base_path = os.path.join(
470 utils.REPO_ROOT,
471 'src/main/java/com/android/tools/r8/utils/CompileDumpBase.java')
Ian Zerny268c9632020-11-13 11:36:35 +0100472 cmd = [
Rico Wind33936d12021-04-07 08:04:14 +0200473 jdk.GetJavacExecutable(jdkhome),
Morten Krogh-Jespersen327e76d2022-06-23 09:31:13 +0200474 path,
Christoffer Quist Adamsen819273a2023-03-02 15:20:45 +0100475 base_path,
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100476 '-d', temp,
477 '-cp', dist,
Ian Zerny268c9632020-11-13 11:36:35 +0100478 ]
479 utils.PrintCmd(cmd)
480 subprocess.check_output(cmd)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100481
482def is_hash(version):
483 return len(version) == 40
484
Christoffer Quist Adamsenbe6661d2023-08-24 11:01:12 +0200485def run1(out, args, otherargs, jdkhome=None, worker_id=None):
Ian Zerny09d42832022-11-17 07:45:02 +0100486 jvmargs = []
487 compilerargs = []
488 for arg in otherargs:
489 if arg.startswith('-D'):
490 jvmargs.append(arg)
491 else:
492 compilerargs.append(arg)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100493 with utils.TempDir() as temp:
Søren Gjesse7360f2b2020-08-10 09:13:35 +0200494 if out:
495 temp = out
Rico Wind9ed87b92020-03-06 12:37:18 +0100496 if not os.path.exists(temp):
497 os.makedirs(temp)
Ian Zerny0e53ff12021-06-15 13:40:14 +0200498 dump = read_dump_from_args(args, temp)
Ian Zerny46bc4cf2020-08-03 15:58:27 +0200499 if not dump.program_jar():
500 error("Cannot compile dump with no program classes")
501 if not dump.library_jar():
Rico Wind3d369b42021-01-12 10:26:24 +0100502 print("WARNING: Unexpected lack of library classes in dump")
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200503 build_properties = determine_build_properties(args, dump)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100504 version = determine_version(args, dump)
Søren Gjesse0f8d88b2021-09-28 15:15:54 +0200505 compiler = determine_compiler(args, build_properties)
Christoffer Quist Adamsen3f21c2b2023-02-28 09:37:22 +0100506 config_files = determine_config_files(args, dump, temp)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100507 out = determine_output(args, temp)
Ian Zerny77bdf5f2020-07-08 11:46:24 +0200508 min_api = determine_min_api(args, build_properties)
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100509 classfile = determine_class_file(args, build_properties)
Morten Krogh-Jespersen9e201ea2022-06-14 12:41:50 +0200510 android_platform_build = determine_android_platform_build(args, build_properties)
511 enable_missing_library_api_modeling = determine_enable_missing_library_api_modeling(args, build_properties)
Morten Krogh-Jespersenaa2f9ec2022-07-04 13:10:17 +0200512 mode = determine_compilation_mode(args, build_properties)
Ian Zernydfc36892023-08-25 14:11:57 +0200513 jar = args.r8_jar if args.r8_jar else download_distribution(version, args, temp)
Ian Zerny268c9632020-11-13 11:36:35 +0100514 if ':' not in jar and not os.path.exists(jar):
515 error("Distribution does not exist: " + jar)
Rico Wind33936d12021-04-07 08:04:14 +0200516 cmd = [jdk.GetJavaExecutable(jdkhome)]
Ian Zerny09d42832022-11-17 07:45:02 +0100517 cmd.extend(jvmargs)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100518 if args.debug_agent:
519 if not args.nolib:
Rico Wind3d369b42021-01-12 10:26:24 +0100520 print("WARNING: Running debugging agent on r8lib is questionable...")
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100521 cmd.append(
522 '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005')
Ian Zerny77bdf5f2020-07-08 11:46:24 +0200523 if args.xmx:
524 cmd.append('-Xmx' + args.xmx)
Christoffer Quist Adamsen08da5e52023-09-22 09:37:37 +0200525 if not args.disable_assertions:
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100526 cmd.append('-ea')
Morten Krogh-Jespersen23f0b032021-07-06 18:10:15 +0200527 cmd.append('-Dcom.android.tools.r8.enableTestAssertions=1')
Morten Krogh-Jespersen6c702402021-06-21 12:29:48 +0200528 if args.print_times:
Rico Wind28653642020-03-31 13:59:07 +0200529 cmd.append('-Dcom.android.tools.r8.printtimes=1')
Christoffer Quist Adamsen2f48f3f2021-10-14 17:25:03 +0200530 if args.r8_flags:
531 cmd.extend(args.r8_flags.split(' '))
Morten Krogh-Jespersen43f3cea2020-11-12 17:09:51 +0100532 if hasattr(args, 'properties'):
Morten Krogh-Jespersendd12e782023-03-01 16:34:51 +0100533 cmd.extend(args.properties)
Søren Gjesse1768e252021-10-06 12:50:36 +0200534 cmd.extend(determine_properties(build_properties))
Morten Krogh-Jespersen327e76d2022-06-23 09:31:13 +0200535 cmd.extend(['-cp', '%s:%s' % (temp, jar)])
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100536 if compiler == 'd8':
Ian Zerny1ad7cac2023-01-09 14:03:04 +0100537 prepare_d8_wrapper(jar, temp, jdkhome)
Morten Krogh-Jespersen327e76d2022-06-23 09:31:13 +0200538 cmd.append('com.android.tools.r8.utils.CompileDumpD8')
Christoffer Quist Adamsen7953d0a2023-02-27 12:08:33 +0100539 if is_l8_compiler(compiler):
Morten Krogh-Jespersenbb624e42021-04-19 14:33:48 +0200540 cmd.append('com.android.tools.r8.L8')
Morten Krogh-Jespersendd12e782023-03-01 16:34:51 +0100541 if compiler == 'tracereferences':
542 cmd.append('com.android.tools.r8.tracereferences.TraceReferences')
543 cmd.extend(determine_trace_references_commands(build_properties, out))
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100544 if compiler.startswith('r8'):
Ian Zerny1ad7cac2023-01-09 14:03:04 +0100545 prepare_r8_wrapper(jar, temp, jdkhome)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100546 cmd.append('com.android.tools.r8.utils.CompileDumpCompatR8')
547 if compiler == 'r8':
548 cmd.append('--compat')
Morten Krogh-Jespersendd12e782023-03-01 16:34:51 +0100549 if compiler != 'tracereferences':
550 assert mode == 'debug' or mode == 'release'
551 cmd.append('--' + mode)
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100552 # For recompilation of dumps run_on_app_dumps pass in a program jar.
Morten Krogh-Jespersendd12e782023-03-01 16:34:51 +0100553 program_jar = determine_program_jar(args, dump)
554 if compiler != 'tracereferences':
555 cmd.append(program_jar)
556 cmd.extend(['--output', out])
557 else:
558 cmd.extend(['--source', program_jar])
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200559 for feature_jar in dump.feature_jars():
560 cmd.extend(['--feature-jar', feature_jar,
561 determine_feature_output(feature_jar, temp)])
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100562 if dump.library_jar():
563 cmd.extend(['--lib', dump.library_jar()])
Christoffer Quist Adamsen7953d0a2023-02-27 12:08:33 +0100564 if dump.classpath_jar() and not is_l8_compiler(compiler):
Morten Krogh-Jespersendd12e782023-03-01 16:34:51 +0100565 cmd.extend(
566 ['--target' if compiler == 'tracereferences' else '--classpath',
567 dump.classpath_jar()])
Morten Krogh-Jespersend86a81b2020-11-13 12:33:26 +0100568 if dump.desugared_library_json() and not args.disable_desugared_lib:
Clément Béradaae4ca2020-10-27 14:26:41 +0000569 cmd.extend(['--desugared-lib', dump.desugared_library_json()])
Christoffer Quist Adamsen3f21c2b2023-02-28 09:37:22 +0100570 if not is_l8_compiler(compiler):
571 cmd.extend([
572 '--desugared-lib-pg-conf-output',
573 determine_desugared_lib_pg_conf_output(temp)])
574 if (is_r8_compiler(compiler) or compiler == 'l8') and config_files:
575 if hasattr(args, 'config_files_consumer') and args.config_files_consumer:
576 args.config_files_consumer(config_files)
Rico Windc9e52f72021-08-19 08:30:26 +0200577 else:
578 # If we get a dump from the wild we can't use -injars, -libraryjars or
579 # -print{mapping,usage}
Christoffer Quist Adamsen3f21c2b2023-02-28 09:37:22 +0100580 clean_configs(config_files, args)
581 for config_file in config_files:
582 cmd.extend(['--pg-conf', config_file])
583 cmd.extend(['--pg-map-output', '%s.map' % out])
Christoffer Quist Adamsencd7f7ec2022-08-26 13:39:11 +0200584 if dump.main_dex_list_resource():
585 cmd.extend(['--main-dex-list', dump.main_dex_list_resource()])
Morten Krogh-Jespersen1e774252021-03-01 16:56:07 +0100586 if dump.main_dex_rules_resource():
587 cmd.extend(['--main-dex-rules', dump.main_dex_rules_resource()])
Christoffer Quist Adamsen819273a2023-03-02 15:20:45 +0100588 for art_profile_resource in dump.art_profile_resources():
589 residual_art_profile_output = \
590 determine_residual_art_profile_output(art_profile_resource, temp)
591 cmd.extend([
592 '--art-profile', art_profile_resource, residual_art_profile_output])
Christoffer Quist Adamsencd7f7ec2022-08-26 13:39:11 +0200593 for startup_profile_resource in dump.startup_profile_resources():
594 cmd.extend(['--startup-profile', startup_profile_resource])
Ian Zerny77bdf5f2020-07-08 11:46:24 +0200595 if min_api:
596 cmd.extend(['--min-api', min_api])
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100597 if classfile:
598 cmd.extend(['--classfile'])
Morten Krogh-Jespersen9e201ea2022-06-14 12:41:50 +0200599 if android_platform_build:
600 cmd.extend(['--android-platform-build'])
601 if enable_missing_library_api_modeling:
602 cmd.extend(['--enable-missing-library-api-modeling'])
Ian Zerny77bdf5f2020-07-08 11:46:24 +0200603 if args.threads:
604 cmd.extend(['--threads', args.threads])
Ian Zerny09d42832022-11-17 07:45:02 +0100605 cmd.extend(compilerargs)
Christoffer Quist Adamsenbe6661d2023-08-24 11:01:12 +0200606 utils.PrintCmd(cmd, worker_id=worker_id)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100607 try:
Morten Krogh-Jespersen6c702402021-06-21 12:29:48 +0200608 print(subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode('utf-8'))
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100609 return 0
Rico Wind3d369b42021-01-12 10:26:24 +0100610 except subprocess.CalledProcessError as e:
Ian Zerny9ff31b72021-04-22 11:36:26 +0200611 if args.nolib \
612 or version == 'source' \
613 or not try_retrace_output(e, version, temp):
Morten Krogh-Jespersen86222742021-03-02 11:13:33 +0100614 print(e.output.decode('UTF-8'))
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100615 return 1
616
Ian Zerny9ff31b72021-04-22 11:36:26 +0200617def try_retrace_output(e, version, temp):
618 try:
619 stacktrace = os.path.join(temp, 'stacktrace')
620 open(stacktrace, 'w+').write(e.output.decode('UTF-8'))
621 print("=" * 80)
622 print(" RETRACED OUTPUT")
623 print("=" * 80)
Rico Wind759360f2023-09-29 08:10:47 +0200624 retrace.run(get_map_file(version, temp), stacktrace, None, no_r8lib=False)
Ian Zerny9ff31b72021-04-22 11:36:26 +0200625 return True
626 except Exception as e2:
627 print("Failed to retrace for version: %s" % version)
628 print(e2)
629 return False
630
631def get_map_file(version, temp):
632 if version == 'main':
633 return utils.R8LIB_MAP
634 download_path = archive.GetUploadDestination(
635 version,
636 'r8lib.jar.map',
637 is_hash(version))
638 if utils.file_exists_on_cloud_storage(download_path):
639 map_path = os.path.join(temp, 'mapping.map')
640 utils.download_file_from_cloud_storage(download_path, map_path)
641 return map_path
642 else:
643 print('Could not find map file from argument: %s.' % version)
644 return None
645
Ian Zerny0e53ff12021-06-15 13:40:14 +0200646def summarize_dump_files(dumpfiles):
647 if len(dumpfiles) == 0:
648 error('Summary command expects a list of dumps to summarize')
649 for f in dumpfiles:
650 print(f + ':')
651 try:
652 with utils.TempDir() as temp:
653 dump = read_dump(f, temp)
654 summarize_dump(dump)
655 except IOError as e:
656 print("Error: " + str(e))
657 except zipfile.BadZipfile as e:
658 print("Error: " + str(e))
659
660def summarize_dump(dump):
661 version = dump.version()
662 if not version:
663 print('No dump version info')
664 return
665 print('version=' + version)
666 props = dump.build_properties_file()
667 if props:
668 with open(props) as props_file:
669 print(props_file.read())
670 if dump.library_jar():
671 print('library.jar present')
672 if dump.classpath_jar():
673 print('classpath.jar present')
674 prog = dump.program_jar()
675 if prog:
676 print('program.jar content:')
677 summarize_jar(prog)
678
679def summarize_jar(jar):
680 with zipfile.ZipFile(jar) as zip:
681 pkgs = {}
682 for info in zip.infolist():
683 if info.filename.endswith('.class'):
684 pkg, clazz = os.path.split(info.filename)
685 count = pkgs.get(pkg, 0)
686 pkgs[pkg] = count + 1
687 sorted = list(pkgs.keys())
688 sorted.sort()
689 for p in sorted:
690 print(' ' + p + ': ' + str(pkgs[p]))
691
Søren Gjesse7360f2b2020-08-10 09:13:35 +0200692def run(args, otherargs):
Ian Zerny0e53ff12021-06-15 13:40:14 +0200693 if args.summary:
694 summarize_dump_files(otherargs)
695 elif args.loop:
Søren Gjesse7360f2b2020-08-10 09:13:35 +0200696 count = 1
697 while True:
698 print('Iteration {:03d}'.format(count))
699 out = args.temp
700 if out:
701 out = os.path.join(out, '{:03d}'.format(count))
702 run1(out, args, otherargs)
703 count += 1
704 else:
705 run1(args.temp, args, otherargs)
706
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100707if __name__ == '__main__':
708 (args, otherargs) = make_parser().parse_known_args(sys.argv[1:])
709 sys.exit(run(args, otherargs))