blob: 84dd1a2330e6a167c52e3acffbe1dee8ce4d4b9e [file] [log] [blame] [edit]
#!/usr/bin/env python
# Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
'''
Build r8lib.jar with both R8 and ProGuard and print a size comparison.
By default, inlining is disabled in both R8 and ProGuard to make
method-by-method comparison much easier. Pass --inlining to enable inlining.
By default, only shows methods where R8's DEX output is 5 or more instructions
larger than ProGuard+D8's output. Pass --threshold 0 to display all methods.
'''
import argparse
import build_r8lib
import os
import subprocess
import toolhelper
import utils
parser = argparse.ArgumentParser(description=__doc__.strip(),
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('-t', '--tmpdir',
help='Store auxiliary files in given directory')
parser.add_argument('-i', '--inlining', action='store_true',
help='Enable inlining')
parser.add_argument('--threshold')
R8_RELOCATIONS = [
('com.google.common', 'com.android.tools.r8.com.google.common'),
('com.google.gson', 'com.android.tools.r8.com.google.gson'),
('com.google.thirdparty', 'com.android.tools.r8.com.google.thirdparty'),
('joptsimple', 'com.android.tools.r8.joptsimple'),
('org.apache.commons', 'com.android.tools.r8.org.apache.commons'),
('org.objectweb.asm', 'com.android.tools.r8.org.objectweb.asm'),
('it.unimi.dsi.fastutil', 'com.android.tools.r8.it.unimi.dsi.fastutil'),
]
def is_output_newer(input, output):
if not os.path.exists(output):
return False
return os.stat(input).st_mtime < os.stat(output).st_mtime
def check_call(args, **kwargs):
utils.PrintCmd(args)
return subprocess.check_call(args, **kwargs)
def main(tmpdir=None, inlining=True,
run_jarsizecompare=True, threshold=None):
if tmpdir is None:
with utils.TempDir() as tmpdir:
return main(tmpdir, inlining)
inline_suffix = '-inline' if inlining else '-noinline'
pg_config = utils.R8LIB_KEEP_RULES
r8lib_jar = os.path.join(utils.LIBS, 'r8lib%s.jar' % inline_suffix)
r8lib_map = os.path.join(utils.LIBS, 'r8lib%s-map.txt' % inline_suffix)
r8lib_args = None
if not inlining:
r8lib_args = ['-Dcom.android.tools.r8.disableinlining=1']
pg_config = os.path.join(tmpdir, 'keep-noinline.txt')
with open(pg_config, 'w') as new_config:
with open(utils.R8LIB_KEEP_RULES) as old_config:
new_config.write(old_config.read().rstrip('\n') +
'\n-optimizations !method/inlining/*\n')
if not is_output_newer(utils.R8_JAR, r8lib_jar):
r8lib_memory = os.path.join(tmpdir, 'r8lib%s-memory.txt' % inline_suffix)
build_r8lib.build_r8lib(
output_path=r8lib_jar, output_map=r8lib_map,
extra_args=r8lib_args, track_memory_file=r8lib_memory)
pg_output = os.path.join(tmpdir, 'r8lib-pg%s.jar' % inline_suffix)
pg_memory = os.path.join(tmpdir, 'r8lib-pg%s-memory.txt' % inline_suffix)
pg_map = os.path.join(tmpdir, 'r8lib-pg%s-map.txt' % inline_suffix)
pg_args = ['tools/track_memory.sh', pg_memory,
'third_party/proguard/proguard6.0.2/bin/proguard.sh',
'@' + pg_config,
'-lib', utils.RT_JAR,
'-injar', utils.R8_JAR,
'-printmapping', pg_map,
'-outjar', pg_output]
for library_name, relocated_package in R8_RELOCATIONS:
pg_args.extend(['-dontwarn', relocated_package + '.**',
'-dontnote', relocated_package + '.**'])
check_call(pg_args)
if threshold is None:
threshold = 5
toolhelper.run('jarsizecompare',
['--threshold', str(threshold),
'--lib', utils.RT_JAR,
'--input', 'input', utils.R8_JAR,
'--input', 'r8', r8lib_jar, r8lib_map,
'--input', 'pg', pg_output, pg_map])
if __name__ == '__main__':
main(**vars(parser.parse_args()))