Add @Keep and @KeepForSubclassing annotations for public R8 API

Add simple src/main/keep.txt file specifying that public members of
types marked with @Keep and public/protected members of types marked
with @KeepForSubclassing should be kept.

Add tools/build_r8lib.py to build a minified r8lib.jar from r8.jar and
test that d8_api_usage_sample.jar works with the minified r8lib.jar.

Also move RT_JAR from minify_tool.py to utils.py since it is used in
build_r8lib.py as well.

Change-Id: Ie091895705bfd4637513876a93f35911e958c479
diff --git a/tools/build_r8lib.py b/tools/build_r8lib.py
new file mode 100755
index 0000000..e08c141
--- /dev/null
+++ b/tools/build_r8lib.py
@@ -0,0 +1,64 @@
+#!/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 using src/main/keep.txt and test that d8_api_usage_sample.jar
+works with the minified R8.
+'''
+
+import argparse
+import os
+import subprocess
+import toolhelper
+import utils
+
+parser = argparse.ArgumentParser(description=__doc__.strip(),
+                                 formatter_class=argparse.RawTextHelpFormatter)
+
+SAMPLE_JAR = os.path.join(utils.REPO_ROOT, 'tests/d8_api_usage_sample.jar')
+KEEP_RULES = os.path.join(utils.REPO_ROOT, 'src/main/keep.txt')
+R8LIB_JAR = os.path.join(utils.LIBS, 'r8lib.jar')
+R8LIB_MAP_FILE = os.path.join(utils.LIBS, 'r8lib-map.txt')
+
+API_LEVEL = 26
+ANDROID_JAR = 'third_party/android_jar/lib-v%s/android.jar' % API_LEVEL
+
+
+def build_r8lib():
+  toolhelper.run(
+      'r8',
+      ('--release',
+       '--classfile',
+       '--lib', utils.RT_JAR,
+       utils.R8_JAR,
+       '--output', R8LIB_JAR,
+       '--pg-conf', KEEP_RULES,
+       '--pg-map-output', R8LIB_MAP_FILE))
+
+
+def test_d8sample():
+  with utils.TempDir() as path:
+    args = ['java', '-cp', '%s:%s' % (R8LIB_JAR, SAMPLE_JAR),
+            'com.android.tools.apiusagesample.D8ApiUsageSample',
+            '--output', path,
+            '--min-api', str(API_LEVEL),
+            '--lib', ANDROID_JAR,
+            '--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 main():
+  # Handle --help
+  parser.parse_args()
+
+  build_r8lib()
+  test_d8sample()
+
+
+if __name__ == '__main__':
+  main()
diff --git a/tools/minify_tool.py b/tools/minify_tool.py
index 787c1e1..8f440dd 100755
--- a/tools/minify_tool.py
+++ b/tools/minify_tool.py
@@ -27,7 +27,6 @@
 MANIFEST_PATH = 'META-INF/MANIFEST.MF'
 MANIFEST = 'Manifest-Version: 1.0\nMain-Class: %s\n\n'
 MANIFEST_PATTERN = r'Main-Class:\s*(\S+)'
-RT = os.path.join(utils.REPO_ROOT, 'third_party/openjdk/openjdk-rt-1.8/rt.jar')
 
 parser = argparse.ArgumentParser(description=__doc__.strip(),
                                  formatter_class=argparse.RawTextHelpFormatter)
@@ -38,7 +37,7 @@
     '-o', '--output-jar',
     help='Path to output JAR (default: build/libs/<MainClass>-min.jar)')
 parser.add_argument(
-    '-l', '--lib', default=RT,
+    '-l', '--lib', default=utils.RT_JAR,
     help='Path to rt.jar to use instead of OpenJDK 1.8')
 parser.add_argument(
     '-m', '--mainclass',
@@ -85,8 +84,8 @@
           'No --mainclass specified and no Main-Class in input JAR manifest.')
     return mo.group(1)
 
-def minify_tool(mainclass=None, input_jar=utils.R8_JAR, output_jar=None, lib=RT,
-                debug=True, build=True, benchmark_name=None):
+def minify_tool(mainclass=None, input_jar=utils.R8_JAR, output_jar=None,
+                lib=utils.RT_JAR, debug=True, build=True, benchmark_name=None):
   if output_jar is None:
     output_jar = generate_output_name(input_jar, mainclass)
   with utils.TempDir() as path:
diff --git a/tools/utils.py b/tools/utils.py
index 9f6959f..3aab572 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -35,6 +35,7 @@
 COMPATPROGUARD_JAR = os.path.join(LIBS, 'compatproguard.jar')
 MAVEN_ZIP = os.path.join(LIBS, 'r8.zip')
 GENERATED_LICENSE = os.path.join(GENERATED_LICENSE_DIR, 'LICENSE')
+RT_JAR = os.path.join(REPO_ROOT, 'third_party/openjdk/openjdk-rt-1.8/rt.jar')
 
 def PrintCmd(s):
   if type(s) is list: