| #!/usr/bin/env python | |
| # Copyright (c) 2017, 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. | |
| # Run ProGuard and the DX (= D8) tool on GmsCore V10. | |
| from __future__ import print_function | |
| from glob import glob | |
| from os import makedirs | |
| from os.path import exists, join, splitext | |
| from subprocess import check_call | |
| import argparse | |
| import fnmatch | |
| import gmscore_data | |
| import jdk | |
| import os | |
| import stat | |
| import sys | |
| import time | |
| import gmail_data | |
| import gmscore_data | |
| import golem | |
| import proguard | |
| import utils | |
| import youtube_data | |
| APPS = ['gmscore', 'youtube'] | |
| DX_JAR = join(utils.REPO_ROOT, 'tools', 'linux', 'dx', 'framework', 'dx.jar') | |
| def parse_arguments(argv): | |
| parser = argparse.ArgumentParser( | |
| description = 'Run ProGuard and the DX tool on GmsCore V10.') | |
| parser.add_argument('--app', required = True, choices = APPS) | |
| parser.add_argument('--out', | |
| help = 'Output directory for the DX tool.', | |
| default = os.getcwd()) | |
| parser.add_argument('--golem', | |
| help = 'Link in third party dependencies.', | |
| default = False, | |
| action = 'store_true') | |
| parser.add_argument('--print-runtimeraw', | |
| metavar = 'BENCHMARKNAME', | |
| help = 'Print the line \'<BENCHMARKNAME>(RunTimeRaw): <elapsed>' + | |
| ' ms\' at the end where <elapsed> is the elapsed time in' + | |
| ' milliseconds.') | |
| parser.add_argument('--print-memoryuse', | |
| metavar='BENCHMARKNAME', | |
| help='Print the line \'<BENCHMARKNAME>(MemoryUse):' + | |
| ' <mem>\' at the end where <mem> is the peak' + | |
| ' peak resident set size (VmHWM) in bytes.') | |
| parser.add_argument('--print-dexsegments', | |
| metavar = 'BENCHMARKNAME', | |
| help = 'Print the sizes of individual dex segments as ' + | |
| '\'<BENCHMARKNAME>-<segment>(CodeSize): <bytes>\'') | |
| return parser.parse_args(argv) | |
| def Main(argv): | |
| options = parse_arguments(argv) | |
| if options.golem: | |
| golem.link_third_party() | |
| utils.check_java_version() | |
| outdir = options.out | |
| if options.app == 'gmscore': | |
| version = 'v10' | |
| data = gmscore_data | |
| base = data.V10_BASE | |
| elif options.app == 'youtube': | |
| version = '12.22' | |
| data = youtube_data | |
| base = data.V12_22_BASE | |
| else: | |
| raise Exception('Unexpected') | |
| args = ['-forceprocessing'] | |
| if not outdir.endswith('.zip') and not outdir.endswith('.jar') \ | |
| and not exists(outdir): | |
| makedirs(outdir) | |
| values_deploy = data.VERSIONS[version]['deploy'] | |
| values_proguarded = data.VERSIONS[version]['proguarded'] | |
| assert 'pgconf' in values_deploy | |
| for pgconf in values_deploy['pgconf']: | |
| args.extend(['@' + pgconf]) | |
| # find seeds file | |
| inputs = data.VERSIONS[version]['proguarded']['inputs'] | |
| assert len(inputs) == 1 | |
| basename_wo_ext = splitext(os.path.basename(inputs[0]))[0] | |
| seeds_filename = basename_wo_ext + '.seeds' | |
| seeds_files = [] | |
| for root, dirnames, filenames in os.walk(join(base, 'blaze-out')): | |
| for filename in fnmatch.filter(filenames, seeds_filename): | |
| seeds_files.append(os.path.join(root, filename)) | |
| assert len(seeds_files) == 1 | |
| seeds_path = seeds_files[0] | |
| proguarded_jar_path = splitext(seeds_path)[0] + '.jar' | |
| # Remove write-protection from seeds file. The seeds file is an output of | |
| # ProGuard so it aborts if this is not writeable. | |
| st = os.stat(seeds_path) | |
| os.chmod(seeds_path, | |
| st.st_mode | stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH) | |
| t0 = time.time() | |
| proguard_memoryuse = None | |
| with utils.TempDir() as temp: | |
| track_memory_file = None | |
| if options.print_memoryuse: | |
| track_memory_file = join(temp, utils.MEMORY_USE_TMP_FILE) | |
| proguard.run( | |
| args, | |
| version='pg_internal', | |
| track_memory_file = track_memory_file, | |
| stdout=open(os.devnull, 'w')) | |
| if options.print_memoryuse: | |
| proguard_memoryuse = utils.grep_memoryuse(track_memory_file) | |
| # run dex on the result | |
| jar = DX_JAR | |
| with utils.TempDir() as temp: | |
| track_memory_file = None | |
| cmd = [] | |
| if options.print_memoryuse: | |
| track_memory_file = join(temp, utils.MEMORY_USE_TMP_FILE) | |
| cmd.extend(['tools/track_memory.sh', track_memory_file]) | |
| cmd.extend([jdk.GetJavaExecutable(), '-jar', jar, '--multi-dex', | |
| '--output=' + outdir]) | |
| if 'min-api' in values_proguarded: | |
| cmd.append('--min-sdk-version=' + values_proguarded['min-api']) | |
| cmd.extend(['--dex', proguarded_jar_path]) | |
| utils.PrintCmd(cmd); | |
| check_call(cmd) | |
| if options.print_memoryuse: | |
| dx_memoryuse = utils.grep_memoryuse(track_memory_file) | |
| print('{}(MemoryUse): {}' | |
| .format(options.print_memoryuse, | |
| max(proguard_memoryuse, dx_memoryuse))) | |
| if options.print_runtimeraw: | |
| print('{}(RunTimeRaw): {} ms' | |
| .format(options.print_runtimeraw, 1000.0 * (time.time() - t0))) | |
| if options.print_dexsegments: | |
| dex_files = glob(os.path.join(outdir, '*.dex')) | |
| utils.print_dexsegments(options.print_dexsegments, dex_files) | |
| if __name__ == '__main__': | |
| sys.exit(Main(sys.argv[1:])) |