blob: dbb4a186f116cbb3d357ea7d78c1bc1b831bb518 [file] [log] [blame]
Ian Zerny5ffa58f2020-02-26 08:37:14 +01001#!/usr/bin/env python
2# 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
8import subprocess
9import sys
10import zipfile
11
Ian Zerny0e53ff12021-06-15 13:40:14 +020012import archive
13import jdk
14import retrace
Ian Zerny5ffa58f2020-02-26 08:37:14 +010015import utils
16
17
18def make_parser():
19 parser = argparse.ArgumentParser(description = 'Compile a dump artifact.')
20 parser.add_argument(
Ian Zerny0e53ff12021-06-15 13:40:14 +020021 '--summary',
22 help='List a summary of the contents of the dumps.',
23 default=False,
24 action='store_true')
25 parser.add_argument(
Ian Zerny5ffa58f2020-02-26 08:37:14 +010026 '-d',
27 '--dump',
Christoffer Quist Adamsend84a6f02020-05-16 12:29:35 +020028 help='Dump file or directory to compile',
Ian Zerny5ffa58f2020-02-26 08:37:14 +010029 default=None)
30 parser.add_argument(
Rico Wind9ed87b92020-03-06 12:37:18 +010031 '--temp',
32 help='Temp directory to extract the dump to, allows you to rerun the command'
33 ' more easily in the terminal with changes',
34 default=None)
35 parser.add_argument(
Ian Zerny5ffa58f2020-02-26 08:37:14 +010036 '-c',
37 '--compiler',
Rico Windf73f18d2020-03-03 09:28:54 +010038 help='Compiler to use',
Ian Zerny5ffa58f2020-02-26 08:37:14 +010039 default=None)
40 parser.add_argument(
41 '-v',
42 '--version',
43 help='Compiler version to use (default read from dump version file).'
44 'Valid arguments are:'
Rico Wind1b52acf2021-03-21 12:36:55 +010045 ' "main" to run from your own tree,'
Morten Krogh-Jespersen51db2b02020-11-11 12:49:26 +010046 ' "source" to run from build classes directly,'
Ian Zerny5ffa58f2020-02-26 08:37:14 +010047 ' "X.Y.Z" to run a specific version, or'
Rico Wind1b52acf2021-03-21 12:36:55 +010048 ' <hash> to run that hash from main.',
Ian Zerny5ffa58f2020-02-26 08:37:14 +010049 default=None)
50 parser.add_argument(
Morten Krogh-Jespersend8bceb52020-03-06 12:56:48 +010051 '--r8-jar',
52 help='Path to an R8 jar.',
53 default=None)
54 parser.add_argument(
Christoffer Quist Adamsen2f48f3f2021-10-14 17:25:03 +020055 '--r8-flags', '--r8_flags',
56 help='Additional option(s) for the compiler.')
57 parser.add_argument(
Morten Krogh-Jespersen9206a662020-11-23 08:47:06 +010058 '-override',
59 help='Do not override any extracted dump in temp-dir',
60 default=False,
61 action='store_true')
62 parser.add_argument(
Ian Zerny5ffa58f2020-02-26 08:37:14 +010063 '--nolib',
64 help='Use the non-lib distribution (default uses the lib distribution)',
65 default=False,
66 action='store_true')
67 parser.add_argument(
Morten Krogh-Jespersen6c702402021-06-21 12:29:48 +020068 '--print-times',
Rico Wind28653642020-03-31 13:59:07 +020069 help='Print timing information from r8',
70 default=False,
71 action='store_true')
72 parser.add_argument(
Ian Zerny5ffa58f2020-02-26 08:37:14 +010073 '--ea',
74 help='Enable Java assertions when running the compiler (default disabled)',
75 default=False,
76 action='store_true')
77 parser.add_argument(
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +010078 '--classfile',
79 help='Run with classfile output',
80 default=False,
81 action='store_true')
82 parser.add_argument(
Ian Zerny5ffa58f2020-02-26 08:37:14 +010083 '--debug-agent',
84 help='Enable Java debug agent and suspend compilation (default disabled)',
85 default=False,
86 action='store_true')
Ian Zerny77bdf5f2020-07-08 11:46:24 +020087 parser.add_argument(
88 '--xmx',
89 help='Set JVM max heap size (-Xmx)',
90 default=None)
91 parser.add_argument(
92 '--threads',
93 help='Set the number of threads to use',
94 default=None)
95 parser.add_argument(
96 '--min-api',
97 help='Set min-api (default read from dump properties file)',
98 default=None)
Søren Gjesse7360f2b2020-08-10 09:13:35 +020099 parser.add_argument(
Clément Béradaae4ca2020-10-27 14:26:41 +0000100 '--desugared-lib',
101 help='Set desugared-library (default set from dump)',
102 default=None)
103 parser.add_argument(
Morten Krogh-Jespersend86a81b2020-11-13 12:33:26 +0100104 '--disable-desugared-lib',
105 help='Disable desugared-libary if it will be set from dump',
106 default=False,
107 action='store_true'
108 )
109 parser.add_argument(
Søren Gjesse7360f2b2020-08-10 09:13:35 +0200110 '--loop',
111 help='Run the compilation in a loop',
112 default=False,
113 action='store_true')
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100114 return parser
115
116def error(msg):
Rico Wind3d369b42021-01-12 10:26:24 +0100117 print(msg)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100118 sys.exit(1)
119
120class Dump(object):
121
122 def __init__(self, directory):
123 self.directory = directory
124
125 def if_exists(self, name):
126 f = os.path.join(self.directory, name)
127 if os.path.exists(f):
128 return f
129 return None
130
131 def program_jar(self):
132 return self.if_exists('program.jar')
133
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200134 def feature_jars(self):
135 feature_jars = []
136 i = 1
137 while True:
138 feature_jar = self.if_exists('feature-%s.jar' % i)
139 if feature_jar:
140 feature_jars.append(feature_jar)
141 i = i + 1
142 else:
143 return feature_jars
144
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100145 def library_jar(self):
146 return self.if_exists('library.jar')
147
148 def classpath_jar(self):
149 return self.if_exists('classpath.jar')
150
Clément Béradaae4ca2020-10-27 14:26:41 +0000151 def desugared_library_json(self):
152 return self.if_exists('desugared-library.json')
153
Clément Béra64a3c4c2020-11-10 08:16:17 +0000154 def proguard_input_map(self):
155 if self.if_exists('proguard_input.config'):
Rico Wind3d369b42021-01-12 10:26:24 +0100156 print("Unimplemented: proguard_input configuration.")
Clément Béra64a3c4c2020-11-10 08:16:17 +0000157
Morten Krogh-Jespersen1e774252021-03-01 16:56:07 +0100158 def main_dex_list_resource(self):
Clément Béra64a3c4c2020-11-10 08:16:17 +0000159 if self.if_exists('main-dex-list.txt'):
Rico Wind3d369b42021-01-12 10:26:24 +0100160 print("Unimplemented: main-dex-list.")
Clément Béra64a3c4c2020-11-10 08:16:17 +0000161
Morten Krogh-Jespersen1e774252021-03-01 16:56:07 +0100162 def main_dex_rules_resource(self):
163 return self.if_exists('main-dex-rules.txt')
164
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200165 def build_properties_file(self):
166 return self.if_exists('build.properties')
167
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100168 def config_file(self):
169 return self.if_exists('proguard.config')
170
171 def version_file(self):
172 return self.if_exists('r8-version')
173
174 def version(self):
175 f = self.version_file()
176 if f:
177 return open(f).read().split(' ')[0]
178 return None
179
Ian Zerny0e53ff12021-06-15 13:40:14 +0200180def read_dump_from_args(args, temp):
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100181 if args.dump is None:
Christoffer Quist Adamsend84a6f02020-05-16 12:29:35 +0200182 error("A dump file or directory must be specified")
Ian Zerny674099e2021-06-15 13:44:37 +0200183 return read_dump(args.dump, temp, args.override)
Ian Zerny0e53ff12021-06-15 13:40:14 +0200184
185def read_dump(dump, temp, override=False):
186 if os.path.isdir(dump):
187 return Dump(dump)
188 dump_file = zipfile.ZipFile(os.path.abspath(dump), 'r')
189 with utils.ChangedWorkingDirectory(temp, quiet=True):
190 if override or not os.path.isfile('r8-version'):
Morten Krogh-Jespersen9206a662020-11-23 08:47:06 +0100191 dump_file.extractall()
Ian Zerny202330b2021-05-03 13:23:04 +0200192 if not os.path.isfile('r8-version'):
Morten Krogh-Jespersen9206a662020-11-23 08:47:06 +0100193 error("Did not extract into %s. Either the zip file is invalid or the "
194 "dump is missing files" % temp)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100195 return Dump(temp)
196
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200197def determine_build_properties(args, dump):
198 build_properties = {}
199 build_properties_file = dump.build_properties_file()
200 if build_properties_file:
201 with open(build_properties_file) as f:
202 build_properties_contents = f.readlines()
203 for line in build_properties_contents:
204 stripped = line.strip()
205 if stripped:
206 pair = stripped.split('=')
207 build_properties[pair[0]] = pair[1]
208 return build_properties
209
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100210def determine_version(args, dump):
211 if args.version is None:
212 return dump.version()
213 return args.version
214
Søren Gjesse0f8d88b2021-09-28 15:15:54 +0200215def determine_compiler(args, build_properties):
Morten Krogh-Jespersenbb624e42021-04-19 14:33:48 +0200216 compilers = ['d8', 'r8', 'r8full', 'l8']
Søren Gjesse0f8d88b2021-09-28 15:15:54 +0200217 compiler = args.compiler
218 if not compiler and 'tool' in build_properties:
219 compiler = build_properties.get('tool').lower()
220 if (compiler == 'r8'):
221 if not 'force-proguard-compatibility' in build_properties:
222 error("Unable to determine R8 compiler variant from build.properties."
223 " No value for 'force-proguard-compatibility'.")
224 if build_properties.get('force-proguard-compatibility').lower() == 'false':
225 compiler = compiler + 'full'
226 if compiler not in compilers:
Rico Windf73f18d2020-03-03 09:28:54 +0100227 error("Unable to determine a compiler to use. Specified %s,"
228 " Valid options: %s" % (args.compiler, ', '.join(compilers)))
Søren Gjesse0f8d88b2021-09-28 15:15:54 +0200229 return compiler
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100230
231def determine_output(args, temp):
232 return os.path.join(temp, 'out.jar')
233
Ian Zerny77bdf5f2020-07-08 11:46:24 +0200234def determine_min_api(args, build_properties):
235 if args.min_api:
236 return args.min_api
237 if 'min-api' in build_properties:
238 return build_properties.get('min-api')
239 return None
240
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200241def determine_feature_output(feature_jar, temp):
242 return os.path.join(temp, os.path.basename(feature_jar)[:-4] + ".out.jar")
243
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100244def determine_program_jar(args, dump):
245 if hasattr(args, 'program_jar') and args.program_jar:
246 return args.program_jar
247 return dump.program_jar()
248
249def determine_class_file(args, build_properties):
250 if args.classfile:
251 return args.classfile
252 if 'classfile' in build_properties:
253 return True
254 return None
255
Søren Gjesse1768e252021-10-06 12:50:36 +0200256def determine_properties(build_properties):
257 args = []
258 for key, value in build_properties.items():
259 # When writing dumps all system properties starting with com.android.tools.r8
260 # are written to the build.properties file in the format
261 # system-property-com.android.tools.r8.XXX=<value>
262 if key.startswith('system-property-'):
263 name = key[len('system-property-'):]
264 if name.endswith('dumpinputtofile') or name.endswith('dumpinputtodirectory'):
265 continue
266 if len(value) == 0:
267 args.append('-D' + name)
268 else:
269 args.append('-D' + name + '=' + value)
270 return args
271
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100272def download_distribution(args, version, temp):
Rico Wind1b52acf2021-03-21 12:36:55 +0100273 if version == 'main':
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100274 return utils.R8_JAR if args.nolib else utils.R8LIB_JAR
Morten Krogh-Jespersen51db2b02020-11-11 12:49:26 +0100275 if version == 'source':
276 return '%s:%s' % (utils.BUILD_JAVA_MAIN_DIR, utils.ALL_DEPS_JAR)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100277 name = 'r8.jar' if args.nolib else 'r8lib.jar'
278 source = archive.GetUploadDestination(version, name, is_hash(version))
279 dest = os.path.join(temp, 'r8.jar')
280 utils.download_file_from_cloud_storage(source, dest)
281 return dest
282
Rico Windc9e52f72021-08-19 08:30:26 +0200283
284def clean_config(file):
285 with open(file) as f:
286 lines = f.readlines()
287 with open(file, 'w') as f:
288 for line in lines:
289 if ('-injars' not in line and '-libraryjars' not in line and
290 '-print' not in line):
291 f.write(line)
292 else:
293 print('Removing from config line: \n%s' % line)
294
295
Rico Wind33936d12021-04-07 08:04:14 +0200296def prepare_wrapper(dist, temp, jdkhome):
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100297 wrapper_file = os.path.join(
298 utils.REPO_ROOT,
299 'src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java')
Ian Zerny268c9632020-11-13 11:36:35 +0100300 cmd = [
Rico Wind33936d12021-04-07 08:04:14 +0200301 jdk.GetJavacExecutable(jdkhome),
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100302 wrapper_file,
303 '-d', temp,
304 '-cp', dist,
Ian Zerny268c9632020-11-13 11:36:35 +0100305 ]
306 utils.PrintCmd(cmd)
307 subprocess.check_output(cmd)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100308 return temp
309
310def is_hash(version):
311 return len(version) == 40
312
Rico Wind33936d12021-04-07 08:04:14 +0200313def run1(out, args, otherargs, jdkhome=None):
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100314 with utils.TempDir() as temp:
Søren Gjesse7360f2b2020-08-10 09:13:35 +0200315 if out:
316 temp = out
Rico Wind9ed87b92020-03-06 12:37:18 +0100317 if not os.path.exists(temp):
318 os.makedirs(temp)
Ian Zerny0e53ff12021-06-15 13:40:14 +0200319 dump = read_dump_from_args(args, temp)
Ian Zerny46bc4cf2020-08-03 15:58:27 +0200320 if not dump.program_jar():
321 error("Cannot compile dump with no program classes")
322 if not dump.library_jar():
Rico Wind3d369b42021-01-12 10:26:24 +0100323 print("WARNING: Unexpected lack of library classes in dump")
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200324 build_properties = determine_build_properties(args, dump)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100325 version = determine_version(args, dump)
Søren Gjesse0f8d88b2021-09-28 15:15:54 +0200326 compiler = determine_compiler(args, build_properties)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100327 out = determine_output(args, temp)
Ian Zerny77bdf5f2020-07-08 11:46:24 +0200328 min_api = determine_min_api(args, build_properties)
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100329 classfile = determine_class_file(args, build_properties)
Morten Krogh-Jespersend8bceb52020-03-06 12:56:48 +0100330 jar = args.r8_jar if args.r8_jar else download_distribution(args, version, temp)
Ian Zerny268c9632020-11-13 11:36:35 +0100331 if ':' not in jar and not os.path.exists(jar):
332 error("Distribution does not exist: " + jar)
Rico Wind33936d12021-04-07 08:04:14 +0200333 wrapper_dir = prepare_wrapper(jar, temp, jdkhome)
334 cmd = [jdk.GetJavaExecutable(jdkhome)]
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100335 if args.debug_agent:
336 if not args.nolib:
Rico Wind3d369b42021-01-12 10:26:24 +0100337 print("WARNING: Running debugging agent on r8lib is questionable...")
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100338 cmd.append(
339 '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005')
Ian Zerny77bdf5f2020-07-08 11:46:24 +0200340 if args.xmx:
341 cmd.append('-Xmx' + args.xmx)
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100342 if args.ea:
343 cmd.append('-ea')
Morten Krogh-Jespersen23f0b032021-07-06 18:10:15 +0200344 cmd.append('-Dcom.android.tools.r8.enableTestAssertions=1')
Morten Krogh-Jespersen6c702402021-06-21 12:29:48 +0200345 if args.print_times:
Rico Wind28653642020-03-31 13:59:07 +0200346 cmd.append('-Dcom.android.tools.r8.printtimes=1')
Christoffer Quist Adamsen2f48f3f2021-10-14 17:25:03 +0200347 if args.r8_flags:
348 cmd.extend(args.r8_flags.split(' '))
Morten Krogh-Jespersen43f3cea2020-11-12 17:09:51 +0100349 if hasattr(args, 'properties'):
350 cmd.extend(args.properties);
Søren Gjesse1768e252021-10-06 12:50:36 +0200351 cmd.extend(determine_properties(build_properties))
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100352 cmd.extend(['-cp', '%s:%s' % (wrapper_dir, jar)])
353 if compiler == 'd8':
354 cmd.append('com.android.tools.r8.D8')
Morten Krogh-Jespersenbb624e42021-04-19 14:33:48 +0200355 if compiler == 'l8':
356 cmd.append('com.android.tools.r8.L8')
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100357 if compiler.startswith('r8'):
358 cmd.append('com.android.tools.r8.utils.CompileDumpCompatR8')
359 if compiler == 'r8':
360 cmd.append('--compat')
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100361 # For recompilation of dumps run_on_app_dumps pass in a program jar.
362 cmd.append(determine_program_jar(args, dump))
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100363 cmd.extend(['--output', out])
Christoffer Quist Adamsenfcfc63a2020-05-15 19:04:24 +0200364 for feature_jar in dump.feature_jars():
365 cmd.extend(['--feature-jar', feature_jar,
366 determine_feature_output(feature_jar, temp)])
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100367 if dump.library_jar():
368 cmd.extend(['--lib', dump.library_jar()])
Morten Krogh-Jespersenbb624e42021-04-19 14:33:48 +0200369 if dump.classpath_jar() and compiler != 'l8':
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100370 cmd.extend(['--classpath', dump.classpath_jar()])
Morten Krogh-Jespersend86a81b2020-11-13 12:33:26 +0100371 if dump.desugared_library_json() and not args.disable_desugared_lib:
Clément Béradaae4ca2020-10-27 14:26:41 +0000372 cmd.extend(['--desugared-lib', dump.desugared_library_json()])
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100373 if compiler != 'd8' and dump.config_file():
Morten Krogh-Jespersen51a16352020-11-04 09:31:15 +0100374 if hasattr(args, 'config_file_consumer') and args.config_file_consumer:
375 args.config_file_consumer(dump.config_file())
Rico Windc9e52f72021-08-19 08:30:26 +0200376 else:
377 # If we get a dump from the wild we can't use -injars, -libraryjars or
378 # -print{mapping,usage}
379 clean_config(dump.config_file())
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100380 cmd.extend(['--pg-conf', dump.config_file()])
Morten Krogh-Jespersen1e774252021-03-01 16:56:07 +0100381 if dump.main_dex_rules_resource():
382 cmd.extend(['--main-dex-rules', dump.main_dex_rules_resource()])
Morten Krogh-Jespersenbb624e42021-04-19 14:33:48 +0200383 if compiler == 'l8':
384 if dump.config_file():
385 cmd.extend(['--pg-map-output', '%s.map' % out])
386 elif compiler != 'd8':
Ian Zerny588120b2020-04-03 13:08:03 +0200387 cmd.extend(['--pg-map-output', '%s.map' % out])
Ian Zerny77bdf5f2020-07-08 11:46:24 +0200388 if min_api:
389 cmd.extend(['--min-api', min_api])
Morten Krogh-Jespersen45d7a7b2020-11-02 08:31:09 +0100390 if classfile:
391 cmd.extend(['--classfile'])
Ian Zerny77bdf5f2020-07-08 11:46:24 +0200392 if args.threads:
393 cmd.extend(['--threads', args.threads])
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100394 cmd.extend(otherargs)
395 utils.PrintCmd(cmd)
396 try:
Morten Krogh-Jespersen6c702402021-06-21 12:29:48 +0200397 print(subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode('utf-8'))
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100398 return 0
Rico Wind3d369b42021-01-12 10:26:24 +0100399 except subprocess.CalledProcessError as e:
Ian Zerny9ff31b72021-04-22 11:36:26 +0200400 if args.nolib \
401 or version == 'source' \
402 or not try_retrace_output(e, version, temp):
Morten Krogh-Jespersen86222742021-03-02 11:13:33 +0100403 print(e.output.decode('UTF-8'))
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100404 return 1
405
Ian Zerny9ff31b72021-04-22 11:36:26 +0200406def try_retrace_output(e, version, temp):
407 try:
408 stacktrace = os.path.join(temp, 'stacktrace')
409 open(stacktrace, 'w+').write(e.output.decode('UTF-8'))
410 print("=" * 80)
411 print(" RETRACED OUTPUT")
412 print("=" * 80)
413 retrace.run(get_map_file(version, temp), stacktrace, no_r8lib=False)
414 return True
415 except Exception as e2:
416 print("Failed to retrace for version: %s" % version)
417 print(e2)
418 return False
419
420def get_map_file(version, temp):
421 if version == 'main':
422 return utils.R8LIB_MAP
423 download_path = archive.GetUploadDestination(
424 version,
425 'r8lib.jar.map',
426 is_hash(version))
427 if utils.file_exists_on_cloud_storage(download_path):
428 map_path = os.path.join(temp, 'mapping.map')
429 utils.download_file_from_cloud_storage(download_path, map_path)
430 return map_path
431 else:
432 print('Could not find map file from argument: %s.' % version)
433 return None
434
Ian Zerny0e53ff12021-06-15 13:40:14 +0200435def summarize_dump_files(dumpfiles):
436 if len(dumpfiles) == 0:
437 error('Summary command expects a list of dumps to summarize')
438 for f in dumpfiles:
439 print(f + ':')
440 try:
441 with utils.TempDir() as temp:
442 dump = read_dump(f, temp)
443 summarize_dump(dump)
444 except IOError as e:
445 print("Error: " + str(e))
446 except zipfile.BadZipfile as e:
447 print("Error: " + str(e))
448
449def summarize_dump(dump):
450 version = dump.version()
451 if not version:
452 print('No dump version info')
453 return
454 print('version=' + version)
455 props = dump.build_properties_file()
456 if props:
457 with open(props) as props_file:
458 print(props_file.read())
459 if dump.library_jar():
460 print('library.jar present')
461 if dump.classpath_jar():
462 print('classpath.jar present')
463 prog = dump.program_jar()
464 if prog:
465 print('program.jar content:')
466 summarize_jar(prog)
467
468def summarize_jar(jar):
469 with zipfile.ZipFile(jar) as zip:
470 pkgs = {}
471 for info in zip.infolist():
472 if info.filename.endswith('.class'):
473 pkg, clazz = os.path.split(info.filename)
474 count = pkgs.get(pkg, 0)
475 pkgs[pkg] = count + 1
476 sorted = list(pkgs.keys())
477 sorted.sort()
478 for p in sorted:
479 print(' ' + p + ': ' + str(pkgs[p]))
480
Søren Gjesse7360f2b2020-08-10 09:13:35 +0200481def run(args, otherargs):
Ian Zerny0e53ff12021-06-15 13:40:14 +0200482 if args.summary:
483 summarize_dump_files(otherargs)
484 elif args.loop:
Søren Gjesse7360f2b2020-08-10 09:13:35 +0200485 count = 1
486 while True:
487 print('Iteration {:03d}'.format(count))
488 out = args.temp
489 if out:
490 out = os.path.join(out, '{:03d}'.format(count))
491 run1(out, args, otherargs)
492 count += 1
493 else:
494 run1(args.temp, args, otherargs)
495
Ian Zerny5ffa58f2020-02-26 08:37:14 +0100496if __name__ == '__main__':
497 (args, otherargs) = make_parser().parse_known_args(sys.argv[1:])
498 sys.exit(run(args, otherargs))