[Retrace] Compile retrace by R8 with composition

Bug: b/270105162
Bug: b/283881148
Bug: b/281459606
Change-Id: I62e090b29789b3403dc7fb27ca5299958d0b9cbe
diff --git a/build.gradle b/build.gradle
index c1d2994..e4b958d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -913,7 +913,8 @@
     return baseD8CommandLine(allArgs)
 }
 
-def r8LibCreateTask(name, pgConfs = [], r8Task, output, libs = [], classpath = [], excldeps=false) {
+def r8LibCreateTask(
+    name, pgConfs = [], r8Task, output, libs = [], classpath = [], excldeps=false, debug=false) {
     return tasks.create("r8Lib${name}", Exec) {
         inputs.files ([pgConfs, r8WithRelocatedDeps.outputs, r8Task.outputs])
         outputs.file output
@@ -925,6 +926,7 @@
                 "--r8jar", r8Task.outputs.files[0],
                 "--output", output]
                 + (excldeps ? ['--excldeps-variant'] : [])
+                + (debug ? ['--debug-variant'] : [])
                 + (pgConfs.collectMany { ["--pg-conf", it] })
                 + (libs.collectMany { ["--lib", it] })
                 + (classpath.collectMany { ["--classpath", it] }))
@@ -1037,6 +1039,10 @@
             ["src/main/keep_retrace.txt"],
             R8Lib,
             r8RetracePath,
+            [],
+            [],
+            false,
+            true
     ).dependsOn(R8Lib)
     outputs.file r8RetracePath
 }
@@ -1051,6 +1057,7 @@
             [],
             repackageDeps.outputs.files,
             true,
+            true,
     ).dependsOn(R8LibNoDeps)
     outputs.file r8RetraceExludeDepsPath
 }
diff --git a/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt b/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
index 533d70e..2214408 100644
--- a/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
+++ b/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
@@ -257,23 +257,34 @@
   output: File,
   pgConf: List<File>,
   excludingDepsVariant: Boolean,
+  debugVariant: Boolean,
   lib: List<File> = listOf(),
-  classpath: List<File> = listOf()
+  classpath: List<File> = listOf(),
+  pgInputMap: File? = null
 ) : List<String> {
-  val pgList = pgConf.flatMap({ listOf("--pg-conf", "$it") })
-  val libList = lib.flatMap({ listOf("--lib", "$it") })
-  val cpList = classpath.flatMap({ listOf("--classpath", "$it") })
-  val exclList = if (excludingDepsVariant) listOf("--excldeps-variant") else listOf()
-  return listOf(
-    "python3",
-    "${getRoot().resolve("tools").resolve("create_r8lib.py")}",
-    "--r8compiler",
-    "${r8Compiler}",
-    "--r8jar",
-    "${input}",
-    "--output",
-    "${output}",
-  ) + exclList + pgList + libList + cpList
+  return buildList {
+    add("python3")
+    add("${getRoot().resolve("tools").resolve("create_r8lib.py")}")
+    add("--r8compiler")
+    add("${r8Compiler}")
+    add("--r8jar")
+    add("${input}")
+    add("--output")
+    add("${output}")
+    pgConf.forEach { add("--pg-conf"); add("$it") }
+    lib.forEach { add("--lib"); add("$it") }
+    classpath.forEach { add("--classpath"); add("$it") }
+    if (excludingDepsVariant) {
+      add("--excldeps-variant")
+    }
+    if (debugVariant) {
+      add("--debug-variant")
+    }
+    if (pgInputMap != null) {
+      add("--pg-map")
+      add("$pgInputMap")
+    }
+  }
 }
 
 object JvmCompatibility {
diff --git a/d8_r8/test/build.gradle.kts b/d8_r8/test/build.gradle.kts
index 1b19265..884a536 100644
--- a/d8_r8/test/build.gradle.kts
+++ b/d8_r8/test/build.gradle.kts
@@ -86,7 +86,7 @@
     val r8Jar = swissArmyKnifeTask.outputs.files.getSingleFile()
     val deps = mainDepsJarTask.outputs.files.getSingleFile()
     inputs.files(listOf(r8Compiler, r8Jar, deps))
-    val output =  getRoot().resolveAll("build", "libs", "r8lib-exclude-deps.jar")
+    val output = getRoot().resolveAll("build", "libs", "r8lib-exclude-deps.jar")
     outputs.file(output)
     commandLine = createR8LibCommandLine(
       r8Compiler,
@@ -94,9 +94,31 @@
       output,
       listOf(getRoot().resolveAll("src", "main", "keep.txt")),
       true,
+      false,
       listOf(deps))
   }
 
