| #!/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' |
| r8_output_map_path = output_path + '_map.zip' |
| 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, |
| '--partition-map-output', r8_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() |