Change D8 and R8 to output an empty zip when there are no bytecode in the input.
R=sgjesse@google.com, zerny@google.com
Bug: 79987419
Change-Id: I7a3c9096d09c2ca671817449668e2e5bd437d3fa
diff --git a/src/main/java/com/android/tools/r8/ClassFileConsumer.java b/src/main/java/com/android/tools/r8/ClassFileConsumer.java
index 6d7ad87..6c9a286 100644
--- a/src/main/java/com/android/tools/r8/ClassFileConsumer.java
+++ b/src/main/java/com/android/tools/r8/ClassFileConsumer.java
@@ -8,7 +8,6 @@
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.ExceptionDiagnostic;
import com.android.tools.r8.utils.OutputBuilder;
import com.android.tools.r8.utils.ZipUtils;
import com.google.common.io.ByteStreams;
@@ -132,11 +131,7 @@
@Override
public void finished(DiagnosticsHandler handler) {
super.finished(handler);
- try {
- outputBuilder.close();
- } catch (IOException e) {
- handler.error(new ExceptionDiagnostic(e, outputBuilder.getOrigin()));
- }
+ outputBuilder.close(handler);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java b/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java
index ca86c70..f1c0fac 100644
--- a/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java
+++ b/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java
@@ -8,7 +8,6 @@
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.ExceptionDiagnostic;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.OutputBuilder;
import com.android.tools.r8.utils.ZipUtils;
@@ -153,11 +152,7 @@
@Override
public void finished(DiagnosticsHandler handler) {
super.finished(handler);
- try {
- outputBuilder.close();
- } catch (IOException e) {
- handler.error(new ExceptionDiagnostic(e, outputBuilder.getOrigin()));
- }
+ outputBuilder.close(handler);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/DexIndexedConsumer.java b/src/main/java/com/android/tools/r8/DexIndexedConsumer.java
index f26ab73..3bbab64 100644
--- a/src/main/java/com/android/tools/r8/DexIndexedConsumer.java
+++ b/src/main/java/com/android/tools/r8/DexIndexedConsumer.java
@@ -156,11 +156,7 @@
@Override
public void finished(DiagnosticsHandler handler) {
super.finished(handler);
- try {
- outputBuilder.close();
- } catch (IOException e) {
- handler.error(new ExceptionDiagnostic(e, outputBuilder.getOrigin()));
- }
+ outputBuilder.close(handler);
}
public static void writeResources(Path archive, List<ProgramResource> resources)
@@ -242,11 +238,7 @@
@Override
public void finished(DiagnosticsHandler handler) {
super.finished(handler);
- try {
- outputBuilder.close();
- } catch (IOException e) {
- handler.error(new ExceptionDiagnostic(e, outputBuilder.getOrigin()));
- }
+ outputBuilder.close(handler);
}
private synchronized void prepareDirectory() throws IOException {
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index 127ec43..9721d3b 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -199,7 +199,6 @@
// Use a linked hash map as the order matters when addDexProgramData is called below.
Map<VirtualFile, Future<ObjectToOffsetMapping>> offsetMappingFutures = new LinkedHashMap<>();
for (VirtualFile newFile : distribute(executorService)) {
- assert !newFile.isEmpty();
if (!newFile.isEmpty()) {
offsetMappingFutures
.put(newFile, executorService.submit(() -> {
diff --git a/src/main/java/com/android/tools/r8/utils/ArchiveBuilder.java b/src/main/java/com/android/tools/r8/utils/ArchiveBuilder.java
index cd21d17..25512f7 100644
--- a/src/main/java/com/android/tools/r8/utils/ArchiveBuilder.java
+++ b/src/main/java/com/android/tools/r8/utils/ArchiveBuilder.java
@@ -35,31 +35,38 @@
@Override
public synchronized void open() {
assert !closed;
- openCount ++;
+ openCount++;
}
@Override
- public synchronized void close() throws IOException {
+ public synchronized void close(DiagnosticsHandler handler) {
assert !closed;
openCount--;
if (openCount == 0) {
closed = true;
- if (stream != null) {
- stream.close();
+ try {
+ getStreamRaw().close();
stream = null;
+ } catch (IOException e) {
+ handler.error(new ExceptionDiagnostic(e, origin));
}
}
}
+ private ZipOutputStream getStreamRaw() throws IOException {
+ if (stream != null) {
+ return stream;
+ }
+ return new ZipOutputStream(Files.newOutputStream(
+ archive, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING));
+ }
+
/** Get or open the zip output stream. */
private synchronized ZipOutputStream getStream(DiagnosticsHandler handler) {
assert !closed;
if (stream == null) {
try {
- stream =
- new ZipOutputStream(
- Files.newOutputStream(
- archive, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING));
+ getStreamRaw();
} catch (IOException e) {
handler.error(new ExceptionDiagnostic(e, origin));
}
diff --git a/src/main/java/com/android/tools/r8/utils/DirectoryBuilder.java b/src/main/java/com/android/tools/r8/utils/DirectoryBuilder.java
index 2dc4a2d..2058d39 100644
--- a/src/main/java/com/android/tools/r8/utils/DirectoryBuilder.java
+++ b/src/main/java/com/android/tools/r8/utils/DirectoryBuilder.java
@@ -30,7 +30,7 @@
}
@Override
- public void close() {
+ public void close(DiagnosticsHandler handler) {
}
@Override
diff --git a/src/main/java/com/android/tools/r8/utils/OutputBuilder.java b/src/main/java/com/android/tools/r8/utils/OutputBuilder.java
index 27d07c4..9237485 100644
--- a/src/main/java/com/android/tools/r8/utils/OutputBuilder.java
+++ b/src/main/java/com/android/tools/r8/utils/OutputBuilder.java
@@ -7,14 +7,15 @@
import com.android.tools.r8.DataEntryResource;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.origin.Origin;
-import java.io.Closeable;
import java.nio.file.Path;
-public interface OutputBuilder extends Closeable {
+public interface OutputBuilder {
char NAME_SEPARATOR = '/';
void open();
+ void close(DiagnosticsHandler handler);
+
void addDirectory(String name, DiagnosticsHandler handler);
void addFile(String name, DataEntryResource content, DiagnosticsHandler handler);
diff --git a/src/test/java/com/android/tools/r8/D8CommandTest.java b/src/test/java/com/android/tools/r8/D8CommandTest.java
index dc16cac..a11c960 100644
--- a/src/test/java/com/android/tools/r8/D8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/D8CommandTest.java
@@ -418,6 +418,17 @@
.build()));
}
+ @Test
+ public void noInputOutputsEmptyZip() throws CompilationFailedException, IOException {
+ Path emptyZip = temp.getRoot().toPath().resolve("empty.zip");
+ D8.run(
+ D8Command.builder()
+ .setOutput(emptyZip, OutputMode.DexIndexed)
+ .build());
+ assertTrue(Files.exists(emptyZip));
+ assertEquals(0, new ZipFile(emptyZip.toFile()).size());
+ }
+
private D8Command parse(String... args) throws CompilationFailedException {
return D8Command.parse(args, EmbeddedOrigin.INSTANCE).build();
}
diff --git a/src/test/java/com/android/tools/r8/R8CommandTest.java b/src/test/java/com/android/tools/r8/R8CommandTest.java
index a89cbd4..a7c7e02 100644
--- a/src/test/java/com/android/tools/r8/R8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/R8CommandTest.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.origin.EmbeddedOrigin;
import com.android.tools.r8.utils.FileUtils;
import com.google.common.collect.ImmutableList;
+import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -21,6 +22,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.zip.ZipFile;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -428,6 +430,17 @@
assertTrue(result.stdout.contains("-printconfiguration"));
}
+ @Test
+ public void noInputOutputsEmptyZip() throws CompilationFailedException, IOException {
+ Path emptyZip = temp.getRoot().toPath().resolve("empty.zip");
+ R8.run(
+ R8Command.builder()
+ .setOutput(emptyZip, OutputMode.DexIndexed)
+ .build());
+ assertTrue(Files.exists(emptyZip));
+ assertEquals(0, new ZipFile(emptyZip.toFile()).size());
+ }
+
private R8Command parse(String... args) throws CompilationFailedException {
return R8Command.parse(args, EmbeddedOrigin.INSTANCE).build();
}