+  val retraceNoDeps by registering(Exec::class) {
+    dependsOn(r8LibNoDeps)
+    val r8Compiler = r8WithRelocatedDepsTask.outputs.files.getSingleFile()
+    val r8Jar = r8LibNoDeps.get().outputs.files.getSingleFile()
+    val deps = mainDepsJarTask.outputs.files.getSingleFile()
+    inputs.files(listOf(r8Compiler, r8Jar, deps))
+    val inputMap = file(r8Jar.toString() + ".map")
+    val output = getRoot().resolveAll("build", "libs", "r8retrace-exclude-deps.jar")
+    outputs.file(output)
+    commandLine = createR8LibCommandLine(
+      r8Compiler,
+      r8Jar,
+      output,
+      listOf(getRoot().resolveAll("src", "main", "keep_retrace.txt")),
+      true,
+      true,
+      listOf(deps),
+      listOf(),
+      inputMap)
+  }
+
   val generateKeepRules by registering(Exec::class) {
     dependsOn(r8WithRelocatedDepsTask)
     dependsOn(mainDepsJarTask)
@@ -145,9 +167,31 @@
       r8,
       output,
       listOf(keepTxt, generatedKeepRules, keepResourceShrinkerTxt),
+      false,
       false)
   }
 
+  val retraceWithRelocatedDeps by registering(Exec::class) {
+    dependsOn(r8LibWithRelocatedDeps)
+    val r8Compiler = r8WithRelocatedDepsTask.outputs.files.getSingleFile()
+    val r8Jar = r8LibWithRelocatedDeps.get().outputs.files.getSingleFile()
+    val deps = mainDepsJarTask.outputs.files.getSingleFile()
+    inputs.files(listOf(r8Compiler, r8Jar, deps))
+    val inputMap = file(r8Jar.toString() + ".map")
+    val output = getRoot().resolveAll("build", "libs", "r8retrace.jar")
+    outputs.file(output)
+    commandLine = createR8LibCommandLine(
+      r8Compiler,
+      r8Jar,
+      output,
+      listOf(getRoot().resolveAll("src", "main", "keep_retrace.txt")),
+      false,
+      true,
+      listOf(),
+      listOf(),
+      inputMap)
+  }
+
   val resourceshrinkercli by registering(Exec::class) {
     dependsOn(r8WithRelocatedDepsTask)
     val r8 = r8WithRelocatedDepsTask.outputs.files.getSingleFile()
@@ -161,6 +205,7 @@
       r8,
       output,
       listOf(keepTxt, cliKeep),
+      false,
       false)
   }
 
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index bd0152e..c210df5 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -147,12 +147,22 @@
       return super.addClasspathResourceProvider(provider);
     }
 
-    /** Set input proguard map used for distribution of classes in multi-dex. */
+    /**
+     * Set input proguard map used for distribution of classes in multi-dex. Use {@link
+     * #setProguardMapInputFile}
+     */
+    @Deprecated()
     public Builder setProguardInputMapFile(Path proguardInputMap) {
       getAppBuilder().setProguardMapInputData(proguardInputMap);
       return self();
     }
 
