Support dump in TraceReferences
Change-Id: I06cba6273ca5695a9fbaa4f98f8db08531403a01
diff --git a/src/main/java/com/android/tools/r8/dex/Marker.java b/src/main/java/com/android/tools/r8/dex/Marker.java
index 911789d..4367a38 100644
--- a/src/main/java/com/android/tools/r8/dex/Marker.java
+++ b/src/main/java/com/android/tools/r8/dex/Marker.java
@@ -33,7 +33,8 @@
D8,
R8,
L8,
- Relocator;
+ Relocator,
+ TraceReferences;
public static Tool[] valuesR8andD8() {
return new Tool[] {Tool.D8, Tool.R8};
diff --git a/src/main/java/com/android/tools/r8/dump/DumpOptions.java b/src/main/java/com/android/tools/r8/dump/DumpOptions.java
index 27dddcc..ef3a443 100644
--- a/src/main/java/com/android/tools/r8/dump/DumpOptions.java
+++ b/src/main/java/com/android/tools/r8/dump/DumpOptions.java
@@ -46,6 +46,7 @@
private static final String ENABLE_MISSING_LIBRARY_API_MODELING =
"enable-missing-library-api-modeling";
private static final String ANDROID_PLATFORM_BUILD = "android-platform-build";
+ private static final String TRACE_REFERENCES_CONSUMER = "trace_references_consumer";
private final Tool tool;
private final CompilationMode compilationMode;
@@ -70,6 +71,9 @@
private final Map<String, String> systemProperties;
+ // TraceReferences only.
+ private final String traceReferencesConsumer;
+
// Reporting only.
private final boolean dumpInputToFile;
@@ -93,7 +97,8 @@
boolean enableMissingLibraryApiModeling,
boolean isAndroidPlatformBuild,
Map<String, String> systemProperties,
- boolean dumpInputToFile) {
+ boolean dumpInputToFile,
+ String traceReferencesConsumer) {
this.tool = tool;
this.compilationMode = compilationMode;
this.minApi = minAPI;
@@ -114,6 +119,7 @@
this.isAndroidPlatformBuild = isAndroidPlatformBuild;
this.systemProperties = systemProperties;
this.dumpInputToFile = dumpInputToFile;
+ this.traceReferencesConsumer = traceReferencesConsumer;
}
public String getBuildPropertiesFileContent() {
@@ -126,29 +132,33 @@
public Map<String, String> getBuildProperties() {
Map<String, String> buildProperties = new LinkedHashMap<>();
addDumpEntry(buildProperties, TOOL_KEY, tool.name());
- // We keep the following values for backward compatibility.
- addDumpEntry(
- buildProperties,
- MODE_KEY,
- compilationMode == CompilationMode.DEBUG ? DEBUG_MODE_VALUE : RELEASE_MODE_VALUE);
- addDumpEntry(buildProperties, MIN_API_KEY, minApi);
- addDumpEntry(
- buildProperties, OPTIMIZE_MULTIDEX_FOR_LINEAR_ALLOC_KEY, optimizeMultidexForLinearAlloc);
if (threadCount != ThreadUtils.NOT_SPECIFIED) {
addDumpEntry(buildProperties, THREAD_COUNT_KEY, threadCount);
}
- addDumpEntry(buildProperties, DESUGAR_STATE_KEY, desugarState);
- addDumpEntry(
- buildProperties, ENABLE_MISSING_LIBRARY_API_MODELING, enableMissingLibraryApiModeling);
- if (isAndroidPlatformBuild) {
- addDumpEntry(buildProperties, ANDROID_PLATFORM_BUILD, isAndroidPlatformBuild);
+ if (tool != Tool.TraceReferences) {
+ // We keep the following values for backward compatibility.
+ addDumpEntry(
+ buildProperties,
+ MODE_KEY,
+ compilationMode == CompilationMode.DEBUG ? DEBUG_MODE_VALUE : RELEASE_MODE_VALUE);
+ addDumpEntry(buildProperties, MIN_API_KEY, minApi);
+ addDumpEntry(
+ buildProperties, OPTIMIZE_MULTIDEX_FOR_LINEAR_ALLOC_KEY, optimizeMultidexForLinearAlloc);
+ addDumpEntry(buildProperties, DESUGAR_STATE_KEY, desugarState);
+ addDumpEntry(
+ buildProperties, ENABLE_MISSING_LIBRARY_API_MODELING, enableMissingLibraryApiModeling);
+ if (isAndroidPlatformBuild) {
+ addDumpEntry(buildProperties, ANDROID_PLATFORM_BUILD, isAndroidPlatformBuild);
+ }
+ addOptionalDumpEntry(buildProperties, INTERMEDIATE_KEY, intermediate);
+ addOptionalDumpEntry(buildProperties, INCLUDE_DATA_RESOURCES_KEY, includeDataResources);
+ addOptionalDumpEntry(buildProperties, TREE_SHAKING_KEY, treeShaking);
+ addOptionalDumpEntry(
+ buildProperties, FORCE_PROGUARD_COMPATIBILITY_KEY, forceProguardCompatibility);
+ } else {
+ addDumpEntry(buildProperties, TRACE_REFERENCES_CONSUMER, traceReferencesConsumer);
}
- addOptionalDumpEntry(buildProperties, INTERMEDIATE_KEY, intermediate);
- addOptionalDumpEntry(buildProperties, INCLUDE_DATA_RESOURCES_KEY, includeDataResources);
- addOptionalDumpEntry(buildProperties, TREE_SHAKING_KEY, treeShaking);
addOptionalDumpEntry(buildProperties, MINIFICATION_KEY, minification);
- addOptionalDumpEntry(
- buildProperties, FORCE_PROGUARD_COMPATIBILITY_KEY, forceProguardCompatibility);
ArrayList<String> sortedKeys = new ArrayList<>(systemProperties.keySet());
sortedKeys.sort(String::compareTo);
sortedKeys.forEach(
@@ -212,6 +222,9 @@
case FORCE_PROGUARD_COMPATIBILITY_KEY:
builder.setForceProguardCompatibility(Boolean.parseBoolean(value));
return;
+ case TRACE_REFERENCES_CONSUMER:
+ builder.setTraceReferencesConsumer(value);
+ return;
default:
if (key.startsWith(SYSTEM_PROPERTY_PREFIX)) {
builder.setSystemProperty(key.substring(SYSTEM_PROPERTY_PREFIX.length()), value);
@@ -311,6 +324,8 @@
private boolean enableMissingLibraryApiModeling = false;
private boolean isAndroidPlatformBuild = false;
+ private String traceReferencesConsumer = null;
+
private Map<String, String> systemProperties = new HashMap<>();
// Reporting only.
@@ -323,6 +338,11 @@
return this;
}
+ public Builder setTraceReferencesConsumer(String traceReferencesConsumer) {
+ this.traceReferencesConsumer = traceReferencesConsumer;
+ return this;
+ }
+
public Builder setCompilationMode(CompilationMode compilationMode) {
this.compilationMode = compilationMode;
return this;
@@ -456,7 +476,8 @@
enableMissingLibraryApiModeling,
isAndroidPlatformBuild,
systemProperties,
- dumpInputToFile);
+ dumpInputToFile,
+ traceReferencesConsumer);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/tracereferences/TraceReferences.java b/src/main/java/com/android/tools/r8/tracereferences/TraceReferences.java
index 1344816..416a9a4 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/TraceReferences.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/TraceReferences.java
@@ -28,10 +28,7 @@
public class TraceReferences {
public static void run(TraceReferencesCommand command) throws CompilationFailedException {
- InternalOptions options = new InternalOptions();
- options.loadAllClassDefinitions = true;
- ExceptionUtils.withCompilationHandler(
- command.getReporter(), () -> runInternal(command, options));
+ runForTesting(command, command.getInternalOptions());
}
private static void forEachDescriptor(ProgramResourceProvider provider, Consumer<String> consumer)
diff --git a/src/main/java/com/android/tools/r8/tracereferences/TraceReferencesCommand.java b/src/main/java/com/android/tools/r8/tracereferences/TraceReferencesCommand.java
index 9aff1d0..2635b95 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/TraceReferencesCommand.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/TraceReferencesCommand.java
@@ -18,12 +18,15 @@
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.ProgramResourceProvider;
import com.android.tools.r8.ResourceException;
+import com.android.tools.r8.dex.Marker.Tool;
+import com.android.tools.r8.dump.DumpOptions;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.utils.ArchiveResourceProvider;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.ExceptionUtils;
+import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.ImmutableList;
@@ -396,4 +399,21 @@
TraceReferencesConsumer getConsumer() {
return consumer;
}
+
+ InternalOptions getInternalOptions() {
+ InternalOptions options = new InternalOptions();
+ options.loadAllClassDefinitions = true;
+ TraceReferencesConsumer consumer = getConsumer();
+ DumpOptions.Builder builder =
+ DumpOptions.builder(Tool.TraceReferences)
+ .readCurrentSystemProperties()
+ // The behavior of TraceReferences greatly differs depending if we have a CheckConsumer
+ // or a KeepRules consumer. We log the consumer type and obfuscation if relevant.
+ .setTraceReferencesConsumer(consumer.getClass().getName());
+ if (consumer instanceof TraceReferencesKeepRules) {
+ builder.setMinification(((TraceReferencesKeepRules) consumer).allowObfuscation());
+ }
+ options.dumpOptions = builder.build();
+ return options;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/tracereferences/TraceReferencesKeepRules.java b/src/main/java/com/android/tools/r8/tracereferences/TraceReferencesKeepRules.java
index f648da4..52ea13c 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/TraceReferencesKeepRules.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/TraceReferencesKeepRules.java
@@ -40,6 +40,10 @@
this.allowObfuscation = allowObfuscation;
}
+ public boolean allowObfuscation() {
+ return allowObfuscation;
+ }
+
/**
* Builder for constructing a {@link TraceReferencesKeepRules].
*
diff --git a/src/test/java/com/android/tools/r8/tracereferences/TraceReferenceDumpInputsTest.java b/src/test/java/com/android/tools/r8/tracereferences/TraceReferenceDumpInputsTest.java
new file mode 100644
index 0000000..963c2e7
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/tracereferences/TraceReferenceDumpInputsTest.java
@@ -0,0 +1,123 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.tracereferences;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.StringConsumer.FileConsumer;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.DumpInputFlags;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.ZipUtils;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class TraceReferenceDumpInputsTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withSystemRuntime().build();
+ }
+
+ public TraceReferenceDumpInputsTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testDumpToDirectory() throws Exception {
+ Path dumpDir = temp.newFolder().toPath();
+ TraceReferencesKeepRules keepRulesConsumer =
+ TraceReferencesKeepRules.builder()
+ .setAllowObfuscation(true)
+ .setOutputConsumer(new FileConsumer(temp.newFile().toPath()))
+ .build();
+ TraceReferencesCommand command =
+ TraceReferencesCommand.builder()
+ .setConsumer(keepRulesConsumer)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.T))
+ .addTargetFiles(ToolHelper.getClassFileForTestClass(TestClass.class))
+ .addSourceFiles(ToolHelper.getClassFileForTestClass(OtherTestClass.class))
+ .build();
+ InternalOptions internalOptions = command.getInternalOptions();
+ internalOptions.setDumpInputFlags(DumpInputFlags.dumpToDirectory(dumpDir));
+ TraceReferences.runForTesting(command, internalOptions);
+ verifyDumpDirectory(dumpDir);
+ }
+
+ private void verifyDumpDirectory(Path dumpDir) throws IOException {
+ assertTrue(Files.isDirectory(dumpDir));
+ List<Path> paths = Files.walk(dumpDir, 1).collect(Collectors.toList());
+ boolean hasVerified = false;
+ for (Path path : paths) {
+ if (!path.equals(dumpDir)) {
+ verifyDump(path);
+ hasVerified = true;
+ }
+ }
+ assertTrue(hasVerified);
+ }
+
+ private void verifyDump(Path dumpFile) throws IOException {
+ assertTrue(Files.exists(dumpFile));
+ Path unzipped = temp.newFolder().toPath();
+ ZipUtils.unzip(dumpFile.toString(), unzipped.toFile());
+ assertTrue(Files.exists(unzipped.resolve("r8-version")));
+ assertTrue(Files.exists(unzipped.resolve("build.properties")));
+ assertTrue(Files.exists(unzipped.resolve("program.jar")));
+ assertTrue(Files.exists(unzipped.resolve("library.jar")));
+ assertTrue(Files.exists(unzipped.resolve("classpath.jar")));
+ contains(unzipped, "program.jar", OtherTestClass.class);
+ contains(unzipped, "classpath.jar", TestClass.class);
+ checkProperties(unzipped.resolve("build.properties"));
+ }
+
+ private void checkProperties(Path properties) throws IOException {
+ List<String> lines = Files.readAllLines(properties);
+ assertEquals(4, lines.size());
+ assertEquals("tool=TraceReferences", lines.get(0));
+ assertEquals(
+ "trace_references_consumer=com.android.tools.r8.tracereferences.TraceReferencesKeepRules",
+ lines.get(2));
+ assertEquals("minification=true", lines.get(3));
+ }
+
+ private void contains(Path unzipped, String jar, Class<?> clazz) throws IOException {
+ Set<String> entries = new HashSet<>();
+ ZipUtils.iter(unzipped.resolve(jar).toString(), (entry, input) -> entries.add(entry.getName()));
+ assertTrue(
+ entries.contains(
+ DescriptorUtils.getClassFileName(
+ DescriptorUtils.javaTypeToDescriptor(clazz.getTypeName()))));
+ }
+
+ static class TestClass {
+ public static void main(String[] args) {
+ System.out.println("Hello, world");
+ }
+ }
+
+ static class OtherTestClass {
+ public static void main(String[] args) {
+ TestClass.main(args);
+ }
+ }
+}