|  | #!/usr/bin/env python3 | 
|  | # 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 using src/main/keep.txt and test that d8_api_usage_sample.jar | 
|  | works with the minified R8. | 
|  | ''' | 
|  |  | 
|  | import argparse | 
|  | import gradle | 
|  | import jdk | 
|  | import os | 
|  | import subprocess | 
|  | import toolhelper | 
|  | import utils | 
|  |  | 
|  | parser = argparse.ArgumentParser(description=__doc__.strip(), | 
|  | formatter_class=argparse.RawTextHelpFormatter) | 
|  | parser.add_argument('-e', '--exclude_deps', action='store_true', | 
|  | help='Create lib jar without dependencies') | 
|  | parser.add_argument('-k', '--keep', default=utils.R8LIB_KEEP_RULES, | 
|  | help='Keep rules file for lib') | 
|  | parser.add_argument('-n', '--no_relocate', action='store_true', | 
|  | help='Create lib jar without relocating libraries') | 
|  | parser.add_argument('-o', '--out', default=None, | 
|  | help='Output for built library') | 
|  | parser.add_argument('-t', '--target', default='r8', | 
|  | help='Compile target for library') | 
|  |  | 
|  | API_LEVEL = 26 | 
|  | DEPS_JAR = os.path.join(utils.LIBS, 'deps.jar') | 
|  | SAMPLE_JAR = os.path.join(utils.REPO_ROOT, 'tests', 'd8_api_usage_sample.jar') | 
|  |  | 
|  | def build_r8lib(target, exclude_deps, no_relocate, keep_rules_path, | 
|  | output_path, **kwargs): | 
|  | # Clean the build directory to ensure no repackaging of any existing | 
|  | # lib or deps. | 
|  | gradle.RunGradle(['clean']) | 
|  | lib_args = [target] | 
|  | deps_args = ['repackageDeps'] | 
|  | if exclude_deps: | 
|  | lib_args.append('-Pexclude_deps') | 
|  | if no_relocate: | 
|  | lib_args.append('-Plib_no_relocate') | 
|  | deps_args.append('-Plib_no_relocate') | 
|  | # Produce the r8lib target to be processed later. | 
|  | gradle.RunGradle(lib_args) | 
|  | target_lib = os.path.join(utils.LIBS, target + '.jar') | 
|  | temp_lib = os.path.join(utils.LIBS, target + '_to_process.jar') | 
|  | os.rename(target_lib, temp_lib) | 
|  | # Produce the dependencies needed for running r8 on lib.jar. | 
|  | gradle.RunGradle(deps_args) | 
|  | temp_deps = os.path.join(utils.LIBS, target + 'lib_deps.jar') | 
|  | os.rename(DEPS_JAR, temp_deps) | 
|  | # Produce R8 for compiling lib | 
|  | if output_path is None: | 
|  | output_path = target + 'lib.jar' | 
|  | output_map_path = output_path + '.map' | 
|  | toolhelper.run( | 
|  | 'r8', | 
|  | ('--release', | 
|  | '--classfile', | 
|  | '--lib', utils.RT_JAR, | 
|  | '--lib', temp_deps, | 
|  | temp_lib, | 
|  | '--output', output_path, | 
|  | '--pg-conf', keep_rules_path, | 
|  | '--pg-map-output', output_map_path), | 
|  | **kwargs) | 
|  | if exclude_deps: | 
|  | return [output_path, temp_deps] | 
|  | else: | 
|  | return [output_path] | 
|  |  | 
|  |  | 
|  | def test_d8sample(paths): | 
|  | with utils.TempDir() as path: | 
|  | args = [jdk.GetJavaExecutable(), | 
|  | '-cp', '%s:%s' % (SAMPLE_JAR, ":".join(paths)), | 
|  | 'com.android.tools.apiusagesample.D8ApiUsageSample', | 
|  | '--output', path, | 
|  | '--min-api', str(API_LEVEL), | 
|  | '--lib', utils.get_android_jar(API_LEVEL), | 
|  | '--classpath', utils.R8_JAR, | 
|  | '--main-dex-list', '/dev/null', | 
|  | os.path.join(utils.BUILD, 'test/examples/hello.jar')] | 
|  | utils.PrintCmd(args) | 
|  | subprocess.check_call(args) | 
|  |  | 
|  |  | 
|  | def test_r8command(paths): | 
|  | with utils.TempDir() as path: | 
|  | # SAMPLE_JAR and LIB_JAR should not have any classes in common, since e.g. | 
|  | # R8CommandParser should have been minified in LIB_JAR. | 
|  | # Just in case R8CommandParser is also present in LIB_JAR, we put | 
|  | # SAMPLE_JAR first on the classpath to use its version of R8CommandParser. | 
|  | args = [jdk.GetJavaExecutable(), | 
|  | '-cp', '%s:%s' % (SAMPLE_JAR, ":".join(paths)), | 
|  | 'com.android.tools.r8.R8CommandParser', | 
|  | '--output', path + "/output.zip", | 
|  | '--min-api', str(API_LEVEL), | 
|  | '--lib', utils.get_android_jar(API_LEVEL), | 
|  | '--main-dex-list', '/dev/null', | 
|  | os.path.join(utils.BUILD, 'test/examples/hello.jar')] | 
|  | utils.PrintCmd(args) | 
|  | subprocess.check_call(args) | 
|  |  | 
|  |  | 
|  | def test_r8cfcommand(paths): | 
|  | with utils.TempDir() as path: | 
|  | # SAMPLE_JAR and LIB_JAR should not have any classes in common, since e.g. | 
|  | # R8CommandParser should have been minified in LIB_JAR. | 
|  | # Just in case R8CommandParser is also present in LIB_JAR, we put | 
|  | # SAMPLE_JAR first on the classpath to use its version of R8CommandParser. | 
|  | args = [jdk.GetJavaExecutable(), | 
|  | '-cp', '%s:%s' % (SAMPLE_JAR, ":".join(paths)), | 
|  | 'com.android.tools.r8.R8CommandParser', | 
|  | '--classfile', | 
|  | '--output', path + "/output.jar", | 
|  | '--lib', utils.RT_JAR, | 
|  | os.path.join(utils.BUILD, 'test/examples/hello.jar')] | 
|  | utils.PrintCmd(args) | 
|  | subprocess.check_call(args) | 
|  |  | 
|  |  | 
|  | def main(): | 
|  | # Handle --help | 
|  | args = parser.parse_args() | 
|  | output_paths = build_r8lib( | 
|  | args.target, args.exclude_deps, args.no_relocate, args.keep, args.out) | 
|  | if args.target == 'r8': | 
|  | gradle.RunGradle(['buildExampleJars']) | 
|  | test_r8command(output_paths) | 
|  | test_r8cfcommand(output_paths) | 
|  | if args.target == 'd8': | 
|  | gradle.RunGradle(['buildExampleJars']) | 
|  | test_d8sample(output_paths) | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | main() |