blob: 84dd1a2330e6a167c52e3acffbe1dee8ce4d4b9e [file] [log] [blame]
Mathias Rav56df69d2018-06-07 12:38:21 +02001#!/usr/bin/env python
2# Copyright (c) 2018, 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
6'''
7Build r8lib.jar with both R8 and ProGuard and print a size comparison.
8
9By default, inlining is disabled in both R8 and ProGuard to make
10method-by-method comparison much easier. Pass --inlining to enable inlining.
11
12By default, only shows methods where R8's DEX output is 5 or more instructions
13larger than ProGuard+D8's output. Pass --threshold 0 to display all methods.
14'''
15
16import argparse
17import build_r8lib
18import os
19import subprocess
20import toolhelper
21import utils
22
23
24parser = argparse.ArgumentParser(description=__doc__.strip(),
25 formatter_class=argparse.RawTextHelpFormatter)
26parser.add_argument('-t', '--tmpdir',
27 help='Store auxiliary files in given directory')
28parser.add_argument('-i', '--inlining', action='store_true',
29 help='Enable inlining')
30parser.add_argument('--threshold')
31
32R8_RELOCATIONS = [
33 ('com.google.common', 'com.android.tools.r8.com.google.common'),
34 ('com.google.gson', 'com.android.tools.r8.com.google.gson'),
35 ('com.google.thirdparty', 'com.android.tools.r8.com.google.thirdparty'),
36 ('joptsimple', 'com.android.tools.r8.joptsimple'),
37 ('org.apache.commons', 'com.android.tools.r8.org.apache.commons'),
38 ('org.objectweb.asm', 'com.android.tools.r8.org.objectweb.asm'),
39 ('it.unimi.dsi.fastutil', 'com.android.tools.r8.it.unimi.dsi.fastutil'),
40]
41
42
43def is_output_newer(input, output):
44 if not os.path.exists(output):
45 return False
46 return os.stat(input).st_mtime < os.stat(output).st_mtime
47
48
49def check_call(args, **kwargs):
50 utils.PrintCmd(args)
51 return subprocess.check_call(args, **kwargs)
52
53
54def main(tmpdir=None, inlining=True,
55 run_jarsizecompare=True, threshold=None):
56 if tmpdir is None:
57 with utils.TempDir() as tmpdir:
58 return main(tmpdir, inlining)
59
60 inline_suffix = '-inline' if inlining else '-noinline'
61
62 pg_config = utils.R8LIB_KEEP_RULES
63 r8lib_jar = os.path.join(utils.LIBS, 'r8lib%s.jar' % inline_suffix)
64 r8lib_map = os.path.join(utils.LIBS, 'r8lib%s-map.txt' % inline_suffix)
65 r8lib_args = None
66 if not inlining:
67 r8lib_args = ['-Dcom.android.tools.r8.disableinlining=1']
68 pg_config = os.path.join(tmpdir, 'keep-noinline.txt')
69 with open(pg_config, 'w') as new_config:
70 with open(utils.R8LIB_KEEP_RULES) as old_config:
71 new_config.write(old_config.read().rstrip('\n') +
72 '\n-optimizations !method/inlining/*\n')
73
74 if not is_output_newer(utils.R8_JAR, r8lib_jar):
75 r8lib_memory = os.path.join(tmpdir, 'r8lib%s-memory.txt' % inline_suffix)
76 build_r8lib.build_r8lib(
77 output_path=r8lib_jar, output_map=r8lib_map,
78 extra_args=r8lib_args, track_memory_file=r8lib_memory)
79
80 pg_output = os.path.join(tmpdir, 'r8lib-pg%s.jar' % inline_suffix)
81 pg_memory = os.path.join(tmpdir, 'r8lib-pg%s-memory.txt' % inline_suffix)
82 pg_map = os.path.join(tmpdir, 'r8lib-pg%s-map.txt' % inline_suffix)
83 pg_args = ['tools/track_memory.sh', pg_memory,
84 'third_party/proguard/proguard6.0.2/bin/proguard.sh',
85 '@' + pg_config,
86 '-lib', utils.RT_JAR,
87 '-injar', utils.R8_JAR,
88 '-printmapping', pg_map,
89 '-outjar', pg_output]
Mathias Ravf7501722018-06-08 10:18:36 +020090 for library_name, relocated_package in R8_RELOCATIONS:
Mathias Rav56df69d2018-06-07 12:38:21 +020091 pg_args.extend(['-dontwarn', relocated_package + '.**',
92 '-dontnote', relocated_package + '.**'])
93 check_call(pg_args)
94 if threshold is None:
95 threshold = 5
96 toolhelper.run('jarsizecompare',
97 ['--threshold', str(threshold),
98 '--lib', utils.RT_JAR,
99 '--input', 'input', utils.R8_JAR,
100 '--input', 'r8', r8lib_jar, r8lib_map,
101 '--input', 'pg', pg_output, pg_map])
102
103
104if __name__ == '__main__':
105 main(**vars(parser.parse_args()))