+    /** Set input proguard map used for distribution of classes in multi-dex. */
+    public Builder setProguardMapInputFile(Path proguardInputMap) {
+      getAppBuilder().setProguardMapInputData(proguardInputMap);
+      return self();
+    }
+
     /**
      * Set a consumer for receiving the proguard-map content.
      *
diff --git a/src/main/java/com/android/tools/r8/D8CommandParser.java b/src/main/java/com/android/tools/r8/D8CommandParser.java
index 8bf79ed..49360fd 100644
--- a/src/main/java/com/android/tools/r8/D8CommandParser.java
+++ b/src/main/java/com/android/tools/r8/D8CommandParser.java
@@ -265,7 +265,7 @@
       } else if (arg.equals("--classfile")) {
         outputMode = OutputMode.ClassFile;
       } else if (arg.equals("--pg-map")) {
-        builder.setProguardInputMapFile(Paths.get(nextArg));
+        builder.setProguardMapInputFile(Paths.get(nextArg));
       } else if (arg.equals("--pg-map-output")) {
         builder.setProguardMapOutputPath(Paths.get(nextArg));
       } else if (arg.equals("--partition-map-output")) {
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index fc1122a..1decde2 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -46,6 +46,7 @@
 import com.android.tools.r8.utils.InternalOptions.DesugarState;
 import com.android.tools.r8.utils.InternalOptions.HorizontalClassMergerOptions;
 import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
+import com.android.tools.r8.utils.InternalOptions.MappingComposeOptions;
 import com.android.tools.r8.utils.ProgramClassCollection;
 import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.SemanticVersion;
@@ -289,6 +290,12 @@
       return super.setProguardMapOutputPath(proguardMapOutput);
     }
 
+    /** Set input proguard map used for distribution of classes in multi-dex. */
+    public Builder setProguardMapInputFile(Path proguardInputMap) {
+      getAppBuilder().setProguardMapInputData(proguardInputMap);
+      return self();
+    }
+
     /**
      * Set a consumer for receiving the proguard-map content.
      *
@@ -1091,6 +1098,8 @@
         (internal.isOptimizing() || internal.isMinifying())
             ? LineNumberOptimization.ON
             : LineNumberOptimization.OFF;
+    MappingComposeOptions mappingComposeOptions = internal.mappingComposeOptions();
+    mappingComposeOptions.enableExperimentalMappingComposition = true;
 
     HorizontalClassMergerOptions horizontalClassMergerOptions =
         internal.horizontalClassMergerOptions();
diff --git a/src/main/java/com/android/tools/r8/R8CommandParser.java b/src/main/java/com/android/tools/r8/R8CommandParser.java
index 93fefae..d88314d 100644
--- a/src/main/java/com/android/tools/r8/R8CommandParser.java
+++ b/src/main/java/com/android/tools/r8/R8CommandParser.java
@@ -42,6 +42,7 @@
           "--main-dex-list-output",
           "--pg-conf",
           "--pg-conf-output",
+          "--pg-map",
           "--pg-map-output",
           "--partition-map-output",
           "--desugared-lib",
@@ -71,6 +72,12 @@
         .add(flag0("--pg-compat", "Compile with R8 in Proguard compatibility mode."))
         .add(ParseFlagInfoImpl.getPgConf())
         .add(flag1("--pg-conf-output", "<file>", "Output the collective configuration to <file>."))
+        .add(
+            ParseFlagInfoImpl.flag1(
+                "--pg-map",
+                "<file>",
+                "Use <file> as a mapping file for distribution "
+                    + "and composition with output mapping file."))
         .add(ParseFlagInfoImpl.getPgMapOutput())
         .add(ParseFlagInfoImpl.getPartitionMapOutput())
         .add(ParseFlagInfoImpl.getDesugaredLib())
@@ -295,6 +302,8 @@
       } else if (arg.equals("--pg-conf-output")) {
         FileConsumer consumer = new FileConsumer(Paths.get(nextArg));
         builder.setProguardConfigurationConsumer(consumer);
+      } else if (arg.equals("--pg-map")) {
+        builder.setProguardMapInputFile(Paths.get(nextArg));
       } else if (arg.equals("--pg-map-output")) {
         builder.setProguardMapOutputPath(Paths.get(nextArg));
       } else if (arg.equals("--partition-map-output")) {
diff --git a/src/test/bootstrap/com/android/tools/r8/bootstrap/RetraceStackTraceFunctionalCompositionTest.java b/src/test/bootstrap/com/android/tools/r8/bootstrap/RetraceStackTraceFunctionalCompositionTest.java
index a5c56c1..7fcb455 100644
--- a/src/test/bootstrap/com/android/tools/r8/bootstrap/RetraceStackTraceFunctionalCompositionTest.java
+++ b/src/test/bootstrap/com/android/tools/r8/bootstrap/RetraceStackTraceFunctionalCompositionTest.java
@@ -274,7 +274,7 @@
         .apply(
             b ->
                 b.getBuilder()
-                    .setProguardInputMapFile(previousMappingFile)
+                    .setProguardMapInputFile(previousMappingFile)
                     .setProguardMapConsumer((string, handler) -> mappingComposed.append(string)))
         .compile()
         .writeToZip(jar);
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index b223f76..f550b71 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -138,7 +138,7 @@
         assert System.getProperty("TEST_DATA_LOCATION") != null;
         return Paths.get(System.getProperty("TEST_DATA_LOCATION"));
       } else {
-        return Paths.get("d8_r8", "test_modules", destination);
+        return Paths.get(getProjectRoot(), "d8_r8", "test_modules", destination);
       }
     }
 
@@ -489,7 +489,7 @@
     }
 
     public static DexVm fromVersion(Version version) {
-      return SHORT_NAME_MAP.get(version.shortName + "_" + Kind.HOST.toString());
+      return SHORT_NAME_MAP.get(version.shortName + "_" + Kind.HOST);
     }
 
     public boolean isEqualTo(DexVm other) {
@@ -1068,11 +1068,16 @@
     }
   }
 
-  public static byte[] getClassAsBytes(Class clazz) throws IOException {
+  public static byte[] getClassAsBytes(Class<?> clazz) throws IOException {
     return Files.readAllBytes(getClassFileForTestClass(clazz));
   }
 
-  public static long getClassByteCrc(Class clazz) {
+  public static byte[] getClassAsBytes(Class<?> clazz, TestDataSourceSet dataSourceSet)
+      throws IOException {
+    return Files.readAllBytes(getClassFileForTestClass(clazz, dataSourceSet));
+  }
+
+  public static long getClassByteCrc(Class<?> clazz) {
     byte[] bytes = null;
     try {
       bytes = getClassAsBytes(clazz);
diff --git a/src/test/java/com/android/tools/r8/compilerapi/BinaryCompatibilityTestCollection.java b/src/test/java/com/android/tools/r8/compilerapi/BinaryCompatibilityTestCollection.java
index 6644d30..f39b8ba 100644
--- a/src/test/java/com/android/tools/r8/compilerapi/BinaryCompatibilityTestCollection.java
+++ b/src/test/java/com/android/tools/r8/compilerapi/BinaryCompatibilityTestCollection.java
@@ -153,7 +153,7 @@
           ToolHelper.getClassFilesForInnerClasses(testDataSourceSet, test));
       zipBuilder.addBytes(
           ZipUtils.zipEntryNameForClass(test),
-          ClassFileTransformer.create(test)
+          ClassFileTransformer.create(test, testDataSourceSet)
               .removeInnerClasses(
                   InnerClassPredicate.onName(
                       DescriptorUtils.getBinaryNameFromJavaType(test.getTypeName())))
diff --git a/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java b/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java
index 98b8878..b1e473f 100644
--- a/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java
+++ b/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java
@@ -19,6 +19,7 @@
 import com.android.tools.r8.compilerapi.globalsynthetics.GlobalSyntheticsTest;
 import com.android.tools.r8.compilerapi.globalsyntheticsgenerator.GlobalSyntheticsGeneratorTest;
 import com.android.tools.r8.compilerapi.inputdependencies.InputDependenciesTest;
+import com.android.tools.r8.compilerapi.inputmap.InputMapTest;
 import com.android.tools.r8.compilerapi.mapid.CustomMapIdTest;
 import com.android.tools.r8.compilerapi.mockdata.MockClass;
 import com.android.tools.r8.compilerapi.mockdata.MockClassWithAssertion;
@@ -64,7 +65,8 @@
           ExtractMarkerApiTest.ApiTest.class,
           PartitionMapCommandTest.ApiTest.class,
           CancelCompilationCheckerTest.ApiTest.class,
-          GlobalSyntheticsGeneratorTest.ApiTest.class);
+          GlobalSyntheticsGeneratorTest.ApiTest.class,
+          InputMapTest.ApiTest.class);
 
   private static final List<Class<? extends CompilerApiTest>> CLASSES_PENDING_BINARY_COMPATIBILITY =
       ImmutableList.of();
diff --git a/src/test/java/com/android/tools/r8/compilerapi/inputmap/InputMapTest.java b/src/test/java/com/android/tools/r8/compilerapi/inputmap/InputMapTest.java
new file mode 100644
index 0000000..af8c674
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/compilerapi/inputmap/InputMapTest.java
@@ -0,0 +1,123 @@
+// Copyright (c) 2023, 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.
+package com.android.tools.r8.compilerapi.inputmap;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.D8;
+import com.android.tools.r8.D8Command;
+import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.ProgramConsumer;
+import com.android.tools.r8.R8;
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.StringConsumer;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.compilerapi.CompilerApiTest;
+import com.android.tools.r8.compilerapi.CompilerApiTestRunner;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.BooleanBox;
+import com.android.tools.r8.utils.ThrowingBiConsumer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Test;
+
+public class InputMapTest extends CompilerApiTestRunner {
+
+  public InputMapTest(TestParameters parameters) {
+    super(parameters);
+  }
+
+  @Override
+  public Class<? extends CompilerApiTest> binaryTestClass() {
+    return ApiTest.class;
+  }
+
+  @Test
+  public void testD8() throws Exception {
+    ApiTest test = new ApiTest(ApiTest.PARAMETERS);
+    runTest(test::runTestD8);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    ApiTest test = new ApiTest(ApiTest.PARAMETERS);
+    runTest(test::runTestR8);
+  }
+
+  private void runTest(ThrowingBiConsumer<ProgramConsumer, StringConsumer, Exception> test)
+      throws Exception {
+    Path output = temp.newFolder().toPath().resolve("out.jar");
+    StringBuilder mappingBuilder = new StringBuilder();
+    BooleanBox didGetMappingContent = new BooleanBox(false);
+    test.accept(
+        new DexIndexedConsumer.ArchiveConsumer(output),
+        (mappingContent, handler) -> {
+          mappingBuilder.append(mappingContent);
+          didGetMappingContent.set(true);
+        });
+    assertTrue(didGetMappingContent.get());
+
+    // Extract the map hash from the file. This is always set by R8 to a SHA 256 hash.
+    String mappingContent = mappingBuilder.toString();
+    assertThat(mappingContent, containsString("com.android.tools.r8.compilerapi.originaldata ->"));
+  }
+
+  public static class ApiTest extends CompilerApiTest {
+    private static final List<String> mappingLines =
+        Arrays.asList(
+            "# {'id':'com.android.tools.r8.mapping','version':'2.2'}",
+            "com.android.tools.r8.compilerapi.originaldata ->"
+                + " com.android.tools.r8.compilerapi.mockdata:");
+
+    public ApiTest(Object parameters) {
+      super(parameters);
+    }
+
+    public void runTestR8(ProgramConsumer programConsumer, StringConsumer mappingConsumer)
+        throws Exception {
+      temp.create();
+      Path inputMap = temp.newFolder().toPath().resolve("r8inputmapping.txt");
+      Files.write(inputMap, mappingLines, StandardOpenOption.CREATE_NEW);
+      R8.run(
+          R8Command.builder()
+              .addClassProgramData(getBytesForClass(getMockClass()), Origin.unknown())
+              .addProguardConfiguration(getKeepMainRules(getMockClass()), Origin.unknown())
+              .addLibraryFiles(getJava8RuntimeJar())
+              .setProgramConsumer(programConsumer)
+              .setProguardMapConsumer(mappingConsumer)
+              .setProguardMapInputFile(inputMap)
+              .build());
+    }
+
+    public void runTestD8(ProgramConsumer programConsumer, StringConsumer mappingConsumer)
+        throws Exception {
+      temp.create();
+      Path inputMap = temp.newFolder().toPath().resolve("d8inputmap.txt");
+      Files.write(inputMap, mappingLines, StandardOpenOption.CREATE_NEW);
+      D8.run(
+          D8Command.builder()
+              .addClassProgramData(getBytesForClass(getMockClass()), Origin.unknown())
+              .addLibraryFiles(getJava8RuntimeJar())
+              .setProgramConsumer(programConsumer)
+              .setProguardMapConsumer(mappingConsumer)
+              .setProguardMapInputFile(inputMap)
+              .build());
+    }
+
+    @Test
+    public void testD8() throws Exception {
+      runTestD8(DexIndexedConsumer.emptyConsumer(), StringConsumer.emptyConsumer());
+    }
+
+    @Test
+    public void testR8() throws Exception {
+      runTestR8(DexIndexedConsumer.emptyConsumer(), StringConsumer.emptyConsumer());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/d8/ProguardMapSortByTest.java b/src/test/java/com/android/tools/r8/d8/ProguardMapSortByTest.java
index eac78c0..e7169c3 100644
--- a/src/test/java/com/android/tools/r8/d8/ProguardMapSortByTest.java
+++ b/src/test/java/com/android/tools/r8/d8/ProguardMapSortByTest.java
@@ -58,7 +58,7 @@
         .release()
         .addProgramClasses(A.class, B.class, C.class, D.class, E.class)
         .setMinApi(parameters)
-        .apply(b -> b.getBuilder().setProguardInputMapFile(mappingFile))
+        .apply(b -> b.getBuilder().setProguardMapInputFile(mappingFile))
         .run(parameters.getRuntime(), A.class)
         .assertSuccessWithOutputLines("Hello world!")
         .app()
diff --git a/src/test/java/com/android/tools/r8/debuginfo/composepc/ComposePcEncodingTest.java b/src/test/java/com/android/tools/r8/debuginfo/composepc/ComposePcEncodingTest.java
index 311ea41..5aca406 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/composepc/ComposePcEncodingTest.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/composepc/ComposePcEncodingTest.java
@@ -111,7 +111,7 @@
         // We only optimize line info in release mode and with a mapping file output enabled.
         .release()
         .internalEnableMappingOutput()
-        .apply(b -> b.getBuilder().setProguardInputMapFile(r8OutputMap))
+        .apply(b -> b.getBuilder().setProguardMapInputFile(r8OutputMap))
         // Forcing jumbo processing will shift the PC values on the methods.
         .addOptionsModification(o -> o.testing.forceJumboStringProcessing = true)
         .compile()
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/ComposeUnknownJsonD8Test.java b/src/test/java/com/android/tools/r8/mappingcompose/ComposeUnknownJsonD8Test.java
index 032f5da..a8e22c5 100644
--- a/src/test/java/com/android/tools/r8/mappingcompose/ComposeUnknownJsonD8Test.java
+++ b/src/test/java/com/android/tools/r8/mappingcompose/ComposeUnknownJsonD8Test.java
@@ -53,7 +53,7 @@
         .addOptionsModification(
             options ->
                 assertTrue(options.mappingComposeOptions().enableExperimentalMappingComposition))
-        .apply(b -> b.getBuilder().setProguardInputMapFile(inputMap))
+        .apply(b -> b.getBuilder().setProguardMapInputFile(inputMap))
         .apply(testBuilder)
         .allowStdoutMessages()
         .collectStdout()
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/ComposeWithMissingDebugInfoTest.java b/src/test/java/com/android/tools/r8/mappingcompose/ComposeWithMissingDebugInfoTest.java
index d042b13..02d145d 100644
--- a/src/test/java/com/android/tools/r8/mappingcompose/ComposeWithMissingDebugInfoTest.java
+++ b/src/test/java/com/android/tools/r8/mappingcompose/ComposeWithMissingDebugInfoTest.java
@@ -57,7 +57,7 @@
         .apply(
             b ->
                 b.getBuilder()
-                    .setProguardInputMapFile(inputMap)
+                    .setProguardMapInputFile(inputMap)
                     .setProguardMapConsumer((string, handler) -> mappingComposed.append(string)))
         .run(parameters.getRuntime(), Main.class)
         .assertSuccessWithOutputLines("42");
diff --git a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
index 5c8821d..e6ba0f6 100644
--- a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
+++ b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
@@ -11,6 +11,7 @@
 
 import com.android.tools.r8.TestRuntime.CfVm;
 import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.TestDataSourceSet;
 import com.android.tools.r8.cf.CfVersion;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.graph.AccessFlags;
@@ -155,6 +156,12 @@
     return create(ToolHelper.getClassAsBytes(clazz), classFromTypeName(clazz.getTypeName()));
   }
 
+  public static ClassFileTransformer create(Class<?> clazz, TestDataSourceSet sourceSet)
+      throws IOException {
+    return create(
+        ToolHelper.getClassAsBytes(clazz, sourceSet), classFromTypeName(clazz.getTypeName()));
+  }
+
   public <E extends Exception> ClassFileTransformer applyIf(
       boolean condition, ThrowingConsumer<ClassFileTransformer, E> consumer) throws E {
     if (condition) {
diff --git a/third_party/binary_compatibility_tests/compiler_api_tests.tar.gz.sha1 b/third_party/binary_compatibility_tests/compiler_api_tests.tar.gz.sha1
index 945fcd2..f514289 100644
--- a/third_party/binary_compatibility_tests/compiler_api_tests.tar.gz.sha1
+++ b/third_party/binary_compatibility_tests/compiler_api_tests.tar.gz.sha1
@@ -1 +1 @@
-8e1c917cd240fa40798ffa0f2175bc9373310f32
\ No newline at end of file
+1274833123c17ea92300f41af2c18bb1a20dcc01
\ No newline at end of file
diff --git a/tools/create_r8lib.py b/tools/create_r8lib.py
index a27cf24..a778ab3 100755
--- a/tools/create_r8lib.py
+++ b/tools/create_r8lib.py
@@ -37,6 +37,11 @@
     default=False,
     help='Mark this artifact as an "excldeps" variant of the compiler')
   parser.add_argument(
+    '--debug-variant',
+    action='store_true',
+    default=False,
+    help='Compile with debug flag')
+  parser.add_argument(
     '--lib',
     action='append',
     help='Additional libraries (JDK 1.8 rt.jar already included)')
@@ -49,6 +54,10 @@
     action='append',
     help='Keep configuration')
   parser.add_argument(
+    '--pg-map',
+    default=None,
+    help='Input map for distribution and composition')
+  parser.add_argument(
     '--r8jar',
     required=True,
     help='The R8 jar to compile')
@@ -95,6 +104,8 @@
     cmd.extend(['-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005'])
   cmd.extend(['-cp', args.r8compiler, 'com.android.tools.r8.R8'])
   cmd.append(args.r8jar)
+  if args.debug_variant:
+    cmd.append('--debug')
   cmd.append('--classfile')
   cmd.extend(['--map-id-template', map_id_template])
   cmd.extend(['--source-file-template', source_file_template])
@@ -111,6 +122,8 @@
   if args.classpath:
     for cp in args.classpath:
       cmd.extend(['--classpath', cp])
+  if args.pg_map:
+    cmd.extend(['--pg-map', args.pg_map])
   print(' '.join(cmd))
   subprocess.check_call(cmd)
 
diff --git a/tools/utils.py b/tools/utils.py
index c6b0126..4c671b9 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -311,7 +311,9 @@
   return defines.IsOsX()
 
 def EnsureDepFromGoogleCloudStorage(dep, tgz, sha1, msg):
-  if not os.path.exists(dep) or os.path.getmtime(tgz) < os.path.getmtime(sha1):
+  if (not os.path.exists(dep)
+     or not os.path.exists(tgz)
+     or os.path.getmtime(tgz) < os.path.getmtime(sha1)):
     DownloadFromGoogleCloudStorage(sha1)
     # Update the mtime of the tar file to make sure we do not run again unless
     # there is an update.