Mathias Rav | 56df69d | 2018-06-07 12:38:21 +0200 | [diff] [blame] | 1 | #!/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 | ''' |
| 7 | Build r8lib.jar with both R8 and ProGuard and print a size comparison. |
| 8 | |
| 9 | By default, inlining is disabled in both R8 and ProGuard to make |
| 10 | method-by-method comparison much easier. Pass --inlining to enable inlining. |
| 11 | |
| 12 | By default, only shows methods where R8's DEX output is 5 or more instructions |
| 13 | larger than ProGuard+D8's output. Pass --threshold 0 to display all methods. |
| 14 | ''' |
| 15 | |
| 16 | import argparse |
| 17 | import build_r8lib |
| 18 | import os |
| 19 | import subprocess |
| 20 | import toolhelper |
| 21 | import utils |
| 22 | |
| 23 | |
| 24 | parser = argparse.ArgumentParser(description=__doc__.strip(), |
| 25 | formatter_class=argparse.RawTextHelpFormatter) |
| 26 | parser.add_argument('-t', '--tmpdir', |
| 27 | help='Store auxiliary files in given directory') |
| 28 | parser.add_argument('-i', '--inlining', action='store_true', |
| 29 | help='Enable inlining') |
| 30 | parser.add_argument('--threshold') |
| 31 | |
| 32 | R8_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 | |
| 43 | def 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 | |
| 49 | def check_call(args, **kwargs): |
| 50 | utils.PrintCmd(args) |
| 51 | return subprocess.check_call(args, **kwargs) |
| 52 | |
| 53 | |
| 54 | def 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 Rav | f750172 | 2018-06-08 10:18:36 +0200 | [diff] [blame] | 90 | for library_name, relocated_package in R8_RELOCATIONS: |
Mathias Rav | 56df69d | 2018-06-07 12:38:21 +0200 | [diff] [blame] | 91 | 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 | |
| 104 | if __name__ == '__main__': |
| 105 | main(**vars(parser.parse_args())) |