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.
4package com.android.tools.r8;
5
6import com.android.tools.r8.dex.Constants;
7import com.android.tools.r8.utils.AndroidApp;
8import com.android.tools.r8.utils.FileUtils;
9import com.android.tools.r8.utils.InternalOptions;
10import com.android.tools.r8.utils.OutputMode;
11import java.io.IOException;
12import java.nio.file.Path;
13import java.util.Collection;
14
15abstract 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
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
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
56  public boolean isPrintHelp() {
57    return printHelp;
58  }
59
60  public boolean isPrintVersion() {
61    return printVersion;
62  }
63
64  // Internal access to the input resources.
65  AndroidApp getInputApp() {
66    return app;
67  }
68
69  // Internal access to the internal options.
70  abstract InternalOptions getInternalOptions();
71
72  public Path getOutputPath() {
73    return outputPath;
74  }
75
76  public CompilationMode getMode() {
77    return mode;
78  }
79
80  public int getMinApiLevel() {
81    return minApiLevel;
82  }
83
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
98    protected Builder(CompilationMode mode) {
99      this(AndroidApp.builder(), mode);
100    }
101
102    // Internal constructor for testing.
103    Builder(AndroidApp app, CompilationMode mode) {
104      this(AndroidApp.builder(app), mode);
105    }
106
107    private Builder(AndroidApp.Builder builder, CompilationMode mode) {
108      assert mode != null;
109      this.app = builder;
110      this.mode = mode;
111    }
112
113    abstract B self();
114
115    public abstract C build() throws CompilationException, IOException;
116
117    // Internal accessor for the application resources.
118    AndroidApp.Builder getAppBuilder() {
119      return app;
120    }
121
122    /** Add program file resources. */
123    public B addProgramFiles(Path... files) throws IOException {
124      app.addProgramFiles(files);
125      return self();
126    }
127
128    /** Add program file resources. */
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. */
135    public B addClasspathFiles(Path... files) throws IOException {
136      app.addClasspathFiles(files);
137      return self();
138    }
139
140    /** Add classpath file resources. */
141    public B addClasspathFiles(Collection<Path> files) throws IOException {
142      app.addClasspathFiles(files);
143      return self();
144    }
145
146    /** Add library file resources. */
147    public B addLibraryFiles(Path... files) throws IOException {
148      app.addLibraryFiles(files);
149      return self();
150    }
151
152    /** Add library file resources. */
153    public B addLibraryFiles(Collection<Path> files) throws IOException {
154      app.addLibraryFiles(files);
155      return self();
156    }
157
158    /** Add Java-bytecode program-data. */
159    public B addClassProgramData(byte[]... data) {
160      app.addClassProgramData(data);
161      return self();
162    }
163
164    /** Add Java-bytecode program-data. */
165    public B addClassProgramData(Collection<byte[]> data) {
166      app.addClassProgramData(data);
167      return self();
168    }
169
170    /** Add dex program-data. */
171    public B addDexProgramData(byte[]... data) {
172      app.addDexProgramData(data);
173      return self();
174    }
175
176    /** Add dex program-data. */
177    public B addDexProgramData(Collection<byte[]> data) {
178      app.addDexProgramData(data);
179      return self();
180    }
181
182    /** Get current compilation mode. */
183    public CompilationMode getMode() {
184      return mode;
185    }
186
187    /** Set compilation 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. */
195    public Path getOutputPath() {
196      return outputPath;
197    }
198
199    /** Get the output mode. */
200    public OutputMode getOutputMode() {
201      return outputMode;
202    }
203
204    /** Set an output path. Must be an existing directory or a zip file. */
205    public B setOutputPath(Path outputPath) {
206      this.outputPath = outputPath;
207      return self();
208    }
209
210    /** Set an output mode. */
211    public B setOutputMode(OutputMode outputMode) {
212      this.outputMode = outputMode;
213      return self();
214    }
215
216    /** Get the minimum API level (aka SDK version). */
217    public int getMinApiLevel() {
218      return minApiLevel;
219    }
220
221    /** Set the minimum required API level (aka SDK version). */
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. */
229    public B setMainDexListFile(Path file) {
230      app.setMainDexListFile(file);
231      return self();
232    }
233
234    /** True if the print-help flag is enabled. */
235    public boolean isPrintHelp() {
236      return printHelp;
237    }
238
239    /** Set the value of the print-help flag. */
240    public B setPrintHelp(boolean printHelp) {
241      this.printHelp = printHelp;
242      return self();
243    }
244
245    /** True if the print-version flag is enabled. */
246    public boolean isPrintVersion() {
247      return printVersion;
248    }
249
250    /** Set the value of the print-version flag. */
251    public B setPrintVersion(boolean printVersion) {
252      this.printVersion = printVersion;
253      return self();
254    }
255
256    protected void validate() throws CompilationException {
257      FileUtils.validateOutputFile(outputPath);
258    }
259  }
260}
261