Remove the deprecated D8 API.

This change removes the deprecated parts of the D8 API and moves OutputMode
out of utils (which breaks both the old and new API). All clients will need
to be updated as part of updating to the D8 API after this change lands.

Change-Id: I73236b538eee540c490b375ea3333b06697b5f19
diff --git a/build.gradle b/build.gradle
index 6d767e0..e0d28fa 100644
--- a/build.gradle
+++ b/build.gradle
@@ -706,12 +706,6 @@
     dependsOn createJctfTests
 }
 
-task buildApiUsageSample(type: Jar) {
-    from sourceSets.apiUsageSample.output
-    baseName 'api_usage_sample'
-    destinationDir file('tests')
-}
-
 task buildD8ApiUsageSample(type: Jar) {
     from sourceSets.apiUsageSample.output
     baseName 'd8_api_usage_sample'
@@ -725,7 +719,6 @@
 }
 
 task buildApiSampleJars {
-    dependsOn buildApiUsageSample
     dependsOn buildD8ApiUsageSample
     dependsOn buildR8ApiUsageSample
 }
@@ -1704,6 +1697,8 @@
   include '**/com/android/tools/r8/DexFilePerClassFileConsumer.java'
   include '**/com/android/tools/r8/Diagnostic.java'
   include '**/com/android/tools/r8/DiagnosticsHandler.java'
+  include '**/com/android/tools/r8/DirectoryClassFileProvider.java'
+  include '**/com/android/tools/r8/OutputMode.java'
   include '**/com/android/tools/r8/ProgramConsumer.java'
   include '**/com/android/tools/r8/ProgramResource.java'
   include '**/com/android/tools/r8/ProgramResourceProvider.java'
@@ -1732,6 +1727,8 @@
   include '**/com/android/tools/r8/DexIndexedConsumer.java'
   include '**/com/android/tools/r8/Diagnostic.java'
   include '**/com/android/tools/r8/DiagnosticsHandler.java'
+  include '**/com/android/tools/r8/DirectoryClassFileProvider.java'
+  include '**/com/android/tools/r8/OutputMode.java'
   include '**/com/android/tools/r8/ProgramConsumer.java'
   include '**/com/android/tools/r8/ProgramResource.java'
   include '**/com/android/tools/r8/ProgramResourceProvider.java'
diff --git a/src/main/java/com/android/tools/r8/ArchiveClassFileProvider.java b/src/main/java/com/android/tools/r8/ArchiveClassFileProvider.java
index 1fa9130..e17acd0 100644
--- a/src/main/java/com/android/tools/r8/ArchiveClassFileProvider.java
+++ b/src/main/java/com/android/tools/r8/ArchiveClassFileProvider.java
@@ -83,12 +83,6 @@
   }
 
   @Override
