Merge "Add CF backend to KeepAttributesTest."
diff --git a/build.gradle b/build.gradle
index e6432e4..580bcaf 100644
--- a/build.gradle
+++ b/build.gradle
@@ -478,13 +478,16 @@
     }
 }
 
-static configureRelocations(ShadowJar task) {
+static mergeServiceFiles(ShadowJar task) {
     // Everything under META-INF is not included by default.
     // Should include before 'relocate' so that the service file path and its content
     // are properly relocated as well.
     task.mergeServiceFiles {
         include 'META-INF/services/*'
     }
+}
+
+static configureRelocations(ShadowJar task) {
     task.relocate('com.google.common', 'com.android.tools.r8.com.google.common')
     task.relocate('com.google.gson', 'com.android.tools.r8.com.google.gson')
     task.relocate('com.google.thirdparty', 'com.android.tools.r8.com.google.thirdparty')
@@ -500,7 +503,10 @@
 
 task repackageDeps(type: ShadowJar) {
     configurations = [project.configurations.compile]
-    configureRelocations(it)
+    mergeServiceFiles(it)
+    if (!project.hasProperty('lib_no_relocate')) {
+        configureRelocations(it)
+    }
     exclude { it.getRelativePath().getPathString() == "module-info.class" }
     exclude { it.getRelativePath().getPathString().startsWith("META-INF/maven/") }
     baseName 'deps'
@@ -508,7 +514,10 @@
 
 task repackageSources(type: ShadowJar) {
     from sourceSets.main.output
-    configureRelocations(it)
+    mergeServiceFiles(it)
+    if (!project.hasProperty('lib_no_relocate')) {
+        configureRelocations(it)
+    }
     baseName 'sources'
 }
 
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
index fa856cb..6c6fda4 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
@@ -206,7 +206,10 @@
     if (localsChanged()) {
       assert emittedPc != pc;
       int pcDelta = emittedPc == NO_PC_INFO ? pc : pc - emittedPc;
-      events.add(factory.createAdvancePC(pcDelta));
+      assert pcDelta > 0 || emittedPc == NO_PC_INFO;
+      if (pcDelta > 0) {
+        events.add(factory.createAdvancePC(pcDelta));
+      }
       emittedPc = pc;
       emitLocalChangeEvents(emittedLocals, pendingLocals, lastKnownLocals, events, factory);
       pendingLocalChanges = false;
diff --git a/tools/build_r8lib.py b/tools/build_r8lib.py
index 4b7473e..5af6d4d 100755
--- a/tools/build_r8lib.py
+++ b/tools/build_r8lib.py
@@ -9,6 +9,7 @@
 '''
 
 import argparse
+import gradle
 import os
 import subprocess
 import toolhelper
@@ -16,39 +17,70 @@
 
 parser = argparse.ArgumentParser(description=__doc__.strip(),
                                  formatter_class=argparse.RawTextHelpFormatter)
-
-SAMPLE_JAR = os.path.join(utils.REPO_ROOT, 'tests/d8_api_usage_sample.jar')
-R8LIB_JAR = os.path.join(utils.LIBS, 'r8lib.jar')
-R8LIB_MAP_FILE = os.path.join(utils.LIBS, 'r8lib-map.txt')
+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
-ANDROID_JAR = 'third_party/android_jar/lib-v%s/android.jar' % API_LEVEL
+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(output_path=None, output_map=None, **kwargs):
+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 = R8LIB_JAR
-  if output_map is None:
-    output_map = R8LIB_MAP_FILE
+    output_path = target + 'lib.jar'
+  output_map_path = os.path.splitext(output_path)[0] + '.map'
   toolhelper.run(
       'r8',
       ('--release',
        '--classfile',
        '--lib', utils.RT_JAR,
-       utils.R8_JAR,
+       '--lib', temp_deps,
+       temp_lib,
        '--output', output_path,
-       '--pg-conf', utils.R8LIB_KEEP_RULES,
-       '--pg-map-output', output_map),
+       '--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():
+def test_d8sample(paths):
   with utils.TempDir() as path:
-    args = ['java', '-cp', '%s:%s' % (SAMPLE_JAR, R8LIB_JAR),
+    args = ['java', '-cp', '%s:%s' % (SAMPLE_JAR, ":".join(paths)),
             'com.android.tools.apiusagesample.D8ApiUsageSample',
             '--output', path,
             '--min-api', str(API_LEVEL),
-            '--lib', ANDROID_JAR,
+            '--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')]
@@ -56,30 +88,30 @@
     subprocess.check_call(args)
 
 
-def test_r8command():
+def test_r8command(paths):
   with utils.TempDir() as path:
-    # SAMPLE_JAR and R8LIB_JAR should not have any classes in common, since e.g.
-    # R8CommandParser should have been minified in R8LIB_JAR.
-    # Just in case R8CommandParser is also present in R8LIB_JAR, we put
+    # 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 = ['java', '-cp', '%s:%s' % (SAMPLE_JAR, R8LIB_JAR),
+    args = ['java', '-cp', '%s:%s' % (SAMPLE_JAR, ":".join(paths)),
             'com.android.tools.r8.R8CommandParser',
             '--output', path + "/output.zip",
             '--min-api', str(API_LEVEL),
-            '--lib', ANDROID_JAR,
+            '--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():
+def test_r8cfcommand(paths):
   with utils.TempDir() as path:
-    # SAMPLE_JAR and R8LIB_JAR should not have any classes in common, since e.g.
-    # R8CommandParser should have been minified in R8LIB_JAR.
-    # Just in case R8CommandParser is also present in R8LIB_JAR, we put
+    # 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 = ['java', '-cp', '%s:%s' % (SAMPLE_JAR, R8LIB_JAR),
+    args = ['java', '-cp', '%s:%s' % (SAMPLE_JAR, ":".join(paths)),
             'com.android.tools.r8.R8CommandParser',
             '--classfile',
             '--output', path + "/output.jar",
@@ -91,12 +123,16 @@
 
 def main():
   # Handle --help
-  parser.parse_args()
-
-  build_r8lib()
-  test_d8sample()
-  test_r8command()
-  test_r8cfcommand()
+  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__':