Dump all input when dumpInputToFile is set
We will now also dump library input, classpath input, proguard config and the version
Change-Id: If234b027cd28104df67f4da4e524eced53b9e270
diff --git a/src/main/java/com/android/tools/r8/ClassFileConsumer.java b/src/main/java/com/android/tools/r8/ClassFileConsumer.java
index f940c29..18f68ba 100644
--- a/src/main/java/com/android/tools/r8/ClassFileConsumer.java
+++ b/src/main/java/com/android/tools/r8/ClassFileConsumer.java
@@ -3,24 +3,19 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8;
-import static com.android.tools.r8.utils.FileUtils.CLASS_EXTENSION;
-
import com.android.tools.r8.utils.ArchiveBuilder;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.DirectoryBuilder;
import com.android.tools.r8.utils.OutputBuilder;
import com.android.tools.r8.utils.ZipUtils;
-import com.google.common.io.ByteStreams;
import com.google.common.io.Closer;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
-import java.util.Iterator;
import java.util.List;
import java.util.Set;
-import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
@@ -123,7 +118,7 @@
@Override
public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) {
super.accept(data, descriptor, handler);
- outputBuilder.addFile(getClassFileName(descriptor), data, handler);
+ outputBuilder.addFile(DescriptorUtils.getClassFileName(descriptor), data, handler);
}
@Override
@@ -147,11 +142,6 @@
return outputBuilder.getPath();
}
- private static String getClassFileName(String classDescriptor) {
- assert classDescriptor != null && DescriptorUtils.isClassDescriptor(classDescriptor);
- return DescriptorUtils.getClassBinaryNameFromDescriptor(classDescriptor) + CLASS_EXTENSION;
- }
-
public static void writeResources(
Path archive, List<ProgramResource> resources, Set<DataEntryResource> dataResources)
throws IOException, ResourceException {
@@ -159,22 +149,11 @@
new OpenOption[] {StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING};
try (Closer closer = Closer.create()) {
try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(archive, options))) {
- for (ProgramResource resource : resources) {
- assert resource.getClassDescriptors().size() == 1;
- Iterator<String> iterator = resource.getClassDescriptors().iterator();
- String className = iterator.next();
- String entryName = getClassFileName(className);
- byte[] bytes = ByteStreams.toByteArray(closer.register(resource.getByteStream()));
- ZipUtils.writeToZipStream(out, entryName, bytes, ZipEntry.DEFLATED);
- }
- for (DataEntryResource dataResource : dataResources) {
- String entryName = dataResource.getName();
- byte[] bytes = ByteStreams.toByteArray(closer.register(dataResource.getByteStream()));
- ZipUtils.writeToZipStream(out, entryName, bytes, ZipEntry.DEFLATED);
- }
+ ZipUtils.writeResourcesToZip(resources, dataResources, closer, out);
}
}
}
+
}
/** Directory consumer to write program resources to a directory. */
@@ -210,7 +189,7 @@
@Override
public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) {
super.accept(data, descriptor, handler);
- outputBuilder.addFile(ArchiveConsumer.getClassFileName(descriptor), data, handler);
+ outputBuilder.addFile(DescriptorUtils.getClassFileName(descriptor), data, handler);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
index d6a9696..6e95cac 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -9,14 +9,15 @@
import static com.android.tools.r8.utils.ExceptionUtils.unwrapExecutionException;
import static com.android.tools.r8.utils.InternalOptions.ASM_VERSION;
-import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.ClassFileResourceProvider;
+import com.android.tools.r8.DataEntryResource;
import com.android.tools.r8.DataResourceProvider;
import com.android.tools.r8.ProgramResource;
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.ProgramResourceProvider;
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.StringResource;
+import com.android.tools.r8.Version;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.ClassKind;
import com.android.tools.r8.graph.DexApplication;
@@ -42,21 +43,30 @@
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
+import com.android.tools.r8.utils.ZipUtils;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.ByteStreams;
+import com.google.common.io.Closer;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.OpenOption;
import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Queue;
+import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
import org.objectweb.asm.ClassVisitor;
public class ApplicationReader {
@@ -151,34 +161,108 @@
}
private void dumpInputToFile() throws IOException {
- List<ProgramResource> programResourcesWithDescriptors = new ArrayList<>();
try {
- for (ProgramResourceProvider programResourceProvider : inputApp
- .getProgramResourceProviders()) {
- for (ProgramResource programResource : programResourceProvider.getProgramResources()) {
- if (programResource.getKind() != Kind.CF) {
- continue;
+ List<ProgramResourceProvider> programResourceProviders =
+ inputApp.getProgramResourceProviders();
+ Set<DataEntryResource> dataEntryResources = inputApp.getDataEntryResourcesForTesting();
+ List<ProgramResource> programResourcesWithDescriptors = new ArrayList<>();
+ for (ProgramResourceProvider programResourceProvider : programResourceProviders) {
+ addProgramResourcesWithDescriptor(
+ programResourcesWithDescriptors, programResourceProvider.getProgramResources());
+ }
+
+ List<ProgramResource> libraryProgramResourcesWithDescriptors =
+ getProgramResourcesWithDescriptors(inputApp.getLibraryResourceProviders());
+
+ List<ProgramResource> classpathProgramResourcesWithDescriptors =
+ getProgramResourcesWithDescriptors(inputApp.getClasspathResourceProviders());
+
+ OpenOption[] openOptions =
+ new OpenOption[] {StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING};
+ try (Closer closer = Closer.create()) {
+ try (ZipOutputStream out =
+ new ZipOutputStream(
+ Files.newOutputStream(Paths.get(options.dumpInputToFile), openOptions))) {
+ writeToZip(
+ dataEntryResources, programResourcesWithDescriptors, closer, out, "program.jar");
+ writeToZip(
+ ImmutableSet.of(),
+ libraryProgramResourcesWithDescriptors,
+ closer,
+ out,
+ "library.jar");
+ writeToZip(
+ ImmutableSet.of(),
+ classpathProgramResourcesWithDescriptors,
+ closer,
+ out,
+ "classpath.jar");
+ if (options.hasProguardConfiguration()) {
+ String proguardConfig = options.getProguardConfiguration().getParsedConfiguration();
+ ZipUtils.writeToZipStream(
+ out, "proguard.config", proguardConfig.getBytes(), ZipEntry.DEFLATED);
}
- try (InputStream inputStream = programResource.getByteStream()) {
- byte[] bytes = ByteStreams.toByteArray(inputStream);
- String descriptor = extractClassInternalType(bytes);
- programResourcesWithDescriptors.add(
- ProgramResource.fromBytes(
- programResource.getOrigin(),
- programResource.getKind(),
- bytes,
- ImmutableSet.of(descriptor)));
- }
+
+ ZipUtils.writeToZipStream(
+ out, "r8-version", Version.getVersionString().getBytes(), ZipEntry.DEFLATED);
}
}
- ClassFileConsumer.ArchiveConsumer.writeResources(
- Paths.get(options.dumpInputToFile),
- programResourcesWithDescriptors, inputApp.getDataEntryResourcesForTesting());
} catch (ResourceException e) {
options.reporter.fatalError("Failed to write input:" + e.getMessage());
}
}
+ private static void writeToZip(
+ Set<DataEntryResource> dataEntryResources,
+ List<ProgramResource> programResourcesWithDescriptors,
+ Closer closer,
+ ZipOutputStream out,
+ String entry)
+ throws IOException, ResourceException {
+ try (ByteArrayOutputStream programByteStream = new ByteArrayOutputStream()) {
+ try (ZipOutputStream archiveOutputStream = new ZipOutputStream(programByteStream)) {
+ ZipUtils.writeResourcesToZip(
+ programResourcesWithDescriptors, dataEntryResources, closer, archiveOutputStream);
+ }
+ ZipUtils.writeToZipStream(out, entry, programByteStream.toByteArray(), ZipEntry.DEFLATED);
+ }
+ }
+
+ private static List<ProgramResource> getProgramResourcesWithDescriptors(
+ List<ClassFileResourceProvider> classFileResourceProviders)
+ throws IOException, ResourceException {
+ ArrayList<ProgramResource> programResourcesWithDescriptors = new ArrayList<>();
+ for (ClassFileResourceProvider libraryResourceProvider : classFileResourceProviders) {
+ List<ProgramResource> programResources = new ArrayList<>();
+ for (String classDescriptor : libraryResourceProvider.getClassDescriptors()) {
+ programResources.add(libraryResourceProvider.getProgramResource(classDescriptor));
+ }
+ addProgramResourcesWithDescriptor(programResourcesWithDescriptors, programResources);
+ }
+ return programResourcesWithDescriptors;
+ }
+
+ private static void addProgramResourcesWithDescriptor(
+ List<ProgramResource> programResourcesWithDescriptors,
+ Collection<ProgramResource> programResources)
+ throws IOException, ResourceException {
+ for (ProgramResource programResource : programResources) {
+ if (programResource.getKind() != Kind.CF) {
+ continue;
+ }
+ try (InputStream inputStream = programResource.getByteStream()) {
+ byte[] bytes = ByteStreams.toByteArray(inputStream);
+ String descriptor = extractClassInternalType(bytes);
+ programResourcesWithDescriptors.add(
+ ProgramResource.fromBytes(
+ programResource.getOrigin(),
+ programResource.getKind(),
+ bytes,
+ ImmutableSet.of(descriptor)));
+ }
+ }
+ }
+
private static String extractClassInternalType(byte[] bytes) throws IOException {
class ClassNameExtractor extends ClassVisitor {
private String className;
diff --git a/src/main/java/com/android/tools/r8/utils/DescriptorUtils.java b/src/main/java/com/android/tools/r8/utils/DescriptorUtils.java
index ba9af9d..af056a8 100644
--- a/src/main/java/com/android/tools/r8/utils/DescriptorUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/DescriptorUtils.java
@@ -444,4 +444,9 @@
assert isValidJavaType(typeName);
return typeName.replace(JAVA_PACKAGE_SEPARATOR, DESCRIPTOR_PACKAGE_SEPARATOR) + ".class";
}
+
+ public static String getClassFileName(String classDescriptor) {
+ assert classDescriptor != null && isClassDescriptor(classDescriptor);
+ return getClassBinaryNameFromDescriptor(classDescriptor) + CLASS_EXTENSION;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/utils/ZipUtils.java b/src/main/java/com/android/tools/r8/utils/ZipUtils.java
index da87e2b..89ef8f3 100644
--- a/src/main/java/com/android/tools/r8/utils/ZipUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ZipUtils.java
@@ -8,8 +8,12 @@
import static com.android.tools.r8.utils.FileUtils.MODULE_INFO_CLASS;
import com.android.tools.r8.ByteDataView;
+import com.android.tools.r8.DataEntryResource;
+import com.android.tools.r8.ProgramResource;
+import com.android.tools.r8.ResourceException;
import com.android.tools.r8.errors.CompilationError;
import com.google.common.io.ByteStreams;
+import com.google.common.io.Closer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -19,7 +23,9 @@
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.Iterator;
import java.util.List;
+import java.util.Set;
import java.util.function.Predicate;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
@@ -28,6 +34,27 @@
public class ZipUtils {
+ public static void writeResourcesToZip(
+ List<ProgramResource> resources,
+ Set<DataEntryResource> dataResources,
+ Closer closer,
+ ZipOutputStream out)
+ throws IOException, ResourceException {
+ for (ProgramResource resource : resources) {
+ assert resource.getClassDescriptors().size() == 1;
+ Iterator<String> iterator = resource.getClassDescriptors().iterator();
+ String className = iterator.next();
+ String entryName = DescriptorUtils.getClassFileName(className);
+ byte[] bytes = ByteStreams.toByteArray(closer.register(resource.getByteStream()));
+ writeToZipStream(out, entryName, bytes, ZipEntry.DEFLATED);
+ }
+ for (DataEntryResource dataResource : dataResources) {
+ String entryName = dataResource.getName();
+ byte[] bytes = ByteStreams.toByteArray(closer.register(dataResource.getByteStream()));
+ writeToZipStream(out, entryName, bytes, ZipEntry.DEFLATED);
+ }
+ }
+
public interface OnEntryHandler {
void onEntry(ZipEntry entry, InputStream input) throws IOException;
}
diff --git a/src/test/java/com/android/tools/r8/R8EntryPointTests.java b/src/test/java/com/android/tools/r8/R8EntryPointTests.java
index 0bbc7bc..553ff0e 100644
--- a/src/test/java/com/android/tools/r8/R8EntryPointTests.java
+++ b/src/test/java/com/android/tools/r8/R8EntryPointTests.java
@@ -9,13 +9,20 @@
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.ZipUtils;
+import com.android.tools.r8.utils.ZipUtils.OnEntryHandler;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
+import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.zip.ZipEntry;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -173,6 +180,53 @@
}
@Test
+ public void testDumpInputs() throws IOException {
+ Path out = temp.newFile("dex.zip").toPath();
+ Path dump = temp.newFile("dump.zip").toPath();
+ ProcessResult r8 =
+ ToolHelper.forkR8WithJavaOptions(
+ Paths.get("."),
+ ImmutableList.of("-Dcom.android.tools.r8.dumpinputtofile=" + dump.toString()),
+ "--lib",
+ ToolHelper.getDefaultAndroidJar().toString(),
+ "--dex",
+ "--output",
+ out.toString(),
+ "--pg-conf",
+ PROGUARD_FLAGS.toString(),
+ "--pg-conf",
+ testFlags.toString(),
+ INPUT_JAR.toString());
+
+ List<ZipEntry> entries = new ArrayList<>();
+ ZipUtils.iter(
+ dump.toString(),
+ new OnEntryHandler() {
+ @Override
+ public void onEntry(ZipEntry entry, InputStream input) throws IOException {
+ entries.add(entry);
+ }
+ });
+ Assert.assertTrue(hasEntry(entries, "program.jar"));
+ Assert.assertTrue(hasEntry(entries, "library.jar"));
+ Assert.assertTrue(hasEntry(entries, "classpath.jar"));
+ Assert.assertTrue(hasEntry(entries, "proguard.config"));
+ Assert.assertTrue(hasEntry(entries, "r8-version"));
+ // When dumping the inputs we throw an error in the program to exit early.
+ Assert.assertNotEquals(0, r8.exitCode);
+ }
+
+ private boolean hasEntry(Collection<ZipEntry> entries, String name) {
+ for (ZipEntry entry : entries) {
+ if (entry.getName().equals(name)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Test
public void testSpecifyDexAndClassfileNotAllowed() throws IOException, InterruptedException {
Path out = temp.newFile("dex.zip").toPath();
ProcessResult r8 =
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 84e8cc9..d363c34 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -1353,6 +1353,12 @@
return forkJava(dir, R8.class, args);
}
+ public static ProcessResult forkR8WithJavaOptions(
+ Path dir, List<String> javaOptions, String... args) throws IOException {
+ String r8Jar = R8_JAR.toAbsolutePath().toString();
+ return forkJavaWithJarAndJavaOptions(dir, r8Jar, Arrays.asList(args), javaOptions);
+ }
+
public static ProcessResult forkR8Jar(Path dir, String... args)
throws IOException, InterruptedException {
String r8Jar = R8_JAR.toAbsolutePath().toString();
@@ -1379,14 +1385,23 @@
private static ProcessResult forkJavaWithJar(Path dir, String jarPath, List<String> args)
throws IOException {
- List<String> command = new ImmutableList.Builder<String>()
- .add(getJavaExecutable())
- .add("-jar").add(jarPath)
- .addAll(args)
- .build();
+ return forkJavaWithJarAndJavaOptions(dir, jarPath, args, ImmutableList.of());
+ }
+
+ private static ProcessResult forkJavaWithJarAndJavaOptions(
+ Path dir, String jarPath, List<String> args, List<String> javaOptions) throws IOException {
+ List<String> command =
+ new ImmutableList.Builder<String>()
+ .add(getJavaExecutable())
+ .addAll(javaOptions)
+ .add("-jar")
+ .add(jarPath)
+ .addAll(args)
+ .build();
return runProcess(new ProcessBuilder(command).directory(dir.toFile()));
}
+
private static ProcessResult forkJava(Path dir, Class clazz, List<String> args)
throws IOException {
List<String> command = new ImmutableList.Builder<String>()