-  @Deprecated
-  public Resource getResource(String descriptor) {
-    return getProgramResource(descriptor);
-  }
-
-  @Override
   public ProgramResource getProgramResource(String descriptor) {
     if (!descriptors.contains(descriptor)) {
       return null;
diff --git a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
index d95eeae..ea4ee2f 100644
--- a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
@@ -3,13 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8;
 
-import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.DefaultDiagnosticsHandler;
 import com.android.tools.r8.utils.FileUtils;
-import com.android.tools.r8.utils.OutputMode;
 import com.android.tools.r8.utils.Reporter;
 import java.nio.file.Path;
 import java.util.ArrayList;
@@ -25,20 +23,6 @@
  */
 public abstract class BaseCompilerCommand extends BaseCommand {
 
-  // TODO(b/70656566): Remove this once the deprecated API is removed.
-  @Deprecated
-  static class OutputOptions {
-    final Path path;
-    final OutputMode mode;
-
-    public OutputOptions(Path path, OutputMode mode) {
-      this.path = path;
-      this.mode = mode;
-    }
-  }
-
-  private final OutputOptions outputOptions;
-
   private final CompilationMode mode;
   private final ProgramConsumer programConsumer;
   private final int minApiLevel;
@@ -52,14 +36,12 @@
     minApiLevel = 0;
     reporter = new Reporter(new DefaultDiagnosticsHandler());
     enableDesugaring = true;
-    outputOptions = null;
   }
 
   BaseCompilerCommand(
       AndroidApp app,
       CompilationMode mode,
       ProgramConsumer programConsumer,
-      OutputOptions outputOptions,
       int minApiLevel,
       Reporter reporter,
       boolean enableDesugaring) {
@@ -71,7 +53,6 @@
     this.minApiLevel = minApiLevel;
     this.reporter = reporter;
     this.enableDesugaring = enableDesugaring;
-    this.outputOptions = outputOptions;
   }
 
   /**
@@ -87,27 +68,6 @@
     return minApiLevel;
   }
 
-  // Package private predicate for the API transition.
-  boolean usingDeprecatedAPI() {
-    return outputOptions != null;
-  }
-
-  @Deprecated
-  public Path getOutputPath() {
-    if (!usingDeprecatedAPI()) {
-      throw new CompilationError("Use of deprecated API may not be used with new consumer API");
-    }
-    return outputOptions.path;
-  }
-
-  @Deprecated
-  public OutputMode getOutputMode() {
-    if (!usingDeprecatedAPI()) {
-      throw new CompilationError("Use of deprecated API may not be used with new consumer API");
-    }
-    return outputOptions.mode;
-  }
-
   /**
    * Get the program consumer that will receive the compilation output.
    *
@@ -138,7 +98,7 @@
     private ProgramConsumer programConsumer = null;
     private Path outputPath = null;
     // TODO(b/70656566): Remove default output mode when deprecated API is removed.
-    private OutputMode outputMode = OutputMode.Indexed;
+    private OutputMode outputMode = OutputMode.DexIndexed;
 
     private CompilationMode mode;
     private int minApiLevel = AndroidApiLevel.getDefault().getLevel();
@@ -237,55 +197,26 @@
     public B setOutput(Path outputPath, OutputMode outputMode) {
       assert outputPath != null;
       assert outputMode != null;
-      assert !outputMode.isDeprecated();
       this.outputPath = outputPath;
       this.outputMode = outputMode;
       programConsumer = createProgramOutputConsumer(outputPath, outputMode);
       return self();
     }
 
-    /**
-     * Set an output path. Must be an existing directory or a zip file.
-     *
-     * @see #setOutput
-     */
-    @Deprecated
-    public B setOutputPath(Path outputPath) {
-      // Ensure this is not mixed with uses of the new consumer API.
-      assert programConsumer == null;
-      this.outputPath = outputPath;
-      return self();
-    }
-
-    /**
-     * Set an output mode.
-     *
-     * @see #setOutput
-     */
-    @Deprecated
-    public B setOutputMode(OutputMode outputMode) {
-      // Ensure this is not mixed with uses of the new consumer API.
-      assert programConsumer == null;
-      assert outputMode == null || outputMode.isDeprecated();
-      assert this.outputMode == null || this.outputMode.isDeprecated();
-      this.outputMode = outputMode;
-      return self();
-    }
-
     private InternalProgramOutputPathConsumer createProgramOutputConsumer(
         Path path,
         OutputMode mode) {
-      if (mode.isDexIndexed()) {
+      if (mode == OutputMode.DexIndexed) {
         return FileUtils.isArchive(path)
             ? new DexIndexedConsumer.ArchiveConsumer(path)
             : new DexIndexedConsumer.DirectoryConsumer(path);
       }
-      if (mode.isDexFilePerClassFile()) {
+      if (mode == OutputMode.DexFilePerClassFile) {
         return FileUtils.isArchive(path)
             ? new DexFilePerClassFileConsumer.ArchiveConsumer(path)
             : new DexFilePerClassFileConsumer.DirectoryConsumer(path);
       }
-      if (mode.isClassFile()) {
+      if (mode == OutputMode.ClassFile) {
         return FileUtils.isArchive(path)
             ? new ClassFileConsumer.ArchiveConsumer(path)
             : new ClassFileConsumer.DirectoryConsumer(path);
@@ -331,6 +262,10 @@
         reporter.error("Expected valid compilation mode, was null");
       }
       FileUtils.validateOutputFile(outputPath, reporter);
+      if (getProgramConsumer() == null) {
+        // This is never the case for a command-line parse, so we report using API references.
+        reporter.error("A ProgramConsumer or Output is required for compilation");
+      }
       List<Class> programConsumerClasses = new ArrayList<>(3);
       if (programConsumer instanceof DexIndexedConsumer) {
         programConsumerClasses.add(DexIndexedConsumer.class);
diff --git a/src/main/java/com/android/tools/r8/BaseOutput.java b/src/main/java/com/android/tools/r8/BaseOutput.java
deleted file mode 100644
index 3ca5665..0000000
--- a/src/main/java/com/android/tools/r8/BaseOutput.java
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2017, 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;
-
-import com.android.tools.r8.errors.InternalCompilerError;
-import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.OutputMode;
-import com.google.common.collect.ImmutableList;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.List;
-
-abstract class BaseOutput {
-
-  private final AndroidApp app;
-  private final OutputMode outputMode;
-
-  BaseOutput(AndroidApp app, OutputMode outputMode) {
-    this.app = app;
-    this.outputMode = outputMode;
-  }
-
-  // Internal access to the underlying app.
-  AndroidApp getAndroidApp() {
-    return app;
-  }
-
-  // Internal access to the options.
-  public OutputMode getOutputMode() {
-    return outputMode;
-  }
-
-  /**
-   * Get the list of compiled DEX resources.
-   *
-   * <p>The order of the list corresponds to the usual naming convention:
-   *
-   * <pre>
-   *   resources.get(0)     ~=~ classes.dex  (the main dex file)
-   *   resources.get(N - 1) ~=~ classesN.dex (where N > 0).
-   * </pre>
-   *
-   * @return an immutable list of compiled DEX resources.
-   */
-  public List<Resource> getDexResources() {
-    try {
-      return ImmutableList.copyOf(app.getDexProgramResourcesForTesting());
-    } catch (IOException e) {
-      throw new InternalCompilerError("Unexpected resource error", e);
-    }
-  }
-
-  /**
-   * Write the output resources to a zip-archive or directory.
-   *
-   * @param output Path to an existing directory or a zip-archive.
-   */
-  public abstract void write(Path output) throws IOException;
-}
diff --git a/src/main/java/com/android/tools/r8/ClassFileResourceProvider.java b/src/main/java/com/android/tools/r8/ClassFileResourceProvider.java
index 0312169..4c71d88 100644
--- a/src/main/java/com/android/tools/r8/ClassFileResourceProvider.java
+++ b/src/main/java/com/android/tools/r8/ClassFileResourceProvider.java
@@ -3,9 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8;
 
-import com.android.tools.r8.origin.Origin;
-import java.io.IOException;
-import java.io.InputStream;
 import java.util.Set;
 
 /**
@@ -34,50 +31,5 @@
    * <p>Method may be called several times for the same resource, and should support concurrent
    * calls from different threads.
    */
-  default ProgramResource getProgramResource(String descriptor) {
-    Resource resource = getResource(descriptor);
-    return resource == null ? null : new ClassFileResource(resource);
-  }
-
-  @Deprecated
-  Resource getResource(String descriptor);
-
-  @Deprecated
-  class ClassFileResource implements ProgramResource {
-    private final Resource resource;
-
-    public ClassFileResource(Resource resource) {
-      this.resource = resource;
-      assert resource.getClassDescriptors() == null || resource.getClassDescriptors().size() == 1;
-    }
-
-    @Override
-    public Kind getKind() {
-      return Kind.CF;
-    }
-
-    @Override
-    public InputStream getByteStream() throws ResourceException {
-      try {
-        return resource.getStream();
-      } catch (IOException e) {
-        throw new ResourceException(resource.getOrigin(), e);
-      }
-    }
-
-    @Override
-    public Set<String> getClassDescriptors() {
-      return resource.getClassDescriptors();
-    }
-
-    @Override
-    public Origin getOrigin() {
-      return resource.getOrigin();
-    }
-
-    @Override
-    public InputStream getStream() throws IOException {
-      return resource.getStream();
-    }
-  };
+  ProgramResource getProgramResource(String descriptor);
 }
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index f10bd31..a806138 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -15,7 +15,6 @@
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.origin.CommandLineOrigin;
 import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.AndroidAppConsumers;
 import com.android.tools.r8.utils.CfgPrinter;
 import com.android.tools.r8.utils.ExceptionUtils;
 import com.android.tools.r8.utils.InternalOptions;
@@ -61,12 +60,10 @@
    *
    * @param command D8 command.
    */
-  public static D8Output run(D8Command command) throws CompilationFailedException {
+  public static void run(D8Command command) throws CompilationFailedException {
     AndroidApp app = command.getInputApp();
     InternalOptions options = command.getInternalOptions();
     ExecutorService executor = ThreadUtils.getExecutorService(options);
-    AndroidAppConsumers compatSink =
-        command.usingDeprecatedAPI() ? new AndroidAppConsumers(options) : null;
     ExceptionUtils.withD8CompilationHandler(
         command.getReporter(),
         () -> {
@@ -76,7 +73,6 @@
             executor.shutdown();
           }
         });
-    return compatSink == null ? null : new D8Output(compatSink.build(), command.getOutputMode());
   }
 
   /**
@@ -85,18 +81,15 @@
    * @param command D8 command.
    * @param executor executor service from which to get threads for multi-threaded processing.
    */
-  public static D8Output run(D8Command command, ExecutorService executor)
+  public static void run(D8Command command, ExecutorService executor)
       throws CompilationFailedException {
     AndroidApp app = command.getInputApp();
     InternalOptions options = command.getInternalOptions();
-    AndroidAppConsumers compatSink =
-        command.usingDeprecatedAPI() ? new AndroidAppConsumers(options) : null;
     ExceptionUtils.withD8CompilationHandler(
         command.getReporter(),
         () -> {
           run(app, options, executor);
         });
-    return compatSink == null ? null : new D8Output(compatSink.build(), command.getOutputMode());
   }
 
   private static void run(String[] args) throws CompilationFailedException {
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index c7299bc..82d02db 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -9,7 +9,6 @@
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.OutputMode;
 import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.google.common.collect.ImmutableList;
@@ -112,11 +111,6 @@
       if (getProgramConsumer() instanceof ClassFileConsumer) {
         reporter.error("D8 does not support compiling to Java class files");
       }
-      // TODO(b/70656566): Move up super once the deprecated API is removed.
-      if (getProgramConsumer() == null && getOutputPath() == null && getOutputMode() == null) {
-        // This is never the case for a command-line parse, so we report using API references.
-        reporter.error("A ProgramConsumer or Output is required for compilation");
-      }
       if (getAppBuilder().hasMainDexList()) {
         if (intermediate) {
           reporter.error("Option --main-dex-list cannot be used with --intermediate");
@@ -134,25 +128,12 @@
         return new D8Command(isPrintHelp(), isPrintVersion());
       }
 
-      // Usage of the deprecated API will not have set a consumer. In this case we setup the output
-      // options, indicating usage of the deprecated API, and construct a suitable program consumer.
-      OutputOptions outputOptions = null;
-      ProgramConsumer consumer = getProgramConsumer();
-      if (consumer == null) {
-        outputOptions = new OutputOptions(getOutputPath(), getOutputMode());
-        consumer =
-            getOutputMode().isDexIndexed()
-                ? createIndexedConsumer(getOutputPath())
-                : createPerClassFileConsumer(getOutputPath());
-      }
-
-      intermediate |= consumer instanceof DexFilePerClassFileConsumer;
+      intermediate |= getProgramConsumer() instanceof DexFilePerClassFileConsumer;
 
       return new D8Command(
           getAppBuilder().build(),
           getMode(),
-          consumer,
-          outputOptions,
+          getProgramConsumer(),
           getMinApiLevel(),
           getReporter(),
           getEnableDesugaring(),
@@ -299,7 +280,6 @@
       AndroidApp inputApp,
       CompilationMode mode,
       ProgramConsumer programConsumer,
-      OutputOptions outputOptions,
       int minApiLevel,
       Reporter diagnosticsHandler,
       boolean enableDesugaring,
@@ -308,7 +288,6 @@
         inputApp,
         mode,
         programConsumer,
-        outputOptions,
         minApiLevel,
         diagnosticsHandler,
         enableDesugaring);
diff --git a/src/main/java/com/android/tools/r8/D8Output.java b/src/main/java/com/android/tools/r8/D8Output.java
deleted file mode 100644
index 829c3f0..0000000
--- a/src/main/java/com/android/tools/r8/D8Output.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2017, 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;
-
-import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.OutputMode;
-import java.io.IOException;
-import java.nio.file.Path;
-
-/** Represents the output of a D8 compilation. */
-@Deprecated
-public class D8Output extends BaseOutput {
-
-  D8Output(AndroidApp app, OutputMode outputMode) {
-    super(app, outputMode);
-  }
-
-  @Override
-  public void write(Path output) throws IOException {
-    getAndroidApp().write(output, getOutputMode());
-  }
-}
diff --git a/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java b/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java
index d31ff85..9aab62c 100644
--- a/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java
+++ b/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java
@@ -167,7 +167,7 @@
         Path archive,
         List<ProgramResource> resources,
         Map<Resource, String> primaryClassDescriptors)
-        throws IOException {
+        throws IOException, ResourceException {
       OpenOption[] options =
           new OpenOption[] {StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING};
       try (Closer closer = Closer.create()) {
@@ -175,7 +175,7 @@
           for (ProgramResource resource : resources) {
             String primaryClassDescriptor = primaryClassDescriptors.get(resource);
             String entryName = getDexFileName(primaryClassDescriptor);
-            byte[] bytes = ByteStreams.toByteArray(closer.register(resource.getStream()));
+            byte[] bytes = ByteStreams.toByteArray(closer.register(resource.getByteStream()));
             ZipUtils.writeToZipStream(out, entryName, bytes);
           }
         }
@@ -226,12 +226,12 @@
         Path directory,
         List<ProgramResource> resources,
         Map<Resource, String> primaryClassDescriptors)
-        throws IOException {
+        throws IOException, ResourceException {
       try (Closer closer = Closer.create()) {
         for (ProgramResource resource : resources) {
           String primaryClassDescriptor = primaryClassDescriptors.get(resource);
           Path target = getTargetDexFile(directory, primaryClassDescriptor);
-          writeFile(ByteStreams.toByteArray(closer.register(resource.getStream())), target);
+          writeFile(ByteStreams.toByteArray(closer.register(resource.getByteStream())), target);
         }
       }
     }
diff --git a/src/main/java/com/android/tools/r8/DexIndexedConsumer.java b/src/main/java/com/android/tools/r8/DexIndexedConsumer.java
index be47249..89dee13 100644
--- a/src/main/java/com/android/tools/r8/DexIndexedConsumer.java
+++ b/src/main/java/com/android/tools/r8/DexIndexedConsumer.java
@@ -157,7 +157,7 @@
     }
 
     public static void writeResources(Path archive, List<ProgramResource> resources)
-        throws IOException {
+        throws IOException, ResourceException {
       OpenOption[] options =
           new OpenOption[] {StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING};
       try (Closer closer = Closer.create()) {
@@ -165,7 +165,7 @@
           for (int i = 0; i < resources.size(); i++) {
             ProgramResource resource = resources.get(i);
             String entryName = getDefaultDexFileName(i);
-            byte[] bytes = ByteStreams.toByteArray(closer.register(resource.getStream()));
+            byte[] bytes = ByteStreams.toByteArray(closer.register(resource.getByteStream()));
             ZipUtils.writeToZipStream(out, entryName, bytes);
           }
         }
@@ -231,13 +231,13 @@
     }
 
     public static void writeResources(Path directory, List<ProgramResource> resources)
-        throws IOException {
+        throws IOException, ResourceException {
       deleteClassesDexFiles(directory);
       try (Closer closer = Closer.create()) {
         for (int i = 0; i < resources.size(); i++) {
-          Resource resource = resources.get(i);
+          ProgramResource resource = resources.get(i);
           Path target = getTargetDexFile(directory, i);
-          writeFile(ByteStreams.toByteArray(closer.register(resource.getStream())), target);
+          writeFile(ByteStreams.toByteArray(closer.register(resource.getByteStream())), target);
         }
       }
     }
diff --git a/src/main/java/com/android/tools/r8/utils/DirectoryClassFileProvider.java b/src/main/java/com/android/tools/r8/DirectoryClassFileProvider.java
similarity index 83%
rename from src/main/java/com/android/tools/r8/utils/DirectoryClassFileProvider.java
rename to src/main/java/com/android/tools/r8/DirectoryClassFileProvider.java
index 7dd24ba..5d5f751 100644
--- a/src/main/java/com/android/tools/r8/utils/DirectoryClassFileProvider.java
+++ b/src/main/java/com/android/tools/r8/DirectoryClassFileProvider.java
@@ -1,15 +1,13 @@
-// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// 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.
-package com.android.tools.r8.utils;
+package com.android.tools.r8;
 
 import static com.android.tools.r8.utils.FileUtils.CLASS_EXTENSION;
 import static com.android.tools.r8.utils.FileUtils.isClassFile;
 
-import com.android.tools.r8.ClassFileResourceProvider;
-import com.android.tools.r8.ProgramResource;
 import com.android.tools.r8.ProgramResource.Kind;
-import com.android.tools.r8.Resource;
+import com.android.tools.r8.utils.DescriptorUtils;
 import com.google.common.collect.Sets;
 import java.io.File;
 import java.nio.file.Files;
@@ -70,18 +68,7 @@
         : null;
   }
 
-  @Override
-  @Deprecated
-  public Resource getResource(String descriptor) {
-    return getProgramResource(descriptor);
-  }
-
   public Path getRoot() {
     return root;
   }
-
-  @Override
-  public String toString() {
-    return "directory(" + root + ")";
-  }
 }
diff --git a/src/main/java/com/android/tools/r8/OutputMode.java b/src/main/java/com/android/tools/r8/OutputMode.java
new file mode 100644
index 0000000..0da34b7
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/OutputMode.java
@@ -0,0 +1,17 @@
+// 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.
+package com.android.tools.r8;
+
+/** Enumeration of the possible output formats of compilation. */
+public enum OutputMode {
+
+  /** Produce DEX files using standard indexed-multidex for programs larger that a single file. */
+  DexIndexed,
+
+  /** Produce a DEX file for each Java class-file input file. */
+  DexFilePerClassFile,
+
+  /** Produce Java class files. */
+  ClassFile
+}
diff --git a/src/main/java/com/android/tools/r8/ProgramResource.java b/src/main/java/com/android/tools/r8/ProgramResource.java
index 646afdb..cabeabc 100644
--- a/src/main/java/com/android/tools/r8/ProgramResource.java
+++ b/src/main/java/com/android/tools/r8/ProgramResource.java
@@ -63,7 +63,6 @@
    *
    * @return Set of class descriptors defined by the resource or null if unknown.
    */
-  @Override // Need to keep this to not trip up error prone until the base method is gone.
   Set<String> getClassDescriptors();
 
   /** File-based program resource. */
@@ -103,12 +102,6 @@
     public Set<String> getClassDescriptors() {
       return classDescriptors;
     }
-
-    @Override
-    @Deprecated
-    public InputStream getStream() throws IOException {
-      return Files.newInputStream(file);
-    }
   }
 
   /** Byte-content based program resource. */
@@ -145,11 +138,5 @@
     public Set<String> getClassDescriptors() {
       return classDescriptors;
     }
-
-    @Override
-    @Deprecated
-    public InputStream getStream() throws IOException {
-      return new ByteArrayInputStream(bytes);
-    }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index d56fae5..4d6ae7b 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -4,7 +4,6 @@
 package com.android.tools.r8;
 
 import com.android.tools.r8.ProgramResource.Kind;
-import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.origin.PathOrigin;
@@ -20,7 +19,6 @@
 import com.android.tools.r8.utils.IOExceptionDiagnostic;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
-import com.android.tools.r8.utils.OutputMode;
 import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.google.common.collect.ImmutableList;
@@ -228,20 +226,6 @@
       return self();
     }
 
-    /** Unsupported API. Will throw on any usage. */
-    @Override
-    @Deprecated
-    public Builder setOutputMode(OutputMode outputMode) {
-      throw new CompilationError("Invalid API use for R8");
-    }
-
-    /** Unsupported API. Will throw on any usage. */
-    @Override
-    @Deprecated
-    public Builder setOutputPath(Path outputPath) {
-      throw new CompilationError("Invalid API use for R8");
-    }
-
     @Override
     public Builder addProgramResourceProvider(ProgramResourceProvider programProvider) {
       return super.addProgramResourceProvider(
@@ -251,11 +235,6 @@
     @Override
     void validate() {
       Reporter reporter = getReporter();
-      // TODO(b/70656566): Move up super once the deprecated API is removed.
-      if (getProgramConsumer() == null) {
-        // This is never the case for a command-line parse, so we report using API references.
-        reporter.error("A ProgramConsumer or Output is required for compilation");
-      }
       if (getProgramConsumer() instanceof DexFilePerClassFileConsumer) {
         reporter.error("R8 does not support compiling to a single DEX file per Java class file");
       }
@@ -332,7 +311,6 @@
           new R8Command(
               getAppBuilder().build(),
               getProgramConsumer(),
-              null,
               mainDexKeepRules,
               mainDexListConsumer,
               configuration,
@@ -569,7 +547,6 @@
   R8Command(
       AndroidApp inputApp,
       ProgramConsumer programConsumer,
-      OutputOptions outputOptions,
       ImmutableList<ProguardConfigurationRule> mainDexKeepRules,
       StringConsumer mainDexListConsumer,
       ProguardConfiguration proguardConfiguration,
@@ -582,7 +559,7 @@
       boolean forceProguardCompatibility,
       StringConsumer proguardMapConsumer,
       Path proguardCompatibilityRulesOutput) {
-    super(inputApp, mode, programConsumer, outputOptions, minApiLevel, reporter, enableDesugaring);
+    super(inputApp, mode, programConsumer, minApiLevel, reporter, enableDesugaring);
     assert proguardConfiguration != null;
     assert mainDexKeepRules != null;
     this.mainDexKeepRules = mainDexKeepRules;
diff --git a/src/main/java/com/android/tools/r8/Resource.java b/src/main/java/com/android/tools/r8/Resource.java
index 5f73466..f8f70d6 100644
--- a/src/main/java/com/android/tools/r8/Resource.java
+++ b/src/main/java/com/android/tools/r8/Resource.java
@@ -5,13 +5,6 @@
 package com.android.tools.r8;
 
 import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.origin.PathOrigin;
-import java.io.ByteArrayInputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Path;
-import java.util.Set;
 
 /**
  * Base interface for application resources.
@@ -36,95 +29,4 @@
    */
   Origin getOrigin();
 
-  // Deprecated API: See StringResource and ProgramResource.
-
-  @Deprecated
-  static Resource fromFile(Path file) {
-    return new FileResource(file);
-  }
-
-  @Deprecated
-  static Resource fromBytes(Origin origin, byte[] bytes) {
-    return new ByteResource(origin, bytes);
-  }
-
-  @Deprecated
-  static Resource fromBytes(Origin origin, byte[] bytes, Set<String> typeDescriptors) {
-    return new ByteResource(origin, bytes, typeDescriptors);
-  }
-
-  @Deprecated
-  InputStream getStream() throws IOException;
-
-  @Deprecated
-  Set<String> getClassDescriptors();
-
-  @Deprecated
-  class FileResource implements Resource {
-    final Origin origin;
-    final Path file;
-
-    private FileResource(Path file) {
-      assert file != null;
-      origin = new PathOrigin(file);
-      this.file = file;
-    }
-
-    @Override
-    public Origin getOrigin() {
-      return origin;
-    }
-
-    @Override
-    @Deprecated
-    public InputStream getStream() throws IOException {
-      return new FileInputStream(file.toFile());
-    }
-
-    @Override
-    @Deprecated
-    public Set<String> getClassDescriptors() {
-      return null;
-    }
-  }
-
-  @Deprecated
-  class ByteResource implements Resource {
-    final Origin origin;
-    final byte[] bytes;
-    final Set<String> classDescriptors;
-
-    private ByteResource(Origin origin, byte[] bytes) {
-      assert bytes != null;
-      this.origin = origin;
-      this.bytes = bytes;
-      classDescriptors = null;
-    }
-
-    /** Deprecated: Moved class descriptors to ProgramResource. */
-    @Deprecated
-    ByteResource(Origin origin, byte[] bytes, Set<String> classDescriptors) {
-      assert bytes != null;
-      this.origin = origin;
-      this.bytes = bytes;
-      this.classDescriptors = classDescriptors;
-    }
-
-    @Override
-    @Deprecated
-    public InputStream getStream() throws IOException {
-      return new ByteArrayInputStream(bytes);
-    }
-
-    @Override
-    public Origin getOrigin() {
-      return origin;
-    }
-
-    @Override
-    @Deprecated
-    public Set<String> getClassDescriptors() {
-      return classDescriptors;
-    }
-  }
 }
diff --git a/src/main/java/com/android/tools/r8/StringResource.java b/src/main/java/com/android/tools/r8/StringResource.java
index 4e35025..a28f936 100644
--- a/src/main/java/com/android/tools/r8/StringResource.java
+++ b/src/main/java/com/android/tools/r8/StringResource.java
@@ -3,17 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8;
 
-import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.origin.PathOrigin;
 import com.android.tools.r8.utils.FileUtils;
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
-import java.util.Set;
 
 public interface StringResource extends Resource {
 
@@ -59,23 +55,7 @@
    * @return The string content of the resource.
    * @throws ResourceException Exception thrown if the resource fails to produce its content.
    */
-  abstract String getString() throws ResourceException;
-
-  @Override
-  @Deprecated
-  default InputStream getStream() throws IOException {
-    try {
-      return new ByteArrayInputStream(getString().getBytes(StandardCharsets.UTF_8));
-    } catch (ResourceException e) {
-      throw (IOException) e.getCause();
-    }
-  }
-
-  @Override
-  @Deprecated
-  default Set<String> getClassDescriptors() {
-    throw new Unreachable();
-  }
+  String getString() throws ResourceException;
 
   class StringContentResource implements StringResource {
     private final Origin origin;
diff --git a/src/main/java/com/android/tools/r8/benchmarks/FrameworkIncrementalDexingBenchmark.java b/src/main/java/com/android/tools/r8/benchmarks/FrameworkIncrementalDexingBenchmark.java
index c130921..bf01553 100644
--- a/src/main/java/com/android/tools/r8/benchmarks/FrameworkIncrementalDexingBenchmark.java
+++ b/src/main/java/com/android/tools/r8/benchmarks/FrameworkIncrementalDexingBenchmark.java
@@ -19,7 +19,6 @@
 import com.android.tools.r8.ProgramConsumer;
 import com.android.tools.r8.ProgramResource;
 import com.android.tools.r8.ProgramResource.Kind;
-import com.android.tools.r8.Resource;
 import com.android.tools.r8.ResourceException;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.origin.PathOrigin;
@@ -77,12 +76,15 @@
     }
 
     @Override
-    public Resource getResource(String descriptor) {
+    public ProgramResource getProgramResource(String descriptor) {
       byte[] bytes = resources.get(descriptor);
       return bytes == null
           ? null
-          : Resource.fromBytes(
-              new EntryOrigin(descriptor, origin), bytes, Collections.singleton(descriptor));
+          : ProgramResource.fromBytes(
+              new EntryOrigin(descriptor, origin),
+              Kind.CF,
+              bytes,
+              Collections.singleton(descriptor));
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/bisect/Bisect.java b/src/main/java/com/android/tools/r8/bisect/Bisect.java
index 6d4ce98..4fed15d 100644
--- a/src/main/java/com/android/tools/r8/bisect/Bisect.java
+++ b/src/main/java/com/android/tools/r8/bisect/Bisect.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.bisect;
 
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.bisect.BisectOptions.Result;
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.dex.ApplicationWriter;
@@ -13,7 +14,6 @@
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.AndroidAppConsumers;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.OutputMode;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.io.CharStreams;
 import java.io.File;
@@ -180,7 +180,7 @@
     AndroidAppConsumers compatSink = new AndroidAppConsumers(options);
     ApplicationWriter writer = new ApplicationWriter(app, options, null, null, null, null, null);
     writer.write(executor);
-    compatSink.build().writeToDirectory(output, OutputMode.Indexed);
+    compatSink.build().writeToDirectory(output, OutputMode.DexIndexed);
   }
 
   public static void main(String[] args) throws Exception {
diff --git a/src/main/java/com/android/tools/r8/compatproguard/CompatProguard.java b/src/main/java/com/android/tools/r8/compatproguard/CompatProguard.java
index ac6989e..aa9698a 100644
--- a/src/main/java/com/android/tools/r8/compatproguard/CompatProguard.java
+++ b/src/main/java/com/android/tools/r8/compatproguard/CompatProguard.java
@@ -9,13 +9,13 @@
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.DexIndexedConsumer;
 import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.Version;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.origin.CommandLineOrigin;
 import com.android.tools.r8.utils.AbortException;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
 import java.nio.file.Paths;
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index e21a9fa..4e24a94 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -11,6 +11,8 @@
 import com.android.tools.r8.ClassFileResourceProvider;
 import com.android.tools.r8.DexFilePerClassFileConsumer;
 import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.DirectoryClassFileProvider;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.ProgramResource;
 import com.android.tools.r8.ProgramResource.Kind;
 import com.android.tools.r8.ProgramResourceProvider;
@@ -202,11 +204,15 @@
    */
   public void writeToDirectory(Path directory, OutputMode outputMode) throws IOException {
     List<ProgramResource> dexProgramSources = getDexProgramResourcesForTesting();
-    if (outputMode.isDexIndexed()) {
-      DexIndexedConsumer.DirectoryConsumer.writeResources(directory, dexProgramSources);
-    } else {
-      DexFilePerClassFileConsumer.DirectoryConsumer.writeResources(
-          directory, dexProgramSources, programResourcesMainDescriptor);
+    try {
+      if (outputMode == OutputMode.DexIndexed) {
+        DexIndexedConsumer.DirectoryConsumer.writeResources(directory, dexProgramSources);
+      } else {
+        DexFilePerClassFileConsumer.DirectoryConsumer.writeResources(
+            directory, dexProgramSources, programResourcesMainDescriptor);
+      }
+    } catch (ResourceException e) {
+      throw new IOException("Resource Error", e);
     }
   }
 
@@ -215,13 +221,17 @@
    */
   public void writeToZip(Path archive, OutputMode outputMode) throws IOException {
     List<ProgramResource> resources = getDexProgramResourcesForTesting();
-    if (outputMode.isDexIndexed()) {
-      DexIndexedConsumer.ArchiveConsumer.writeResources(archive, resources);
-    } else if (outputMode.isDexFilePerClassFile()) {
-      DexFilePerClassFileConsumer.ArchiveConsumer.writeResources(
-          archive, resources, programResourcesMainDescriptor);
-    } else {
-      throw new Unreachable("Unsupported output-mode for writing: " + outputMode);
+    try {
+      if (outputMode == OutputMode.DexIndexed) {
+        DexIndexedConsumer.ArchiveConsumer.writeResources(archive, resources);
+      } else if (outputMode == OutputMode.DexFilePerClassFile) {
+        DexFilePerClassFileConsumer.ArchiveConsumer.writeResources(
+            archive, resources, programResourcesMainDescriptor);
+      } else {
+        throw new Unreachable("Unsupported output-mode for writing: " + outputMode);
+      }
+    } catch (ResourceException e) {
+      throw new IOException("Resource Error", e);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java b/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java
index afd97ae..b6ff3b2 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java
@@ -3,13 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.utils;
 
+import com.android.tools.r8.BaseCompilerCommand;
 import com.android.tools.r8.ClassFileConsumer;
 import com.android.tools.r8.DexFilePerClassFileConsumer;
 import com.android.tools.r8.DexIndexedConsumer;
 import com.android.tools.r8.DexIndexedConsumer.ForwardingConsumer;
 import com.android.tools.r8.DiagnosticsHandler;
 import com.android.tools.r8.ProgramConsumer;
-import com.android.tools.r8.R8Command;
 import com.android.tools.r8.StringConsumer;
 import com.android.tools.r8.origin.Origin;
 import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap;
@@ -32,7 +32,7 @@
     // Nothing to do.
   }
 
-  public AndroidAppConsumers(R8Command.Builder builder) {
+  public AndroidAppConsumers(BaseCompilerCommand.Builder builder) {
     builder.setProgramConsumer(wrapProgramConsumer(builder.getProgramConsumer()));
   }
 
diff --git a/src/main/java/com/android/tools/r8/utils/ClassProvider.java b/src/main/java/com/android/tools/r8/utils/ClassProvider.java
index 990aab9..47d273b 100644
--- a/src/main/java/com/android/tools/r8/utils/ClassProvider.java
+++ b/src/main/java/com/android/tools/r8/utils/ClassProvider.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.ClassFileResourceProvider;
 import com.android.tools.r8.ProgramResource;
+import com.android.tools.r8.ResourceException;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.graph.ClassKind;
 import com.android.tools.r8.graph.DexClass;
@@ -98,8 +99,9 @@
         try (Closer closer = Closer.create()) {
           JarClassFileReader classReader =
               new JarClassFileReader(reader, classKind.bridgeConsumer(classConsumer));
-          classReader.read(resource.getOrigin(), classKind, closer.register(resource.getStream()));
-        } catch (IOException e) {
+          classReader.read(
+              resource.getOrigin(), classKind, closer.register(resource.getByteStream()));
+        } catch (ResourceException | IOException e) {
           throw new CompilationError("Failed to load class: " + descriptor, e);
         }
       }
diff --git a/src/main/java/com/android/tools/r8/utils/OneShotByteResource.java b/src/main/java/com/android/tools/r8/utils/OneShotByteResource.java
index 6bf8a45..da958c3 100644
--- a/src/main/java/com/android/tools/r8/utils/OneShotByteResource.java
+++ b/src/main/java/com/android/tools/r8/utils/OneShotByteResource.java
@@ -5,10 +5,8 @@
 
 import com.android.tools.r8.ProgramResource;
 import com.android.tools.r8.ResourceException;
-import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.origin.Origin;
 import java.io.ByteArrayInputStream;
-import java.io.IOException;
 import java.io.InputStream;
 import java.util.Set;
 
@@ -55,14 +53,4 @@
   public Set<String> getClassDescriptors() {
     return classDescriptors;
   }
-
-  @Override
-  @Deprecated
-  public InputStream getStream() throws IOException {
-    try {
-      return getByteStream();
-    } catch (ResourceException e) {
-      throw new Unreachable(e);
-    }
-  }
 }
diff --git a/src/main/java/com/android/tools/r8/utils/OutputMode.java b/src/main/java/com/android/tools/r8/utils/OutputMode.java
deleted file mode 100644
index 51f6170..0000000
--- a/src/main/java/com/android/tools/r8/utils/OutputMode.java
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2017, 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.utils;
-
-import com.android.tools.r8.errors.Unreachable;
-
-/** Enumeration of the possible output formats of compilation. */
-public enum OutputMode {
-  @Deprecated
-  Indexed,
-
-  @Deprecated
-  FilePerInputClass,
-
-  /** Produce DEX files using standard indexed-multidex for programs larger that a single file. */
-  DexIndexed,
-
-  /** Produce a DEX file for each Java class-file input file. */
-  DexFilePerClassFile,
-
-  /** Produce Java class files. */
-  ClassFile;
-
-  public boolean isDexIndexed() {
-    return this == Indexed || this == DexIndexed;
-  }
-
-  public boolean isDexFilePerClassFile() {
-    return this == FilePerInputClass || this == DexFilePerClassFile;
-  }
-
-  public boolean isClassFile() {
-    return this == ClassFile;
-  }
-
-  public boolean isDeprecated() {
-    return this == Indexed || this == FilePerInputClass;
-  }
-
-  public OutputMode toNonDeprecated() {
-    assert isDeprecated();
-    switch (this) {
-      case Indexed:
-        return DexIndexed;
-      case FilePerInputClass:
-        return DexFilePerClassFile;
-      default:
-        assert isDeprecated();
-        throw new Unreachable();
-    }
-  }
-}
diff --git a/src/main/java/com/android/tools/r8/utils/PreloadedClassFileProvider.java b/src/main/java/com/android/tools/r8/utils/PreloadedClassFileProvider.java
index ec5fccb..82e6a7e 100644
--- a/src/main/java/com/android/tools/r8/utils/PreloadedClassFileProvider.java
+++ b/src/main/java/com/android/tools/r8/utils/PreloadedClassFileProvider.java
@@ -4,7 +4,8 @@
 package com.android.tools.r8.utils;
 
 import com.android.tools.r8.ClassFileResourceProvider;
-import com.android.tools.r8.Resource;
+import com.android.tools.r8.ProgramResource;
+import com.android.tools.r8.ProgramResource.Kind;
 import com.android.tools.r8.origin.Origin;
 import com.google.common.collect.Sets;
 import java.util.Collections;
@@ -43,13 +44,13 @@
   }
 
   @Override
-  public Resource getResource(String descriptor) {
+  public ProgramResource getProgramResource(String descriptor) {
     byte[] bytes = content.get(descriptor);
     if (bytes == null) {
       return null;
     }
-    return Resource.fromBytes(
-        new ClassDescriptorOrigin(descriptor), bytes, Collections.singleton(descriptor));
+    return ProgramResource.fromBytes(
+        new ClassDescriptorOrigin(descriptor), Kind.CF, bytes, Collections.singleton(descriptor));
   }
 
   public static ClassFileResourceProvider fromClassData(String descriptor, byte[] data) {
diff --git a/src/test/apiUsageSample/com/android/tools/apiusagesample/CachingArchiveClassFileProvider.java b/src/test/apiUsageSample/com/android/tools/apiusagesample/CachingArchiveClassFileProvider.java
index 859876d..775a308 100644
--- a/src/test/apiUsageSample/com/android/tools/apiusagesample/CachingArchiveClassFileProvider.java
+++ b/src/test/apiUsageSample/com/android/tools/apiusagesample/CachingArchiveClassFileProvider.java
@@ -6,8 +6,8 @@
 
 import com.android.tools.r8.ArchiveClassFileProvider;
 import com.android.tools.r8.ClassFileResourceProvider;
-import com.android.tools.r8.Resource;
-import com.android.tools.r8.utils.DirectoryClassFileProvider;
+import com.android.tools.r8.DirectoryClassFileProvider;
+import com.android.tools.r8.ProgramResource;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.nio.file.Files;
@@ -16,15 +16,15 @@
 
 public class CachingArchiveClassFileProvider extends ArchiveClassFileProvider {
 
-  private ConcurrentHashMap<String, Resource> resources = new ConcurrentHashMap<>();
+  private ConcurrentHashMap<String, ProgramResource> resources = new ConcurrentHashMap<>();
 
   private CachingArchiveClassFileProvider(Path archive) throws IOException {
     super(archive);
   }
 
   @Override
-  public Resource getResource(String descriptor) {
-    return resources.computeIfAbsent(descriptor, desc -> super.getResource(desc));
+  public ProgramResource getProgramResource(String descriptor) {
+    return resources.computeIfAbsent(descriptor, super::getProgramResource);
   }
 
   public static ClassFileResourceProvider getProvider(Path entry)
diff --git a/src/test/apiUsageSample/com/android/tools/apiusagesample/D8ApiUsageSample.java b/src/test/apiUsageSample/com/android/tools/apiusagesample/D8ApiUsageSample.java
index 84d0ce9..471c6c2 100644
--- a/src/test/apiUsageSample/com/android/tools/apiusagesample/D8ApiUsageSample.java
+++ b/src/test/apiUsageSample/com/android/tools/apiusagesample/D8ApiUsageSample.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.apiusagesample;
 
-import com.android.tools.r8.ArchiveClassFileProvider;
 import com.android.tools.r8.ArchiveProgramResourceProvider;
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.CompilationMode;
@@ -213,10 +212,10 @@
               .setProgramConsumer(new EnsureOutputConsumer())
               .addProgramFiles(inputs);
       for (Path library : libraries) {
-        builder.addLibraryResourceProvider(new ArchiveClassFileProvider(library));
+        builder.addLibraryResourceProvider(CachingArchiveClassFileProvider.getProvider(library));
       }
       for (Path path : classpath) {
-        builder.addClasspathResourceProvider(new ArchiveClassFileProvider(path));
+        builder.addClasspathResourceProvider(CachingArchiveClassFileProvider.getProvider(path));
       }
       D8.run(builder.build());
     } catch (CompilationFailedException e) {
diff --git a/src/test/apiUsageSample/com/android/tools/apiusagesample/D8Compiler.java b/src/test/apiUsageSample/com/android/tools/apiusagesample/D8Compiler.java
deleted file mode 100644
index 12c9b6f..0000000
--- a/src/test/apiUsageSample/com/android/tools/apiusagesample/D8Compiler.java
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright (c) 2017, 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.apiusagesample;
-
-import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.D8;
-import com.android.tools.r8.D8Command;
-import com.android.tools.r8.origin.PathOrigin;
-import com.android.tools.r8.CompilationFailedException;
-import com.android.tools.r8.utils.OutputMode;
-import java.io.IOException;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-public class D8Compiler {
-  private int minSdkVersion;
-  private Path bootclasspath;
-  private List<Path> classpath;
-  private static ExecutorService pool = Executors.newFixedThreadPool(4);
-
-  private D8Compiler(int minSdkVersion, Path bootclasspath, List<Path> classpath) {
-    this.minSdkVersion = minSdkVersion;
-    this.bootclasspath = bootclasspath;
-    this.classpath = classpath;
-  }
-
-  /**
-   * java ...Compiler output input minSdkVersion mainDexClasses bootclasspath [classpathEntries]+
-   */
-  public static void main(String[] args) throws Throwable {
-    try {
-      int argIndex = 0;
-      Path outputDir = Paths.get(args[argIndex++]);
-      Path input = Paths.get(args[argIndex++]);
-      int minSdkVersion = Integer.parseInt(args[argIndex++]);
-      Path mainDexClasses = Paths.get(args[argIndex++]);
-      Path bootclasspath = Paths.get(args[argIndex++]);
-
-      List<Path> classpath = new ArrayList<>(args.length - argIndex);
-      while (argIndex < args.length) {
-        classpath.add(Paths.get(args[argIndex++]));
-      }
-
-      D8Compiler compiler = new D8Compiler(minSdkVersion, bootclasspath, classpath);
-
-      List<Path> toMerge = new ArrayList<>(3);
-
-      int intermediateIndex = 0;
-      for (Path entry : classpath) {
-        Path output = outputDir.resolve(entry.getFileName() + "." + (intermediateIndex++));
-        Files.createDirectory(output);
-        toMerge.add(output);
-        compiler.compile(output, entry);
-      }
-
-      Path output = outputDir.resolve("main." + (intermediateIndex++));
-      Files.createDirectory(output);
-      toMerge.add(output);
-      compiler.compile(output, input);
-
-      compiler.merge(outputDir, mainDexClasses, toMerge);
-    } finally {
-      // Terminate pool threads to prevent the VM to wait on then before exiting.
-      pool.shutdown();
-    }
-  }
-
-  private void compile(Path output, Path input) throws Throwable {
-    D8Command.Builder builder =
-        D8Command.builder(new D8DiagnosticsHandler())
-            // Compile in debug and merge in release to assert access to both modes
-            .setMode(CompilationMode.DEBUG)
-            .setMinApiLevel(minSdkVersion)
-            .setIntermediate(true)
-            .setEnableDesugaring(true)
-            .setOutputPath(output);
-
-    builder.addLibraryResourceProvider(CachingArchiveClassFileProvider.getProvider(bootclasspath));
-
-    for (Path entry : classpath) {
-      builder.addClasspathResourceProvider(CachingArchiveClassFileProvider.getProvider(entry));
-    }
-
-    if (Files.isRegularFile(input)) {
-      builder.setOutputMode(OutputMode.Indexed);
-      builder.addProgramFiles(input);
-    } else {
-      builder.setOutputMode(OutputMode.FilePerInputClass);
-      Files.walkFileTree(input, new SimpleFileVisitor<Path>() {
-        @Override
-        public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes)
-            throws IOException {
-          builder.addClassProgramData(Files.readAllBytes(path), new PathOrigin(path));
-          return FileVisitResult.CONTINUE;
-        }
-      });
-    }
-
-    D8.run(builder.build(), pool);
-  }
-
-  private void merge(Path outputDir, Path mainDexClasses,
-      List<Path> toMerge) throws IOException, CompilationFailedException {
-    D8Command.Builder merger = D8Command.builder(new D8DiagnosticsHandler());
-    merger.setEnableDesugaring(false);
-
-    for (Path mergeInput : toMerge) {
-      Files.walkFileTree(mergeInput, new SimpleFileVisitor<Path>() {
-        @Override
-        public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes)
-            throws IOException {
-          merger.addDexProgramData(Files.readAllBytes(path), new PathOrigin(path));
-          return FileVisitResult.CONTINUE;
-        }
-      });
-    }
-    if (mainDexClasses != null) {
-      merger.addMainDexListFiles(mainDexClasses);
-    }
-    merger.setMinApiLevel(minSdkVersion)
-        .setMode(CompilationMode.RELEASE)
-        .setOutputPath(outputDir)
-        .setEnableDesugaring(false)
-        .setIntermediate(false);
-    D8.run(merger.build());
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java b/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
index 86f0319..61893a6 100644
--- a/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
+++ b/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
@@ -9,10 +9,8 @@
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.FileUtils;
 import com.google.common.collect.ImmutableList;
-import com.google.common.io.Files;
 import java.io.File;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.List;
@@ -28,44 +26,7 @@
   public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
 
   @Test
-  public void testCompatibilityDeprecatedApi() throws IOException {
-    Path compilerJar = Paths.get("tests", "api_usage_sample.jar");
-    String compiler = "com.android.tools.apiusagesample.D8Compiler";
-    String output = temp.newFolder().getAbsolutePath();
-    int minSdkVersion = AndroidApiLevel.K.getLevel();
-    String androidJar = ToolHelper.getAndroidJar(minSdkVersion);
-    Path lib1 = Paths.get(ToolHelper.EXAMPLES_ANDROID_O_BUILD_DIR,
-        "desugaringwithmissingclasslib1" + JAR_EXTENSION);
-    Path lib2 = Paths.get(ToolHelper.EXAMPLES_ANDROID_O_BUILD_DIR,
-        "desugaringwithmissingclasslib2" + JAR_EXTENSION);
-    Path input = Paths.get(ToolHelper.EXAMPLES_ANDROID_O_BUILD_DIR,
-        "classes", "desugaringwithmissingclasstest1");
-    File mainDexClasses = temp.newFile();
-    Files.asCharSink(mainDexClasses, StandardCharsets.UTF_8)
-        .write("desugaringwithmissingclasstest1/Main.class");
-
-    List<String> command = ImmutableList.of(
-        ToolHelper.getJavaExecutable(),
-        "-cp",
-        compilerJar.toString() + File.pathSeparator + System.getProperty("java.class.path"),
-        compiler,
-        // Compiler arguments.
-        output,
-        input.toString(),
-        Integer.toString(minSdkVersion),
-        mainDexClasses.getAbsolutePath(),
-        androidJar,
-        lib1.toString(),
-        lib2.toString());
-    ProcessBuilder builder = new ProcessBuilder(command);
-    ProcessResult result = ToolHelper.runProcess(builder);
-    Assert.assertEquals(result.stderr + "\n" + result.stdout, 0, result.exitCode);
-    Assert.assertTrue(result.stdout, result.stdout.isEmpty());
-    Assert.assertTrue(result.stderr, result.stderr.isEmpty());
-  }
-
-  @Test
-  public void testCompatibilityNewApi() throws IOException {
+  public void testCompatibility() throws IOException {
     Path jar = Paths.get("tests", "d8_api_usage_sample.jar");
     String main = "com.android.tools.apiusagesample.D8ApiUsageSample";
     int minApiLevel = AndroidApiLevel.K.getLevel();
diff --git a/src/test/java/com/android/tools/r8/D8CommandTest.java b/src/test/java/com/android/tools/r8/D8CommandTest.java
index f263d4e..7583e97 100644
--- a/src/test/java/com/android/tools/r8/D8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/D8CommandTest.java
@@ -15,8 +15,6 @@
 import com.android.tools.r8.origin.EmbeddedOrigin;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.DirectoryClassFileProvider;
-import com.android.tools.r8.utils.OutputMode;
 import com.android.tools.r8.utils.ZipUtils;
 import com.google.common.collect.ImmutableList;
 import java.nio.file.Files;
@@ -284,7 +282,11 @@
     ProgramResourceProvider myProvider =
         ArchiveProgramResourceProvider.fromSupplier(
             new MyOrigin(), () -> new ZipFile(input.toFile()));
-    D8Command command = D8Command.builder().addProgramResourceProvider(myProvider).build();
+    D8Command command =
+        D8Command.builder()
+            .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
+            .addProgramResourceProvider(myProvider)
+            .build();
 
     // Check that each resource was provided by our provider.
     ProgramResourceProvider inAppProvider =
diff --git a/src/test/java/com/android/tools/r8/D8IncrementalRunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/D8IncrementalRunExamplesAndroidOTest.java
index 7f85e91..e354237 100644
--- a/src/test/java/com/android/tools/r8/D8IncrementalRunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/D8IncrementalRunExamplesAndroidOTest.java
@@ -17,7 +17,6 @@
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.OffOrAuto;
-import com.android.tools.r8.utils.OutputMode;
 import com.beust.jcommander.internal.Lists;
 import com.google.common.io.ByteStreams;
 import java.io.File;
@@ -56,17 +55,18 @@
 
     @Override
     void build(Path testJarFile, Path out, OutputMode mode) throws Throwable {
-      Map<String, Resource> files = compileClassesTogether(testJarFile, null);
+      Map<String, ProgramResource> files = compileClassesTogether(testJarFile, null);
       mergeClassFiles(Lists.newArrayList(files.values()), out, mode);
     }
 
     // Dex classes separately.
-    SortedMap<String, Resource> compileClassesSeparately(Path testJarFile) throws Throwable {
-      TreeMap<String, Resource> fileToResource = new TreeMap<>();
+    SortedMap<String, ProgramResource> compileClassesSeparately(Path testJarFile) throws Throwable {
+      TreeMap<String, ProgramResource> fileToResource = new TreeMap<>();
       List<String> classFiles = collectClassFiles(testJarFile);
       for (String classFile : classFiles) {
-        AndroidApp app = compileClassFiles(
-            testJarFile, Collections.singletonList(classFile), null, OutputMode.Indexed);
+        AndroidApp app =
+            compileClassFiles(
+                testJarFile, Collections.singletonList(classFile), null, OutputMode.DexIndexed);
         assert app.getDexProgramResourcesForTesting().size() == 1;
         fileToResource.put(
             makeRelative(testJarFile, Paths.get(classFile)).toString(),
@@ -76,12 +76,12 @@
     }
 
     // Dex classes in one D8 invocation.
-    SortedMap<String, Resource> compileClassesTogether(
-        Path testJarFile, Path output) throws Throwable {
-      TreeMap<String, Resource> fileToResource = new TreeMap<>();
+    SortedMap<String, ProgramResource> compileClassesTogether(Path testJarFile, Path output)
+        throws Throwable {
+      TreeMap<String, ProgramResource> fileToResource = new TreeMap<>();
       List<String> classFiles = collectClassFiles(testJarFile);
-      AndroidApp app = compileClassFiles(
-          testJarFile, classFiles, output, OutputMode.FilePerInputClass);
+      AndroidApp app =
+          compileClassFiles(testJarFile, classFiles, output, OutputMode.DexFilePerClassFile);
       for (ProgramResource resource : app.getDexProgramResourcesForTesting()) {
         Set<String> descriptors = resource.getClassDescriptors();
         String mainClassDescriptor = app.getPrimaryClassDescriptor(resource);
@@ -155,8 +155,9 @@
       }
     }
 
-    AndroidApp compileClassFiles(Path testJarFile,
-        List<String> inputFiles, Path output, OutputMode outputMode) throws Throwable {
+    AndroidApp compileClassFiles(
+        Path testJarFile, List<String> inputFiles, Path outputPath, OutputMode outputMode)
+        throws Throwable {
       D8Command.Builder builder = D8Command.builder();
       addClasspathReference(testJarFile, builder);
       for (String inputFile : inputFiles) {
@@ -165,15 +166,19 @@
       for (UnaryOperator<D8Command.Builder> transformation : builderTransformations) {
         builder = transformation.apply(builder);
       }
-      builder = builder.setOutputMode(outputMode);
-      if (output != null) {
-        builder = builder.setOutputPath(output);
+      if (outputPath != null) {
+        builder.setOutput(outputPath, outputMode);
+      } else if (outputMode == OutputMode.DexIndexed) {
+        builder.setProgramConsumer(DexIndexedConsumer.emptyConsumer());
+      } else if (outputMode == OutputMode.DexFilePerClassFile) {
+        builder.setProgramConsumer(DexFilePerClassFileConsumer.emptyConsumer());
+      } else {
+        throw new Unreachable("Unexpected output mode " + outputMode);
       }
       addLibraryReference(builder, Paths.get(ToolHelper.getAndroidJar(
           androidJarVersion == null ? builder.getMinApiLevel() : androidJarVersion)));
-      D8Command command = builder.build();
       try {
-        return ToolHelper.runD8(command, this::combinedOptionConsumer);
+        return ToolHelper.runD8(builder, this::combinedOptionConsumer);
       } catch (Unimplemented | CompilationError | InternalCompilerError re) {
         throw re;
       } catch (RuntimeException re) {
@@ -181,24 +186,30 @@
       }
     }
 
-    Resource mergeClassFiles(List<Resource> dexFiles, Path out) throws Throwable {
-      return mergeClassFiles(dexFiles, out, OutputMode.Indexed);
+    ProgramResource mergeClassFiles(List<ProgramResource> dexFiles, Path out) throws Throwable {
+      return mergeClassFiles(dexFiles, out, OutputMode.DexIndexed);
     }
 
-    Resource mergeClassFiles(List<Resource> dexFiles, Path out, OutputMode mode) throws Throwable {
-      D8Command.Builder builder = D8Command.builder().setOutputMode(mode);
-      for (Resource dexFile : dexFiles) {
+    ProgramResource mergeClassFiles(
+        List<ProgramResource> dexFiles, Path outputPath, OutputMode outputMode) throws Throwable {
+      Builder builder = D8Command.builder();
+      for (ProgramResource dexFile : dexFiles) {
         builder.addDexProgramData(readResource(dexFile), dexFile.getOrigin());
       }
-      for (UnaryOperator<D8Command.Builder> transformation : builderTransformations) {
+      for (UnaryOperator<Builder> transformation : builderTransformations) {
         builder = transformation.apply(builder);
       }
-      if (out != null) {
-        builder = builder.setOutputPath(out);
+      if (outputPath != null) {
+        builder.setOutput(outputPath, outputMode);
+      } else if (outputMode == OutputMode.DexIndexed) {
+        builder.setProgramConsumer(DexIndexedConsumer.emptyConsumer());
+      } else if (outputMode == OutputMode.DexFilePerClassFile) {
+        builder.setProgramConsumer(DexFilePerClassFileConsumer.emptyConsumer());
+      } else {
+        throw new Unreachable("Unexpected output mode " + outputMode);
       }
-      D8Command command = builder.build();
       try {
-        AndroidApp app = ToolHelper.runD8(command, this::combinedOptionConsumer);
+        AndroidApp app = ToolHelper.runD8(builder, this::combinedOptionConsumer);
         assert app.getDexProgramResourcesForTesting().size() == 1;
         return app.getDexProgramResourcesForTesting().get(0);
       } catch (Unimplemented | CompilationError | InternalCompilerError re) {
@@ -224,19 +235,19 @@
 
     D8IncrementalTestRunner test = test(testName, testPackage, mainClass);
 
-    Map<String, Resource> compiledSeparately = test.compileClassesSeparately(inputJarFile);
-    Map<String, Resource> compiledTogether = test.compileClassesTogether(inputJarFile, null);
+    Map<String, ProgramResource> compiledSeparately = test.compileClassesSeparately(inputJarFile);
+    Map<String, ProgramResource> compiledTogether = test.compileClassesTogether(inputJarFile, null);
     Assert.assertEquals(compiledSeparately.size(), compiledTogether.size());
 
-    for (Map.Entry<String, Resource> entry : compiledSeparately.entrySet()) {
-      Resource otherResource = compiledTogether.get(entry.getKey());
+    for (Map.Entry<String, ProgramResource> entry : compiledSeparately.entrySet()) {
+      ProgramResource otherResource = compiledTogether.get(entry.getKey());
       Assert.assertNotNull(otherResource);
       Assert.assertArrayEquals(readResource(entry.getValue()), readResource(otherResource));
     }
 
-    Resource mergedFromCompiledSeparately =
+    ProgramResource mergedFromCompiledSeparately =
         test.mergeClassFiles(Lists.newArrayList(compiledSeparately.values()), null);
-    Resource mergedFromCompiledTogether =
+    ProgramResource mergedFromCompiledTogether =
         test.mergeClassFiles(Lists.newArrayList(compiledTogether.values()), null);
     Assert.assertArrayEquals(
         readResource(mergedFromCompiledSeparately),
@@ -254,12 +265,12 @@
     D8IncrementalTestRunner test = test(testName, testPackage, mainClass);
     test.withInterfaceMethodDesugaring(OffOrAuto.Auto);
 
-    Resource mergedFromCompiledSeparately =
-        test.mergeClassFiles(Lists.newArrayList(
-            test.compileClassesSeparately(inputJarFile).values()), null);
-    Resource mergedFromCompiledTogether =
-        test.mergeClassFiles(Lists.newArrayList(
-            test.compileClassesTogether(inputJarFile, null).values()), null);
+    ProgramResource mergedFromCompiledSeparately =
+        test.mergeClassFiles(
+            Lists.newArrayList(test.compileClassesSeparately(inputJarFile).values()), null);
+    ProgramResource mergedFromCompiledTogether =
+        test.mergeClassFiles(
+            Lists.newArrayList(test.compileClassesTogether(inputJarFile, null).values()), null);
 
     Assert.assertArrayEquals(
         readResource(mergedFromCompiledSeparately),
@@ -318,8 +329,8 @@
     throw new Unreachable();
   }
 
-  static byte[] readResource(Resource resource) throws IOException {
-    try (InputStream input = resource.getStream()) {
+  static byte[] readResource(ProgramResource resource) throws IOException, ResourceException {
+    try (InputStream input = resource.getByteStream()) {
       return ByteStreams.toByteArray(input);
     }
   }
diff --git a/src/test/java/com/android/tools/r8/D8LazyRunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/D8LazyRunExamplesAndroidOTest.java
index 36f92b4..d1ef6e7 100644
--- a/src/test/java/com/android/tools/r8/D8LazyRunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/D8LazyRunExamplesAndroidOTest.java
@@ -10,7 +10,6 @@
 import com.android.tools.r8.D8Command.Builder;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.DirectoryClassFileProvider;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.OffOrAuto;
 import com.android.tools.r8.utils.ZipUtils;
@@ -77,11 +76,11 @@
     // Build all at once.
     AndroidApp fullBuildResult;
     {
-      D8Command command = D8Command.builder()
-          .setMinApiLevel(minAPILevel)
-          .addLibraryFiles(androidJar)
-          .addProgramFiles(inputFile)
-          .build();
+      D8Command.Builder command =
+          D8Command.builder()
+              .setMinApiLevel(minAPILevel)
+              .addLibraryFiles(androidJar)
+              .addProgramFiles(inputFile);
 
       fullBuildResult = ToolHelper.runD8(
           command, options -> {
@@ -91,7 +90,7 @@
     }
 
     // Build each class individually using tmpClassesDir as classpath for desugaring.
-    List<Resource> individalDexes = new ArrayList<>();
+    List<ProgramResource> individalDexes = new ArrayList<>();
     List<Path> individualClassFiles =
         Files.walk(tmpClassesDir)
         .filter(classFile -> FileUtils.isClassFile(classFile))
@@ -105,7 +104,7 @@
               .addProgramFiles(classFile);
       AndroidApp individualResult =
           ToolHelper.runD8(
-              builder.build(),
+              builder,
               options -> {
                 options.interfaceMethodDesugaring = OffOrAuto.Auto;
                 options.setMarker(null);
@@ -119,15 +118,14 @@
         readResource(mergedResult.getDexProgramResourcesForTesting().get(0))));
   }
 
-  private AndroidApp mergeDexResources(int minAPILevel, List<Resource> individalDexes)
-      throws IOException, CompilationException, CompilationFailedException {
+  private AndroidApp mergeDexResources(int minAPILevel, List<ProgramResource> individalDexes)
+      throws IOException, CompilationException, CompilationFailedException, ResourceException {
     D8Command.Builder builder = D8Command.builder()
         .setMinApiLevel(minAPILevel);
-    for (Resource resource : individalDexes) {
+    for (ProgramResource resource : individalDexes) {
       builder.addDexProgramData(readResource(resource), resource.getOrigin());
     }
-    AndroidApp mergedResult = ToolHelper.runD8(builder.build(),
-        options -> options.setMarker(null));
+    AndroidApp mergedResult = ToolHelper.runD8(builder, options -> options.setMarker(null));
     return mergedResult;
   }
 
diff --git a/src/test/java/com/android/tools/r8/D8RunExamplesAndroidNTest.java b/src/test/java/com/android/tools/r8/D8RunExamplesAndroidNTest.java
index 7fb4bcf..9e00452 100644
--- a/src/test/java/com/android/tools/r8/D8RunExamplesAndroidNTest.java
+++ b/src/test/java/com/android/tools/r8/D8RunExamplesAndroidNTest.java
@@ -29,10 +29,12 @@
       for (UnaryOperator<Builder> transformation : builderTransformations) {
         builder = transformation.apply(builder);
       }
-      builder.addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(builder.getMinApiLevel())));
-      D8Command command = builder.addProgramFiles(inputFile).setOutputPath(out).build();
+      builder
+          .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(builder.getMinApiLevel())))
+          .addProgramFiles(inputFile)
+          .setOutput(out, OutputMode.DexIndexed);
       try {
-        ToolHelper.runD8(command, this::combinedOptionConsumer);
+        ToolHelper.runD8(builder, this::combinedOptionConsumer);
       } catch (RuntimeException re) {
         throw re instanceof CompilationError ? re : re.getCause();
       }
diff --git a/src/test/java/com/android/tools/r8/D8RunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/D8RunExamplesAndroidOTest.java
index e885d40..4f9a652 100644
--- a/src/test/java/com/android/tools/r8/D8RunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/D8RunExamplesAndroidOTest.java
@@ -9,7 +9,6 @@
 import com.android.tools.r8.errors.Unimplemented;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.OffOrAuto;
-import com.android.tools.r8.utils.OutputMode;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.function.UnaryOperator;
@@ -39,7 +38,7 @@
 
     @Override
     void build(Path inputFile, Path out, OutputMode mode) throws Throwable {
-      D8Command.Builder builder = D8Command.builder().setOutputMode(mode);
+      D8Command.Builder builder = D8Command.builder().setOutput(out, mode);
       for (UnaryOperator<D8Command.Builder> transformation : builderTransformations) {
         builder = transformation.apply(builder);
       }
@@ -47,9 +46,9 @@
           Paths.get(
               ToolHelper.getAndroidJar(
                   androidJarVersion == null ? builder.getMinApiLevel() : androidJarVersion)));
-      D8Command command = builder.addProgramFiles(inputFile).setOutputPath(out).build();
+      builder.addProgramFiles(inputFile);
       try {
-        ToolHelper.runD8(command, this::combinedOptionConsumer);
+        ToolHelper.runD8(builder, this::combinedOptionConsumer);
       } catch (Unimplemented | CompilationError | InternalCompilerError re) {
         throw re;
       } catch (RuntimeException re) {
diff --git a/src/test/java/com/android/tools/r8/D8RunExamplesAndroidPTest.java b/src/test/java/com/android/tools/r8/D8RunExamplesAndroidPTest.java
index 9063dd2..41c0b9f 100644
--- a/src/test/java/com/android/tools/r8/D8RunExamplesAndroidPTest.java
+++ b/src/test/java/com/android/tools/r8/D8RunExamplesAndroidPTest.java
@@ -37,10 +37,12 @@
         builder = transformation.apply(builder);
       }
       // TODO(mikaelpeltier) Add new android.jar build from aosp and use it
-      builder.addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(AndroidApiLevel.O.getLevel())));
-      D8Command command = builder.addProgramFiles(inputFile).setOutputPath(out).build();
+      builder
+          .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(AndroidApiLevel.O.getLevel())))
+          .addProgramFiles(inputFile)
+          .setOutput(out, OutputMode.DexIndexed);
       try {
-        ToolHelper.runD8(command, this::combinedOptionConsumer);
+        ToolHelper.runD8(builder, this::combinedOptionConsumer);
       } catch (Unimplemented | CompilationError | InternalCompilerError re) {
         throw re;
       } catch (RuntimeException re) {
diff --git a/src/test/java/com/android/tools/r8/D8RunExamplesJava9Test.java b/src/test/java/com/android/tools/r8/D8RunExamplesJava9Test.java
index a98ac69..9240d8c 100644
--- a/src/test/java/com/android/tools/r8/D8RunExamplesJava9Test.java
+++ b/src/test/java/com/android/tools/r8/D8RunExamplesJava9Test.java
@@ -8,7 +8,6 @@
 import com.android.tools.r8.errors.InternalCompilerError;
 import com.android.tools.r8.errors.Unimplemented;
 import com.android.tools.r8.utils.AndroidApiLevel;
-import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.function.UnaryOperator;
@@ -38,10 +37,12 @@
         builder = transformation.apply(builder);
       }
       // TODO(mikaelpeltier) Add new android.jar build from aosp and use it
-      builder.addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(AndroidApiLevel.P.getLevel())));
-      D8Command command = builder.addProgramFiles(inputFile).setOutputPath(out).build();
+      builder
+          .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(AndroidApiLevel.P.getLevel())))
+          .addProgramFiles(inputFile)
+          .setOutput(out, OutputMode.DexIndexed);
       try {
-        ToolHelper.runD8(command, this::combinedOptionConsumer);
+        ToolHelper.runD8(builder, this::combinedOptionConsumer);
       } catch (Unimplemented | CompilationError | InternalCompilerError re) {
         throw re;
       } catch (RuntimeException re) {
diff --git a/src/test/java/com/android/tools/r8/R8CodeCanonicalizationTest.java b/src/test/java/com/android/tools/r8/R8CodeCanonicalizationTest.java
index ae44a5a..c84349d 100644
--- a/src/test/java/com/android/tools/r8/R8CodeCanonicalizationTest.java
+++ b/src/test/java/com/android/tools/r8/R8CodeCanonicalizationTest.java
@@ -6,7 +6,6 @@
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.DexFileReader;
 import com.android.tools.r8.dex.Segment;
-import com.android.tools.r8.utils.OutputMode;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
diff --git a/src/test/java/com/android/tools/r8/R8CommandTest.java b/src/test/java/com/android/tools/r8/R8CommandTest.java
index 808d49e..f782a94 100644
--- a/src/test/java/com/android/tools/r8/R8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/R8CommandTest.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.origin.EmbeddedOrigin;
 import com.android.tools.r8.utils.FileUtils;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import java.lang.reflect.Method;
 import java.nio.file.Files;
diff --git a/src/test/java/com/android/tools/r8/R8EntryPointTests.java b/src/test/java/com/android/tools/r8/R8EntryPointTests.java
index da1ef11..01a9ebe 100644
--- a/src/test/java/com/android/tools/r8/R8EntryPointTests.java
+++ b/src/test/java/com/android/tools/r8/R8EntryPointTests.java
@@ -6,7 +6,6 @@
 
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.utils.FileUtils;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
 import java.nio.file.Files;
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
index 1bfea4e..fc3fd44 100644
--- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -21,7 +21,6 @@
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
 import com.android.tools.r8.utils.ListUtils;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.base.Charsets;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableListMultimap;
@@ -886,7 +885,7 @@
           // When starting from the Jar frontend we see the A$B class both from the Java source
           // code and from the smali dex code. We reject that because there are then two definitions
           // of the same class in the application. When running from the final dex files there is
-          // only on A$B class because of a custom build script that merges them.
+          // only one A$B class because of a custom build script that merges them.
           .put("121-modifiers", TestCondition.match(TestCondition.tools(DexTool.NONE)))
           // This test uses register r1 in method that is declared to only use 1 register (r0).
           .put("142-classloader2", TestCondition.match(TestCondition.R8_COMPILER))
@@ -1388,7 +1387,7 @@
           builder.addLibraryFiles(Paths.get(
               ToolHelper.getAndroidJar(AndroidApiLevel.getDefault().getLevel())));
         }
-        ToolHelper.runD8(builder.build());
+        D8.run(builder.build());
         break;
       }
       case R8:
@@ -1782,7 +1781,7 @@
         executeCompilerUnderTest(
             compilerUnderTest, fileNames, resultDir.getCanonicalPath(), compilationMode,
             specification.disableInlining);
-      } catch (CompilationException e) {
+      } catch (CompilationException | CompilationFailedException e) {
         throw new CompilationError(e.getMessage(), e);
       } catch (ExecutionException e) {
         throw e.getCause();
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidNTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidNTest.java
index 8f515da..8d89f42 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidNTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidNTest.java
@@ -4,7 +4,6 @@
 
 package com.android.tools.r8;
 
-import com.android.tools.r8.utils.OutputMode;
 import java.nio.file.Path;
 import java.util.function.UnaryOperator;
 
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
index 57ae420..e7434c3 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
@@ -7,7 +7,6 @@
 import com.android.tools.r8.ToolHelper.DexVm;
 import com.android.tools.r8.ToolHelper.DexVm.Version;
 import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import java.nio.file.Path;
@@ -69,7 +68,7 @@
 
     @Override
     void build(Path inputFile, Path out, OutputMode mode) throws Throwable {
-      R8Command.Builder builder = R8Command.builder().setOutput(out, mode.toNonDeprecated());
+      R8Command.Builder builder = R8Command.builder().setOutput(out, mode);
       for (UnaryOperator<R8Command.Builder> transformation : builderTransformations) {
         builder = transformation.apply(builder);
       }
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidPTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidPTest.java
index b063770..58899c0 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidPTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidPTest.java
@@ -6,7 +6,6 @@
 
 import com.android.tools.r8.ToolHelper.DexVm;
 import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import java.nio.file.Path;
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesCommon.java b/src/test/java/com/android/tools/r8/R8RunExamplesCommon.java
index 8e23386..f31e99c 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesCommon.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesCommon.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.ToolHelper.DexVm;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
-import com.android.tools.r8.utils.OutputMode;
 import java.io.IOException;
 import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
@@ -127,7 +126,7 @@
     switch (compiler) {
       case D8: {
         assertTrue(output == Output.DEX);
-        ToolHelper.runD8(
+        D8.run(
             D8Command.builder()
                 .addProgramFiles(getInputFile())
                 .setOutput(getOutputFile(), outputMode)
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesJava9Test.java b/src/test/java/com/android/tools/r8/R8RunExamplesJava9Test.java
index f872901..54fe1ab 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesJava9Test.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesJava9Test.java
@@ -5,7 +5,6 @@
 package com.android.tools.r8;
 
 import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.OutputMode;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.function.UnaryOperator;
diff --git a/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java b/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
index 126bccf..c99dcaa 100644
--- a/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
@@ -7,7 +7,6 @@
 
 import com.android.tools.r8.ToolHelper.DexVm;
 import com.android.tools.r8.ToolHelper.DexVm.Version;
-import com.android.tools.r8.utils.OutputMode;
 import com.android.tools.r8.utils.StringUtils;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
diff --git a/src/test/java/com/android/tools/r8/RunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/RunExamplesAndroidOTest.java
index 32f0707..ddaa777 100644
--- a/src/test/java/com/android/tools/r8/RunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/RunExamplesAndroidOTest.java
@@ -21,7 +21,6 @@
 import com.android.tools.r8.utils.DexInspector.InvokeInstructionSubject;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.OffOrAuto;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.io.ByteStreams;
@@ -172,7 +171,7 @@
     }
 
     void build(Path inputFile, Path out) throws Throwable {
-      build(inputFile, out, OutputMode.Indexed);
+      build(inputFile, out, OutputMode.DexIndexed);
     }
 
     abstract void build(Path inputFile, Path out, OutputMode mode) throws Throwable;
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index a6d49eb..479ef03 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -13,12 +13,12 @@
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.AndroidAppConsumers;
 import com.android.tools.r8.utils.DexInspector;
 import com.android.tools.r8.utils.DexInspector.ClassSubject;
 import com.android.tools.r8.utils.DexInspector.MethodSubject;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.io.ByteStreams;
@@ -153,8 +153,10 @@
    */
   protected AndroidApp compileWithD8(AndroidApp app)
       throws CompilationException, ExecutionException, IOException, CompilationFailedException {
-    D8Command command = ToolHelper.prepareD8CommandBuilder(app).build();
-    return ToolHelper.runD8(command);
+    D8Command.Builder builder = ToolHelper.prepareD8CommandBuilder(app);
+    AndroidAppConsumers appSink = new AndroidAppConsumers(builder);
+    D8.run(builder.build());
+    return appSink.build();
   }
 
   /**
@@ -162,8 +164,7 @@
    */
   protected AndroidApp compileWithD8(AndroidApp app, Consumer<InternalOptions> optionsConsumer)
       throws CompilationException, ExecutionException, IOException, CompilationFailedException {
-    D8Command command = ToolHelper.prepareD8CommandBuilder(app).build();
-    return ToolHelper.runD8(command, optionsConsumer);
+    return ToolHelper.runD8(app, optionsConsumer);
   }
 
   /**
@@ -172,8 +173,7 @@
   protected AndroidApp compileWithR8(Class... classes)
       throws CompilationException, ProguardRuleParserException, ExecutionException, IOException,
       CompilationFailedException {
-    R8Command command = ToolHelper.prepareR8CommandBuilder(readClasses(classes)).build();
-    return ToolHelper.runR8(command);
+    return ToolHelper.runR8(readClasses(classes));
   }
 
   /**
@@ -330,7 +330,7 @@
    */
   protected ProcessResult runOnArtRaw(AndroidApp app, String mainClass) throws IOException {
     Path out = File.createTempFile("junit", ".zip", temp.getRoot()).toPath();
-    app.writeToZip(out, OutputMode.Indexed);
+    app.writeToZip(out, OutputMode.DexIndexed);
     return ToolHelper.runArtRaw(ImmutableList.of(out.toString()), mainClass, null);
   }
 
@@ -367,7 +367,7 @@
    */
   protected String runOnArt(AndroidApp app, Class mainClass, List<String> args) throws IOException {
     Path out = File.createTempFile("junit", ".zip", temp.getRoot()).toPath();
-    app.writeToZip(out, OutputMode.Indexed);
+    app.writeToZip(out, OutputMode.DexIndexed);
     return ToolHelper.runArtNoVerificationErrors(
         ImmutableList.of(out.toString()), mainClass.getCanonicalName(),
         builder -> {
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index efb39dc..6eb7c51 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -783,23 +783,21 @@
   public static AndroidApp runD8(AndroidApp app, Consumer<InternalOptions> optionsConsumer)
       throws CompilationException, IOException {
     try {
-      return runD8(D8Command.builder(app).build(), optionsConsumer);
+      return runD8(D8Command.builder(app), optionsConsumer);
     } catch (CompilationFailedException e) {
       throw new RuntimeException(e);
     }
   }
 
-  public static AndroidApp runD8(D8Command command) throws IOException, CompilationException {
-    return runD8(command, null);
-  }
-
-  public static AndroidApp runD8(D8Command command, Consumer<InternalOptions> optionsConsumer)
-      throws IOException, CompilationException {
+  public static AndroidApp runD8(
+      D8Command.Builder builder, Consumer<InternalOptions> optionsConsumer)
+      throws IOException, CompilationException, CompilationFailedException {
+    AndroidAppConsumers compatSink = new AndroidAppConsumers(builder);
+    D8Command command = builder.build();
     InternalOptions options = command.getInternalOptions();
     if (optionsConsumer != null) {
       optionsConsumer.accept(options);
     }
-    AndroidAppConsumers compatSink = new AndroidAppConsumers(options);
     D8.runForTesting(command.getInputApp(), options);
     return compatSink.build();
   }
diff --git a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
index a3f74d3..52066a6 100644
--- a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
@@ -8,12 +8,12 @@
 
 import com.android.tools.r8.CompilationException;
 import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import com.android.tools.r8.utils.DexInspector;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
 import java.nio.file.Path;
diff --git a/src/test/java/com/android/tools/r8/compatdexbuilder/CompatDexBuilderTests.java b/src/test/java/com/android/tools/r8/compatdexbuilder/CompatDexBuilderTests.java
index 4afaf9c..e49c740 100644
--- a/src/test/java/com/android/tools/r8/compatdexbuilder/CompatDexBuilderTests.java
+++ b/src/test/java/com/android/tools/r8/compatdexbuilder/CompatDexBuilderTests.java
@@ -10,9 +10,9 @@
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.D8;
 import com.android.tools.r8.D8Command;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
 import java.nio.file.Path;
diff --git a/src/test/java/com/android/tools/r8/compatproguard/CompatProguardSmaliTestBase.java b/src/test/java/com/android/tools/r8/compatproguard/CompatProguardSmaliTestBase.java
index bf42eef..178337a 100644
--- a/src/test/java/com/android/tools/r8/compatproguard/CompatProguardSmaliTestBase.java
+++ b/src/test/java/com/android/tools/r8/compatproguard/CompatProguardSmaliTestBase.java
@@ -4,13 +4,13 @@
 package com.android.tools.r8.compatproguard;
 
 import com.android.tools.r8.CompatProguardCommandBuilder;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.smali.SmaliBuilder;
 import com.android.tools.r8.smali.SmaliTestBase;
 import com.android.tools.r8.utils.DexInspector;
-import com.android.tools.r8.utils.OutputMode;
 import java.nio.file.Path;
 import java.util.List;
 
diff --git a/src/test/java/com/android/tools/r8/d8/D8FrameworkDexPassthroughMarkerTest.java b/src/test/java/com/android/tools/r8/d8/D8FrameworkDexPassthroughMarkerTest.java
index ecc5253..9ce3d9c 100644
--- a/src/test/java/com/android/tools/r8/d8/D8FrameworkDexPassthroughMarkerTest.java
+++ b/src/test/java/com/android/tools/r8/d8/D8FrameworkDexPassthroughMarkerTest.java
@@ -5,11 +5,9 @@
 
 import static org.junit.Assert.assertEquals;
 
-import com.android.tools.r8.CompilationException;
 import com.android.tools.r8.D8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.dex.ApplicationReader;
-import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.Marker;
 import com.android.tools.r8.dex.Marker.Tool;
 import com.android.tools.r8.graph.DexApplication;
@@ -17,12 +15,10 @@
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.Timing;
-import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.concurrent.ExecutionException;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
@@ -60,10 +56,8 @@
 
   @Test
   public void compile() throws Exception {
-    D8Command command = D8Command.builder()
-        .setMinApiLevel(minApi)
-        .addProgramFiles(FRAMEWORK_JAR)
-        .build();
+    D8Command.Builder command =
+        D8Command.builder().setMinApiLevel(minApi).addProgramFiles(FRAMEWORK_JAR);
     Marker marker = new Marker(Tool.D8)
         .setVersion("1.0.0")
         .setMinApi(minApi);
diff --git a/src/test/java/com/android/tools/r8/d8/DexVersionTests.java b/src/test/java/com/android/tools/r8/d8/DexVersionTests.java
index bd85131..59034a5 100644
--- a/src/test/java/com/android/tools/r8/d8/DexVersionTests.java
+++ b/src/test/java/com/android/tools/r8/d8/DexVersionTests.java
@@ -3,14 +3,19 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.d8;
 
+import static org.junit.Assert.assertTrue;
+
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.D8;
 import com.android.tools.r8.D8Command;
+import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.OutputMode;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.Set;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -31,7 +36,6 @@
   @Rule public TemporaryFolder androidNApiFolder1 = ToolHelper.getTemporaryFolderForTest();
   @Rule public TemporaryFolder androidNApiFolder2 = ToolHelper.getTemporaryFolderForTest();
 
-
   @Before
   public void compileVersions() throws Exception {
     D8Command.Builder arrayAccessBuilder = D8Command.builder().addProgramFiles(ARRAYACCESS_JAR);
@@ -67,6 +71,22 @@
             .build());
   }
 
+  private class EnsureOutputConsumer implements DexIndexedConsumer {
+
+    boolean hasOutput = false;
+
+    @Override
+    public void accept(
+        int fileIndex, byte[] data, Set<String> descriptors, DiagnosticsHandler handler) {
+      hasOutput = true;
+    }
+
+    @Override
+    public void finished(DiagnosticsHandler handler) {
+      assertTrue(hasOutput);
+    }
+  }
+
   private Path default1() {
     return defaultApiFolder1.getRoot().toPath().resolve("classes.dex");
   }
@@ -94,46 +114,82 @@
   @Test
   public void mergeCompatibleVersions() throws Exception {
     // Verify that we can merge between all versions when no explicit min sdk version is set.
-    D8.run(D8Command.builder().addProgramFiles(default1()).addProgramFiles(default2()).build());
-    D8.run(D8Command.builder().addProgramFiles(default1()).addProgramFiles(androidO2()).build());
-    D8.run(D8Command.builder().addProgramFiles(default1()).addProgramFiles(androidN2()).build());
-    D8.run(D8Command.builder().addProgramFiles(androidO1()).addProgramFiles(androidN2()).build());
-    D8.run(D8Command.builder().addProgramFiles(androidO1()).addProgramFiles(androidO2()).build());
-    D8.run(D8Command.builder().addProgramFiles(androidN1()).addProgramFiles(androidN2()).build());
+    D8.run(
+        D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
+            .addProgramFiles(default1())
+            .addProgramFiles(default2())
+            .build());
+    D8.run(
+        D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
+            .addProgramFiles(default1())
+            .addProgramFiles(androidO2())
+            .build());
+    D8.run(
+        D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
+            .addProgramFiles(default1())
+            .addProgramFiles(androidN2())
+            .build());
+    D8.run(
+        D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
+            .addProgramFiles(androidO1())
+            .addProgramFiles(androidN2())
+            .build());
+    D8.run(
+        D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
+            .addProgramFiles(androidO1())
+            .addProgramFiles(androidO2())
+            .build());
+    D8.run(
+        D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
+            .addProgramFiles(androidN1())
+            .addProgramFiles(androidN2())
+            .build());
     // Verify that we can merge between all version when api version is explicitly
     // set to Android O.
     D8.run(
         D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
             .setMinApiLevel(AndroidApiLevel.O.getLevel())
             .addProgramFiles(default1())
             .addProgramFiles(default2())
             .build());
     D8.run(
         D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
             .setMinApiLevel(AndroidApiLevel.O.getLevel())
             .addProgramFiles(default1())
             .addProgramFiles(androidO2())
             .build());
     D8.run(
         D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
             .setMinApiLevel(AndroidApiLevel.O.getLevel())
             .addProgramFiles(default1())
             .addProgramFiles(androidN2())
             .build());
     D8.run(
         D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
             .setMinApiLevel(AndroidApiLevel.O.getLevel())
             .addProgramFiles(androidO1())
             .addProgramFiles(androidN2())
             .build());
     D8.run(
         D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
             .setMinApiLevel(AndroidApiLevel.O.getLevel())
             .addProgramFiles(androidO1())
             .addProgramFiles(androidO2())
             .build());
     D8.run(
         D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
             .setMinApiLevel(AndroidApiLevel.O.getLevel())
             .addProgramFiles(androidN1())
             .addProgramFiles(androidN2())
@@ -142,18 +198,21 @@
     // Android N.
     D8.run(
         D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
             .setMinApiLevel(AndroidApiLevel.N.getLevel())
             .addProgramFiles(default1())
             .addProgramFiles(default2())
             .build());
     D8.run(
         D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
             .setMinApiLevel(AndroidApiLevel.N.getLevel())
             .addProgramFiles(default1())
             .addProgramFiles(androidN2())
             .build());
     D8.run(
         D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
             .setMinApiLevel(AndroidApiLevel.N.getLevel())
             .addProgramFiles(androidN1())
             .addProgramFiles(androidN2())
@@ -162,6 +221,7 @@
     // Android K.
     D8.run(
         D8Command.builder()
+            .setProgramConsumer(new EnsureOutputConsumer())
             .setMinApiLevel(AndroidApiLevel.K.getLevel())
             .addProgramFiles(default1())
             .addProgramFiles(default2())
@@ -172,6 +232,7 @@
   public void mergeErrorVersionNWithVersionOInput() throws Exception {
     D8.run(
         D8Command.builder()
+            .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
             .setMinApiLevel(AndroidApiLevel.N.getLevel())
             .addProgramFiles(default1())
             .addProgramFiles(androidO2())
@@ -182,6 +243,7 @@
   public void mergeErrorVersionKWithVersionOInput() throws Exception {
     D8.run(
         D8Command.builder()
+            .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
             .setMinApiLevel(AndroidApiLevel.K.getLevel())
             .addProgramFiles(default1())
             .addProgramFiles(androidO2())
@@ -192,6 +254,7 @@
   public void mergeErrorVersionKWithVersionNInput() throws Exception {
     D8.run(
         D8Command.builder()
+            .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
             .setMinApiLevel(AndroidApiLevel.K.getLevel())
             .addProgramFiles(default1())
             .addProgramFiles(androidN2())
diff --git a/src/test/java/com/android/tools/r8/d8/WriteToArchiveTest.java b/src/test/java/com/android/tools/r8/d8/WriteToArchiveTest.java
index d541e3e..6df4c3d 100644
--- a/src/test/java/com/android/tools/r8/d8/WriteToArchiveTest.java
+++ b/src/test/java/com/android/tools/r8/d8/WriteToArchiveTest.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.D8;
 import com.android.tools.r8.D8Command;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.ToolHelper;
 import java.nio.file.Paths;
 import org.junit.Rule;
@@ -24,7 +25,8 @@
     D8Command command =
         D8Command.builder()
             .addProgramFiles(Paths.get(input))
-            .setOutputPath(Paths.get(zipFolder.getRoot().toString() + "/output.zip"))
+            .setOutput(
+                Paths.get(zipFolder.getRoot().toString() + "/output.zip"), OutputMode.DexIndexed)
             .build();
     D8.run(command);
   }
@@ -34,7 +36,8 @@
     D8Command command =
         D8Command.builder()
             .addProgramFiles(Paths.get(input))
-            .setOutputPath(Paths.get(jarFolder.getRoot().toString() + "/output.jar"))
+            .setOutput(
+                Paths.get(jarFolder.getRoot().toString() + "/output.jar"), OutputMode.DexIndexed)
             .build();
     D8.run(command);
   }
diff --git a/src/test/java/com/android/tools/r8/debug/D8DebugTestConfig.java b/src/test/java/com/android/tools/r8/debug/D8DebugTestConfig.java
index 3edaaaf..ceac7c1 100644
--- a/src/test/java/com/android/tools/r8/debug/D8DebugTestConfig.java
+++ b/src/test/java/com/android/tools/r8/debug/D8DebugTestConfig.java
@@ -5,10 +5,10 @@
 
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.D8Command;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.OutputMode;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Arrays;
@@ -22,13 +22,13 @@
   public static AndroidApp d8Compile(List<Path> paths, Consumer<InternalOptions> optionsConsumer) {
     try {
       int minSdk = ToolHelper.getMinApiLevelForDexVm(ToolHelper.getDexVm());
+      D8Command.Builder builder = D8Command.builder();
       return ToolHelper.runD8(
-          D8Command.builder()
+          builder
               .addProgramFiles(paths)
               .setMinApiLevel(minSdk)
               .setMode(CompilationMode.DEBUG)
-              .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(minSdk)))
-              .build(),
+              .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(minSdk))),
           optionsConsumer);
     } catch (Exception e) {
       throw new RuntimeException(e);
@@ -47,7 +47,7 @@
       TemporaryFolder temp, List<Path> paths, Consumer<InternalOptions> optionsConsumer) {
     try {
       Path out = temp.newFolder().toPath().resolve("d8_compiled.jar");
-      d8Compile(paths, optionsConsumer).write(out, OutputMode.Indexed);
+      d8Compile(paths, optionsConsumer).write(out, OutputMode.DexIndexed);
       addPaths(out);
       return this;
     } catch (Exception e) {
diff --git a/src/test/java/com/android/tools/r8/debug/D8DebugTestResourcesConfig.java b/src/test/java/com/android/tools/r8/debug/D8DebugTestResourcesConfig.java
index 3534cad..299fd75 100644
--- a/src/test/java/com/android/tools/r8/debug/D8DebugTestResourcesConfig.java
+++ b/src/test/java/com/android/tools/r8/debug/D8DebugTestResourcesConfig.java
@@ -3,8 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.debug;
 
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.OutputMode;
 import java.nio.file.Path;
 import java.util.Collections;
 import org.junit.rules.TemporaryFolder;
@@ -24,7 +24,7 @@
   public D8DebugTestResourcesConfig(TemporaryFolder temp) {
     try {
       Path path = temp.newFolder().toPath().resolve("d8_debug_test_resources.jar");
-      getCompiledResources().write(path, OutputMode.Indexed);
+      getCompiledResources().write(path, OutputMode.DexIndexed);
       addPaths(path);
     } catch (Throwable e) {
       throw new RuntimeException(e);
diff --git a/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java b/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
index b5e1fc5..7affcfb 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
@@ -4,11 +4,11 @@
 package com.android.tools.r8.debug;
 
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.debug.DebugTestBase.JUnit3Wrapper.Command;
 import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import java.nio.file.Path;
 import java.nio.file.Paths;
diff --git a/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java b/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
index 9e24a13..913d39e 100644
--- a/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
+++ b/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
@@ -4,12 +4,12 @@
 package com.android.tools.r8.debug;
 
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.DexVm.Version;
 import com.android.tools.r8.debug.DebugTestBase.JUnit3Wrapper.DebuggeeState;
 import com.android.tools.r8.utils.FileUtils;
-import com.android.tools.r8.utils.OutputMode;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.stream.Stream;
diff --git a/src/test/java/com/android/tools/r8/debug/KotlinDebugTestBase.java b/src/test/java/com/android/tools/r8/debug/KotlinDebugTestBase.java
index cbbcfb0..845a450 100644
--- a/src/test/java/com/android/tools/r8/debug/KotlinDebugTestBase.java
+++ b/src/test/java/com/android/tools/r8/debug/KotlinDebugTestBase.java
@@ -4,9 +4,9 @@
 
 package com.android.tools.r8.debug;
 
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.OutputMode;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Arrays;
@@ -41,7 +41,7 @@
       super();
       try {
         Path out = temp.newFolder().toPath().resolve("d8_debug_test_resources_kotlin.jar");
-        getCompiledResources().write(out, OutputMode.Indexed);
+        getCompiledResources().write(out, OutputMode.DexIndexed);
         addPaths(out);
       } catch (Throwable e) {
         throw new RuntimeException(e);
diff --git a/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java b/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java
index 66577d2..63bb0ed 100644
--- a/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java
+++ b/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java
@@ -4,10 +4,10 @@
 package com.android.tools.r8.debug;
 
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
-import com.android.tools.r8.utils.OutputMode;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import org.junit.Test;
diff --git a/src/test/java/com/android/tools/r8/debug/MinificationTest.java b/src/test/java/com/android/tools/r8/debug/MinificationTest.java
index 7dff1f1..f8ca3a2 100644
--- a/src/test/java/com/android/tools/r8/debug/MinificationTest.java
+++ b/src/test/java/com/android/tools/r8/debug/MinificationTest.java
@@ -4,12 +4,12 @@
 package com.android.tools.r8.debug;
 
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.TestBase.MinifyMode;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import java.nio.file.Path;
 import java.nio.file.Paths;
diff --git a/src/test/java/com/android/tools/r8/debuginfo/DebugInfoTestBase.java b/src/test/java/com/android/tools/r8/debuginfo/DebugInfoTestBase.java
index fb1fd31..479a558 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/DebugInfoTestBase.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/DebugInfoTestBase.java
@@ -8,12 +8,14 @@
 import com.android.tools.r8.CompilationException;
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.D8;
 import com.android.tools.r8.D8Command;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.OutputMode;
+import com.android.tools.r8.utils.AndroidAppConsumers;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
 import java.nio.file.Path;
@@ -36,7 +38,9 @@
     for (Class clazz : classes) {
       builder.addProgramFiles(ToolHelper.getClassFileForTestClass(clazz));
     }
-    return ToolHelper.runD8(builder.setMode(CompilationMode.DEBUG).build());
+    AndroidAppConsumers appSink = new AndroidAppConsumers(builder);
+    D8.run(builder.setMode(CompilationMode.DEBUG).build());
+    return appSink.build();
   }
 
   static AndroidApp getDxCompiledSources() throws IOException {
@@ -52,7 +56,7 @@
 
   protected String runOnArt(AndroidApp app, String main) throws IOException {
     Path out = temp.getRoot().toPath().resolve("out.zip");
-    app.writeToZip(out, OutputMode.Indexed);
+    app.writeToZip(out, OutputMode.DexIndexed);
     return ToolHelper.runArtNoVerificationErrors(ImmutableList.of(out.toString()), main, null);
   }
 
diff --git a/src/test/java/com/android/tools/r8/desugar/BasicTestDependenciesDesugaringTest.java b/src/test/java/com/android/tools/r8/desugar/BasicTestDependenciesDesugaringTest.java
index 1f99cf0..ae69ff8 100644
--- a/src/test/java/com/android/tools/r8/desugar/BasicTestDependenciesDesugaringTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/BasicTestDependenciesDesugaringTest.java
@@ -82,11 +82,11 @@
       thrown.expect(CompilationError.class);
     }
     ToolHelper.runD8(
-        D8Command.builder().addClasspathFiles(classpath)
-        .addProgramFiles(toCompile)
-        .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(AndroidApiLevel.K.getLevel())))
-        .setMinApiLevel(AndroidApiLevel.K.getLevel())
-        .build(),
+        D8Command.builder()
+            .addClasspathFiles(classpath)
+            .addProgramFiles(toCompile)
+            .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(AndroidApiLevel.K.getLevel())))
+            .setMinApiLevel(AndroidApiLevel.K.getLevel()),
         options -> options.interfaceMethodDesugaring = OffOrAuto.Auto);
   }
 
@@ -96,11 +96,11 @@
       thrown.expect(CompilationError.class);
     }
     ToolHelper.runD8(
-        D8Command.builder().addClasspathFiles(classpath)
-        .addProgramFiles(toCompile)
-        .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(AndroidApiLevel.K.getLevel())))
-        .setMinApiLevel(AndroidApiLevel.K.getLevel())
-        .build(),
+        D8Command.builder()
+            .addClasspathFiles(classpath)
+            .addProgramFiles(toCompile)
+            .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(AndroidApiLevel.K.getLevel())))
+            .setMinApiLevel(AndroidApiLevel.K.getLevel()),
         options -> options.interfaceMethodDesugaring = OffOrAuto.Off);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/dexmerger/DexFileMergerTests.java b/src/test/java/com/android/tools/r8/dexmerger/DexFileMergerTests.java
index 9dfc37b..fe0e6ce 100644
--- a/src/test/java/com/android/tools/r8/dexmerger/DexFileMergerTests.java
+++ b/src/test/java/com/android/tools/r8/dexmerger/DexFileMergerTests.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.D8;
 import com.android.tools.r8.D8Command;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
 import com.android.tools.r8.dex.Constants;
@@ -18,7 +19,6 @@
 import com.android.tools.r8.utils.AbortException;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
 import java.nio.file.Path;
diff --git a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
index 672973f..a542b70 100644
--- a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
+++ b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
@@ -11,18 +11,21 @@
 import com.android.tools.r8.CompilationException;
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.D8;
 import com.android.tools.r8.D8Command;
 import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.ProgramResource;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
-import com.android.tools.r8.Resource;
+import com.android.tools.r8.ResourceException;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.naming.MemberNaming.FieldSignature;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.AndroidAppConsumers;
 import com.android.tools.r8.utils.ArtErrorParser;
 import com.android.tools.r8.utils.ArtErrorParser.ArtErrorInfo;
 import com.android.tools.r8.utils.ArtErrorParser.ArtErrorParserException;
@@ -32,7 +35,6 @@
 import com.android.tools.r8.utils.DexInspector.FoundMethodSubject;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.ListUtils;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.io.ByteStreams;
 import com.google.common.io.Closer;
 import java.io.File;
@@ -68,9 +70,13 @@
         compiler, mode, referenceApk, pgConf, null, Collections.singletonList(input));
   }
 
-  public AndroidApp runAndCheckVerification(D8Command command, String referenceApk)
-      throws IOException, ExecutionException, CompilationException {
-    return checkVerification(ToolHelper.runD8(command), referenceApk);
+  public AndroidApp runAndCheckVerification(D8Command.Builder builder, String referenceApk)
+      throws IOException, ExecutionException, CompilationException, CompilationFailedException {
+    AndroidAppConsumers appSink = new AndroidAppConsumers(builder);
+    D8.run(builder.build());
+    AndroidApp result = appSink.build();
+    checkVerification(result, referenceApk);
+    return result;
   }
 
   public AndroidApp runAndCheckVerification(
@@ -83,7 +89,7 @@
       throws ExecutionException, IOException, ProguardRuleParserException, CompilationException,
       CompilationFailedException {
     assertTrue(referenceApk == null || new File(referenceApk).exists());
-    AndroidApp outputApp;
+    AndroidAppConsumers outputApp;
     if (compiler == CompilerUnderTest.R8) {
       R8Command.Builder builder = R8Command.builder();
       builder.addProgramFiles(ListUtils.map(inputs, Paths::get));
@@ -99,25 +105,26 @@
             pgConfig.setPrintSeeds(false);
             pgConfig.setIgnoreWarnings(true);
           });
-      outputApp = ToolHelper.runR8(builder.build(), optionsConsumer);
+      outputApp = new AndroidAppConsumers(builder);
+      ToolHelper.runR8(builder.build(), optionsConsumer);
     } else {
       assert compiler == CompilerUnderTest.D8;
-      outputApp =
-          ToolHelper.runD8(
-              D8Command.builder()
-                  .addProgramFiles(ListUtils.map(inputs, Paths::get))
-                  .setMode(mode)
-                  .setMinApiLevel(AndroidApiLevel.L.getLevel())
-                  .build());
+      D8Command.Builder builder =
+          D8Command.builder()
+              .addProgramFiles(ListUtils.map(inputs, Paths::get))
+              .setMode(mode)
+              .setMinApiLevel(AndroidApiLevel.L.getLevel());
+      outputApp = new AndroidAppConsumers(builder);
+      D8.run(builder.build());
     }
-    return checkVerification(outputApp, referenceApk);
+    return checkVerification(outputApp.build(), referenceApk);
   }
 
   public AndroidApp checkVerification(AndroidApp outputApp, String referenceApk)
       throws IOException, ExecutionException {
     Path out = temp.getRoot().toPath().resolve("all.zip");
     Path oatFile = temp.getRoot().toPath().resolve("all.oat");
-    outputApp.writeToZip(out, OutputMode.Indexed);
+    outputApp.writeToZip(out, OutputMode.DexIndexed);
     try {
       ToolHelper.runDex2Oat(out, oatFile);
       return outputApp;
@@ -149,33 +156,34 @@
     }
   }
 
-  public int applicationSize(AndroidApp app) throws IOException {
+  public int applicationSize(AndroidApp app) throws IOException, ResourceException {
     int bytes = 0;
     try (Closer closer = Closer.create()) {
-      for (Resource dex : app.getDexProgramResourcesForTesting()) {
-        bytes += ByteStreams.toByteArray(closer.register(dex.getStream())).length;
+      for (ProgramResource dex : app.getDexProgramResourcesForTesting()) {
+        bytes += ByteStreams.toByteArray(closer.register(dex.getByteStream())).length;
       }
     }
     return bytes;
   }
 
-  public void assertIdenticalApplications(AndroidApp app1, AndroidApp app2) throws IOException {
+  public void assertIdenticalApplications(AndroidApp app1, AndroidApp app2)
+      throws IOException, ResourceException {
     assertIdenticalApplications(app1, app2, false);
   }
 
   public void assertIdenticalApplications(AndroidApp app1, AndroidApp app2, boolean write)
-      throws IOException {
+      throws IOException, ResourceException {
     try (Closer closer = Closer.create()) {
       if (write) {
-        app1.writeToDirectory(temp.newFolder("app1").toPath(), OutputMode.Indexed);
-        app2.writeToDirectory(temp.newFolder("app2").toPath(), OutputMode.Indexed);
+        app1.writeToDirectory(temp.newFolder("app1").toPath(), OutputMode.DexIndexed);
+        app2.writeToDirectory(temp.newFolder("app2").toPath(), OutputMode.DexIndexed);
       }
       List<ProgramResource> files1 = app1.getDexProgramResourcesForTesting();
       List<ProgramResource> files2 = app2.getDexProgramResourcesForTesting();
       assertEquals(files1.size(), files2.size());
       for (int index = 0; index < files1.size(); index++) {
-        InputStream file1 = closer.register(files1.get(index).getStream());
-        InputStream file2 = closer.register(files2.get(index).getStream());
+        InputStream file1 = closer.register(files1.get(index).getByteStream());
+        InputStream file2 = closer.register(files2.get(index).getByteStream());
         byte[] bytes1 = ByteStreams.toByteArray(file1);
         byte[] bytes2 = ByteStreams.toByteArray(file2);
         assertArrayEquals("File index " + index, bytes1, bytes2);
diff --git a/src/test/java/com/android/tools/r8/internal/D8Framework14082017DesugaredVerificationTest.java b/src/test/java/com/android/tools/r8/internal/D8Framework14082017DesugaredVerificationTest.java
index 026918e..ff34444 100644
--- a/src/test/java/com/android/tools/r8/internal/D8Framework14082017DesugaredVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/D8Framework14082017DesugaredVerificationTest.java
@@ -18,8 +18,7 @@
         D8Command.builder()
             .addProgramFiles(Paths.get(JAR))
             .setMode(CompilationMode.DEBUG)
-            .setMinApiLevel(MIN_SDK)
-            .build(),
+            .setMinApiLevel(MIN_SDK),
         JAR);
   }
 
@@ -29,8 +28,7 @@
         D8Command.builder()
             .addProgramFiles(Paths.get(JAR))
             .setMode(CompilationMode.RELEASE)
-            .setMinApiLevel(MIN_SDK)
-            .build(),
+            .setMinApiLevel(MIN_SDK),
         JAR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/D8Framework14082017VerificationTest.java b/src/test/java/com/android/tools/r8/internal/D8Framework14082017VerificationTest.java
index d62de88..f4ec74e 100644
--- a/src/test/java/com/android/tools/r8/internal/D8Framework14082017VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/D8Framework14082017VerificationTest.java
@@ -18,8 +18,7 @@
         D8Command.builder()
             .addProgramFiles(Paths.get(JAR))
             .setMode(CompilationMode.DEBUG)
-            .setMinApiLevel(MIN_SDK)
-            .build(),
+            .setMinApiLevel(MIN_SDK),
         JAR);
   }
 
@@ -29,8 +28,7 @@
         D8Command.builder()
             .addProgramFiles(Paths.get(JAR))
             .setMode(CompilationMode.RELEASE)
-            .setMinApiLevel(MIN_SDK)
-            .build(),
+            .setMinApiLevel(MIN_SDK),
         JAR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/D8FrameworkDeterministicTest.java b/src/test/java/com/android/tools/r8/internal/D8FrameworkDeterministicTest.java
index 12bf52f..e546607 100644
--- a/src/test/java/com/android/tools/r8/internal/D8FrameworkDeterministicTest.java
+++ b/src/test/java/com/android/tools/r8/internal/D8FrameworkDeterministicTest.java
@@ -4,10 +4,12 @@
 package com.android.tools.r8.internal;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.D8;
 import com.android.tools.r8.D8Command;
-import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.AndroidAppConsumers;
 import java.io.IOException;
 import java.nio.file.Paths;
 import org.junit.Test;
@@ -16,17 +18,21 @@
   private static final int MIN_SDK = 24;
   private static final String JAR = "third_party/framework/framework_160115954.jar";
 
-  private AndroidApp doRun(D8Command command) throws IOException, CompilationException {
-    return ToolHelper.runD8(command);
+  private AndroidApp doRun(D8Command.Builder builder)
+      throws IOException, CompilationException, CompilationFailedException {
+    builder.setProgramConsumer(null);
+    AndroidAppConsumers appSink = new AndroidAppConsumers(builder);
+    D8.run(builder.build());
+    return appSink.build();
   }
 
   @Test
   public void verifyDebugBuild() throws Exception {
-    D8Command command = D8Command.builder()
-        .addProgramFiles(Paths.get(JAR))
-        .setMode(CompilationMode.DEBUG)
-        .setMinApiLevel(MIN_SDK)
-        .build();
+    D8Command.Builder command =
+        D8Command.builder()
+            .addProgramFiles(Paths.get(JAR))
+            .setMode(CompilationMode.DEBUG)
+            .setMinApiLevel(MIN_SDK);
     AndroidApp app1 = doRun(command);
     AndroidApp app2 = doRun(command);
     assertIdenticalApplications(app1, app2);
@@ -34,11 +40,11 @@
 
   @Test
   public void verifyReleaseBuild() throws Exception {
-    D8Command command = D8Command.builder()
-        .addProgramFiles(Paths.get(JAR))
-        .setMode(CompilationMode.RELEASE)
-        .setMinApiLevel(MIN_SDK)
-        .build();
+    D8Command.Builder command =
+        D8Command.builder()
+            .addProgramFiles(Paths.get(JAR))
+            .setMode(CompilationMode.RELEASE)
+            .setMinApiLevel(MIN_SDK);
     AndroidApp app1 = doRun(command);
     AndroidApp app2 = doRun(command);
     assertIdenticalApplications(app1, app2);
diff --git a/src/test/java/com/android/tools/r8/internal/D8FrameworkVerificationTest.java b/src/test/java/com/android/tools/r8/internal/D8FrameworkVerificationTest.java
index 8cd9409..1396281 100644
--- a/src/test/java/com/android/tools/r8/internal/D8FrameworkVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/D8FrameworkVerificationTest.java
@@ -18,8 +18,7 @@
         D8Command.builder()
             .addProgramFiles(Paths.get(JAR))
             .setMode(CompilationMode.DEBUG)
-            .setMinApiLevel(MIN_SDK)
-            .build(),
+            .setMinApiLevel(MIN_SDK),
         JAR);
   }
 
@@ -29,8 +28,7 @@
         D8Command.builder()
             .addProgramFiles(Paths.get(JAR))
             .setMode(CompilationMode.RELEASE)
-            .setMinApiLevel(MIN_SDK)
-            .build(),
+            .setMinApiLevel(MIN_SDK),
         JAR);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreDeterministicTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreDeterministicTest.java
index bdcd628..5e1c61f 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreDeterministicTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreDeterministicTest.java
@@ -6,13 +6,13 @@
 import com.android.tools.r8.CompilationException;
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.OutputMode;
 import com.beust.jcommander.internal.Lists;
 import java.io.IOException;
 import java.nio.file.Path;
@@ -63,7 +63,7 @@
     // Check that the generated bytecode runs through the dex2oat verifier with no errors.
     Path combinedInput = temp.getRoot().toPath().resolve("all.jar");
     Path oatFile = temp.getRoot().toPath().resolve("all.oat");
-    app1.writeToZip(combinedInput, OutputMode.Indexed);
+    app1.writeToZip(combinedInput, OutputMode.DexIndexed);
     ToolHelper.runDex2Oat(combinedInput, oatFile);
 
     // Verify that the result of the two compilations was the same.
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java
index 5b5c6da..2da83a6 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java
@@ -5,25 +5,22 @@
 
 import static org.junit.Assert.assertTrue;
 
-import com.android.tools.r8.CompilationException;
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
-import com.android.tools.r8.shaking.ProguardRuleParserException;
 import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.utils.InternalOptions;
 import com.google.common.collect.ImmutableList;
-import java.io.IOException;
-import java.util.concurrent.ExecutionException;
 import java.util.function.Consumer;
 
 public class R8GMSCoreTreeShakeJarVerificationTest extends GMSCoreCompilationTestBase {
 
   public AndroidApp buildAndTreeShakeFromDeployJar(
-      CompilationMode mode, String base, boolean hasReference, int maxSize,
+      CompilationMode mode,
+      String base,
+      boolean hasReference,
+      int maxSize,
       Consumer<InternalOptions> optionsConsumer)
-      throws ExecutionException, IOException, ProguardRuleParserException, CompilationException,
-      CompilationFailedException {
+      throws Exception {
     AndroidApp app = runAndCheckVerification(
         CompilerUnderTest.R8,
         mode,
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java
index f8aa934..e139aea 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java
@@ -6,9 +6,9 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.ProgramResource;
 import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
 import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.Resource;
 import com.google.common.collect.ImmutableList;
 import com.google.common.io.ByteStreams;
 import com.google.common.io.Closer;
@@ -30,8 +30,8 @@
         ImmutableList.of());
     int bytes = 0;
     try (Closer closer = Closer.create()) {
-      for (Resource dex : app.getDexProgramResourcesForTesting()) {
-        bytes += ByteStreams.toByteArray(closer.register(dex.getStream())).length;
+      for (ProgramResource dex : app.getDexProgramResourcesForTesting()) {
+        bytes += ByteStreams.toByteArray(closer.register(dex.getByteStream())).length;
       }
     }
     assertTrue("Expected max size of " + maxSize + ", got " + bytes, bytes < maxSize);
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java
index 453a1c8..69af2bd 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java
@@ -8,6 +8,7 @@
 
 import com.android.tools.r8.CompilationException;
 import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.code.Const4;
@@ -21,7 +22,6 @@
 import com.android.tools.r8.utils.DexInspector;
 import com.android.tools.r8.utils.DexInspector.ClassSubject;
 import com.android.tools.r8.utils.FileUtils;
-import com.android.tools.r8.utils.OutputMode;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
index c38859f..9e6bc86 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
@@ -7,6 +7,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/R8StaticInlining.java b/src/test/java/com/android/tools/r8/ir/optimize/R8StaticInlining.java
index 5102878..61af592 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/R8StaticInlining.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/R8StaticInlining.java
@@ -7,20 +7,18 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.FileUtils;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Collection;
 import org.junit.Assume;
 import org.junit.Ignore;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
diff --git a/src/test/java/com/android/tools/r8/jar/UnicodeSetRegression/UnicodeSetRegressionTest.java b/src/test/java/com/android/tools/r8/jar/UnicodeSetRegression/UnicodeSetRegressionTest.java
index d821deb..16fed9e 100644
--- a/src/test/java/com/android/tools/r8/jar/UnicodeSetRegression/UnicodeSetRegressionTest.java
+++ b/src/test/java/com/android/tools/r8/jar/UnicodeSetRegression/UnicodeSetRegressionTest.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.jar.UnicodeSetRegression;
 
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.AndroidApp;
@@ -11,7 +12,6 @@
 import com.android.tools.r8.utils.ArtErrorParser.ArtErrorInfo;
 import com.android.tools.r8.utils.ArtErrorParser.ArtErrorParserException;
 import com.android.tools.r8.utils.DexInspector;
-import com.android.tools.r8.utils.OutputMode;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
diff --git a/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java b/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
index 3249a44..10b07e0 100644
--- a/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
+++ b/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
@@ -5,6 +5,7 @@
 
 import static org.junit.Assert.fail;
 
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
@@ -14,7 +15,6 @@
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.OutputMode;
 import com.android.tools.r8.utils.StringUtils;
 import com.google.common.collect.ImmutableList;
 import java.io.File;
@@ -217,23 +217,23 @@
 
   protected ProcessResult runOnArtRaw(AndroidApp app, String main) throws IOException {
     Path out = temp.getRoot().toPath().resolve("out.zip");
-    app.writeToZip(out, OutputMode.Indexed);
+    app.writeToZip(out, OutputMode.DexIndexed);
     return ToolHelper.runArtRaw(out.toString(), main);
   }
 
   protected ProcessResult runOnArtRaw(AndroidApp program, AndroidApp library, String main)
       throws IOException {
     Path out = temp.getRoot().toPath().resolve("out.zip");
-    program.writeToZip(out, OutputMode.Indexed);
+    program.writeToZip(out, OutputMode.DexIndexed);
     Path libraryOut = temp.getRoot().toPath().resolve("libraryOut.zip");
-    library.writeToZip(libraryOut, OutputMode.Indexed);
+    library.writeToZip(libraryOut, OutputMode.DexIndexed);
     return ToolHelper.runArtRaw(ImmutableList.of(out.toString(), libraryOut.toString()), main,
         null);
   }
 
   protected String runOnArt(AndroidApp app, String main) throws IOException {
     Path out = temp.getRoot().toPath().resolve("out.zip");
-    app.writeToZip(out, OutputMode.Indexed);
+    app.writeToZip(out, OutputMode.DexIndexed);
     return ToolHelper.runArtNoVerificationErrors(out.toString(), main);
   }
 
diff --git a/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java b/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
index 9b5b618..3f20e8e 100644
--- a/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
+++ b/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.D8;
 import com.android.tools.r8.D8Command;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.DexVm;
 import com.android.tools.r8.ToolHelper.DexVm.Version;
@@ -240,7 +241,7 @@
     D8.run(
         D8Command.builder()
             .addProgramFiles(jdwpTestsJar)
-            .setOutputPath(d8Out.toPath())
+            .setOutput(d8Out.toPath(), OutputMode.DexIndexed)
             .setMinApiLevel(minApi)
             .setMode(CompilationMode.DEBUG)
             .build());
diff --git a/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java b/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
index 8e2242d..7de75d9 100644
--- a/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
+++ b/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
@@ -5,17 +5,19 @@
 
 import com.android.tools.r8.CompilationException;
 import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.D8;
 import com.android.tools.r8.D8Command;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.DexAnnotationElement;
 import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.AndroidAppConsumers;
 import com.android.tools.r8.utils.DexInspector;
 import com.android.tools.r8.utils.DexInspector.AnnotationSubject;
 import com.android.tools.r8.utils.DexInspector.ClassSubject;
-import com.android.tools.r8.utils.OutputMode;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.nio.file.Files;
@@ -49,12 +51,14 @@
 
   private AndroidApp compileWithD8(Path intputPath, Path outputPath)
       throws IOException, CompilationException, CompilationFailedException {
-    return ToolHelper.runD8(
+    D8Command.Builder builder =
         D8Command.builder()
             .setMinApiLevel(AndroidApiLevel.O.getLevel())
             .addProgramFiles(intputPath)
-            .setOutputPath(outputPath)
-            .build());
+            .setOutput(outputPath, OutputMode.DexIndexed);
+    AndroidAppConsumers appSink = new AndroidAppConsumers(builder);
+    D8.run(builder.build());
+    return appSink.build();
   }
 
   private AndroidApp compileWithR8(Path inputPath, Path outputPath, Path keepRulesPath)
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListOutputTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListOutputTest.java
index eefb53e..515b1f9 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListOutputTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListOutputTest.java
@@ -11,11 +11,11 @@
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.Diagnostic;
 import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.utils.FileUtils;
-import com.android.tools.r8.utils.OutputMode;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.google.common.collect.ImmutableList;
 import java.nio.file.Path;
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index d7976f9..5df6bd5 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -13,7 +13,9 @@
 import com.android.tools.r8.CompilationException;
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.D8;
 import com.android.tools.r8.D8Command;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.StringResource;
 import com.android.tools.r8.TestBase;
@@ -61,7 +63,6 @@
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.MainDexList;
-import com.android.tools.r8.utils.OutputMode;
 import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.collect.ImmutableList;
@@ -115,18 +116,18 @@
     AndroidApp generated = generateApplication(
         MANY_CLASSES, AndroidApiLevel.getDefault().getLevel(),
         MANY_CLASSES_SINGLE_DEX_METHODS_PER_CLASS);
-    generated.write(getManyClassesSingleDexAppPath(), OutputMode.Indexed);
+    generated.write(getManyClassesSingleDexAppPath(), OutputMode.DexIndexed);
 
     // Generates an application with many classes, every even in one package and every odd in
     // another. Add enough methods so the application cannot fit into one dex file.
     generated = generateApplication(
         MANY_CLASSES, AndroidApiLevel.L.getLevel(), MANY_CLASSES_MULTI_DEX_METHODS_PER_CLASS);
-    generated.write(getManyClassesMultiDexAppPath(), OutputMode.Indexed);
+    generated.write(getManyClassesMultiDexAppPath(), OutputMode.DexIndexed);
 
     // Generates an application with two classes, each with the maximum possible number of methods.
     generated = generateApplication(TWO_LARGE_CLASSES, AndroidApiLevel.N.getLevel(),
         MAX_METHOD_COUNT);
-    generated.write(getTwoLargeClassesAppPath(), OutputMode.Indexed);
+    generated.write(getTwoLargeClassesAppPath(), OutputMode.DexIndexed);
   }
 
   private static Path getTwoLargeClassesAppPath() {
@@ -293,10 +294,11 @@
               .collect(Collectors.toList()));
     }
 
-    D8Command.Builder builder = D8Command.builder()
-        .addProgramFiles(input)
-        .setMode(mode)
-        .setOutputPath(testDir);
+    D8Command.Builder builder =
+        D8Command.builder()
+            .addProgramFiles(input)
+            .setMode(mode)
+            .setOutput(testDir, OutputMode.DexIndexed);
     if (mainDexClasses != null) {
       if (useFile) {
         builder.addMainDexListFiles(listFile);
@@ -304,7 +306,7 @@
         builder.addMainDexClasses(mainDexClasses);
       }
     }
-    ToolHelper.runD8(builder.build());
+    D8.run(builder.build());
     return testDir;
   }
 
@@ -396,7 +398,7 @@
       jasminBuilder.addClass(name);
     }
     Path input = temp.newFolder().toPath().resolve("input.zip");
-    ToolHelper.runR8(jasminBuilder.build()).writeToZip(input, OutputMode.Indexed);
+    ToolHelper.runR8(jasminBuilder.build()).writeToZip(input, OutputMode.DexIndexed);
 
     // Test with empty main dex list.
     runDeterministicTest(input, null, true);
@@ -429,7 +431,7 @@
     // Notice that this one allows multidex while using lower API.
     AndroidApp generated = generateApplication(
         MANY_CLASSES, AndroidApiLevel.K.getLevel(), true, MANY_CLASSES_MULTI_DEX_METHODS_PER_CLASS);
-    generated.write(getManyClassesForceMultiDexAppPath(), OutputMode.Indexed);
+    generated.write(getManyClassesForceMultiDexAppPath(), OutputMode.DexIndexed);
     // Make sure the generated app indeed has multiple dex files.
     assertTrue(generated.getDexProgramResourcesForTesting().size() > 1);
   }
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java
index 14427f7..d330225 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java
@@ -9,13 +9,13 @@
 
 import com.android.tools.r8.GenerateMainDexList;
 import com.android.tools.r8.GenerateMainDexListCommand;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ir.desugar.LambdaRewriter;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.OutputMode;
 import com.android.tools.r8.utils.StringUtils;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
index 71ad0ac..1c3992a47 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
@@ -6,6 +6,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
@@ -16,7 +17,6 @@
 import com.android.tools.r8.utils.DexInspector.InvokeInstructionSubject;
 import com.android.tools.r8.utils.DexInspector.MethodSubject;
 import com.android.tools.r8.utils.ListUtils;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
 import java.nio.file.Path;
diff --git a/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java b/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
index 8d6893e..b9e0c75 100644
--- a/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
+++ b/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
@@ -11,6 +11,7 @@
 
 import com.android.tools.r8.CompilationException;
 import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.StringConsumer;
 import com.android.tools.r8.ToolHelper;
@@ -23,7 +24,6 @@
 import com.android.tools.r8.utils.DexInspector.InvokeInstructionSubject;
 import com.android.tools.r8.utils.DexInspector.MethodSubject;
 import com.android.tools.r8.utils.FileUtils;
-import com.android.tools.r8.utils.OutputMode;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
diff --git a/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java b/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
index cca27cf..6ea432a 100644
--- a/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
+++ b/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
@@ -9,6 +9,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.code.ConstString;
@@ -21,7 +22,6 @@
 import com.android.tools.r8.utils.DexInspector.ClassSubject;
 import com.android.tools.r8.utils.DexInspector.MethodSubject;
 import com.android.tools.r8.utils.ListUtils;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Sets;
 import java.nio.file.Path;
diff --git a/src/test/java/com/android/tools/r8/naming/RenameSourceFileDebugTest.java b/src/test/java/com/android/tools/r8/naming/RenameSourceFileDebugTest.java
index 252a4bd..014c9b4 100644
--- a/src/test/java/com/android/tools/r8/naming/RenameSourceFileDebugTest.java
+++ b/src/test/java/com/android/tools/r8/naming/RenameSourceFileDebugTest.java
@@ -4,12 +4,12 @@
 package com.android.tools.r8.naming;
 
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.debug.DebugTestBase;
 import com.android.tools.r8.debug.DebugTestConfig;
 import com.android.tools.r8.debug.DexDebugTestConfig;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import java.nio.file.Path;
 import java.nio.file.Paths;
diff --git a/src/test/java/com/android/tools/r8/regress/Regress37740372.java b/src/test/java/com/android/tools/r8/regress/Regress37740372.java
index 26a3930..64df6ed 100644
--- a/src/test/java/com/android/tools/r8/regress/Regress37740372.java
+++ b/src/test/java/com/android/tools/r8/regress/Regress37740372.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.D8Command.Builder;
 import com.android.tools.r8.DexIndexedConsumer;
 import com.android.tools.r8.DiagnosticsHandler;
-import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.origin.EmbeddedOrigin;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.smali.SmaliTestBase;
@@ -165,6 +164,8 @@
     // Build an application with the java.lang.Object stub from a dex file.
     Builder builder = D8Command.builder();
     builder.addDexProgramData(consumer.data, Origin.unknown());
-    checkApplicationOnlyHasJavaLangObject(ToolHelper.runD8(builder.build()));
+    appConsumer = new AndroidAppConsumers(builder);
+    D8.run(builder.build());
+    checkApplicationOnlyHasJavaLangObject(appConsumer.build());
   }
 }
diff --git a/src/test/java/com/android/tools/r8/rewrite/longcompare/LongCompare.java b/src/test/java/com/android/tools/r8/rewrite/longcompare/LongCompare.java
index 472b328..e6c9ada 100644
--- a/src/test/java/com/android/tools/r8/rewrite/longcompare/LongCompare.java
+++ b/src/test/java/com/android/tools/r8/rewrite/longcompare/LongCompare.java
@@ -4,11 +4,12 @@
 package com.android.tools.r8.rewrite.longcompare;
 
 import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.D8;
 import com.android.tools.r8.D8Command;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
-import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.utils.DexInspector;
 import com.android.tools.r8.utils.DexInspector.ClassSubject;
 import com.android.tools.r8.utils.DexInspector.InstructionSubject;
@@ -35,7 +36,11 @@
 
   void compileWithD8(Path intputPath, Path outputPath)
       throws IOException, CompilationException, CompilationFailedException {
-    D8.run(D8Command.builder().addProgramFiles(intputPath).setOutputPath(outputPath).build());
+    D8.run(
+        D8Command.builder()
+            .addProgramFiles(intputPath)
+            .setOutput(outputPath, OutputMode.DexIndexed)
+            .build());
   }
 
   void runTest(Path dexFile) {
diff --git a/src/test/java/com/android/tools/r8/rewrite/longcompare/RequireNonNullRewriteTest.java b/src/test/java/com/android/tools/r8/rewrite/longcompare/RequireNonNullRewriteTest.java
index a1bece1..fe74da9 100644
--- a/src/test/java/com/android/tools/r8/rewrite/longcompare/RequireNonNullRewriteTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/longcompare/RequireNonNullRewriteTest.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.D8;
 import com.android.tools.r8.D8Command;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
 import com.android.tools.r8.ToolHelper.ProcessResult;
@@ -38,7 +39,7 @@
         D8Command.builder()
             .setMode(mode)
             .addProgramFiles(intputPath)
-            .setOutputPath(outputPath)
+            .setOutput(outputPath, OutputMode.DexIndexed)
             .build());
   }
 
diff --git a/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java b/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java
index 3446242..82ae65b 100644
--- a/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java
@@ -7,11 +7,11 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.shaking.PrintUsageTest.PrintUsageInspector.ClassSubject;
 import com.android.tools.r8.utils.ListUtils;
-import com.android.tools.r8.utils.OutputMode;
 import com.google.common.collect.ImmutableList;
 import java.io.File;
 import java.io.IOException;
diff --git a/src/test/java/com/android/tools/r8/shaking/TreeShakingSpecificTest.java b/src/test/java/com/android/tools/r8/shaking/TreeShakingSpecificTest.java
index 6d78fd8..f8a3cc9 100644
--- a/src/test/java/com/android/tools/r8/shaking/TreeShakingSpecificTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/TreeShakingSpecificTest.java
@@ -9,10 +9,10 @@
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.Diagnostic;
 import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.utils.OutputMode;
 import java.io.BufferedReader;
 import java.io.PrintStream;
 import java.io.StringReader;
diff --git a/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java b/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
index 1023667..ce8f842 100644
--- a/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
@@ -5,6 +5,7 @@
 
 import static com.android.tools.r8.ToolHelper.DEFAULT_PROGUARD_MAP_FILE;
 
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.TestBase.MinifyMode;
 import com.android.tools.r8.ToolHelper;
@@ -21,7 +22,6 @@
 import com.android.tools.r8.utils.DexInspector.InstructionSubject;
 import com.android.tools.r8.utils.DexInspector.MethodSubject;
 import com.android.tools.r8.utils.ListUtils;
-import com.android.tools.r8.utils.OutputMode;
 import com.android.tools.r8.utils.StringUtils;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
diff --git a/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java b/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java
index 0b6d16b..69e3a23 100644
--- a/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java
+++ b/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.CompilationException;
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.ProgramResource;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.TestBase;
@@ -27,7 +28,6 @@
 import com.android.tools.r8.utils.DexInspector;
 import com.android.tools.r8.utils.DexInspector.ClassSubject;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.OutputMode;
 import com.android.tools.r8.utils.Timing;
 import java.io.IOException;
 import java.nio.file.Path;
@@ -243,7 +243,7 @@
     try {
       Path out = temp.getRoot().toPath().resolve("run-art-input.zip");
       // TODO(sgjesse): Pass in a unique temp directory for each run.
-      application.writeToZip(out, OutputMode.Indexed);
+      application.writeToZip(out, OutputMode.DexIndexed);
       return ToolHelper.runArtNoVerificationErrors(out.toString(), mainClass);
     } catch (IOException e) {
       throw new RuntimeException(e);
@@ -263,7 +263,7 @@
     try {
       Path dexOut = temp.getRoot().toPath().resolve("run-dex2oat-input.zip");
       Path oatFile = temp.getRoot().toPath().resolve("oat-file");
-      application.writeToZip(dexOut, OutputMode.Indexed);
+      application.writeToZip(dexOut, OutputMode.DexIndexed);
       ToolHelper.runDex2Oat(dexOut, oatFile);
     } catch (IOException e) {
       throw new RuntimeException(e);
diff --git a/tests/api_usage_sample.jar b/tests/api_usage_sample.jar
deleted file mode 100644
index 80b68e1..0000000
--- a/tests/api_usage_sample.jar
+++ /dev/null
Binary files differ
diff --git a/tests/d8_api_usage_sample.jar b/tests/d8_api_usage_sample.jar
index d57efe0..eb6f10f 100644
--- a/tests/d8_api_usage_sample.jar
+++ b/tests/d8_api_usage_sample.jar
Binary files differ
diff --git a/tests/r8_api_usage_sample.jar b/tests/r8_api_usage_sample.jar
index 9547ac2..d838141 100644
--- a/tests/r8_api_usage_sample.jar
+++ b/tests/r8_api_usage_sample.jar
Binary files differ