Merge "Make DexSplitter not warn on main dex list classes missing from the application"
diff --git a/src/main/java/com/android/tools/r8/DexSplitterHelper.java b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
index f78912f..27c564a 100644
--- a/src/main/java/com/android/tools/r8/DexSplitterHelper.java
+++ b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
@@ -58,6 +58,7 @@
InternalOptions options = command.getInternalOptions();
options.enableDesugaring = false;
options.enableMainDexListCheck = false;
+ options.ignoreMainDexMissingClasses = true;
options.minimalMainDex = false;
options.enableMinification = false;
options.enableInlining = false;
diff --git a/src/main/java/com/android/tools/r8/dex/VirtualFile.java b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
index 0e62775..0d12915 100644
--- a/src/main/java/com/android/tools/r8/dex/VirtualFile.java
+++ b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
@@ -307,11 +307,13 @@
mainDexFile.addClass(programClass);
classes.remove(programClass);
} else {
- options.reporter.warning(
- new StringDiagnostic(
- "Application does not contain `"
- + type.toSourceString()
- + "` as referenced in main-dex-list."));
+ if (!options.ignoreMainDexMissingClasses) {
+ options.reporter.warning(
+ new StringDiagnostic(
+ "Application does not contain `"
+ + type.toSourceString()
+ + "` as referenced in main-dex-list."));
+ }
}
mainDexFile.commitTransaction();
}
diff --git a/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java b/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java
index 9062ae7..4b89d9e 100644
--- a/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java
+++ b/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java
@@ -86,7 +86,7 @@
@Keep
public static final class Options {
- private final DiagnosticsHandler diagnosticsHandler = new DiagnosticsHandler() {};
+ private final DiagnosticsHandler diagnosticsHandler;
private List<String> inputArchives = new ArrayList<>();
private List<FeatureJar> featureJars = new ArrayList<>();
private List<String> baseJars = new ArrayList<>();
@@ -97,6 +97,14 @@
private String mainDexList;
private boolean splitNonClassResources = false;
+ public Options() {
+ this(new DiagnosticsHandler() {});
+ }
+
+ public Options(DiagnosticsHandler diagnosticsHandler) {
+ this.diagnosticsHandler = diagnosticsHandler;
+ }
+
public DiagnosticsHandler getDiagnosticsHandler() {
return diagnosticsHandler;
}
@@ -293,7 +301,9 @@
throw new AbortException();
}
- D8Command.Builder builder = D8Command.builder();
+ D8Command.Builder builder = D8Command.builder(options.diagnosticsHandler);
+
+
for (String s : options.inputArchives) {
builder.addProgramFiles(Paths.get(s));
}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index a35100e..a5854b6 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -147,6 +147,10 @@
// Throw exception if there is a warning about invalid debug info.
public boolean invalidDebugInfoFatal = false;
+ // When dexsplitting we ignore main dex classes missing in the application. These will be
+ // fused together by play store when shipped for pre-L devices.
+ public boolean ignoreMainDexMissingClasses = false;
+
// Hidden marker for classes.dex
private boolean hasMarker = false;
private Marker marker;
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 ff948aa..5103951 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -226,14 +226,15 @@
@Test
public void everyThirdClassInMainWithDexSplitter() throws Throwable {
List<String> featureMappings = new ArrayList<>();
+ List<String> inFeatureMapping = new ArrayList<>();
ImmutableList.Builder<String> mainDexBuilder = ImmutableList.builder();
for (int i = 0; i < MANY_CLASSES.size(); i++) {
String clazz = MANY_CLASSES.get(i);
// Write the first 2 classes into the split.
- if (i < 2) {
+ if (i < 10) {
featureMappings.add(clazz + ":feature1");
- continue;
+ inFeatureMapping.add(clazz);
}
if (i % 3 == 0) {
mainDexBuilder.add(clazz);
@@ -246,19 +247,20 @@
FileUtils.writeTextFile(mainDexFile, ListUtils.map(mainDexList, MainDexListTests::typeToEntry));
Path output = temp.getRoot().toPath().resolve("split_output");
Files.createDirectories(output);
-
- Options options = new Options();
+ TestDiagnosticsHandler diagnosticsHandler = new TestDiagnosticsHandler();
+ Options options = new Options(diagnosticsHandler);
options.addInputArchive(getManyClassesMultiDexAppPath().toString());
options.setFeatureSplitMapping(featureSplitMapping.toString());
options.setOutput(output.toString());
options.setMainDexList(mainDexFile.toString());
DexSplitter.run(options);
+ assertEquals(0, diagnosticsHandler.numberOfErrorsAndWarnings());
Path baseDir = output.resolve("base");
CodeInspector inspector =
new CodeInspector(
AndroidApp.builder().addProgramFiles(baseDir.resolve("classes.dex")).build());
for (String clazz : mainDexList) {
- if (!inspector.clazz(clazz).isPresent()) {
+ if (!inspector.clazz(clazz).isPresent() && !inFeatureMapping.contains(clazz)) {
failedToFindClassInExpectedFile(baseDir, clazz);
}
}
@@ -923,10 +925,20 @@
private class TestDiagnosticsHandler implements DiagnosticsHandler {
public List<Diagnostic> errors = new ArrayList<>();
+ public List<Diagnostic> warnings = new ArrayList<>();
+
+ public int numberOfErrorsAndWarnings() {
+ return errors.size() + warnings.size();
+ }
@Override
public void error(Diagnostic error) {
errors.add(error);
}
+
+ @Override
+ public void warning(Diagnostic warning) {
+ warnings.add(warning);
+ }
}
}