Compile all target main classes into one dex

This should not be a problem for the tests quality since all those main
classes are generated, very small and all the same for example:
package dot.junit.opcodes.add_double;
import dot.junit.opcodes.add_double.d.*;
import dot.junit.*;
public class Main_testB1 extends DxAbstractMain {
    public static void main(String[] args) throws Exception {
            T_add_double_1 t = new T_add_double_1();
	    assertEquals(Double.NaN, t.run(Double.MAX_VALUE, Double.NaN));
    }
}

This also changes other source to dex compilations to be done in one
Jack command.

Bug: 20116648

Change-Id: Iac1c516ef5798b24dd920e9920070b5566c21005
diff --git a/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java b/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
index 0e31884..a25fce2 100644
--- a/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
+++ b/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
@@ -19,6 +19,7 @@
 import com.android.dex.util.FileUtils;
 
 import dot.junit.AllTests;
+import util.build.BuildStep.BuildFile;
 
 import junit.framework.TestCase;
 import junit.framework.TestResult;
@@ -56,6 +57,8 @@
  */
 public class BuildDalvikSuite {
 
+    public static final String TARGET_MAIN_FILE = "mains.jar";
+
     public static boolean DEBUG = true;
 
     private static String JAVASRC_FOLDER = "";
@@ -257,14 +260,10 @@
         final String targetCoreJarPath = String.format("%s/dot/junit/dexcore.jar",
                 TARGET_JAR_ROOT_PATH);
 
-        // push class with Main jar.
-        String mjar = "Main_" + method + ".jar";
-        String pPath = pName.replaceAll("\\.","/");
-        String mainJar = String.format("%s/%s/%s", TARGET_JAR_ROOT_PATH, pPath, mjar);
+        String mainsJar = String.format("%s/%s", TARGET_JAR_ROOT_PATH, TARGET_MAIN_FILE);
 
-        String cp = String.format("%s:%s", targetCoreJarPath, mainJar);
+        String cp = String.format("%s:%s", targetCoreJarPath, mainsJar);
         for (String depFqcn : dependentTestClassNames) {
-            int lastDotPos = depFqcn.lastIndexOf('.');
             String sourceName = depFqcn.replaceAll("\\.", "/") + ".jar";
             String targetName= String.format("%s/%s", TARGET_JAR_ROOT_PATH,
                     sourceName);
@@ -289,7 +288,13 @@
         hostJunitBuildStep = new JavacBuildStep(
             HOSTJUNIT_CLASSES_OUTPUT_FOLDER, CLASS_PATH);
 
-        srcBuildStep = new JavacBuildStep(CLASSES_OUTPUT_FOLDER, CLASS_PATH);
+        String mainsJar = OUTPUT_FOLDER + File.separator + TARGET_MAIN_FILE;
+        if (useJack) {
+            srcBuildStep = new JackBuildStep(mainsJar,
+            CLASS_PATH);
+        } else {
+            srcBuildStep = new JavacBuildStep(CLASSES_OUTPUT_FOLDER, CLASS_PATH);
+        }
 
         for (Entry<String, List<String>> entry : map.entrySet()) {
 
@@ -355,23 +360,7 @@
                 File sourceFile = getFileFromPackage(pName, method);
 
                 writeToFile(sourceFile, content);
-                if (useJack) {
-                    File jackFile = new File(CLASSES_OUTPUT_FOLDER + "/" +
-                            getFileName(pName, method, ".jack"));
-                    JackBuildStep step = new JackBuildStep(jackFile.getAbsolutePath(), CLASS_PATH);
-                    step.addSourceFile(sourceFile.getAbsolutePath());
-                    if (!step.build()) {
-                        System.out.println("main src dalvik-cts-buildutil build step failed");
-                        System.exit(1);
-                    }
-                } else {
-                    srcBuildStep.addSourceFile(sourceFile.getAbsolutePath());
-                }
-
-                BuildStep dexBuildStep = generateDexBuildStep(
-                        CLASSES_OUTPUT_FOLDER, getFileName(pName, method, ""), null);
-                targets.add(dexBuildStep);
-
+                srcBuildStep.addSourceFile(sourceFile.getAbsolutePath());
 
                 // prepare the entry in the data file for the bash script.
                 // e.g.
@@ -459,6 +448,15 @@
 
         }
 
+        if (!useJack) {
+          DxBuildStep dexBuildStep = new DxBuildStep(
+              new BuildStep.BuildFile(new File(CLASSES_OUTPUT_FOLDER)),
+              new BuildStep.BuildFile(new File(mainsJar)),
+              false);
+
+          targets.add(dexBuildStep);
+        }
+
         // write latest HOSTJUNIT generated file.
         flushHostJunitFile();
 
@@ -471,12 +469,11 @@
             System.exit(1);
         }
 
-        if (!useJack) {
-            if (!srcBuildStep.build()) {
-                System.out.println("main src dalvik-cts-buildutil build step failed");
-                System.exit(1);
-            }
+        if (!srcBuildStep.build()) {
+            System.out.println("main src dalvik-cts-buildutil build step failed");
+            System.exit(1);
         }
+
         for (BuildStep buildStep : targets) {
             if (!buildStep.build()) {
                 System.out.println("building failed. buildStep: " +
@@ -541,15 +538,17 @@
 
         File srcFile = new File(sourceFolder, fileName + ".java");
         if (srcFile.exists()) {
-            JackBuildStep jackBuildStep = null;
+            BuildStep dexBuildStep;
             if (useJack) {
-                jackBuildStep = new JackBuildStep(
-                        COMPILED_CLASSES_FOLDER + File.separator + fileName + ".jack",
+                JackBuildStep jackBuildStep = new JackBuildStep(
+                    OUTPUT_FOLDER + File.separator + fileName + ".jar",
                         CLASS_PATH);
                 jackBuildStep.addSourceFile(srcFile.getAbsolutePath());
+                dexBuildStep = jackBuildStep;
+            } else {
+              dexBuildStep = generateDexBuildStep(
+                COMPILED_CLASSES_FOLDER, fileName, null);
             }
-            BuildStep dexBuildStep = generateDexBuildStep(
-                COMPILED_CLASSES_FOLDER, fileName, jackBuildStep);
             targets.add(dexBuildStep);
             return;
         }
diff --git a/tools/vm-tests-tf/src/util/build/BuildStep.java b/tools/vm-tests-tf/src/util/build/BuildStep.java
index dbc6bca..e3349bd 100644
--- a/tools/vm-tests-tf/src/util/build/BuildStep.java
+++ b/tools/vm-tests-tf/src/util/build/BuildStep.java
@@ -37,6 +37,10 @@
             this.folder = new File(folder);
             this.fileName = new File(this.folder, fileName);
         }
+        BuildFile(File file) {
+          this.folder = file.getParentFile();
+          this.fileName = file;
+      }
 
         String getPath() {
             return fileName.getAbsolutePath();
@@ -70,7 +74,8 @@
         this.outputFile = outputFile;
     }
 
-    BuildStep() {
+    BuildStep(File output) {
+        this.outputFile = new BuildFile(output);
     }
 
     private Set<BuildStep> children;
@@ -117,8 +122,7 @@
     }
 
     public int compareTo(BuildStep o) {
-        return (inputFile == o.inputFile ? 0 : (inputFile != null
-                ? (o.inputFile != null ? inputFile.getPath().compareTo(
-                        o.inputFile.getPath()) : 1) : -1));
+        return (outputFile == o.outputFile ? 0 : outputFile.getPath().compareTo(
+                        o.outputFile.getPath()));
     }
 }
diff --git a/tools/vm-tests-tf/src/util/build/JackBuildStep.java b/tools/vm-tests-tf/src/util/build/JackBuildStep.java
index dabef17..061ff07 100644
--- a/tools/vm-tests-tf/src/util/build/JackBuildStep.java
+++ b/tools/vm-tests-tf/src/util/build/JackBuildStep.java
@@ -18,10 +18,14 @@
 
 import com.android.jack.CLILogConfiguration;
 import com.android.jack.CLILogConfiguration.LogConfigurationException;
+
+import util.build.BuildStep.BuildFile;
+
 import com.android.jack.Jack;
 import com.android.jack.Main;
 import com.android.jack.Options;
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -42,6 +46,7 @@
     private final Set<String> sourceFiles = new HashSet<String>();
 
     public JackBuildStep(String destPath, String classPath) {
+        super(new File(destPath));
         this.destPath = destPath;
         this.classPath = classPath;
     }
@@ -64,23 +69,44 @@
                         + outDir.getAbsolutePath());
                 return false;
             }
-            List<String> commandLine = new ArrayList(4 + sourceFiles.size());
-            commandLine.add("--verbose");
-            commandLine.add("error");
-            commandLine.add("--classpath");
-            commandLine.add(classPath);
-            commandLine.add("--output-jack");
-            commandLine.add(destPath);
-            commandLine.addAll(sourceFiles);
+
+            File tmpOutDir = new File(outDir, outputFile.fileName.getName() + ".dexTmp");
+            if (!tmpOutDir.exists() && !tmpOutDir.mkdirs()) {
+                System.err.println("failed to create temp dir: "
+                        + tmpOutDir.getAbsolutePath());
+                return false;
+            }
+            File tmpDex = new File(tmpOutDir, "classes.dex");
 
             try {
+                List<String> commandLine = new ArrayList<String>(6 + sourceFiles.size());
+                commandLine.add("--verbose");
+                commandLine.add("error");
+                commandLine.add("--classpath");
+                commandLine.add(classPath);
+                commandLine.add("--output-dex");
+                commandLine.add(tmpOutDir.getAbsolutePath());
+                commandLine.addAll(sourceFiles);
+
                 Options options = Main.parseCommandLine(commandLine);
                 Jack.checkAndRun(options);
+
+                JarBuildStep jarStep = new JarBuildStep(
+                    new BuildFile(tmpDex),
+                    "classes.dex",
+                    outputFile,
+                    /* deleteInputFileAfterBuild = */ true);
+                if (!jarStep.build()) {
+                  throw new IOException("Failed to make jar: " + outputFile.getPath());
+                }
+                return true;
             } catch (Throwable ex) {
                 ex.printStackTrace();
                 return false;
+            } finally {
+              tmpDex.delete();
+              tmpOutDir.delete();
             }
-            return true;
         }
         return false;
     }
