1 /* 2 * Copyright (C) 2015 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 vogar.commands; 18 19 import com.google.common.collect.Lists; 20 21 import java.io.File; 22 import java.util.Collection; 23 import java.util.List; 24 25 import vogar.Log; 26 import vogar.util.Strings; 27 28 /** 29 * Runs the Jack compiler to generate dex files. 30 */ 31 public class Jack { 32 private static final File JACK_SCRIPT; 33 private static final File JACK_JAR; 34 35 // Initialise the files for jack and jill, letting them be null if the files 36 // cannot be found. 37 static { 38 String sdkTop = System.getenv("ANDROID_BUILD_TOP"); 39 40 final File jackScript = new File(sdkTop + "/prebuilts/sdk/tools/jack"); 41 final File jackJar = new File(sdkTop + "/prebuilts/sdk/tools/jack.jar"); 42 43 // If the system environment variable JACK_JAR is set then use that, 44 // otherwise find the jar relative to the AOSP source. 45 String jackJarEnv = System.getenv("JACK_JAR"); 46 47 final File jackJarFromEnv = (jackJarEnv != null) ? new File(jackJarEnv) : null; 48 49 if (!jackScript.exists()) { 50 JACK_SCRIPT = null; 51 } else { 52 JACK_SCRIPT = jackScript; 53 } 54 55 if (jackJarEnv != null && jackJarFromEnv.exists()) { 56 JACK_JAR = jackJarFromEnv; 57 } else { 58 if (!jackJar.exists()) { 59 JACK_JAR = null; 60 } else { 61 JACK_JAR = jackJar; 62 } 63 } 64 } 65 66 /** 67 * Get an instance of the jack command with appropriate path settings. 68 * 69 * @return an instance of a jack command with appropriate paths to its dependencies if needed. 70 * @throws IllegalStateException when the jack command cannot be found. 71 */ getJackCommand(Log log)72 public static Jack getJackCommand(Log log) throws IllegalStateException { 73 if (JACK_SCRIPT != null) { 74 // Configure jack compiler with right JACK_SCRIPT path. 75 return new Jack(log, Lists.newArrayList(JACK_SCRIPT.getAbsolutePath())); 76 } 77 if (JACK_JAR != null) { 78 // Fallback to jack.jar, for previous releases. 79 return new Jack(log, Lists.newArrayList("java", "-jar", JACK_JAR.getAbsolutePath())); 80 } 81 throw new IllegalStateException("Jack library not found, cannot use jack."); 82 } 83 84 private final Command.Builder builder; 85 Jack(Log log, Collection<String> jackArgs)86 private Jack(Log log, Collection<String> jackArgs) { 87 this.builder = new Command.Builder(log); 88 builder.args(jackArgs); 89 } 90 importFile(String path)91 public Jack importFile(String path) { 92 builder.args("--import", path); 93 return this; 94 } 95 importMeta(String dir)96 public Jack importMeta(String dir) { 97 builder.args("--import-meta", dir); 98 return this; 99 } 100 importResource(String dir)101 public Jack importResource(String dir) { 102 builder.args("--import-resource", dir); 103 return this; 104 } 105 incrementalFolder(String dir)106 public Jack incrementalFolder(String dir) { 107 builder.args("--incremental--folder", dir); 108 return this; 109 } 110 multiDex(String mode)111 public Jack multiDex(String mode) { 112 builder.args("--multi-dex", mode); 113 return this; 114 } 115 sourceVersion(String version)116 public Jack sourceVersion(String version) { 117 setProperty("jack.java.source.version=" + version); 118 return this; 119 } 120 minApiLevel(String minApiLevel)121 public Jack minApiLevel(String minApiLevel) { 122 setProperty("jack.android.min-api-level=" + minApiLevel); 123 return this; 124 } 125 outputDex(String dir)126 public Jack outputDex(String dir) { 127 builder.args("--output-dex", dir); 128 return this; 129 } 130 outputDexZip(String zipFile)131 public Jack outputDexZip(String zipFile) { 132 builder.args("--output-dex-zip", zipFile); 133 return this; 134 } 135 outputJack(String path)136 public Jack outputJack(String path) { 137 builder.args("--output-jack", path); 138 return this; 139 } 140 processor(String names)141 public Jack processor(String names) { 142 builder.args("--processor", names); 143 return this; 144 } 145 processorPath(String path)146 public Jack processorPath(String path) { 147 builder.args("--processorpath", path); 148 return this; 149 } 150 verbose(String mode)151 public Jack verbose(String mode) { 152 builder.args("--verbose", mode); 153 return this; 154 } 155 addAnnotationProcessor(String processor)156 public Jack addAnnotationProcessor(String processor) { 157 builder.args("-A", processor); 158 return this; 159 } 160 setProperty(String property)161 public Jack setProperty(String property) { 162 builder.args("-D", property); 163 return this; 164 } 165 setClassPath(String classPath)166 public Jack setClassPath(String classPath) { 167 builder.args("-cp", classPath); 168 return this; 169 } 170 setDebug()171 public Jack setDebug() { 172 builder.args("-g"); 173 return this; 174 } 175 setEnvVar(String key, String value)176 public Jack setEnvVar(String key, String value) { 177 builder.env(key, value); 178 return this; 179 } 180 181 /** 182 * Runs the command with the preconfigured options on Jack, and returns the outcome. 183 * 184 * @return A list of output lines from running the command. 185 */ invoke()186 public List<String> invoke() { 187 return builder.execute(); 188 } 189 190 /** 191 * Runs the command with the preconfigured options on Jack, and returns the outcome. 192 * This method does not dirty the existing Jack instance, and can be safely reused 193 * to compile other files. 194 * @param files The files to compile. 195 * @return A list of output lines from running the command. 196 */ compile(Collection<File> files)197 public List<String> compile(Collection<File> files) { 198 return new Command.Builder(builder) 199 .args((Object[]) Strings.objectsToStrings(files)) 200 .execute(); 201 } 202 } 203