Adding multidex support to vogar am: 388fcad526 am: 4904ba849e
am: dd2e92f185

Change-Id: I6dc7e4b759445908b02fac817b73a0f640babd72
diff --git a/src/vogar/Run.java b/src/vogar/Run.java
index e69e1f2..ef20a47 100644
--- a/src/vogar/Run.java
+++ b/src/vogar/Run.java
@@ -82,6 +82,7 @@
     public final Language language;
     public final List<String> javacArgs;
     public final List<String> jackArgs;
+    public final boolean multidex;
     public final boolean benchmark;
     public final File runnerDir;
     public final boolean cleanBefore;
@@ -142,6 +143,7 @@
         this.language = vogar.language;
         this.javacArgs = vogar.javacArgs;
         this.jackArgs = vogar.jackArgs;
+        this.multidex = vogar.multidex;
         this.javaHome = vogar.javaHome;
         this.largeTimeoutSeconds = vogar.timeoutSeconds * Vogar.LARGE_TIMEOUT_MULTIPLIER;
         this.maxConcurrentActions = (vogar.stream || vogar.modeId == ModeId.ACTIVITY)
diff --git a/src/vogar/Vogar.java b/src/vogar/Vogar.java
index ef9d918..d07b9ea 100644
--- a/src/vogar/Vogar.java
+++ b/src/vogar/Vogar.java
@@ -143,6 +143,9 @@
     @Option(names = { "--jack-arg" })
     List<String> jackArgs = new ArrayList<String>();
 
+    @Option(names = { "--multidex" })
+    boolean multidex = true;
+
     @Option(names = { "--use-bootclasspath" })
     boolean useBootClasspath = false;
 
diff --git a/src/vogar/android/AndroidSdk.java b/src/vogar/android/AndroidSdk.java
index 68663e4..94c34a1 100644
--- a/src/vogar/android/AndroidSdk.java
+++ b/src/vogar/android/AndroidSdk.java
@@ -239,12 +239,15 @@
     /**
      * Converts all the .class files on 'classpath' into a dex file written to 'output'.
      */
-    public void dex(File output, Classpath classpath) {
+    public void dex(boolean multidex, File output, Classpath classpath) {
         mkdir.mkdirs(output.getParentFile());
 
-        String key = dexCache.makeKey(classpath);
-        if (key != null) {
-            boolean cacheHit = dexCache.getFromCache(output, key);
+        String classpathSubKey = dexCache.makeKey(classpath);
+        String cacheKey = null;
+        if (classpathSubKey != null) {
+            String multidexSubKey = "mdex=" + multidex;
+            cacheKey = dexCache.makeKey(classpathSubKey, multidexSubKey);
+            boolean cacheHit = dexCache.getFromCache(output, cacheKey);
             if (cacheHit) {
                 log.verbose("dex cache hit for " + classpath);
                 return;
@@ -262,15 +265,19 @@
          * Memory options pulled from build/core/definitions.mk to
          * handle large dx input when building dex for APK.
          */
-        new Command.Builder(log)
+        Command.Builder builder = new Command.Builder(log)
                 .args("dx")
                 .args("-JXms16M")
-                .args("-JXmx1536M")
-                .args("--dex")
+                .args("-JXmx1536M");
+        if (multidex) {
+            builder.args("--multi-dex");
+        }
+        builder.args("--dex")
                 .args("--output=" + output)
                 .args("--core-library")
-                .args((Object[]) Strings.objectsToStrings(classpath.getElements())).execute();
-        dexCache.insert(key, output);
+                .args((Object[]) Strings.objectsToStrings(classpath.getElements()));
+        builder.execute();
+        dexCache.insert(cacheKey, output);
     }
 
     public void packageApk(File apk, File manifest) {
diff --git a/src/vogar/android/DeviceRuntime.java b/src/vogar/android/DeviceRuntime.java
index 5e8c934..0771c99 100644
--- a/src/vogar/android/DeviceRuntime.java
+++ b/src/vogar/android/DeviceRuntime.java
@@ -144,7 +144,7 @@
                     action, localDex);
         } else {
             dex = new DexTask(run.androidSdk, classpath, run.benchmark, name, classpathElement,
-                    action, localDex);
+                    action, localDex, run.multidex);
         }
         return dex;
     }
diff --git a/src/vogar/android/DexTask.java b/src/vogar/android/DexTask.java
index d8afdb4..2e6f17e 100644
--- a/src/vogar/android/DexTask.java
+++ b/src/vogar/android/DexTask.java
@@ -29,9 +29,10 @@
     private final File jar;
     private final Action action;
     private final File localDex;
+    private final boolean multidex;
 
     public DexTask(AndroidSdk androidSdk, Classpath classpath, boolean benchmark, String name,
-            File jar, Action action, File localDex) {
+            File jar, Action action, File localDex, boolean multidex) {
         super("dex " + name);
         this.androidSdk = androidSdk;
         this.classpath = classpath;
@@ -39,6 +40,7 @@
         this.jar = jar;
         this.action = action;
         this.localDex = localDex;
+        this.multidex = multidex;
     }
 
     @Override protected Result execute() throws Exception {
@@ -47,7 +49,7 @@
         if (benchmark && action != null) {
             cp.addAll(classpath);
         }
-        androidSdk.dex(localDex, cp);
+        androidSdk.dex(multidex, localDex, cp);
         return Result.SUCCESS;
     }
 }
