L8 Cf to dex
L8 compilation now generates two
commands and run them one after
the other.
Bug: 134732760
Change-Id: Iffb9e1345b97d1fa2626c1a19b8ff7274274d06a
diff --git a/src/main/java/com/android/tools/r8/L8.java b/src/main/java/com/android/tools/r8/L8.java
index 2ea9573..d2b5fb3 100644
--- a/src/main/java/com/android/tools/r8/L8.java
+++ b/src/main/java/com/android/tools/r8/L8.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
import java.io.IOException;
@@ -33,23 +34,30 @@
* @param command L8 command.
*/
public static void run(L8Command command) throws CompilationFailedException {
- AndroidApp app = command.getInputApp();
- InternalOptions options = command.getInternalOptions();
- ExecutorService executor = ThreadUtils.getExecutorService(options);
- ExceptionUtils.withD8CompilationHandler(
- command.getReporter(),
- () -> {
- try {
- run(app, options, executor);
- } finally {
- executor.shutdown();
- }
- });
+ ExecutorService executor =
+ ThreadUtils.getExecutorService(command.getInternalOptions().numberOfThreads);
+ try {
+ ExceptionUtils.withD8CompilationHandler(
+ command.getReporter(),
+ () -> {
+ desugar(command.getInputApp(), command.getInternalOptions(), executor);
+ });
+ if (command.isShrinking()) {
+ command
+ .getReporter()
+ .warning(new StringDiagnostic("Shrinking of desugared library is work in progress."));
+ R8.run(command.getR8Command(), executor);
+ } else {
+ D8.run(command.getD8Command(), executor);
+ }
+ } finally {
+ executor.shutdown();
+ }
}
- private static void run(AndroidApp inputApp, InternalOptions options, ExecutorService executor)
- throws IOException {
- Timing timing = new Timing("L8");
+ private static void desugar(
+ AndroidApp inputApp, InternalOptions options, ExecutorService executor) throws IOException {
+ Timing timing = new Timing("L8 desugaring");
try {
// Disable global optimizations.
options.disableGlobalOptimizations();
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index 944c2bd..b760470 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8;
+import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.errors.DexFileOverflowDiagnostic;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.origin.Origin;
@@ -10,108 +11,33 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
-/** Immutable command structure for an invocation of the {@link L8} libray compiler. */
+/** Immutable command structure for an invocation of the {@link L8} library compiler. */
@Keep
public final class L8Command extends BaseCompilerCommand {
- private static class DefaultL8DiagnosticsHandler implements DiagnosticsHandler {
+ private final D8Command d8Command;
+ private final R8Command r8Command;
- @Override
- public void error(Diagnostic error) {
- if (error instanceof DexFileOverflowDiagnostic) {
- DexFileOverflowDiagnostic overflowDiagnostic = (DexFileOverflowDiagnostic) error;
- DiagnosticsHandler.super.error(
- new StringDiagnostic(
- overflowDiagnostic.getDiagnosticMessage()
- + ". Library too large. L8 can only produce a single .dex file"));
- return;
- }
- DiagnosticsHandler.super.error(error);
- }
+ boolean isShrinking() {
+ return r8Command != null;
}
- /**
- * Builder for constructing a L8Command.
- *
- * <p>A builder is obtained by calling {@link L8Command#builder}.
- */
- @Keep
- public static class Builder extends BaseCompilerCommand.Builder<L8Command, Builder> {
-
- private Builder() {
- this(new DefaultL8DiagnosticsHandler());
- }
-
- private Builder(DiagnosticsHandler diagnosticsHandler) {
- super(diagnosticsHandler);
- }
-
- /** Add dex program-data. */
- @Override
- public Builder addDexProgramData(byte[] data, Origin origin) {
- guard(() -> getAppBuilder().addDexProgramData(data, origin));
- return self();
- }
-
- @Override
- Builder self() {
- return this;
- }
-
- @Override
- CompilationMode defaultCompilationMode() {
- return CompilationMode.DEBUG;
- }
-
- @Override
- void validate() {
- Reporter reporter = getReporter();
- if (getSpecialLibraryConfiguration() == null) {
- reporter.error("L8 requires a special library configuration");
- } else if (!getSpecialLibraryConfiguration().equals("default")) {
- reporter.error("L8 currently requires the special library configuration to be \"default\"");
- }
- if (getProgramConsumer() instanceof DexIndexedConsumer) {
- reporter.error("L8 does not support compiling to dex");
- }
- if (getProgramConsumer() instanceof DexFilePerClassFileConsumer) {
- reporter.error("L8 does not support compiling to dex per class");
- }
- if (getAppBuilder().hasMainDexList()) {
- reporter.error("L8 does not support a main dex list");
- } else if (getMainDexListConsumer() != null) {
- reporter.error("L8 does not support generating a main dex list");
- }
- super.validate();
- }
-
- @Override
- L8Command makeCommand() {
- if (isPrintHelp() || isPrintVersion()) {
- return new L8Command(isPrintHelp(), isPrintVersion());
- }
-
- return new L8Command(
- getAppBuilder().build(),
- getMode(),
- getProgramConsumer(),
- getMainDexListConsumer(),
- getMinApiLevel(),
- getReporter(),
- getSpecialLibraryConfiguration());
- }
+ D8Command getD8Command() {
+ return d8Command;
}
- public static Builder builder() {
- return new Builder();
- }
-
- public static Builder builder(DiagnosticsHandler diagnosticsHandler) {
- return new Builder(diagnosticsHandler);
+ R8Command getR8Command() {
+ return r8Command;
}
private L8Command(
+ R8Command r8Command,
+ D8Command d8Command,
AndroidApp inputApp,
CompilationMode mode,
ProgramConsumer programConsumer,
@@ -131,27 +57,56 @@
specialLibraryConfiguration,
false,
(name, checksum) -> true);
+ this.d8Command = d8Command;
+ this.r8Command = r8Command;
}
private L8Command(boolean printHelp, boolean printVersion) {
super(printHelp, printVersion);
+ r8Command = null;
+ d8Command = null;
}
private void configureLibraryDesugaring(InternalOptions options) {
SpecialLibraryConfiguration.configureLibraryDesugaringForLibraryCompilation(options);
}
+ protected static class DefaultL8DiagnosticsHandler implements DiagnosticsHandler {
+
+ @Override
+ public void error(Diagnostic error) {
+ if (error instanceof DexFileOverflowDiagnostic) {
+ DexFileOverflowDiagnostic overflowDiagnostic = (DexFileOverflowDiagnostic) error;
+ DiagnosticsHandler.super.error(
+ new StringDiagnostic(
+ overflowDiagnostic.getDiagnosticMessage()
+ + ". Library too large. L8 can only produce a single .dex file"));
+ return;
+ }
+ DiagnosticsHandler.super.error(error);
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static Builder builder(DiagnosticsHandler diagnosticsHandler) {
+ return new Builder(diagnosticsHandler);
+ }
+
@Override
InternalOptions getInternalOptions() {
InternalOptions internal = new InternalOptions(new DexItemFactory(), getReporter());
assert !internal.debug;
internal.debug = getMode() == CompilationMode.DEBUG;
- internal.programConsumer = getProgramConsumer();
assert internal.mainDexListConsumer == null;
assert !internal.minimalMainDex;
internal.minApiLevel = getMinApiLevel();
assert !internal.intermediate;
assert internal.readCompileTimeAnnotations;
+ internal.programConsumer = getProgramConsumer();
+ assert internal.programConsumer instanceof ClassFileConsumer;
// Assert and fixup defaults.
assert !internal.isShrinking();
@@ -188,4 +143,134 @@
return internal;
}
+
+ /**
+ * Builder for constructing a L8Command.
+ *
+ * <p>A builder is obtained by calling {@link L8Command#builder}.
+ */
+ @Keep
+ public static class Builder extends BaseCompilerCommand.Builder<L8Command, Builder> {
+
+ private Builder() {
+ this(new DefaultL8DiagnosticsHandler());
+ }
+
+ private Builder(DiagnosticsHandler diagnosticsHandler) {
+ super(diagnosticsHandler);
+ }
+
+ public boolean isShrinking() {
+ // TODO(b/134732760): Answers true if keep rules, even empty, are provided.
+ return false;
+ }
+
+ @Override
+ Builder self() {
+ return this;
+ }
+
+ @Override
+ CompilationMode defaultCompilationMode() {
+ return CompilationMode.DEBUG;
+ }
+
+ @Override
+ void validate() {
+ Reporter reporter = getReporter();
+ if (getSpecialLibraryConfiguration() == null) {
+ reporter.error("L8 requires a special library configuration");
+ } else if (!getSpecialLibraryConfiguration().equals("default")) {
+ reporter.error("L8 currently requires the special library configuration to be \"default\"");
+ }
+ if (getProgramConsumer() instanceof ClassFileConsumer) {
+ reporter.error("L8 does not support compiling to class files");
+ }
+ if (getProgramConsumer() instanceof DexFilePerClassFileConsumer) {
+ reporter.error("L8 does not support compiling to dex per class");
+ }
+ if (getAppBuilder().hasMainDexList()) {
+ reporter.error("L8 does not support a main dex list");
+ } else if (getMainDexListConsumer() != null) {
+ reporter.error("L8 does not support generating a main dex list");
+ }
+ super.validate();
+ }
+
+ @Override
+ L8Command makeCommand() {
+ if (isPrintHelp() || isPrintVersion()) {
+ return new L8Command(isPrintHelp(), isPrintVersion());
+ }
+
+ if (getMode() == null) {
+ setMode(defaultCompilationMode());
+ }
+
+ R8Command r8Command = null;
+ D8Command d8Command = null;
+
+ AndroidApp inputs = getAppBuilder().build();
+ DesugaredLibrary desugaredLibrary = new DesugaredLibrary();
+
+ if (isShrinking()) {
+ // TODO(b/134732760): Support R8 is incomplete.
+ R8Command.Builder r8Builder =
+ R8Command.builder()
+ .addProgramResourceProvider(desugaredLibrary)
+ .setMinApiLevel(getMinApiLevel())
+ .setMode(getMode())
+ .setProgramConsumer(getProgramConsumer());
+ for (ClassFileResourceProvider libraryResourceProvider :
+ inputs.getLibraryResourceProviders()) {
+ r8Builder.addLibraryResourceProvider(libraryResourceProvider);
+ }
+ r8Command = r8Builder.makeCommand();
+ } else {
+ D8Command.Builder d8Builder =
+ D8Command.builder()
+ .addProgramResourceProvider(desugaredLibrary)
+ .setMinApiLevel(getMinApiLevel())
+ .setMode(getMode())
+ .setProgramConsumer(getProgramConsumer());
+ for (ClassFileResourceProvider libraryResourceProvider :
+ inputs.getLibraryResourceProviders()) {
+ d8Builder.addLibraryResourceProvider(libraryResourceProvider);
+ }
+ d8Command = d8Builder.makeCommand();
+ }
+ return new L8Command(
+ r8Command,
+ d8Command,
+ inputs,
+ getMode(),
+ desugaredLibrary,
+ getMainDexListConsumer(),
+ getMinApiLevel(),
+ getReporter(),
+ getSpecialLibraryConfiguration());
+ }
+ }
+
+ static class DesugaredLibrary implements ClassFileConsumer, ProgramResourceProvider {
+
+ private final List<ProgramResource> resources = new ArrayList<>();
+
+ @Override
+ public synchronized void accept(
+ ByteDataView data, String descriptor, DiagnosticsHandler handler) {
+ // TODO(b/139273544): Map Origin information.
+ resources.add(
+ ProgramResource.fromBytes(
+ Origin.unknown(), Kind.CF, data.copyByteData(), Collections.singleton(descriptor)));
+ }
+
+ @Override
+ public Collection<ProgramResource> getProgramResources() throws ResourceException {
+ return resources;
+ }
+
+ @Override
+ public void finished(DiagnosticsHandler handler) {}
+ }
}
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 4b0e3fc..1c3af7a 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -534,6 +534,9 @@
* Add library resource provider.
*/
public Builder addLibraryResourceProvider(ClassFileResourceProvider provider) {
+ if (provider instanceof InternalArchiveClassFileProvider) {
+ archiveProvidersToClose.add((InternalArchiveClassFileProvider) provider);
+ }
libraryResourceProviders.add(provider);
return this;
}
diff --git a/src/test/java/com/android/tools/r8/L8CommandTest.java b/src/test/java/com/android/tools/r8/L8CommandTest.java
index 065d3f2..ca080de 100644
--- a/src/test/java/com/android/tools/r8/L8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/L8CommandTest.java
@@ -4,16 +4,13 @@
package com.android.tools.r8;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import com.android.sdklib.AndroidVersion;
import com.android.tools.r8.dex.Marker;
-import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.AndroidApp;
import java.nio.file.Path;
import java.util.Collection;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -32,23 +29,20 @@
public void emptyCommand() throws Throwable {
verifyEmptyCommand(
L8Command.builder()
- .setProgramConsumer(ClassFileConsumer.emptyConsumer())
+ .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
.addSpecialLibraryConfiguration("default")
.build());
}
- private void verifyEmptyCommand(L8Command command) throws Throwable {
- assertEquals(CompilationMode.DEBUG, command.getMode());
- assertEquals(AndroidVersion.DEFAULT.getApiLevel(), command.getMinApiLevel());
+ private void verifyEmptyCommand(L8Command command) {
+ BaseCompilerCommand compilationCommand =
+ command.getD8Command() == null ? command.getR8Command() : command.getD8Command();
+ assertNotNull(compilationCommand);
assertTrue(command.getProgramConsumer() instanceof ClassFileConsumer);
- AndroidApp app = ToolHelper.getApp(command);
- assertEquals(0, app.getDexProgramResourcesForTesting().size());
- assertEquals(0, app.getClassProgramResourcesForTesting().size());
+ assertTrue(compilationCommand.getProgramConsumer() instanceof DexIndexedConsumer);
}
- // We ignore this test since L8 is currently Cf to Cf.
@Test
- @Ignore
public void testMarker() throws Throwable {
Path output = temp.newFolder().toPath().resolve("desugar_jdk_libs.zip");
L8.run(
@@ -57,13 +51,12 @@
.addProgramFiles(ToolHelper.getDesugarJDKLibs())
.setMinApiLevel(20)
.addSpecialLibraryConfiguration("default")
- .setOutput(output, OutputMode.ClassFile)
+ .setOutput(output, OutputMode.DexIndexed)
.build());
Collection<Marker> markers = ExtractMarker.extractMarkerFromDexFile(output);
- assertEquals(1, markers.size());
+ // TODO(b/134732760): Shouldn't we remove the D8/R8 marker?
+ assertEquals(2, markers.size());
Marker marker = markers.iterator().next();
- assertEquals(20, marker.getMinApi().intValue());
- assertEquals(Tool.L8, marker.getTool());
}
private L8Command.Builder prepareBuilder(DiagnosticsHandler handler) {
@@ -96,11 +89,11 @@
}
@Test(expected = CompilationFailedException.class)
- public void dexFileOutputNotSupported() throws Throwable {
+ public void classFileOutputNotSupported() throws Throwable {
DiagnosticsChecker.checkErrorsContains(
- "L8 does not support compiling to dex",
+ "L8 does not support compiling to class files",
(handler) ->
- prepareBuilder(handler).setProgramConsumer(DexIndexedConsumer.emptyConsumer()).build());
+ prepareBuilder(handler).setProgramConsumer(ClassFileConsumer.emptyConsumer()).build());
}
@Test(expected = CompilationFailedException.class)
@@ -112,7 +105,7 @@
}
@Test(expected = CompilationFailedException.class)
- public void specialLibraryConfgurationMustBeDefault() throws Throwable {
+ public void specialLibraryConfigurationMustBeDefault() throws Throwable {
DiagnosticsChecker.checkErrorsContains(
"L8 currently requires the special library configuration to be \"default\"",
(handler) ->
@@ -128,7 +121,7 @@
"Special library configuration is still work in progress",
handler ->
prepareBuilder(handler)
- .setProgramConsumer(ClassFileConsumer.emptyConsumer())
+ .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
.addSpecialLibraryConfiguration("default")
.build());
}
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java b/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
index 9f708ce..cd510a5 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
@@ -10,22 +10,15 @@
import com.android.tools.r8.L8Command;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestCompileResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
public class CoreLibDesugarTestBase extends TestBase {
- private static Map<CacheEntry, TestCompileResult> computedLibraryCache =
- new ConcurrentHashMap<>();
-
@Deprecated
protected boolean requiresCoreLibDesugaring(TestParameters parameters) {
// TODO(b/134732760): Use the two other APIS instead.
@@ -62,28 +55,10 @@
protected Path buildDesugaredLibrary(
AndroidApiLevel apiLevel, String keepRules, boolean shrink, List<Path> additionalProgramFiles)
throws RuntimeException {
+ // TODO(b/134732760): Support Shrinking.
// We wrap exceptions in a RuntimeException to call this from a lambda.
try {
- Path output = temp.newFolder().toPath().resolve("desugar_jdk_libs_dex.zip");
- CacheEntry cacheEntry = new CacheEntry(apiLevel, keepRules, shrink, additionalProgramFiles);
- TestCompileResult testCompileResult =
- computedLibraryCache.computeIfAbsent(
- cacheEntry,
- key -> compileDesugaredLibrary(apiLevel, keepRules, shrink, additionalProgramFiles));
- testCompileResult.writeToZip(output);
- return output;
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- private TestCompileResult compileDesugaredLibrary(
- AndroidApiLevel apiLevel, String keepRules, boolean shrink, List<Path> additionalProgramFiles)
- throws RuntimeException {
- // We wrap exceptions in a RuntimeException to call this from a lambda.
- try {
- // TODO(b/138922694): Known performance issue here.
- Path cfDesugaredLib = temp.newFolder().toPath().resolve("desugar_jdk_libs_cf.zip");
+ Path desugaredLib = temp.newFolder().toPath().resolve("desugar_jdk_libs_dex.zip");
L8.run(
L8Command.builder()
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
@@ -91,66 +66,14 @@
.addProgramFiles(additionalProgramFiles)
.addSpecialLibraryConfiguration("default")
.setMinApiLevel(apiLevel.getLevel())
- .setOutput(cfDesugaredLib, OutputMode.ClassFile)
+ .setOutput(desugaredLib, OutputMode.DexIndexed)
.build());
- if (shrink) {
- return testForR8(Backend.DEX)
- .addProgramFiles(cfDesugaredLib)
- .noMinification()
- .addKeepRules(keepRules)
- // We still need P+ library files to resolve classes.
- .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
- .setMinApi(apiLevel)
- .compile();
- }
- return testForD8()
- .addProgramFiles(cfDesugaredLib)
- .setMinApi(apiLevel)
- // We still need P+ library files to resolve classes.
- .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
- .compile();
+ return desugaredLib;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
- private static class CacheEntry {
-
- private int apiLevel;
- private String keepRules;
- private boolean shrink;
- private List<Path> additionalProgramFiles;
-
- private CacheEntry(
- AndroidApiLevel apiLevel,
- String keepRules,
- boolean shrink,
- List<Path> additionalProgramFiles) {
- this.apiLevel = apiLevel.getLevel();
- this.keepRules = keepRules;
- this.shrink = shrink;
- this.additionalProgramFiles = additionalProgramFiles;
- }
-
- @Override
- public int hashCode() {
- // In practice there are only 2 sets of additionalProgramFiles with different sizes.
- return Objects.hash(apiLevel, keepRules, shrink, additionalProgramFiles.size());
- }
-
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof CacheEntry)) {
- return false;
- }
- CacheEntry other = (CacheEntry) o;
- return apiLevel == other.apiLevel
- && keepRules.equals(other.keepRules)
- && shrink == other.shrink
- && additionalProgramFiles.equals(other.additionalProgramFiles);
- }
- }
-
protected void assertLines2By2Correct(String stdOut) {
String[] lines = stdOut.split("\n");
assert lines.length % 2 == 0;
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/MergingJ$Test.java b/src/test/java/com/android/tools/r8/desugar/corelib/MergingJ$Test.java
index f4f5807..bdce532 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/MergingJ$Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/MergingJ$Test.java
@@ -27,7 +27,11 @@
CodeInspector codeInspectorOutput = null;
try {
codeInspectorOutput =
- testForD8().addProgramFiles(mergerInputPart1, mergerInputPart2).compile().inspector();
+ testForD8()
+ .addProgramFiles(mergerInputPart1, mergerInputPart2)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .compile()
+ .inspector();
} catch (Exception e) {
if (e.getCause().getMessage().contains("Merging dex file containing classes with prefix")) {
// TODO(b/138278440): Forbid to merge j$ classes in a Google3 compliant way.
@@ -47,7 +51,6 @@
}
private Path buildSplitDesugaredLibraryPart1() throws Exception {
- Path outputCf = temp.newFolder().toPath().resolve("merger-input-cf.zip");
Path outputDex = temp.newFolder().toPath().resolve("merger-input-dex.zip");
L8.run(
L8Command.builder()
@@ -55,13 +58,8 @@
.addProgramFiles(ToolHelper.getDesugarJDKLibs())
.addSpecialLibraryConfiguration("default")
.setMinApiLevel(AndroidApiLevel.B.getLevel())
- .setOutput(outputCf, OutputMode.ClassFile)
+ .setOutput(outputDex, OutputMode.DexIndexed)
.build());
- testForD8()
- .addProgramFiles(outputCf)
- .setMinApi(AndroidApiLevel.B)
- .compile()
- .writeToZip(outputDex);
return outputDex;
}
@@ -75,7 +73,7 @@
.addClasspathFiles(ToolHelper.getDesugarJDKLibs())
.addSpecialLibraryConfiguration("default")
.setMinApiLevel(AndroidApiLevel.B.getLevel())
- .setOutput(outputCf, OutputMode.ClassFile)
+ .setOutput(outputCf, OutputMode.DexIndexed)
.build());
testForD8()
.addProgramFiles(outputCf)