diff --git a/tools/vm-tests-tf/src/util/build/JackDexBuildStep.java b/tools/vm-tests-tf/src/util/build/JackDexBuildStep.java
index 304eaa0..8734cf0 100644
--- a/tools/vm-tests-tf/src/util/build/JackDexBuildStep.java
+++ b/tools/vm-tests-tf/src/util/build/JackDexBuildStep.java
@@ -21,6 +21,7 @@
 import com.android.jack.Options;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -41,7 +42,7 @@
             String outputFilePath = outputFile.fileName.getAbsolutePath();
             if (outputFilePath.endsWith(".dex")) {
               throw new AssertionError(
-                  "DexBuildStep does not support dex output outside of an archive");
+                  "JackDexBuildStep does not support dex output outside of an archive");
             }
 
             File outDir = outputFile.fileName.getParentFile();
@@ -51,17 +52,34 @@
                 return false;
             }
 
-            List<String> commandLine = new ArrayList<String>(4);
-            commandLine.add("--verbose");
-            commandLine.add("error");
-            commandLine.add("--output-dex-zip");
-            commandLine.add(outputFilePath);
-            commandLine.add("--import");
-            commandLine.add(inputFile.fileName.getAbsolutePath());
+            File tmpOutDir = new File(outDir, outputFile.fileName.getName() + ".dexTmp");
+            if (!tmpOutDir.exists() && !tmpOutDir.mkdirs()) {
+                System.err.println("failed to create temp dir: "
+                        + tmpOutDir.getAbsolutePath());
+                return false;
+            }
+            File tmpDex = new File(tmpOutDir, "classes.dex");
 
             try {
-               Options options = Main.parseCommandLine(commandLine);
-               Jack.checkAndRun(options);
+                List<String> commandLine = new ArrayList<String>(4);
+                commandLine.add("--verbose");
+                commandLine.add("error");
+                commandLine.add("--output-dex");
+                commandLine.add(tmpOutDir.getAbsolutePath());
+                commandLine.add("--import");
+                commandLine.add(inputFile.fileName.getAbsolutePath());
+
+                Options options = Main.parseCommandLine(commandLine);
+                Jack.checkAndRun(options);
+
+                JarBuildStep jarStep = new JarBuildStep(
+                    new BuildFile(tmpDex),
+                    "classes.dex",
+                    outputFile,
+                    /* deleteInputFileAfterBuild = */ true);
+                if (!jarStep.build()) {
+                  throw new IOException("Failed to make jar: " + outputFile.getPath());
+                }
                 if (deleteInputFileAfterBuild) {
                     inputFile.fileName.delete();
                 }
@@ -71,6 +89,9 @@
                         + inputFile.fileName.getAbsolutePath() + " to "
                         + outputFile.fileName.getAbsolutePath());
                 ex.printStackTrace();
