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);
+    }
   }
 }