Add --verbose option to the extractmarker tool

Using --verbose will print out the filename in front of the marker.

Useful when checking markers in a collection of files:

  find -name '*.dex' | xargs -n1 java -jar extractmarker.jar --verbose

Change-Id: Icbd321cf2a4a0692912c462bedce01aa3934def7
diff --git a/src/main/java/com/android/tools/r8/BaseCommand.java b/src/main/java/com/android/tools/r8/BaseCommand.java
index 1e5fea9..3724ddf 100644
--- a/src/main/java/com/android/tools/r8/BaseCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCommand.java
@@ -9,8 +9,10 @@
 import com.android.tools.r8.utils.ListUtils;
 import java.io.IOException;
 import java.nio.file.Path;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
 
 /**
  * Base class for commands and command builders for applications/tools which take an Android
@@ -60,6 +62,8 @@
     private boolean printVersion = false;
     private final AndroidApp.Builder app;
 
+    protected List<Path> programFiles = new ArrayList<>();
+
     protected Builder() {
       this(AndroidApp.builder(), false);
     }
@@ -96,6 +100,7 @@
     /** Add program file resources. */
     public B addProgramFiles(Collection<Path> files) throws IOException {
       app.addProgramFiles(ListUtils.map(files, FilteredClassPath::unfiltered));
+      programFiles.addAll(files);
       return self();
     }
 
diff --git a/src/main/java/com/android/tools/r8/ExtractMarker.java b/src/main/java/com/android/tools/r8/ExtractMarker.java
index f73fb66..c8a82f4 100644
--- a/src/main/java/com/android/tools/r8/ExtractMarker.java
+++ b/src/main/java/com/android/tools/r8/ExtractMarker.java
@@ -5,13 +5,16 @@
 
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.dex.Marker;
+import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
+import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.List;
 import java.util.concurrent.ExecutionException;
 
 public class ExtractMarker {
@@ -20,11 +23,18 @@
     public static class Builder
         extends BaseCommand.Builder<ExtractMarker.Command, ExtractMarker.Command.Builder> {
 
+      private boolean verbose;
+
       @Override
       ExtractMarker.Command.Builder self() {
         return this;
       }
 
+      public Builder setVerbose(boolean verbose) {
+        this.verbose = verbose;
+        return self();
+      }
+
       @Override
       public ExtractMarker.Command build() throws CompilationException, IOException {
         // If printing versions ignore everything else.
@@ -32,7 +42,7 @@
           return new ExtractMarker.Command(isPrintHelp());
         }
         validate();
-        return new ExtractMarker.Command(getAppBuilder().build());
+        return new ExtractMarker.Command(getAppBuilder().build(), verbose, programFiles);
       }
     }
 
@@ -40,6 +50,7 @@
         "Usage: extractmarker [options] <input-files>",
         " where <input-files> are dex or vdex files",
         "  --version               # Print the version of r8.",
+        "  --verbose               # More verbose output.",
         "  --help                  # Print this message."));
 
     public static ExtractMarker.Command.Builder builder() {
@@ -59,6 +70,8 @@
         String arg = args[i].trim();
         if (arg.length() == 0) {
           continue;
+        } else if (arg.equals("--verbose")) {
+          builder.setVerbose(true);
         } else if (arg.equals("--help")) {
           builder.setPrintHelp(true);
         } else {
@@ -70,12 +83,27 @@
       }
     }
 
-    private Command(AndroidApp inputApp) {
+    private final List<Path> programFiles;
+    private final boolean verbose;
+
+    private Command(AndroidApp inputApp, boolean verbose, List<Path> programFiles) {
       super(inputApp);
+      this.programFiles = programFiles;
+      this.verbose = verbose;
     }
 
     private Command(boolean printHelp) {
       super(printHelp, false);
+      this.verbose = false;
+      programFiles = ImmutableList.of();
+    }
+
+    public List<Path> getProgramFiles() {
+      return programFiles;
+    }
+
+    public boolean getVerbose() {
+      return verbose;
     }
 
     @Override
@@ -92,18 +120,33 @@
       System.out.println(ExtractMarker.Command.USAGE_MESSAGE);
       return;
     }
-    AndroidApp app = command.getInputApp();
-    InternalOptions options = new InternalOptions();
-    // Dex code is not needed for getting the marker. VDex files typically contains quickened byte
-    // codes which cannot be read, and we want to get the marker from vdex files as well.
-    options.skipReadingDexCode = true;
-    DexApplication dexApp = new ApplicationReader(app, options, new Timing("ExtractMarker")).read();
-    Marker readMarker = dexApp.dexItemFactory.extractMarker();
-    if (readMarker == null) {
-      System.out.println("D8/R8 marker not found.");
-      System.exit(1);
-    } else {
-      System.out.println(readMarker.toString());
+
+    try {
+      AndroidApp app = command.getInputApp();
+      InternalOptions options = new InternalOptions();
+      // Dex code is not needed for getting the marker. VDex files typically contains quickened byte
+      // codes which cannot be read, and we want to get the marker from vdex files as well.
+      options.skipReadingDexCode = true;
+      DexApplication dexApp = new ApplicationReader(app, options, new Timing("ExtractMarker"))
+          .read();
+      Marker readMarker = dexApp.dexItemFactory.extractMarker();
+      if (command.getVerbose()) {
+        for (int i = 0; i < command.getProgramFiles().size(); i++) {
+          if (i != 0) {
+            System.out.print(", ");
+          }
+          System.out.print(command.getProgramFiles().get(i));
+        }
+        System.out.print(": ");
+      }
+      if (readMarker == null) {
+        System.out.println("D8/R8 marker not found.");
+        System.exit(1);
+      } else {
+        System.out.println(readMarker.toString());
+      }
+    } catch (CompilationError e) {
+      System.out.println("Failed to read dex file: '" + e.getMessage() + "'");
       System.exit(0);
     }
   }