+            } finally {
+              tmpDex.delete();
+              tmpOutDir.delete();
             }
         }
         return false;
diff --git a/tools/vm-tests-tf/src/util/build/JavacBuildStep.java b/tools/vm-tests-tf/src/util/build/JavacBuildStep.java
index a07bb69..a1cde1f 100644
--- a/tools/vm-tests-tf/src/util/build/JavacBuildStep.java
+++ b/tools/vm-tests-tf/src/util/build/JavacBuildStep.java
@@ -29,6 +29,7 @@
     private final String classPath;
     private final Set<String> sourceFiles = new HashSet<String>();
     public JavacBuildStep(String destPath, String classPath) {
+        super(new File(destPath));
         this.destPath = destPath;
         this.classPath = classPath;
     }
diff --git a/tools/vm-tests-tf/src/util/build/SourceBuildStep.java b/tools/vm-tests-tf/src/util/build/SourceBuildStep.java
index 4a68a05..9f9142d 100644
--- a/tools/vm-tests-tf/src/util/build/SourceBuildStep.java
+++ b/tools/vm-tests-tf/src/util/build/SourceBuildStep.java
@@ -16,8 +16,14 @@
 
 package util.build;
 
+import java.io.File;
+
 public abstract class SourceBuildStep extends BuildStep {
 
+  SourceBuildStep(File destFile) {
+    super(destFile);
+  }
+
   public abstract void addSourceFile(String sourceFile);
 
 }