Home | History | Annotate | Download | only in build
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package util.build;
     18 
     19 import java.io.File;
     20 import java.io.FileWriter;
     21 import java.io.IOException;
     22 import java.io.Writer;
     23 import java.util.ArrayList;
     24 import java.util.HashSet;
     25 import java.util.List;
     26 import java.util.Set;
     27 
     28 public class JackBuildStep extends SourceBuildStep {
     29 
     30     private final String destPath;
     31     private final String classPath;
     32     private final Set<String> sourceFiles = new HashSet<String>();
     33 
     34     public JackBuildStep(String destPath, String classPath) {
     35         super(new File(destPath));
     36         this.destPath = destPath;
     37         this.classPath = classPath;
     38     }
     39 
     40     @Override
     41     public void addSourceFile(String sourceFile) {
     42         sourceFiles.add(sourceFile);
     43     }
     44 
     45     @Override
     46     boolean build() {
     47         if (super.build()) {
     48             if (sourceFiles.isEmpty()) {
     49                 return true;
     50             }
     51 
     52             File outDir = new File(destPath).getParentFile();
     53             if (!outDir.exists() && !outDir.mkdirs()) {
     54                 System.err.println("failed to create output dir: "
     55                         + outDir.getAbsolutePath());
     56                 return false;
     57             }
     58 
     59             File tmpOutDir = new File(outDir, outputFile.fileName.getName() + ".dexTmp");
     60             if (!tmpOutDir.exists() && !tmpOutDir.mkdirs()) {
     61                 System.err.println("failed to create temp dir: "
     62                         + tmpOutDir.getAbsolutePath());
     63                 return false;
     64             }
     65             File tmpDex = new File(tmpOutDir, "classes.dex");
     66 
     67             File tmpArgs = new File(outDir, outputFile.fileName.getName() + ".args");
     68 
     69             Writer argsOut = null;
     70             try {
     71                 argsOut = new FileWriter(tmpArgs);
     72                 for (String source : sourceFiles) {
     73                     argsOut.append(source);
     74                     argsOut.append('\n');
     75                 }
     76                 argsOut.close();
     77                 argsOut = null;
     78 
     79                 List<String> commandLine = new ArrayList<String>(6 + sourceFiles.size());
     80                 commandLine.add("--verbose");
     81                 commandLine.add("error");
     82                 commandLine.add("--classpath");
     83                 commandLine.add(classPath);
     84                 commandLine.add("--output-dex");
     85                 commandLine.add(tmpOutDir.getAbsolutePath());
     86                 commandLine.add("@" + tmpArgs.getPath());
     87 
     88                 ExecuteFile exec = new ExecuteFile(JackBuildDalvikSuite.JACK,
     89                     commandLine.toArray(new String[commandLine.size()]));
     90                 exec.setErr(System.err);
     91                 exec.setOut(System.out);
     92                 if (!exec.run()) {
     93                     return false;
     94                 }
     95 
     96                 JarBuildStep jarStep = new JarBuildStep(
     97                     new BuildFile(tmpDex),
     98                     "classes.dex",
     99                     outputFile,
    100                     /* deleteInputFileAfterBuild = */ true);
    101                 if (!jarStep.build()) {
    102                   throw new IOException("Failed to make jar: " + outputFile.getPath());
    103                 }
    104                 return true;
    105             } catch (Throwable ex) {
    106                 ex.printStackTrace();
    107                 return false;
    108             } finally {
    109                 tmpDex.delete();
    110                 tmpArgs.delete();
    111                 tmpOutDir.delete();
    112                 if (argsOut != null) {
    113                     try {
    114                         argsOut.close();
    115                     } catch (IOException io) {
    116                         // Ignore, don't override already thrown exception
    117                     }
    118                 }
    119             }
    120         }
    121         return false;
    122     }
    123 
    124     @Override
    125     public boolean equals(Object obj) {
    126         if (super.equals(obj)) {
    127             JackBuildStep other = (JackBuildStep) obj;
    128             return destPath.equals(other.destPath) && classPath.equals(other.classPath)
    129                     && sourceFiles.equals(other.sourceFiles);
    130         }
    131         return false;
    132     }
    133 
    134     @Override
    135     public int hashCode() {
    136         return destPath.hashCode() ^ classPath.hashCode() ^ sourceFiles.hashCode();
    137     }
    138 }
    139