Enable adding --classpath on commandline and in test builders
Change-Id: Ib054e22eb30ab2175344940e19f6d48a6de583b3
diff --git a/src/main/java/com/android/tools/r8/BaseCommand.java b/src/main/java/com/android/tools/r8/BaseCommand.java
index b7d6cfe..5eb8ce9 100644
--- a/src/main/java/com/android/tools/r8/BaseCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCommand.java
@@ -213,6 +213,28 @@
return self();
}
+ /** Add classpath file resources. */
+ public B addClasspathFiles(Path... files) {
+ guard(() -> Arrays.stream(files).forEach(this::addClasspathFile));
+ return self();
+ }
+
+ /** Add classpath file resources. */
+ public B addClasspathFiles(Collection<Path> files) {
+ guard(() -> files.forEach(this::addClasspathFile));
+ return self();
+ }
+
+ private void addClasspathFile(Path file) {
+ guard(() -> getAppBuilder().addClasspathFile(file));
+ }
+
+ /** Add classfile resources provider for class-path resources. */
+ public B addClasspathResourceProvider(ClassFileResourceProvider provider) {
+ guard(() -> getAppBuilder().addClasspathResourceProvider(provider));
+ return self();
+ }
+
/** Add Java-bytecode program-data. */
public B addClassProgramData(byte[] data, Origin origin) {
guard(() -> app.addClassProgramData(data, origin));
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 545e102..6bfcfe2 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import java.nio.file.Path;
-import java.util.Arrays;
import java.util.Collection;
/**
@@ -84,26 +83,22 @@
return self();
}
- /** Add classpath file resources. */
+ /** Add classpath file resources. These have @Override to ensure binary compatibility. */
+ @Override
public Builder addClasspathFiles(Path... files) {
- guard(() -> Arrays.stream(files).forEach(this::addClasspathFile));
- return self();
+ return super.addClasspathFiles(files);
}
/** Add classpath file resources. */
+ @Override
public Builder addClasspathFiles(Collection<Path> files) {
- guard(() -> files.forEach(this::addClasspathFile));
- return self();
- }
-
- private void addClasspathFile(Path file) {
- guard(() -> getAppBuilder().addClasspathFile(file));
+ return super.addClasspathFiles(files);
}
/** Add classfile resources provider for class-path resources. */
+ @Override
public Builder addClasspathResourceProvider(ClassFileResourceProvider provider) {
- guard(() -> getAppBuilder().addClasspathResourceProvider(provider));
- return self();
+ return super.addClasspathResourceProvider(provider);
}
/**
diff --git a/src/main/java/com/android/tools/r8/R8CommandParser.java b/src/main/java/com/android/tools/r8/R8CommandParser.java
index b91739a..6984283 100644
--- a/src/main/java/com/android/tools/r8/R8CommandParser.java
+++ b/src/main/java/com/android/tools/r8/R8CommandParser.java
@@ -19,6 +19,7 @@
ImmutableSet.of(
"--output",
"--lib",
+ "--classpath",
"--min-api",
"--main-dex-rules",
"--main-dex-list",
@@ -59,6 +60,7 @@
" --output <file> # Output result in <file>.",
" # <file> must be an existing directory or a zip file.",
" --lib <file> # Add <file> as a library resource.",
+ " --classpath <file> # Add <file> as a classpath resource.",
" --min-api <number> # Minimum Android API level compatibility, default: "
+ AndroidApiLevel.getDefault().getLevel()
+ ".",
@@ -178,6 +180,8 @@
state.outputPath = Paths.get(nextArg);
} else if (arg.equals("--lib")) {
builder.addLibraryFiles(Paths.get(nextArg));
+ } else if (arg.equals("--classpath")) {
+ builder.addClasspathFiles(Paths.get(nextArg));
} else if (arg.equals("--min-api")) {
if (state.hasDefinedApiLevel) {
builder.error(new StringDiagnostic("Cannot set multiple --min-api options", argsOrigin));
diff --git a/src/test/java/com/android/tools/r8/D8TestBuilder.java b/src/test/java/com/android/tools/r8/D8TestBuilder.java
index 5e450f0..00b8cd6 100644
--- a/src/test/java/com/android/tools/r8/D8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/D8TestBuilder.java
@@ -7,6 +7,8 @@
import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
+import java.nio.file.Path;
+import java.util.Collection;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -28,6 +30,18 @@
}
@Override
+ public D8TestBuilder addClasspathClasses(Collection<Class<?>> classes) {
+ builder.addClasspathResourceProvider(ClassFileResourceProviderFromClasses(classes));
+ return self();
+ }
+
+ @Override
+ public D8TestBuilder addClasspathFiles(Collection<Path> files) {
+ builder.addClasspathFiles(files);
+ return self();
+ }
+
+ @Override
D8TestCompileResult internalCompile(
Builder builder, Consumer<InternalOptions> optionsConsumer, Supplier<AndroidApp> app)
throws CompilationFailedException {
diff --git a/src/test/java/com/android/tools/r8/DXTestBuilder.java b/src/test/java/com/android/tools/r8/DXTestBuilder.java
index 8462f7b..84ecee1 100644
--- a/src/test/java/com/android/tools/r8/DXTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/DXTestBuilder.java
@@ -65,6 +65,16 @@
}
@Override
+ public DXTestBuilder addClasspathClasses(Collection<Class<?>> classes) {
+ throw new Unimplemented("No support for adding classpath data directly");
+ }
+
+ @Override
+ public DXTestBuilder addClasspathFiles(Collection<Path> files) {
+ throw new Unimplemented("No support for adding classpath data directly");
+ }
+
+ @Override
public DXTestBuilder addProgramClasses(Collection<Class<?>> classes) {
return addProgramClassFileData(
ListUtils.map(
diff --git a/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java b/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
index 0225784..3584faa 100644
--- a/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
@@ -188,6 +188,16 @@
}
@Override
+ public ExternalR8TestBuilder addClasspathClasses(Collection<Class<?>> classes) {
+ throw new Unimplemented("No support for adding classpath data directly");
+ }
+
+ @Override
+ public ExternalR8TestBuilder addClasspathFiles(Collection<Path> files) {
+ throw new Unimplemented("No support for adding classpath data directly");
+ }
+
+ @Override
public ExternalR8TestBuilder addKeepRuleFiles(List<Path> proguardConfigFiles) {
this.proguardConfigFiles.addAll(proguardConfigFiles);
return self();
diff --git a/src/test/java/com/android/tools/r8/ProguardTestBuilder.java b/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
index ac3b582..15200b5 100644
--- a/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
@@ -259,6 +259,16 @@
}
@Override
+ public ProguardTestBuilder addClasspathClasses(Collection<Class<?>> classes) {
+ throw new Unimplemented("No support for adding classpath data directly");
+ }
+
+ @Override
+ public ProguardTestBuilder addClasspathFiles(Collection<Path> files) {
+ throw new Unimplemented("No support for adding classpath data directly");
+ }
+
+ @Override
public ProguardTestBuilder setProgramConsumer(ProgramConsumer programConsumer) {
throw new Unimplemented("No support for program consumer");
}
diff --git a/src/test/java/com/android/tools/r8/R8TestBuilder.java b/src/test/java/com/android/tools/r8/R8TestBuilder.java
index 8edbb41..bb3d9cd 100644
--- a/src/test/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8TestBuilder.java
@@ -116,6 +116,18 @@
graphConsumer);
}
+ @Override
+ public R8TestBuilder addClasspathClasses(Collection<Class<?>> classes) {
+ builder.addClasspathResourceProvider(ClassFileResourceProviderFromClasses(classes));
+ return self();
+ }
+
+ @Override
+ public R8TestBuilder addClasspathFiles(Collection<Path> files) {
+ builder.addClasspathFiles(files);
+ return self();
+ }
+
public R8TestBuilder addDataResources(List<DataEntryResource> resources) {
resources.forEach(builder.getAppBuilder()::addDataResource);
return self();
diff --git a/src/test/java/com/android/tools/r8/TestBaseBuilder.java b/src/test/java/com/android/tools/r8/TestBaseBuilder.java
index 61d6996..581bfe8 100644
--- a/src/test/java/com/android/tools/r8/TestBaseBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestBaseBuilder.java
@@ -63,30 +63,7 @@
@Override
public T addLibraryClasses(Collection<Class<?>> classes) {
- addLibraryProvider(
- new ClassFileResourceProvider() {
- final Map<String, ProgramResource> resources;
-
- {
- ImmutableMap.Builder<String, ProgramResource> builder = ImmutableMap.builder();
- classes.forEach(
- c ->
- builder.put(
- DescriptorUtils.javaTypeToDescriptor(c.getTypeName()),
- ProgramResource.fromFile(Kind.CF, ToolHelper.getClassFileForTestClass(c))));
- resources = builder.build();
- }
-
- @Override
- public Set<String> getClassDescriptors() {
- return resources.keySet();
- }
-
- @Override
- public ProgramResource getProgramResource(String descriptor) {
- return resources.get(descriptor);
- }
- });
+ builder.addLibraryResourceProvider(ClassFileResourceProviderFromClasses(classes));
return self();
}
@@ -94,4 +71,31 @@
builder.addMainDexListFiles(files);
return self();
}
+
+ public static ClassFileResourceProvider ClassFileResourceProviderFromClasses(
+ Collection<Class<?>> classes) {
+ return new ClassFileResourceProvider() {
+ final Map<String, ProgramResource> resources;
+
+ {
+ ImmutableMap.Builder<String, ProgramResource> builder = ImmutableMap.builder();
+ classes.forEach(
+ c ->
+ builder.put(
+ DescriptorUtils.javaTypeToDescriptor(c.getTypeName()),
+ ProgramResource.fromFile(Kind.CF, ToolHelper.getClassFileForTestClass(c))));
+ resources = builder.build();
+ }
+
+ @Override
+ public Set<String> getClassDescriptors() {
+ return resources.keySet();
+ }
+
+ @Override
+ public ProgramResource getProgramResource(String descriptor) {
+ return resources.get(descriptor);
+ }
+ };
+ }
}
diff --git a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
index 94c15db..7014cff 100644
--- a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -3,22 +3,18 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8;
-import com.android.tools.r8.ClassFileConsumer.ArchiveConsumer;
import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.debug.DebugTestConfig;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.AndroidAppConsumers;
-import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.base.Suppliers;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Path;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -47,9 +43,6 @@
private Consumer<InternalOptions> optionsConsumer = DEFAULT_OPTIONS;
private PrintStream stdout = null;
- // Consider an in-order collection of both class and files on the classpath.
- private List<Class<?>> classpathClasses = new ArrayList<>();
-
TestCompilerBuilder(TestState state, B builder, Backend backend) {
super(state, builder);
this.backend = backend;
@@ -80,31 +73,6 @@
if (backend == Backend.DEX && defaultMinApiLevel != null) {
builder.setMinApiLevel(defaultMinApiLevel.getLevel());
}
- if (!classpathClasses.isEmpty()) {
- Path cp;
- try {
- cp = getState().getNewTempFolder().resolve("cp.jar");
- } catch (IOException e) {
- throw builder.getReporter().fatalError("Failed to create temp file for classpath archive");
- }
- ArchiveConsumer archiveConsumer = new ArchiveConsumer(cp);
- for (Class<?> classpathClass : classpathClasses) {
- try {
- archiveConsumer.accept(
- ByteDataView.of(ToolHelper.getClassAsBytes(classpathClass)),
- DescriptorUtils.javaTypeToDescriptor(classpathClass.getTypeName()),
- builder.getReporter());
- } catch (IOException e) {
- builder
- .getReporter()
- .error("Failed to read bytes for classpath class: " + classpathClass.getTypeName());
- }
- }
- archiveConsumer.finished(builder.getReporter());
- // TODO(zerny): Remove this HACK to add classpath to R8.
- builder.getAppBuilder().addClasspathFiles(cp);
- }
-
PrintStream oldOut = System.out;
try {
if (stdout != null) {
@@ -209,19 +177,13 @@
return addClasspathClasses(Arrays.asList(classes));
}
- public T addClasspathClasses(Collection<Class<?>> classes) {
- classpathClasses.addAll(classes);
- return self();
- }
+ public abstract T addClasspathClasses(Collection<Class<?>> classes);
public T addClasspathFiles(Path... files) {
return addClasspathFiles(Arrays.asList(files));
}
- public T addClasspathFiles(Collection<Path> files) {
- builder.getAppBuilder().addClasspathFiles(files);
- return self();
- }
+ public abstract T addClasspathFiles(Collection<Path> files);
public T noDesugaring() {
builder.setDisableDesugaring(true);