Add --output flag to LibraryAnalyzer and write protobuf
If no output path is given, print output to stdout.
Bug: b/479726064
Change-Id: I149971821a2666ec95b36960db34d8c6e7e0d38f
diff --git a/src/libanalyzer/java/com/android/tools/r8/libanalyzer/LibraryAnalyzer.java b/src/libanalyzer/java/com/android/tools/r8/libanalyzer/LibraryAnalyzer.java
index 59c5301..f31ddfa 100644
--- a/src/libanalyzer/java/com/android/tools/r8/libanalyzer/LibraryAnalyzer.java
+++ b/src/libanalyzer/java/com/android/tools/r8/libanalyzer/LibraryAnalyzer.java
@@ -11,6 +11,9 @@
import com.android.tools.r8.R8;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.keepanno.annotations.KeepForApi;
+import com.android.tools.r8.libanalyzer.proto.D8CompileResult;
+import com.android.tools.r8.libanalyzer.proto.LibraryAnalysisResult;
+import com.android.tools.r8.libanalyzer.proto.R8CompileResult;
import com.android.tools.r8.libanalyzer.utils.DexIndexedSizeConsumer;
import com.android.tools.r8.libanalyzer.utils.LibraryAnalyzerOptions;
import com.android.tools.r8.origin.CommandLineOrigin;
@@ -19,6 +22,10 @@
import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.ThreadUtils;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
import java.util.List;
import java.util.concurrent.ExecutorService;
@@ -82,17 +89,12 @@
}
private void run(ExecutorService executorService) {
- D8RunResult d8RunResult = runD8(executorService);
- R8RunResult r8RunResult = runR8(executorService);
- // TODO(b/479726064): Write to protobuf.
- System.out.println(
- "D8="
- + (d8RunResult != null ? d8RunResult.size : "N/A")
- + ", R8="
- + (r8RunResult != null ? r8RunResult.size : "N/A"));
+ InternalD8CompileResult d8CompileResult = runD8(executorService);
+ InternalR8CompileResult r8CompileResult = runR8(executorService);
+ writeAnalysisResult(d8CompileResult, r8CompileResult);
}
- private D8RunResult runD8(ExecutorService executorService) {
+ private InternalD8CompileResult runD8(ExecutorService executorService) {
DexIndexedSizeConsumer sizeConsumer = new DexIndexedSizeConsumer();
D8Command.Builder commandBuilder =
D8Command.builder(options.reporter).setProgramConsumer(sizeConsumer);
@@ -104,10 +106,10 @@
options.reporter.clearAbort();
return null;
}
- return new D8RunResult(sizeConsumer.size());
+ return new InternalD8CompileResult(sizeConsumer.size());
}
- private R8RunResult runR8(ExecutorService executorService) {
+ private InternalR8CompileResult runR8(ExecutorService executorService) {
DexIndexedSizeConsumer sizeConsumer = new DexIndexedSizeConsumer();
R8Command.Builder commandBuilder =
R8Command.builder(options.reporter)
@@ -121,7 +123,30 @@
options.reporter.clearAbort();
return null;
}
- return new R8RunResult(sizeConsumer.size());
+ return new InternalR8CompileResult(sizeConsumer.size());
+ }
+
+ private void writeAnalysisResult(
+ InternalD8CompileResult d8CompileResult, InternalR8CompileResult r8CompileResult) {
+ LibraryAnalysisResult.Builder resultBuilder = LibraryAnalysisResult.newBuilder();
+ if (d8CompileResult != null) {
+ resultBuilder.setD8CompileResult(
+ D8CompileResult.newBuilder().setSizeBytes(d8CompileResult.size).build());
+ }
+ if (r8CompileResult != null) {
+ resultBuilder.setR8CompileResult(
+ R8CompileResult.newBuilder().setSizeBytes(r8CompileResult.size).build());
+ }
+ LibraryAnalysisResult result = resultBuilder.build();
+ if (options.outputPath != null) {
+ try (OutputStream output = Files.newOutputStream(options.outputPath)) {
+ result.writeTo(output);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ } else {
+ System.out.println(result);
+ }
}
private void configure(BaseCompilerCommand.Builder<?, ?> commandBuilder) {
@@ -133,25 +158,25 @@
app.getLibraryResourceProviders().forEach(commandBuilder::addLibraryResourceProvider);
}
- private abstract static class RunResult {
+ private abstract static class CompileResult {
final int size;
- RunResult(int size) {
+ CompileResult(int size) {
this.size = size;
}
}
- private static class D8RunResult extends RunResult {
+ private static class InternalD8CompileResult extends CompileResult {
- D8RunResult(int size) {
+ InternalD8CompileResult(int size) {
super(size);
}
}
- private static class R8RunResult extends RunResult {
+ private static class InternalR8CompileResult extends CompileResult {
- R8RunResult(int size) {
+ InternalR8CompileResult(int size) {
super(size);
}
}
diff --git a/src/libanalyzer/java/com/android/tools/r8/libanalyzer/LibraryAnalyzerCommand.java b/src/libanalyzer/java/com/android/tools/r8/libanalyzer/LibraryAnalyzerCommand.java
index 61aacfb..0c1fa13 100644
--- a/src/libanalyzer/java/com/android/tools/r8/libanalyzer/LibraryAnalyzerCommand.java
+++ b/src/libanalyzer/java/com/android/tools/r8/libanalyzer/LibraryAnalyzerCommand.java
@@ -21,15 +21,21 @@
private final AndroidApp app;
private final AndroidApiLevel minApiLevel;
+ private final Path outputPath;
private final Reporter reporter;
private final int threadCount;
private final boolean printHelp;
private final boolean printVersion;
private LibraryAnalyzerCommand(
- AndroidApp app, AndroidApiLevel minApiLevel, Reporter reporter, int threadCount) {
+ AndroidApp app,
+ AndroidApiLevel minApiLevel,
+ Path outputPath,
+ Reporter reporter,
+ int threadCount) {
this.app = app;
this.minApiLevel = minApiLevel;
+ this.outputPath = outputPath;
this.reporter = reporter;
this.threadCount = threadCount;
this.printHelp = false;
@@ -39,6 +45,7 @@
private LibraryAnalyzerCommand(boolean printHelp, boolean printVersion) {
this.app = null;
this.minApiLevel = null;
+ this.outputPath = null;
this.reporter = new Reporter();
this.threadCount = ThreadUtils.NOT_SPECIFIED;
this.printHelp = printHelp;
@@ -50,7 +57,7 @@
}
LibraryAnalyzerOptions getInternalOptions() {
- return new LibraryAnalyzerOptions(minApiLevel, reporter, threadCount);
+ return new LibraryAnalyzerOptions(minApiLevel, outputPath, reporter, threadCount);
}
boolean isPrintHelp() {
@@ -73,6 +80,7 @@
private final AndroidApp.Builder appBuilder;
private AndroidApiLevel minApiLevel = AndroidApiLevel.getDefault();
+ private Path outputPath;
private final Reporter reporter;
private int threadCount;
@@ -98,6 +106,11 @@
return this;
}
+ public Builder setOutputPath(Path outputPath) {
+ this.outputPath = outputPath;
+ return this;
+ }
+
public Builder setMinApiLevel(int minMajorApiLevel, int minMinorApiLevel) {
return setMinApiLevel(AndroidApiLevel.getAndroidApiLevel(minMajorApiLevel, minMinorApiLevel));
}
@@ -127,13 +140,15 @@
return new LibraryAnalyzerCommand(printHelp, printVersion);
}
validate();
- return new LibraryAnalyzerCommand(appBuilder.build(), minApiLevel, reporter, threadCount);
+ return new LibraryAnalyzerCommand(
+ appBuilder.build(), minApiLevel, outputPath, reporter, threadCount);
}
private void validate() {
if (appBuilder.getProgramResourceProviders().isEmpty()) {
reporter.error("LibraryAnalyzer requires an input Android Archive (AAR).");
}
+ reporter.failIfPendingErrors();
}
}
}
diff --git a/src/libanalyzer/java/com/android/tools/r8/libanalyzer/LibraryAnalyzerCommandParser.java b/src/libanalyzer/java/com/android/tools/r8/libanalyzer/LibraryAnalyzerCommandParser.java
index 58acf50..2c91e96 100644
--- a/src/libanalyzer/java/com/android/tools/r8/libanalyzer/LibraryAnalyzerCommandParser.java
+++ b/src/libanalyzer/java/com/android/tools/r8/libanalyzer/LibraryAnalyzerCommandParser.java
@@ -5,6 +5,7 @@
import static com.android.tools.r8.BaseCompilerCommandParser.LIB_FLAG;
import static com.android.tools.r8.BaseCompilerCommandParser.MIN_API_FLAG;
+import static com.android.tools.r8.BaseCompilerCommandParser.OUTPUT_FLAG;
import static com.android.tools.r8.BaseCompilerCommandParser.THREAD_COUNT_FLAG;
import static com.android.tools.r8.BaseCompilerCommandParser.parsePositiveIntArgument;
@@ -26,7 +27,7 @@
private static final String AAR_FLAG = "--aar";
private static final Set<String> OPTIONS_WITH_ONE_PARAMETER =
- ImmutableSet.of(AAR_FLAG, LIB_FLAG, MIN_API_FLAG, THREAD_COUNT_FLAG);
+ ImmutableSet.of(AAR_FLAG, LIB_FLAG, MIN_API_FLAG, OUTPUT_FLAG, THREAD_COUNT_FLAG);
private static final String USAGE_MESSAGE =
StringUtils.lines(
@@ -35,6 +36,7 @@
" --aar <path> # Path to Android Archive (AAR) that should be analyzed.",
" --lib <path> # Path to file or JDK home to use as a library resource.",
" --min-api <major.minor> # Minimum API level to use for analysis.",
+ " --output <path> # Path where to write the analysis result (protobuf).",
" --thread-count <int> # Number of threads to use.",
" --help # Print this message.",
" --version # Print the version.");
@@ -72,6 +74,8 @@
builder.getAppBuilder(), nextArg, origin, reporter);
} else if (arg.equals(MIN_API_FLAG)) {
builder.setMinApiLevel(AndroidApiLevel.parseAndroidApiLevel(nextArg));
+ } else if (arg.equals(OUTPUT_FLAG)) {
+ builder.setOutputPath(Paths.get(nextArg));
} else if (arg.equals(THREAD_COUNT_FLAG)) {
parsePositiveIntArgument(
reporter::error, THREAD_COUNT_FLAG, nextArg, origin, builder::setThreadCount);
diff --git a/src/libanalyzer/java/com/android/tools/r8/libanalyzer/utils/LibraryAnalyzerOptions.java b/src/libanalyzer/java/com/android/tools/r8/libanalyzer/utils/LibraryAnalyzerOptions.java
index 180ddd5..ee053d9 100644
--- a/src/libanalyzer/java/com/android/tools/r8/libanalyzer/utils/LibraryAnalyzerOptions.java
+++ b/src/libanalyzer/java/com/android/tools/r8/libanalyzer/utils/LibraryAnalyzerOptions.java
@@ -6,17 +6,21 @@
import com.android.tools.r8.threading.ThreadingModule;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.Reporter;
+import java.nio.file.Path;
public class LibraryAnalyzerOptions {
public final AndroidApiLevel minApiLevel;
+ public final Path outputPath;
public final Reporter reporter;
public final int threadCount;
private ThreadingModule lazyThreadingModule = null;
- public LibraryAnalyzerOptions(AndroidApiLevel minApiLevel, Reporter reporter, int threadCount) {
+ public LibraryAnalyzerOptions(
+ AndroidApiLevel minApiLevel, Path outputPath, Reporter reporter, int threadCount) {
this.minApiLevel = minApiLevel;
+ this.outputPath = outputPath;
this.reporter = reporter;
this.threadCount = threadCount;
}
diff --git a/src/libanalyzer/proto/libraryanalysisresult.proto b/src/libanalyzer/proto/libraryanalysisresult.proto
index ba6c1c0..8783bc7 100644
--- a/src/libanalyzer/proto/libraryanalysisresult.proto
+++ b/src/libanalyzer/proto/libraryanalysisresult.proto
@@ -15,4 +15,15 @@
option java_package = "com.android.tools.r8.libanalyzer.proto";
// Analysis result produced by the library analyzer.
-message LibraryAnalysisResult {}
+message LibraryAnalysisResult {
+ D8CompileResult d8_compile_result = 1;
+ R8CompileResult r8_compile_result = 2;
+}
+
+message D8CompileResult {
+ uint32 size_bytes = 1;
+}
+
+message R8CompileResult {
+ uint32 size_bytes = 1;
+}
diff --git a/src/main/java/com/android/tools/r8/BaseCompilerCommandParser.java b/src/main/java/com/android/tools/r8/BaseCompilerCommandParser.java
index f8567c6..fabf62a 100644
--- a/src/main/java/com/android/tools/r8/BaseCompilerCommandParser.java
+++ b/src/main/java/com/android/tools/r8/BaseCompilerCommandParser.java
@@ -20,6 +20,7 @@
protected static final String BUILD_METADATA_OUTPUT_FLAG = "--build-metadata-output";
public static final String LIB_FLAG = "--lib";
public static final String MIN_API_FLAG = "--min-api";
+ public static final String OUTPUT_FLAG = "--output";
protected static final String STARTUP_PROFILE_FLAG = "--startup-profile";
public static final String THREAD_COUNT_FLAG = "--thread-count";
protected static final String MAP_DIAGNOSTICS = "--map-diagnostics";