Add D8 support for main-dex rules.
Bug: 176880642
Change-Id: I2c9708c6ac6f1ae8c5b6a827a82827f39cae6cbf
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index bc8d186..4def5d0 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -183,6 +183,12 @@
AppView<AppInfo> appView = readApp(inputApp, options, executor, timing);
SyntheticItems.collectSyntheticInputs(appView);
+ if (!options.mainDexKeepRules.isEmpty()) {
+ new GenerateMainDexList(options)
+ .traceMainDex(
+ executor, appView.appInfo().app(), appView.appInfo().getMainDexClasses()::addAll);
+ }
+
final CfgPrinter printer = options.printCfg ? new CfgPrinter() : null;
if (AssertionsRewriter.isEnabled(options)) {
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index f720ee9..047df78 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -13,6 +13,11 @@
import com.android.tools.r8.inspector.internal.InspectorImpl;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.shaking.ProguardConfigurationParser;
+import com.android.tools.r8.shaking.ProguardConfigurationRule;
+import com.android.tools.r8.shaking.ProguardConfigurationSource;
+import com.android.tools.r8.shaking.ProguardConfigurationSourceFile;
+import com.android.tools.r8.shaking.ProguardConfigurationSourceStrings;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.AssertionConfigurationWithDefault;
@@ -21,7 +26,11 @@
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.ThreadUtils;
+import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.BiPredicate;
@@ -75,6 +84,7 @@
private boolean enableMainDexListCheck = true;
private boolean minimalMainDex = false;
private boolean skipDump = false;
+ private final List<ProguardConfigurationSource> mainDexRules = new ArrayList<>();
private Builder() {
this(new DefaultD8DiagnosticsHandler());
@@ -203,6 +213,26 @@
return self();
}
+ /** Add proguard configuration files with rules for automatic main-dex-list calculation. */
+ public Builder addMainDexRulesFiles(Path... paths) {
+ return addMainDexRulesFiles(Arrays.asList(paths));
+ }
+
+ /** Add proguard configuration files with rules for automatic main-dex-list calculation. */
+ public Builder addMainDexRulesFiles(Collection<Path> paths) {
+ guard(() -> paths.forEach(p -> mainDexRules.add(new ProguardConfigurationSourceFile(p))));
+ return self();
+ }
+
+ /** Add proguard rules for automatic main-dex-list calculation. */
+ public Builder addMainDexRules(List<String> lines, Origin origin) {
+ guard(
+ () ->
+ mainDexRules.add(
+ new ProguardConfigurationSourceStrings(lines, Paths.get("."), origin)));
+ return self();
+ }
+
@Override
void validate() {
if (isPrintHelp()) {
@@ -219,8 +249,20 @@
if (getProgramConsumer() instanceof DexFilePerClassFileConsumer) {
reporter.error("Option --main-dex-list cannot be used with --file-per-class");
}
- } else if (getMainDexListConsumer() != null) {
- reporter.error("Option --main-dex-list-output require --main-dex-list");
+ }
+ if (!mainDexRules.isEmpty()) {
+ if (intermediate) {
+ reporter.error("Option --main-dex-rules cannot be used with --intermediate");
+ }
+ if (getProgramConsumer() instanceof DexFilePerClassFileConsumer) {
+ reporter.error("Option --main-dex-rules cannot be used with --file-per-class");
+ }
+ }
+ if (getMainDexListConsumer() != null
+ && mainDexRules.isEmpty()
+ && !getAppBuilder().hasMainDexList()) {
+ reporter.error(
+ "Option --main-dex-list-output requires --main-dex-rules and/or --main-dex-list");
}
if (getMinApiLevel() >= AndroidApiLevel.L.getLevel()) {
if (getMainDexListConsumer() != null || getAppBuilder().hasMainDexList()) {
@@ -248,6 +290,9 @@
DesugaredLibraryConfiguration libraryConfiguration =
getDesugaredLibraryConfiguration(factory, false);
+ ImmutableList<ProguardConfigurationRule> mainDexKeepRules =
+ ProguardConfigurationParser.parse(mainDexRules, factory, getReporter());
+
return new D8Command(
getAppBuilder().build(),
getMode(),
@@ -269,6 +314,7 @@
skipDump,
enableMainDexListCheck,
minimalMainDex,
+ mainDexKeepRules,
getThreadCount(),
factory);
}
@@ -284,6 +330,7 @@
private final boolean skipDump;
private final boolean enableMainDexListCheck;
private final boolean minimalMainDex;
+ private final ImmutableList<ProguardConfigurationRule> mainDexKeepRules;
private final DexItemFactory factory;
public static Builder builder() {
@@ -347,6 +394,7 @@
boolean skipDump,
boolean enableMainDexListCheck,
boolean minimalMainDex,
+ ImmutableList<ProguardConfigurationRule> mainDexKeepRules,
int threadCount,
DexItemFactory factory) {
super(
@@ -371,6 +419,7 @@
this.skipDump = skipDump;
this.enableMainDexListCheck = enableMainDexListCheck;
this.minimalMainDex = minimalMainDex;
+ this.mainDexKeepRules = mainDexKeepRules;
this.factory = factory;
}
@@ -384,6 +433,7 @@
skipDump = false;
enableMainDexListCheck = true;
minimalMainDex = false;
+ mainDexKeepRules = null;
factory = null;
}
@@ -403,6 +453,7 @@
internal.intermediate = intermediate;
internal.readCompileTimeAnnotations = intermediate;
internal.desugarGraphConsumer = desugarGraphConsumer;
+ internal.mainDexKeepRules = mainDexKeepRules;
// Assert and fixup defaults.
assert !internal.isShrinking();
diff --git a/src/main/java/com/android/tools/r8/D8CommandParser.java b/src/main/java/com/android/tools/r8/D8CommandParser.java
index 98a6582..8f90ade 100644
--- a/src/main/java/com/android/tools/r8/D8CommandParser.java
+++ b/src/main/java/com/android/tools/r8/D8CommandParser.java
@@ -31,6 +31,7 @@
"--classpath",
"--pg-map",
MIN_API_FLAG,
+ "--main-dex-rules",
"--main-dex-list",
"--main-dex-list-output",
"--desugared-lib",
@@ -139,6 +140,8 @@
" --no-desugaring # Force disable desugaring.",
" --desugared-lib <file> # Specify desugared library configuration.",
" # <file> is a desugared library configuration (json).",
+ " --main-dex-rules <file> # Proguard keep rules for classes to place in the",
+ " # primary dex file.",
" --main-dex-list <file> # List of classes to place in the primary dex file.",
" --main-dex-list-output <file>",
" # Output resulting main dex list in <file>."),
@@ -252,6 +255,8 @@
} catch (IOException e) {
builder.error(new ExceptionDiagnostic(e, new PathOrigin(file)));
}
+ } else if (arg.equals("--main-dex-rules")) {
+ builder.addMainDexRulesFiles(Paths.get(nextArg));
} else if (arg.equals("--main-dex-list")) {
builder.addMainDexListFiles(Paths.get(nextArg));
} else if (arg.equals("--main-dex-list-output")) {
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexList.java b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
index 04479b1..d260bcb 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexList.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
@@ -10,9 +10,9 @@
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppServices;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.shaking.Enqueuer;
import com.android.tools.r8.shaking.EnqueuerFactory;
@@ -33,6 +33,7 @@
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
@Keep
@@ -40,78 +41,91 @@
private final Timing timing = new Timing("maindex");
private final InternalOptions options;
- private GenerateMainDexList(InternalOptions options) {
+ private List<String> result = null;
+
+ public GenerateMainDexList(InternalOptions options) {
this.options = options;
}
private List<String> run(AndroidApp app, ExecutorService executor)
throws IOException {
try {
- DirectMappedDexApplication application =
- new ApplicationReader(app, options, timing).read(executor).toDirect();
- AppView<? extends AppInfoWithClassHierarchy> appView = AppView.createForR8(application);
- appView.setAppServices(AppServices.builder(appView).build());
+ DexApplication application = new ApplicationReader(app, options, timing).read(executor);
+ traceMainDex(
+ executor,
+ application,
+ mainDexTracingResult -> {
+ result =
+ mainDexTracingResult.getClasses().stream()
+ .map(c -> c.toSourceString().replace('.', '/') + ".class")
+ .sorted()
+ .collect(Collectors.toList());
- MainDexListBuilder.checkForAssumedLibraryTypes(appView.appInfo());
-
- SubtypingInfo subtypingInfo = new SubtypingInfo(appView);
-
- RootSet mainDexRootSet =
- new RootSetBuilder(appView, subtypingInfo, options.mainDexKeepRules).run(executor);
-
- GraphConsumer graphConsumer = options.mainDexKeptGraphConsumer;
- WhyAreYouKeepingConsumer whyAreYouKeepingConsumer = null;
- if (!mainDexRootSet.reasonAsked.isEmpty()) {
- whyAreYouKeepingConsumer = new WhyAreYouKeepingConsumer(graphConsumer);
- graphConsumer = whyAreYouKeepingConsumer;
- }
-
- Enqueuer enqueuer =
- EnqueuerFactory.createForMainDexTracing(appView, subtypingInfo, graphConsumer);
- Set<DexProgramClass> liveTypes = enqueuer.traceMainDex(mainDexRootSet, executor, timing);
- // LiveTypes is the result.
- MainDexTracingResult mainDexTracingResult = new MainDexListBuilder(liveTypes, appView).run();
-
- List<String> result =
- mainDexTracingResult.getClasses().stream()
- .map(c -> c.toSourceString().replace('.', '/') + ".class")
- .sorted()
- .collect(Collectors.toList());
-
- if (options.mainDexListConsumer != null) {
- options.mainDexListConsumer.accept(String.join("\n", result), options.reporter);
- options.mainDexListConsumer.finished(options.reporter);
- }
-
- R8.processWhyAreYouKeepingAndCheckDiscarded(
- mainDexRootSet,
- () -> {
- ArrayList<DexProgramClass> classes = new ArrayList<>();
- // TODO(b/131668850): This is not a deterministic order!
- mainDexTracingResult
- .getClasses()
- .forEach(
- type -> {
- DexClass clazz = appView.definitionFor(type);
- assert clazz.isProgramClass();
- classes.add(clazz.asProgramClass());
- });
- return classes;
- },
- whyAreYouKeepingConsumer,
- appView,
- enqueuer,
- true,
- options,
- timing,
- executor);
-
+ if (options.mainDexListConsumer != null) {
+ options.mainDexListConsumer.accept(String.join("\n", result), options.reporter);
+ options.mainDexListConsumer.finished(options.reporter);
+ }
+ });
return result;
} catch (ExecutionException e) {
throw unwrapExecutionException(e);
}
}
+ public void traceMainDex(
+ ExecutorService executor,
+ DexApplication application,
+ Consumer<MainDexTracingResult> resultConsumer)
+ throws ExecutionException {
+ AppView<? extends AppInfoWithClassHierarchy> appView =
+ AppView.createForR8(application.toDirect());
+ appView.setAppServices(AppServices.builder(appView).build());
+
+ MainDexListBuilder.checkForAssumedLibraryTypes(appView.appInfo());
+
+ SubtypingInfo subtypingInfo = new SubtypingInfo(appView);
+
+ RootSet mainDexRootSet =
+ new RootSetBuilder(appView, subtypingInfo, options.mainDexKeepRules).run(executor);
+
+ GraphConsumer graphConsumer = options.mainDexKeptGraphConsumer;
+ WhyAreYouKeepingConsumer whyAreYouKeepingConsumer = null;
+ if (!mainDexRootSet.reasonAsked.isEmpty()) {
+ whyAreYouKeepingConsumer = new WhyAreYouKeepingConsumer(graphConsumer);
+ graphConsumer = whyAreYouKeepingConsumer;
+ }
+
+ Enqueuer enqueuer =
+ EnqueuerFactory.createForMainDexTracing(appView, subtypingInfo, graphConsumer);
+ Set<DexProgramClass> liveTypes = enqueuer.traceMainDex(mainDexRootSet, executor, timing);
+ // LiveTypes is the result.
+ MainDexTracingResult mainDexTracingResult = new MainDexListBuilder(liveTypes, appView).run();
+ resultConsumer.accept(mainDexTracingResult);
+
+ R8.processWhyAreYouKeepingAndCheckDiscarded(
+ mainDexRootSet,
+ () -> {
+ ArrayList<DexProgramClass> classes = new ArrayList<>();
+ // TODO(b/131668850): This is not a deterministic order!
+ mainDexTracingResult
+ .getClasses()
+ .forEach(
+ type -> {
+ DexClass clazz = appView.definitionFor(type);
+ assert clazz.isProgramClass();
+ classes.add(clazz.asProgramClass());
+ });
+ return classes;
+ },
+ whyAreYouKeepingConsumer,
+ appView,
+ enqueuer,
+ true,
+ options,
+ timing,
+ executor);
+ }
+
/**
* Main API entry for computing the main-dex list.
*
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java b/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
index 07569a7..b08a738 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
@@ -108,15 +108,8 @@
return new GenerateMainDexListCommand(isPrintHelp(), isPrintVersion());
}
- List<ProguardConfigurationRule> mainDexKeepRules;
- if (this.mainDexRules.isEmpty()) {
- mainDexKeepRules = ImmutableList.of();
- } else {
- ProguardConfigurationParser parser =
- new ProguardConfigurationParser(factory, getReporter());
- parser.parse(mainDexRules);
- mainDexKeepRules = parser.getConfig().getRules();
- }
+ List<ProguardConfigurationRule> mainDexKeepRules =
+ ProguardConfigurationParser.parse(mainDexRules, factory, getReporter());
return new GenerateMainDexListCommand(
factory,
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 29112ed..d6ab3a6 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -40,6 +40,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
@@ -182,28 +183,21 @@
/** Add proguard configuration files with rules for automatic main-dex-list calculation. */
public Builder addMainDexRulesFiles(Path... paths) {
- guard(() -> {
- for (Path path : paths) {
- mainDexRules.add(new ProguardConfigurationSourceFile(path));
- }
- });
- return self();
+ return addMainDexRulesFiles(Arrays.asList(paths));
}
/** Add proguard configuration files with rules for automatic main-dex-list calculation. */
public Builder addMainDexRulesFiles(Collection<Path> paths) {
- guard(() -> {
- for (Path path : paths) {
- mainDexRules.add(new ProguardConfigurationSourceFile(path));
- }
- });
+ guard(() -> paths.forEach(p -> mainDexRules.add(new ProguardConfigurationSourceFile(p))));
return self();
}
/** Add proguard rules for automatic main-dex-list calculation. */
public Builder addMainDexRules(List<String> lines, Origin origin) {
- guard(() -> mainDexRules.add(
- new ProguardConfigurationSourceStrings(lines, Paths.get("."), origin)));
+ guard(
+ () ->
+ mainDexRules.add(
+ new ProguardConfigurationSourceStrings(lines, Paths.get("."), origin)));
return self();
}
@@ -432,7 +426,7 @@
&& mainDexRules.isEmpty()
&& !getAppBuilder().hasMainDexList()) {
reporter.error(
- "Option --main-dex-list-output require --main-dex-rules and/or --main-dex-list");
+ "Option --main-dex-list-output requires --main-dex-rules and/or --main-dex-list");
}
if (!(getProgramConsumer() instanceof ClassFileConsumer)
&& getMinApiLevel() >= AndroidApiLevel.L.getLevel()) {
@@ -479,15 +473,8 @@
private R8Command makeR8Command() {
Reporter reporter = getReporter();
DexItemFactory factory = new DexItemFactory();
- List<ProguardConfigurationRule> mainDexKeepRules;
- if (this.mainDexRules.isEmpty()) {
- mainDexKeepRules = ImmutableList.of();
- } else {
- ProguardConfigurationParser parser =
- new ProguardConfigurationParser(factory, reporter);
- parser.parse(mainDexRules);
- mainDexKeepRules = parser.getConfig().getRules();
- }
+ List<ProguardConfigurationRule> mainDexKeepRules =
+ ProguardConfigurationParser.parse(mainDexRules, factory, reporter);
DesugaredLibraryConfiguration libraryConfiguration =
getDesugaredLibraryConfiguration(factory, false);
diff --git a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
index 9706eab..762617e 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -86,7 +86,8 @@
assert !DexAnnotation.isMemberClassesAnnotation(annotation, dexItemFactory);
assert !DexAnnotation.isEnclosingMethodAnnotation(annotation, dexItemFactory);
assert !DexAnnotation.isEnclosingClassAnnotation(annotation, dexItemFactory);
- assert !DexAnnotation.isSignatureAnnotation(annotation, dexItemFactory);
+ assert appView.options().passthroughDexCode
+ || !DexAnnotation.isSignatureAnnotation(annotation, dexItemFactory);
if (config.exceptions && DexAnnotation.isThrowingAnnotation(annotation, dexItemFactory)) {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index 8294be0..47ac1e3 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -104,6 +104,16 @@
private static final List<String> UNSUPPORTED_FLAG_OPTIONS =
ImmutableList.of("skipnonpubliclibraryclasses");
+ public static ImmutableList<ProguardConfigurationRule> parse(
+ List<ProguardConfigurationSource> sources, DexItemFactory factory, Reporter reporter) {
+ if (sources.isEmpty()) {
+ return ImmutableList.of();
+ }
+ ProguardConfigurationParser parser = new ProguardConfigurationParser(factory, reporter);
+ parser.parse(sources);
+ return ImmutableList.copyOf(parser.getConfig().getRules());
+ }
+
public ProguardConfigurationParser(
DexItemFactory dexItemFactory, Reporter reporter) {
this(dexItemFactory, reporter, false);
diff --git a/src/test/java/com/android/tools/r8/D8CommandTest.java b/src/test/java/com/android/tools/r8/D8CommandTest.java
index 9b80b80..3bcb3a7 100644
--- a/src/test/java/com/android/tools/r8/D8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/D8CommandTest.java
@@ -255,6 +255,21 @@
}
@Test
+ public void mainDexRules() throws Throwable {
+ Path mainDexRules1 = temp.newFile("main-dex-1.rules").toPath();
+ Path mainDexRules2 = temp.newFile("main-dex-2.rules").toPath();
+ parse("--main-dex-rules", mainDexRules1.toString());
+ parse(
+ "--main-dex-rules", mainDexRules1.toString(), "--main-dex-rules", mainDexRules2.toString());
+ }
+
+ @Test(expected = CompilationFailedException.class)
+ public void nonExistingMainDexRules() throws Throwable {
+ Path mainDexRules = temp.getRoot().toPath().resolve("main-dex.rules");
+ parse("--main-dex-rules", mainDexRules.toString());
+ }
+
+ @Test
public void mainDexList() throws Throwable {
Path mainDexList1 = temp.newFile("main-dex-list-1.txt").toPath();
Path mainDexList2 = temp.newFile("main-dex-list-2.txt").toPath();
diff --git a/src/test/java/com/android/tools/r8/D8TestBuilder.java b/src/test/java/com/android/tools/r8/D8TestBuilder.java
index 44fe743..4c88d91 100644
--- a/src/test/java/com/android/tools/r8/D8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/D8TestBuilder.java
@@ -81,4 +81,9 @@
}
return self();
}
+
+ public D8TestBuilder addMainDexRulesFiles(Path... mainDexRuleFiles) {
+ builder.addMainDexRulesFiles(mainDexRuleFiles);
+ return self();
+ }
}
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 6ef399e..52b60fe 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java
@@ -358,6 +358,26 @@
.sorted()
.collect(Collectors.toList());
+ // Build main-dex list using D8 & rules.
+ List<String> mainDexListFromD8;
+ {
+ final Box<String> mainDexListOutputFromD8 = new Box<>();
+ testForD8(Backend.DEX)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.K))
+ .addProgramFiles(inputJar)
+ .addProgramFiles(Paths.get(EXAMPLE_BUILD_DIR, "multidexfakeframeworks" + JAR_EXTENSION))
+ .addMainDexRulesFiles(mainDexRules)
+ .setMainDexListConsumer(ToolHelper.consumeString(mainDexListOutputFromD8::set))
+ .setMinApi(minSdk)
+ .allowStdoutMessages()
+ .compile();
+ mainDexListFromD8 =
+ StringUtils.splitLines(mainDexListOutputFromD8.get()).stream()
+ .map(this::mainDexStringToDescriptor)
+ .sorted()
+ .collect(Collectors.toList());
+ }
+
// Build main-dex list using R8.
final Box<String> r8MainDexListOutput = new Box<>();
testForR8(Backend.DEX)
@@ -402,6 +422,13 @@
}
String[] refList = new String(Files.readAllBytes(
expectedMainDexList), StandardCharsets.UTF_8).split("\n");
+ for (int i = 0; i < refList.length; i++) {
+ String reference = refList[i].trim();
+ if (mainDexListFromD8.size() <= i) {
+ fail("D8 main-dex list is missing '" + reference + "'");
+ }
+ checkSameMainDexEntry(reference, mainDexListFromD8.get(i));
+ }
int nonLambdaOffset = 0;
for (int i = 0; i < refList.length; i++) {
String reference = refList[i].trim();