diff --git a/src/vogar/android/HostRuntime.java b/src/vogar/android/HostRuntime.java
index 0c5c7fb..70bc794 100644
--- a/src/vogar/android/HostRuntime.java
+++ b/src/vogar/android/HostRuntime.java
@@ -161,7 +161,7 @@
                     localDex);
         } else {
             dex = new DexTask(run.androidSdk, classpath, run.benchmark, name, classpathElement,
-                    action, localDex);
+                    action, localDex, run.multidex);
         }
         return dex;
     }
diff --git a/src/vogar/android/InstallApkTask.java b/src/vogar/android/InstallApkTask.java
index a23551b..bcd26bd 100644
--- a/src/vogar/android/InstallApkTask.java
+++ b/src/vogar/android/InstallApkTask.java
@@ -70,7 +70,7 @@
             throw new UnsupportedOperationException(
                     "Jack support for --mode=activity not yet implemented");
         }
-        run.androidSdk.dex(dex, classesToDex);
+        run.androidSdk.dex(run.multidex, dex, classesToDex);
         return dex;
     }
 
diff --git a/src/vogar/android/JackDexTask.java b/src/vogar/android/JackDexTask.java
index 59d5570..d6f9876 100644
--- a/src/vogar/android/JackDexTask.java
+++ b/src/vogar/android/JackDexTask.java
@@ -70,6 +70,7 @@
 
         // Check the jack cache first.
         Md5Cache jackCache = run.jackCache;
+        boolean multidex = run.multidex;
         String classpathSubKey = jackCache.makeKey(classpath);
         String cacheKey = null;
         if (classpathSubKey != null) {
@@ -77,8 +78,10 @@
             // classpathSubKey and do not cache.
 
             // cacheKey includes all the arguments that could affect the output.
+            String debuggingSubKey = "debug=" + run.debugging;
+            String multidexSubKey = "mdex=" + multidex;
             cacheKey = jackCache.makeKey(inputFile.toString(), classpathSubKey,
-                run.language.toString(), Boolean.toString(run.debugging));
+                run.language.toString(), debuggingSubKey, multidexSubKey);
 
             if (jackCache.getFromCache(localDex, cacheKey)) {
                 run.log.verbose("JackDexTask: Obtained " + localDex + " from jackCache");
@@ -90,6 +93,7 @@
         Jack jack = Jack.getJackCommand(run.log).outputDexZip(localDex.getPath());
         jack.sourceVersion(run.language.getJackSourceVersion());
         jack.minApiLevel(String.valueOf(run.language.getJackMinApilevel()));
+        jack.multiDex(multidex ? "native" : "none");
         jack.extra(run.jackArgs);
         if (run.debugging) {
             jack.setDebug();