1 // Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file 2 // for details. All rights reserved. Use of this source code is governed by a 3 // BSD-style license that can be found in the LICENSE file. 4 package com.android.tools.r8; 5 6 import com.android.tools.r8.dex.Constants; 7 import com.android.tools.r8.utils.AndroidApp; 8 import com.android.tools.r8.utils.FileUtils; 9 import com.android.tools.r8.utils.InternalOptions; 10 import com.android.tools.r8.utils.OutputMode; 11 import java.io.IOException; 12 import java.nio.file.Path; 13 import java.util.Collection; 14 15 abstract class BaseCommand { 16 17 private final boolean printHelp; 18 private final boolean printVersion; 19 20 private final AndroidApp app; 21 private final Path outputPath; 22 private final OutputMode outputMode; 23 private final CompilationMode mode; 24 private final int minApiLevel; 25 BaseCommand(boolean printHelp, boolean printVersion)26 BaseCommand(boolean printHelp, boolean printVersion) { 27 this.printHelp = printHelp; 28 this.printVersion = printVersion; 29 // All other fields are initialized with stub/invalid values. 30 this.app = null; 31 this.outputPath = null; 32 this.outputMode = OutputMode.Indexed; 33 this.mode = null; 34 this.minApiLevel = 0; 35 } 36 BaseCommand( AndroidApp app, Path outputPath, OutputMode outputMode, CompilationMode mode, int minApiLevel)37 BaseCommand( 38 AndroidApp app, 39 Path outputPath, 40 OutputMode outputMode, 41 CompilationMode mode, 42 int minApiLevel) { 43 assert app != null; 44 assert mode != null; 45 assert minApiLevel > 0; 46 this.app = app; 47 this.outputPath = outputPath; 48 this.outputMode = outputMode; 49 this.mode = mode; 50 this.minApiLevel = minApiLevel; 51 // Print options are not set. 52 printHelp = false; 53 printVersion = false; 54 } 55 isPrintHelp()56 public boolean isPrintHelp() { 57 return printHelp; 58 } 59 isPrintVersion()60 public boolean isPrintVersion() { 61 return printVersion; 62 } 63 64 // Internal access to the input resources. getInputApp()65 AndroidApp getInputApp() { 66 return app; 67 } 68 69 // Internal access to the internal options. getInternalOptions()70 abstract InternalOptions getInternalOptions(); 71 getOutputPath()72 public Path getOutputPath() { 73 return outputPath; 74 } 75 getMode()76 public CompilationMode getMode() { 77 return mode; 78 } 79 getMinApiLevel()80 public int getMinApiLevel() { 81 return minApiLevel; 82 } 83 getOutputMode()84 public OutputMode getOutputMode() { 85 return outputMode; 86 } 87 88 abstract static class Builder<C extends BaseCommand, B extends Builder<C, B>> { 89 90 private boolean printHelp = false; 91 private boolean printVersion = false; 92 private final AndroidApp.Builder app; 93 private Path outputPath = null; 94 private OutputMode outputMode = OutputMode.Indexed; 95 private CompilationMode mode; 96 private int minApiLevel = Constants.DEFAULT_ANDROID_API; 97 Builder(CompilationMode mode)98 protected Builder(CompilationMode mode) { 99 this(AndroidApp.builder(), mode); 100 } 101 102 // Internal constructor for testing. Builder(AndroidApp app, CompilationMode mode)103 Builder(AndroidApp app, CompilationMode mode) { 104 this(AndroidApp.builder(app), mode); 105 } 106 Builder(AndroidApp.Builder builder, CompilationMode mode)107 private Builder(AndroidApp.Builder builder, CompilationMode mode) { 108 assert mode != null; 109 this.app = builder; 110 this.mode = mode; 111 } 112 self()113 abstract B self(); 114 build()115 public abstract C build() throws CompilationException, IOException; 116 117 // Internal accessor for the application resources. getAppBuilder()118 AndroidApp.Builder getAppBuilder() { 119 return app; 120 } 121 122 /** Add program file resources. */ addProgramFiles(Path... files)123 public B addProgramFiles(Path... files) throws IOException { 124 app.addProgramFiles(files); 125 return self(); 126 } 127 128 /** Add program file resources. */ addProgramFiles(Collection<Path> files, boolean skipDex)129 public B addProgramFiles(Collection<Path> files, boolean skipDex) throws IOException { 130 app.addProgramFiles(files, skipDex); 131 return self(); 132 } 133 134 /** Add classpath file resources. */ addClasspathFiles(Path... files)135 public B addClasspathFiles(Path... files) throws IOException { 136 app.addClasspathFiles(files); 137 return self(); 138 } 139 140 /** Add classpath file resources. */ addClasspathFiles(Collection<Path> files)141 public B addClasspathFiles(Collection<Path> files) throws IOException { 142 app.addClasspathFiles(files); 143 return self(); 144 } 145 146 /** Add library file resources. */ addLibraryFiles(Path... files)147 public B addLibraryFiles(Path... files) throws IOException { 148 app.addLibraryFiles(files); 149 return self(); 150 } 151 152 /** Add library file resources. */ addLibraryFiles(Collection<Path> files)153 public B addLibraryFiles(Collection<Path> files) throws IOException { 154 app.addLibraryFiles(files); 155 return self(); 156 } 157 158 /** Add Java-bytecode program-data. */ addClassProgramData(byte[]... data)159 public B addClassProgramData(byte[]... data) { 160 app.addClassProgramData(data); 161 return self(); 162 } 163 164 /** Add Java-bytecode program-data. */ addClassProgramData(Collection<byte[]> data)165 public B addClassProgramData(Collection<byte[]> data) { 166 app.addClassProgramData(data); 167 return self(); 168 } 169 170 /** Add dex program-data. */ addDexProgramData(byte[]... data)171 public B addDexProgramData(byte[]... data) { 172 app.addDexProgramData(data); 173 return self(); 174 } 175 176 /** Add dex program-data. */ addDexProgramData(Collection<byte[]> data)177 public B addDexProgramData(Collection<byte[]> data) { 178 app.addDexProgramData(data); 179 return self(); 180 } 181 182 /** Get current compilation mode. */ getMode()183 public CompilationMode getMode() { 184 return mode; 185 } 186 187 /** Set compilation mode. */ setMode(CompilationMode mode)188 public B setMode(CompilationMode mode) { 189 assert mode != null; 190 this.mode = mode; 191 return self(); 192 } 193 194 /** Get the output path. Null if not set. */ getOutputPath()195 public Path getOutputPath() { 196 return outputPath; 197 } 198 199 /** Get the output mode. */ getOutputMode()200 public OutputMode getOutputMode() { 201 return outputMode; 202 } 203 204 /** Set an output path. Must be an existing directory or a zip file. */ setOutputPath(Path outputPath)205 public B setOutputPath(Path outputPath) { 206 this.outputPath = outputPath; 207 return self(); 208 } 209 210 /** Set an output mode. */ setOutputMode(OutputMode outputMode)211 public B setOutputMode(OutputMode outputMode) { 212 this.outputMode = outputMode; 213 return self(); 214 } 215 216 /** Get the minimum API level (aka SDK version). */ getMinApiLevel()217 public int getMinApiLevel() { 218 return minApiLevel; 219 } 220 221 /** Set the minimum required API level (aka SDK version). */ setMinApiLevel(int minApiLevel)222 public B setMinApiLevel(int minApiLevel) { 223 assert minApiLevel > 0; 224 this.minApiLevel = minApiLevel; 225 return self(); 226 } 227 228 /** Set the main-dex list file. */ setMainDexListFile(Path file)229 public B setMainDexListFile(Path file) { 230 app.setMainDexListFile(file); 231 return self(); 232 } 233 234 /** True if the print-help flag is enabled. */ isPrintHelp()235 public boolean isPrintHelp() { 236 return printHelp; 237 } 238 239 /** Set the value of the print-help flag. */ setPrintHelp(boolean printHelp)240 public B setPrintHelp(boolean printHelp) { 241 this.printHelp = printHelp; 242 return self(); 243 } 244 245 /** True if the print-version flag is enabled. */ isPrintVersion()246 public boolean isPrintVersion() { 247 return printVersion; 248 } 249 250 /** Set the value of the print-version flag. */ setPrintVersion(boolean printVersion)251 public B setPrintVersion(boolean printVersion) { 252 this.printVersion = printVersion; 253 return self(); 254 } 255 validate()256 protected void validate() throws CompilationException { 257 FileUtils.validateOutputFile(outputPath); 258 } 259 } 260 } 261