Merge "Start looking for specific code patterns in the enqueuer"
diff --git a/.gitignore b/.gitignore
index 86cb42d..582f1a9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
build/
+buildSrc/out/
.idea/
+r8.iml
.gradle/
android-data*/
tests/2016-12-19/art.tar.gz
diff --git a/build.gradle b/build.gradle
index d93cbf1..8a5830d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -12,27 +12,38 @@
apply plugin: 'net.ltgt.errorprone-base'
apply plugin: "net.ltgt.apt"
+// Ensure importing into IntelliJ IDEA use the same output directories as Gradle. In tests we
+// use the output path for tests (ultimately through ToolHelper.getClassPathForTests()) and
+// therefore these paths need to be the same. See https://youtrack.jetbrains.com/issue/IDEA-175172
+// for context.
+idea {
+ module {
+ outputDir file('build/classes/main')
+ testOutputDir file('build/classes/test')
+ }
+}
+
def errorProneConfiguration = [
'-XepDisableAllChecks',
// D8 want to use reference equality, thus disable the checker explicitly
'-Xep:ReferenceEquality:OFF',
- '-Xep:ClassCanBeStatic:WARN',
- '-Xep:OperatorPrecedence:WARN',
- '-Xep:RemoveUnusedImports:WARN',
- '-Xep:MissingOverride:WARN',
- '-Xep:OvershadowingSubclassFields:WARN',
- '-Xep:IntLongMath:WARN',
- '-Xep:EqualsHashCode:WARN',
- '-Xep:InconsistentOverloads:WARN',
- '-Xep:ArrayHashCode:WARN',
- '-Xep:EqualsIncompatibleType:WARN',
- '-Xep:NonOverridingEquals:WARN',
- '-Xep:FallThrough:WARN',
- '-Xep:MissingCasesInEnumSwitch:WARN',
- '-Xep:MissingDefault:WARN',
- '-Xep:MultipleTopLevelClasses:WARN',
- '-Xep:NarrowingCompoundAssignment:WARN',
- '-Xep:BoxedPrimitiveConstructor:WARN']
+ '-Xep:ClassCanBeStatic:ERROR',
+ '-Xep:OperatorPrecedence:ERROR',
+ '-Xep:RemoveUnusedImports:ERROR',
+ '-Xep:MissingOverride:ERROR',
+ '-Xep:OvershadowingSubclassFields:ERROR',
+ '-Xep:IntLongMath:ERROR',
+ '-Xep:EqualsHashCode:ERROR',
+ '-Xep:InconsistentOverloads:ERROR',
+ '-Xep:ArrayHashCode:ERROR',
+ '-Xep:EqualsIncompatibleType:ERROR',
+ '-Xep:NonOverridingEquals:ERROR',
+ '-Xep:FallThrough:ERROR',
+ '-Xep:MissingCasesInEnumSwitch:ERROR',
+ '-Xep:MissingDefault:ERROR',
+ '-Xep:MultipleTopLevelClasses:ERROR',
+ '-Xep:NarrowingCompoundAssignment:ERROR',
+ '-Xep:BoxedPrimitiveConstructor:ERROR']
apply from: 'copyAdditionalJctfCommonFiles.gradle'
diff --git a/src/main/java/com/android/tools/r8/BaseCommand.java b/src/main/java/com/android/tools/r8/BaseCommand.java
index e35010a..5cd87fb 100644
--- a/src/main/java/com/android/tools/r8/BaseCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCommand.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.shaking.FilteredClassPath;
import com.android.tools.r8.utils.AbortException;
@@ -159,26 +160,14 @@
}
/** Add Java-bytecode program-data. */
- public B addClassProgramData(byte[]... data) {
- app.addClassProgramData(data);
- return self();
- }
-
- /** Add Java-bytecode program-data. */
- public B addClassProgramData(Collection<byte[]> data) {
- app.addClassProgramData(data);
+ public B addClassProgramData(byte[] data, Origin origin) {
+ app.addClassProgramData(data, origin);
return self();
}
/** Add dex program-data. */
- public B addDexProgramData(byte[]... data) {
- app.addDexProgramData(data);
- return self();
- }
-
- /** Add dex program-data. */
- public B addDexProgramData(Collection<byte[]> data) {
- app.addDexProgramData(data);
+ public B addDexProgramData(byte[] data, Origin origin) {
+ app.addDexProgramData(data, origin);
return self();
}
diff --git a/src/main/java/com/android/tools/r8/ExtractMarker.java b/src/main/java/com/android/tools/r8/ExtractMarker.java
index a32aa20..24dfb07 100644
--- a/src/main/java/com/android/tools/r8/ExtractMarker.java
+++ b/src/main/java/com/android/tools/r8/ExtractMarker.java
@@ -12,137 +12,40 @@
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
-import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.List;
import java.util.concurrent.ExecutionException;
public class ExtractMarker {
- private static class Command {
- public static class Builder {
- private boolean printHelp = false;
- private boolean verbose;
- private boolean summary;
- private List<Path> programFiles = new ArrayList<>();
+ public static Marker extractMarkerFromDexFile(Path file) throws IOException, ExecutionException {
+ AndroidApp.Builder appBuilder = AndroidApp.builder();
+ appBuilder.setVdexAllowed();
+ appBuilder.addProgramFiles(FilteredClassPath.unfiltered(file));
+ return extractMarker(appBuilder.build());
+ }
- public Builder setPrintHelp(boolean printHelp) {
- this.printHelp = printHelp;
- return this;
- }
+ public static Marker extractMarkerFromDexProgramData(byte[] data)
+ throws IOException, ExecutionException {
+ AndroidApp app = AndroidApp.fromDexProgramData(data);
+ return extractMarker(app);
+ }
- public boolean isPrintHelp() {
- return printHelp;
- }
-
- public Builder setVerbose(boolean verbose) {
- this.verbose = verbose;
- return this;
- }
-
- public Builder setSummary(boolean summary) {
- this.summary = summary;
- return this;
- }
-
- public Builder addProgramFile(Path programFile) {
- programFiles.add(programFile);
- return this;
- }
-
- public ExtractMarker.Command build() throws CompilationException, IOException {
- // If printing versions ignore everything else.
- if (isPrintHelp()) {
- return new ExtractMarker.Command(isPrintHelp());
- }
- return new ExtractMarker.Command(verbose, summary, programFiles);
- }
- }
-
- static final String USAGE_MESSAGE = String.join("\n", ImmutableList.of(
- "Usage: extractmarker [options] <input-files>",
- " where <input-files> are dex or vdex files",
- " --verbose # More verbose output.",
- " --summary # Print summary at the end.",
- " --help # Print this message."));
-
- public static ExtractMarker.Command.Builder builder() {
- return new Builder();
- }
-
- public static ExtractMarker.Command.Builder parse(String[] args)
- throws CompilationException, IOException {
- ExtractMarker.Command.Builder builder = builder();
- parse(args, builder);
- return builder;
- }
-
- private static void parse(String[] args, ExtractMarker.Command.Builder builder)
- throws CompilationException, IOException {
- for (int i = 0; i < args.length; i++) {
- String arg = args[i].trim();
- if (arg.length() == 0) {
- continue;
- } else if (arg.equals("--verbose")) {
- builder.setVerbose(true);
- } else if (arg.equals("--summary")) {
- builder.setSummary(true);
- } else if (arg.equals("--help")) {
- builder.setPrintHelp(true);
- } else {
- if (arg.startsWith("--")) {
- throw new CompilationException("Unknown option: " + arg);
- }
- builder.addProgramFile(Paths.get(arg));
- }
- }
- }
-
- private final boolean printHelp;
- private final boolean verbose;
- private final boolean summary;
- private final List<Path> programFiles;
-
- private Command(boolean verbose, boolean summary, List<Path> programFiles) {
- this.printHelp = false;
- this.verbose = verbose;
- this.summary = summary;
- this.programFiles = programFiles;
- }
-
- private Command(boolean printHelp) {
- this.printHelp = printHelp;
- this.verbose = false;
- this.summary = false;
- programFiles = ImmutableList.of();
- }
-
- public boolean isPrintHelp() {
- return printHelp;
- }
-
- public List<Path> getProgramFiles() {
- return programFiles;
- }
-
- public boolean getVerbose() {
- return verbose;
- }
-
- public boolean getSummary() {
- return summary;
- }
+ private static Marker extractMarker(AndroidApp app) throws IOException, ExecutionException {
+ InternalOptions options = new InternalOptions();
+ options.skipReadingDexCode = true;
+ options.minApiLevel = AndroidApiLevel.P.getLevel();
+ DexApplication dexApp =
+ new ApplicationReader(app, options, new Timing("ExtractMarker")).read();
+ return dexApp.dexItemFactory.extractMarker();
}
public static void main(String[] args)
throws IOException, CompilationException, ExecutionException {
- ExtractMarker.Command.Builder builder = ExtractMarker.Command.parse(args);
- ExtractMarker.Command command = builder.build();
+ ExtractMarkerCommand.Builder builder = ExtractMarkerCommand.parse(args);
+ ExtractMarkerCommand command = builder.build();
if (command.isPrintHelp()) {
- System.out.println(ExtractMarker.Command.USAGE_MESSAGE);
+ System.out.println(ExtractMarkerCommand.USAGE_MESSAGE);
return;
}
@@ -153,26 +56,17 @@
int otherCount = 0;
for (Path programFile : command.getProgramFiles()) {
try {
- InternalOptions options = new InternalOptions();
- options.skipReadingDexCode = true;
- options.minApiLevel = AndroidApiLevel.P.getLevel();
- AndroidApp.Builder appBuilder = AndroidApp.builder();
- appBuilder.setVdexAllowed();
- appBuilder.addProgramFiles(FilteredClassPath.unfiltered(programFile));
- DexApplication dexApp =
- new ApplicationReader(appBuilder.build(), options, new Timing("ExtractMarker"))
- .read();
- Marker readMarker = dexApp.dexItemFactory.extractMarker();
if (command.getVerbose()) {
System.out.print(programFile);
System.out.print(": ");
}
- if (readMarker == null) {
+ Marker marker = extractMarkerFromDexFile(programFile);
+ if (marker == null) {
System.out.println("D8/R8 marker not found.");
otherCount++;
} else {
- System.out.println(readMarker.toString());
- if (readMarker.isD8()) {
+ System.out.println(marker.toString());
+ if (marker.isD8()) {
d8Count++;
} else {
r8Count++;
diff --git a/src/main/java/com/android/tools/r8/ExtractMarkerCommand.java b/src/main/java/com/android/tools/r8/ExtractMarkerCommand.java
new file mode 100644
index 0000000..729b50a
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ExtractMarkerCommand.java
@@ -0,0 +1,127 @@
+// Copyright (c) 2017, 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;
+
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+class ExtractMarkerCommand {
+
+ public static class Builder {
+ private boolean printHelp = false;
+ private boolean verbose;
+ private boolean summary;
+ private List<Path> programFiles = new ArrayList<>();
+
+ public Builder setPrintHelp(boolean printHelp) {
+ this.printHelp = printHelp;
+ return this;
+ }
+
+ public boolean isPrintHelp() {
+ return printHelp;
+ }
+
+ public Builder setVerbose(boolean verbose) {
+ this.verbose = verbose;
+ return this;
+ }
+
+ public Builder setSummary(boolean summary) {
+ this.summary = summary;
+ return this;
+ }
+
+ public Builder addProgramFile(Path programFile) {
+ programFiles.add(programFile);
+ return this;
+ }
+
+ public ExtractMarkerCommand build() throws CompilationException, IOException {
+ // If printing versions ignore everything else.
+ if (isPrintHelp()) {
+ return new ExtractMarkerCommand(isPrintHelp());
+ }
+ return new ExtractMarkerCommand(verbose, summary, programFiles);
+ }
+ }
+
+ static final String USAGE_MESSAGE = String.join("\n", ImmutableList.of(
+ "Usage: extractmarker [options] <input-files>",
+ " where <input-files> are dex or vdex files",
+ " --verbose # More verbose output.",
+ " --summary # Print summary at the end.",
+ " --help # Print this message."));
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static Builder parse(String[] args)
+ throws CompilationException, IOException {
+ Builder builder = builder();
+ parse(args, builder);
+ return builder;
+ }
+
+ private static void parse(String[] args, Builder builder)
+ throws CompilationException, IOException {
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i].trim();
+ if (arg.length() == 0) {
+ continue;
+ } else if (arg.equals("--verbose")) {
+ builder.setVerbose(true);
+ } else if (arg.equals("--summary")) {
+ builder.setSummary(true);
+ } else if (arg.equals("--help")) {
+ builder.setPrintHelp(true);
+ } else {
+ if (arg.startsWith("--")) {
+ throw new CompilationException("Unknown option: " + arg);
+ }
+ builder.addProgramFile(Paths.get(arg));
+ }
+ }
+ }
+
+ private final boolean printHelp;
+ private final boolean verbose;
+ private final boolean summary;
+ private final List<Path> programFiles;
+
+ private ExtractMarkerCommand(boolean verbose, boolean summary, List<Path> programFiles) {
+ this.printHelp = false;
+ this.verbose = verbose;
+ this.summary = summary;
+ this.programFiles = programFiles;
+ }
+
+ private ExtractMarkerCommand(boolean printHelp) {
+ this.printHelp = printHelp;
+ this.verbose = false;
+ this.summary = false;
+ programFiles = ImmutableList.of();
+ }
+
+ public boolean isPrintHelp() {
+ return printHelp;
+ }
+
+ public List<Path> getProgramFiles() {
+ return programFiles;
+ }
+
+ public boolean getVerbose() {
+ return verbose;
+ }
+
+ public boolean getSummary() {
+ return summary;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 44e1bf4..4368013 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -8,6 +8,8 @@
public final class Version {
+ // This field is accessed from release scripts using simple pattern matching.
+ // Therefore, changing this field could break our release scripts.
public static final String LABEL = "v0.2.0-dev";
private Version() {
diff --git a/src/main/java/com/android/tools/r8/benchmarks/FrameworkIncrementalDexingBenchmark.java b/src/main/java/com/android/tools/r8/benchmarks/FrameworkIncrementalDexingBenchmark.java
index a1ff8b8..7a5f627 100644
--- a/src/main/java/com/android/tools/r8/benchmarks/FrameworkIncrementalDexingBenchmark.java
+++ b/src/main/java/com/android/tools/r8/benchmarks/FrameworkIncrementalDexingBenchmark.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.D8;
import com.android.tools.r8.D8Command;
+import com.android.tools.r8.D8Command.Builder;
import com.android.tools.r8.D8Output;
import com.android.tools.r8.Resource;
import com.android.tools.r8.origin.Origin;
@@ -141,21 +142,21 @@
long start = System.nanoTime();
for (int iteration = 0; iteration < ITERATIONS; iteration++) {
int index = iteration * increment;
- List<byte[]> inputs = new ArrayList<>(count);
+ Builder builder = D8Command.builder()
+ .setMinApiLevel(API)
+ .setIntermediate(true)
+ .setMode(CompilationMode.DEBUG)
+ .addClasspathResourceProvider(provider)
+ .addLibraryFiles(LIB)
+ .setOutputMode(OutputMode.FilePerInputClass)
+ .setEnableDesugaring(desugar);
for (int j = 0; j < count; j++) {
- provider.resources.get(descriptors.get(index + j));
+ builder.addClassProgramData(provider.resources.get(descriptors.get(index + j)),
+ Origin.unknown());
}
D8Output out =
D8.run(
- D8Command.builder()
- .setMinApiLevel(API)
- .setIntermediate(true)
- .setMode(CompilationMode.DEBUG)
- .addClassProgramData(inputs)
- .addClasspathResourceProvider(provider)
- .addLibraryFiles(LIB)
- .setOutputMode(OutputMode.FilePerInputClass)
- .setEnableDesugaring(desugar)
+ builder
.build(),
executor);
for (Resource resource : out.getDexResources()) {
@@ -174,22 +175,21 @@
Map<String, Resource> outputs,
ExecutorService executor)
throws IOException, CompilationException, CompilationFailedException {
- List<byte[]> bytes = new ArrayList<>(outputs.size());
+ Builder builder = D8Command.builder()
+ .setMinApiLevel(API)
+ .setIntermediate(false)
+ .setMode(CompilationMode.DEBUG)
+ .setOutputMode(OutputMode.Indexed)
+ .setEnableDesugaring(false);
for (Resource input : outputs.values()) {
try (InputStream inputStream = input.getStream()) {
- bytes.add(ByteStreams.toByteArray(inputStream));
+ builder.addDexProgramData(ByteStreams.toByteArray(inputStream), input.origin);
}
}
long start = System.nanoTime();
D8Output out =
D8.run(
- D8Command.builder()
- .setMinApiLevel(API)
- .setIntermediate(false)
- .setMode(CompilationMode.DEBUG)
- .addDexProgramData(bytes)
- .setOutputMode(OutputMode.Indexed)
- .setEnableDesugaring(false) // never need to desugar when merging dex.
+ builder // never need to desugar when merging dex.
.build(),
executor);
printRuntimeNanoseconds(title("DexMerge", desugar), System.nanoTime() - start);
diff --git a/src/main/java/com/android/tools/r8/compatdexbuilder/CompatDexBuilder.java b/src/main/java/com/android/tools/r8/compatdexbuilder/CompatDexBuilder.java
index 8972a96..07496c8 100644
--- a/src/main/java/com/android/tools/r8/compatdexbuilder/CompatDexBuilder.java
+++ b/src/main/java/com/android/tools/r8/compatdexbuilder/CompatDexBuilder.java
@@ -7,6 +7,8 @@
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.D8;
import com.android.tools.r8.D8Output;
+import com.android.tools.r8.origin.ArchiveEntryOrigin;
+import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.CompilationFailedException;
import com.android.tools.r8.utils.ThreadUtils;
@@ -135,7 +137,9 @@
try (InputStream stream = zipFile.getInputStream(classEntry)) {
CompatDexBuilderCommandBuilder builder = new CompatDexBuilderCommandBuilder();
builder
- .addClassProgramData(ByteStreams.toByteArray(stream))
+ .addClassProgramData(ByteStreams.toByteArray(stream),
+ new ArchiveEntryOrigin(classEntry.getName(),
+ new PathOrigin(Paths.get(zipFile.getName()))))
.setMode(noLocals ? CompilationMode.RELEASE : CompilationMode.DEBUG)
.setMinApiLevel(AndroidApiLevel.H_MR2.getLevel());
return D8.run(builder.build(), executor);
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 463d484..e1f3316 100644
--- a/src/main/java/com/android/tools/r8/dex/Marker.java
+++ b/src/main/java/com/android/tools/r8/dex/Marker.java
@@ -51,6 +51,10 @@
return tool == Tool.R8;
}
+ public String getVersion() {
+ return (String) content.get("version");
+ }
+
public Marker put(String key, int value) {
// value is converted to Long ensuring equals works with the parsed json string.
return internalPut(key, Long.valueOf(value));
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstString.java b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
index 412a7a1..1cfd2ae 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
@@ -86,22 +86,24 @@
}
@Override
- public boolean canBeDeadCode(IRCode code, InternalOptions options) {
- // The const-string instruction can be a throwing instruction in DEX, if decode() fails,
- // but not so in CF.
- if (options.outputClassFiles) {
- return true;
- }
+ public boolean instructionInstanceCanThrow() {
+ // The const-string instruction can be a throwing instruction in DEX, if decode() fails.
try {
value.toString();
} catch (RuntimeException e) {
if (e.getCause() instanceof UTFDataFormatException) {
- return false;
+ return true;
} else {
throw e;
}
}
- return true;
+ return false;
+ }
+
+ @Override
+ public boolean canBeDeadCode(IRCode code, InternalOptions options) {
+ // No side-effect, such as throwing an exception, in CF.
+ return options.outputClassFiles || !instructionInstanceCanThrow();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
index 2790c03..bbf3a3a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
@@ -104,7 +104,6 @@
&& !current.outValue().isUsed()) {
current.setOutValue(null);
}
- // Never remove instructions that can have side effects, except for const-class.
if (!current.canBeDeadCode(code, options)) {
continue;
}
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index d08b0b7..e8e05cf 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -579,8 +579,9 @@
/**
* Add dex program-data.
*/
- public Builder addDexProgramData(byte[]... data) {
- return addDexProgramData(Arrays.asList(data));
+ public Builder addDexProgramData(byte[] data, Origin origin) {
+ addProgramResources(Kind.DEX, Resource.fromBytes(origin, data));
+ return this;
}
/**
@@ -596,13 +597,6 @@
/**
* Add Java-bytecode program data.
*/
- public Builder addClassProgramData(byte[]... data) {
- return addClassProgramData(Arrays.asList(data));
- }
-
- /**
- * Add Java-bytecode program data.
- */
public Builder addClassProgramData(Collection<byte[]> data) {
for (byte[] datum : data) {
addProgramResources(Kind.CLASS, Resource.fromBytes(Origin.unknown(), datum));
diff --git a/src/test/apiUsageSample/com/android/tools/apiusagesample/D8Compiler.java b/src/test/apiUsageSample/com/android/tools/apiusagesample/D8Compiler.java
index 7842a6a..97818f2 100644
--- a/src/test/apiUsageSample/com/android/tools/apiusagesample/D8Compiler.java
+++ b/src/test/apiUsageSample/com/android/tools/apiusagesample/D8Compiler.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.D8;
import com.android.tools.r8.D8Command;
+import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.utils.CompilationFailedException;
import com.android.tools.r8.utils.OutputMode;
import java.io.IOException;
@@ -99,7 +100,7 @@
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes)
throws IOException {
- builder.addClassProgramData(Files.readAllBytes(path));
+ builder.addClassProgramData(Files.readAllBytes(path), new PathOrigin(path));
return FileVisitResult.CONTINUE;
}
});
@@ -118,7 +119,7 @@
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes)
throws IOException {
- merger.addDexProgramData(Files.readAllBytes(path));
+ merger.addDexProgramData(Files.readAllBytes(path), new PathOrigin(path));
return FileVisitResult.CONTINUE;
}
});
diff --git a/src/test/java/com/android/tools/r8/D8IncrementalRunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/D8IncrementalRunExamplesAndroidOTest.java
index c8ca57e..7f9b06f 100644
--- a/src/test/java/com/android/tools/r8/D8IncrementalRunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/D8IncrementalRunExamplesAndroidOTest.java
@@ -183,7 +183,7 @@
Resource mergeClassFiles(List<Resource> dexFiles, Path out) throws Throwable {
D8Command.Builder builder = D8Command.builder();
for (Resource dexFile : dexFiles) {
- builder.addDexProgramData(readFromResource(dexFile));
+ builder.addDexProgramData(readFromResource(dexFile), dexFile.origin);
}
for (UnaryOperator<D8Command.Builder> transformation : builderTransformations) {
builder = transformation.apply(builder);
diff --git a/src/test/java/com/android/tools/r8/D8LazyRunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/D8LazyRunExamplesAndroidOTest.java
index 1c68d75..f8b388b 100644
--- a/src/test/java/com/android/tools/r8/D8LazyRunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/D8LazyRunExamplesAndroidOTest.java
@@ -127,7 +127,7 @@
D8Command.Builder builder = D8Command.builder()
.setMinApiLevel(minAPILevel);
for (Resource resource : individalDexes) {
- builder.addDexProgramData(readFromResource(resource));
+ builder.addDexProgramData(readFromResource(resource), resource.origin);
}
AndroidApp mergedResult = ToolHelper.runD8(builder.build(),
options -> options.setMarker(null));
diff --git a/src/test/java/com/android/tools/r8/ExtractMarkerTest.java b/src/test/java/com/android/tools/r8/ExtractMarkerTest.java
new file mode 100644
index 0000000..fd1bfcb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ExtractMarkerTest.java
@@ -0,0 +1,31 @@
+// Copyright (c) 2017, 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;
+
+import com.android.tools.r8.dex.Marker;
+import com.android.tools.r8.dex.Marker.Tool;
+import com.android.tools.r8.utils.CompilationFailedException;
+import com.google.common.io.ByteStreams;
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.concurrent.ExecutionException;
+import org.junit.Test;
+
+public class ExtractMarkerTest {
+
+ @Test
+ public void extractMarkerTest()
+ throws CompilationFailedException, IOException, ExecutionException {
+ String classFile = ToolHelper.EXAMPLES_BUILD_DIR + "classes/trivial/Trivial.class";
+ D8Command command = D8Command.builder()
+ .addProgramFiles(Paths.get(classFile))
+ .build();
+ D8Output output = D8.run(command);
+ byte[] data = ByteStreams.toByteArray(output.getDexResources().get(0).getStream());
+ Marker marker = ExtractMarker.extractMarkerFromDexProgramData(data);
+ assert marker != null;
+ assert marker.getTool() == Tool.D8;
+ assert marker.getVersion().equals(Version.LABEL);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/compatproguard/ForNameTest.java b/src/test/java/com/android/tools/r8/compatproguard/ForNameTest.java
index 8480791..7c1ce1b 100644
--- a/src/test/java/com/android/tools/r8/compatproguard/ForNameTest.java
+++ b/src/test/java/com/android/tools/r8/compatproguard/ForNameTest.java
@@ -97,7 +97,7 @@
Path dexOutputDir = temp.newFolder().toPath();
R8Command command =
new CompatProguardCommandBuilder(true, true)
- .addDexProgramData(builder.compile())
+ .addDexProgramData(builder.compile(), Origin.unknown())
.setOutputPath(dexOutputDir)
.addProguardConfiguration(proguardConfigurations, Origin.unknown())
.build();
diff --git a/src/test/java/com/android/tools/r8/debug/BlockReorderingTest.java b/src/test/java/com/android/tools/r8/debug/BlockReorderingTest.java
index 3376cb8..07a4463 100644
--- a/src/test/java/com/android/tools/r8/debug/BlockReorderingTest.java
+++ b/src/test/java/com/android/tools/r8/debug/BlockReorderingTest.java
@@ -3,8 +3,12 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.debug;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.D8Command;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -17,15 +21,24 @@
public static final String CLASS = "BlockReordering";
public static final String FILE = "BlockReordering.java";
- private static DebuggeePath debuggeePath;
+ private static DebugTestConfig dexConfig;
@BeforeClass
- public static void initDebuggeePath() throws Exception {
+ public static void setup() throws Exception {
// Force inversion of all conditionals to reliably construct a regression test for incorrect
// line information when reordering blocks.
- debuggeePath =
- DebuggeePath.makeDex(
- compileToDex(DEBUGGEE_JAR, options -> options.testing.invertConditionals = true));
+ Path result = temp.newFolder().toPath().resolve("inverted_conditionals.jar");
+ int minSdk = ToolHelper.getMinApiLevelForDexVm(ToolHelper.getDexVm());
+ ToolHelper.runD8(
+ D8Command.builder()
+ .addProgramFiles(DEBUGGEE_JAR)
+ .setOutputPath(result)
+ .setMinApiLevel(minSdk)
+ .setMode(CompilationMode.DEBUG)
+ .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(minSdk)))
+ .build(),
+ options -> options.testing.invertConditionals = true);
+ dexConfig = new D8BaseDebugTestConfig(temp, result);
}
@Test
@@ -35,7 +48,7 @@
ToolHelper.getDexVm().getVersion().isNewerThan(Version.V6_0_1));
final String method = "conditionalReturn";
runDebugTest(
- debuggeePath,
+ dexConfig,
CLASS,
breakpoint(CLASS, method),
run(),
@@ -58,7 +71,7 @@
ToolHelper.getDexVm().getVersion().isNewerThan(Version.V6_0_1));
final String method = "invertConditionalReturn";
runDebugTest(
- debuggeePath,
+ dexConfig,
CLASS,
breakpoint(CLASS, method),
run(),
@@ -81,7 +94,7 @@
ToolHelper.getDexVm().getVersion().isNewerThan(Version.V6_0_1));
final String method = "fallthroughReturn";
runDebugTest(
- debuggeePath,
+ dexConfig,
CLASS,
breakpoint(CLASS, method),
run(),
diff --git a/src/test/java/com/android/tools/r8/debug/CfBaseDebugTestConfig.java b/src/test/java/com/android/tools/r8/debug/CfBaseDebugTestConfig.java
new file mode 100644
index 0000000..ec6038c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debug/CfBaseDebugTestConfig.java
@@ -0,0 +1,30 @@
+// Copyright (c) 2017, 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.debug;
+
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Path;
+import java.util.List;
+
+public class CfBaseDebugTestConfig extends DebugTestConfig {
+
+ public static final Path JDWP_JAR = ToolHelper.getJdwpTestsJarPath(AndroidApiLevel.N.getLevel());
+
+ @Override
+ public RuntimeKind getRuntimeKind() {
+ return RuntimeKind.CF;
+ }
+
+ @Override
+ public List<Path> getPaths() {
+ return ImmutableList.of(JDWP_JAR);
+ }
+
+ @Override
+ public Path getProguardMap() {
+ return null;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/debug/D8BaseDebugTestConfig.java b/src/test/java/com/android/tools/r8/debug/D8BaseDebugTestConfig.java
new file mode 100644
index 0000000..10c6191
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debug/D8BaseDebugTestConfig.java
@@ -0,0 +1,95 @@
+// Copyright (c) 2017, 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.debug;
+
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.D8Command;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.OutputMode;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.rules.TemporaryFolder;
+
+public class D8BaseDebugTestConfig extends DebugTestConfig {
+
+ public static final Path JDWP_JAR =
+ ToolHelper.getJdwpTestsJarPath(ToolHelper.getMinApiLevelForDexVm(ToolHelper.getDexVm()));
+
+ // Internal cache to avoid multiple compilations of the base JDWP code.
+ private static AndroidApp compiledJdwp = null;
+
+ private static synchronized AndroidApp getCompiledJdwp() {
+ if (compiledJdwp == null) {
+ int minSdk = ToolHelper.getMinApiLevelForDexVm(ToolHelper.getDexVm());
+ try {
+ compiledJdwp =
+ ToolHelper.runD8(
+ D8Command.builder()
+ .addProgramFiles(JDWP_JAR)
+ .setMinApiLevel(minSdk)
+ .setMode(CompilationMode.DEBUG)
+ .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(minSdk)))
+ .build());
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return compiledJdwp;
+ }
+
+ private final List<Path> paths = new ArrayList<>();
+
+ private Path proguardMap = null;
+
+ public D8BaseDebugTestConfig(TemporaryFolder temp) {
+ this(temp, ImmutableList.of());
+ }
+
+ public D8BaseDebugTestConfig(TemporaryFolder temp, Path... paths) {
+ this(temp, Arrays.asList(paths));
+ }
+
+ public D8BaseDebugTestConfig(TemporaryFolder temp, List<Path> paths) {
+ addPaths(paths);
+ try {
+ Path out = temp.newFolder().toPath().resolve("d8_jdwp.jar");
+ getCompiledJdwp().write(out, OutputMode.Indexed);
+ addPaths(out);
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public RuntimeKind getRuntimeKind() {
+ return RuntimeKind.DEX;
+ }
+
+ @Override
+ public List<Path> getPaths() {
+ return paths;
+ }
+
+ @Override
+ public Path getProguardMap() {
+ return proguardMap;
+ }
+
+ public void addPaths(Path... paths) {
+ addPaths(Arrays.asList(paths));
+ }
+
+ public void addPaths(List<Path> paths) {
+ this.paths.addAll(paths);
+ }
+
+ public void setProguardMap(Path proguardMap) {
+ this.proguardMap = proguardMap;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/debug/D8DebugTestResourcesConfig.java b/src/test/java/com/android/tools/r8/debug/D8DebugTestResourcesConfig.java
new file mode 100644
index 0000000..448949c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debug/D8DebugTestResourcesConfig.java
@@ -0,0 +1,46 @@
+// Copyright (c) 2017, 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.debug;
+
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.D8Command;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.OutputMode;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.rules.TemporaryFolder;
+
+// Shared test configuration for D8 compiled resources from the "debugTestResources" target.
+public class D8DebugTestResourcesConfig extends D8BaseDebugTestConfig {
+
+ private static AndroidApp compiledResources = null;
+
+ private static synchronized AndroidApp getCompiledResources() throws Throwable {
+ if (compiledResources == null) {
+ int minSdk = ToolHelper.getMinApiLevelForDexVm(ToolHelper.getDexVm());
+ compiledResources =
+ ToolHelper.runD8(
+ D8Command.builder()
+ .addProgramFiles(DebugTestBase.DEBUGGEE_JAR)
+ .setMinApiLevel(minSdk)
+ .setMode(CompilationMode.DEBUG)
+ .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(minSdk)))
+ .build(),
+ null);
+ }
+ return compiledResources;
+ }
+
+ public D8DebugTestResourcesConfig(TemporaryFolder temp) {
+ super(temp);
+ try {
+ Path path = temp.newFolder().toPath().resolve("d8_debug_test_resources.jar");
+ getCompiledResources().write(path, OutputMode.Indexed);
+ addPaths(path);
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
index 510aea1..692dd13 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
@@ -11,8 +11,7 @@
import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.ToolHelper.DexVm.Version;
-import com.android.tools.r8.ToolHelper.ProcessResult;
-import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.debug.DebugTestConfig.RuntimeKind;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.ClassNamingForNameMapper;
import com.android.tools.r8.naming.MemberNaming;
@@ -31,7 +30,6 @@
import it.unimi.dsi.fastutil.longs.LongList;
import java.io.File;
import java.io.IOException;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayDeque;
@@ -74,7 +72,6 @@
import org.apache.harmony.jpda.tests.share.JPDATestOptions;
import org.junit.Assert;
import org.junit.Assume;
-import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Rule;
@@ -93,104 +90,50 @@
public static final StepFilter INTELLIJ_FILTER = new StepFilter.IntelliJStepFilter();
private static final StepFilter DEFAULT_FILTER = NO_FILTER;
- enum DexCompilerKind {
- DX,
- D8
- }
-
- enum BinaryKind {
- CF,
- DEX
- }
-
protected static class DebuggeePath {
- public final BinaryKind kind;
+ public final RuntimeKind kind;
public final Path path;
public static DebuggeePath makeDex(Path path) {
- return new DebuggeePath(BinaryKind.DEX, path);
+ return new DebuggeePath(DebugTestConfig.RuntimeKind.DEX, path);
}
public static DebuggeePath makeClassFile(Path path) {
- return new DebuggeePath(BinaryKind.CF, path);
+ return new DebuggeePath(DebugTestConfig.RuntimeKind.CF, path);
}
- public DebuggeePath(BinaryKind kind, Path path) {
+ public DebuggeePath(RuntimeKind kind, Path path) {
this.kind = kind;
this.path = path;
}
}
- private static final DexCompilerKind DEX_COMPILER_KIND = DexCompilerKind.D8;
-
private static final int FIRST_LINE = -1;
// Set to true to enable verbose logs
private static final boolean DEBUG_TESTS = false;
- private static final Path JDWP_JAR = ToolHelper
- .getJdwpTestsJarPath(ToolHelper.getMinApiLevelForDexVm(ToolHelper.getDexVm()));
- protected static final Path DEBUGGEE_JAR =
+ public static final Path DEBUGGEE_JAR =
Paths.get(ToolHelper.BUILD_DIR, "test", "debug_test_resources.jar");
+
private static final Path DEBUGGEE_JAVA8_JAR = Paths
.get(ToolHelper.BUILD_DIR, "test", "debug_test_resources_java8.jar");
- private static final Path DEBUGGEE_KOTLIN_JAR = Paths
- .get(ToolHelper.BUILD_DIR, "test", "debug_test_resources_kotlin.jar");
private static final String PROGUARD_MAP_FILENAME = "proguard.map";
@ClassRule
- public static TemporaryFolder temp = new TemporaryFolder();
-
- // TODO(tamaskenez): Separate test setup from test runner.
- private static Path jdwpDexD8;
- private static Path debuggeeDexD8;
- private static Path debuggeeJava8DexD8;
- private static Path debuggeeKotlinDexD8;
+ public static TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
@Rule
public TestName testName = new TestName();
- @BeforeClass
- public static void setUp() throws Exception {
- jdwpDexD8 = compileToDex(JDWP_JAR, null);
- debuggeeDexD8 = null;
- debuggeeJava8DexD8 = null;
- debuggeeKotlinDexD8 = null;
- }
-
- protected static synchronized Path getDebuggeeDexD8()
+ private static Path getDebuggeeJava8DexD8()
throws IOException, CompilationException, CompilationFailedException {
- if (debuggeeDexD8 == null) {
- debuggeeDexD8 = compileToDex(DEBUGGEE_JAR, null);
- }
- return debuggeeDexD8;
- }
-
- private static synchronized Path getDebuggeeJava8DexD8()
- throws IOException, CompilationException, CompilationFailedException {
- if (debuggeeJava8DexD8 == null) {
- debuggeeJava8DexD8 =
- compileToDex(
- DEBUGGEE_JAVA8_JAR,
- options -> {
- // Enable desugaring for preN runtimes
- options.interfaceMethodDesugaring = OffOrAuto.Auto;
- });
- }
- return debuggeeJava8DexD8;
- }
-
- private static synchronized Path getDebuggeeKotlinDexD8()
- throws IOException, CompilationException, CompilationFailedException {
- if (debuggeeKotlinDexD8 == null) {
- debuggeeKotlinDexD8 = compileToDex(DEBUGGEE_KOTLIN_JAR, null);
- }
- return debuggeeKotlinDexD8;
- }
-
- protected static DebuggeePath getDebuggeeDexD8OrCf(boolean cf)
- throws IOException, CompilationException, CompilationFailedException {
- return cf ? DebuggeePath.makeClassFile(DEBUGGEE_JAR) : DebuggeePath.makeDex(getDebuggeeDexD8());
+ return compileToDex(
+ DEBUGGEE_JAVA8_JAR,
+ options -> {
+ // Enable desugaring for preN runtimes
+ options.interfaceMethodDesugaring = OffOrAuto.Auto;
+ });
}
protected static DebuggeePath getDebuggeeJava8DexD8OrCf(boolean cf)
@@ -200,46 +143,20 @@
: DebuggeePath.makeDex(getDebuggeeJava8DexD8());
}
- protected static Path compileToDex(Path jarToCompile, Consumer<InternalOptions> optionsConsumer)
- throws IOException, CompilationException, CompilationFailedException {
- return compileToDex(DEX_COMPILER_KIND, jarToCompile, optionsConsumer);
- }
-
- static Path compileToDex(
- DexCompilerKind compiler, Path jarToCompile, Consumer<InternalOptions> optionsConsumer)
+ static Path compileToDex(Path jarToCompile, Consumer<InternalOptions> optionsConsumer)
throws IOException, CompilationException, CompilationFailedException {
int minSdk = ToolHelper.getMinApiLevelForDexVm(ToolHelper.getDexVm());
assert jarToCompile.toFile().exists();
Path dexOutputDir = temp.newFolder().toPath();
- switch (compiler) {
- case D8:
- {
- ToolHelper.runD8(
- D8Command.builder()
- .addProgramFiles(jarToCompile)
- .setOutputPath(dexOutputDir)
- .setMinApiLevel(minSdk)
- .setMode(CompilationMode.DEBUG)
- .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(minSdk)))
- .build(),
- optionsConsumer);
- break;
- }
- case DX:
- {
- ProcessResult result =
- ToolHelper.runDX(
- new String[] {
- "--output=" + dexOutputDir,
- "--min-sdk-version=" + minSdk,
- jarToCompile.toString()
- });
- Assert.assertEquals(result.stderr, 0, result.exitCode);
- break;
- }
- default:
- throw new Unreachable();
- }
+ ToolHelper.runD8(
+ D8Command.builder()
+ .addProgramFiles(jarToCompile)
+ .setOutputPath(dexOutputDir)
+ .setMinApiLevel(minSdk)
+ .setMode(CompilationMode.DEBUG)
+ .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(minSdk)))
+ .build(),
+ optionsConsumer);
return dexOutputDir.resolve("classes.dex");
}
@@ -276,9 +193,9 @@
return dexOutputDir.resolve("classes.dex");
}
- private BinaryKind currentlyRunningBinaryKind = null;
+ private RuntimeKind currentlyRunningBinaryKind = null;
- protected final BinaryKind getCurrentlyRunningBinaryKind() {
+ protected final RuntimeKind getCurrentlyRunningBinaryKind() {
if (currentlyRunningBinaryKind == null) {
throw new RuntimeException("Nothing is running currently.");
}
@@ -291,63 +208,42 @@
}
protected final boolean isRunningJava() {
- return getCurrentlyRunningBinaryKind() == BinaryKind.CF;
+ return getCurrentlyRunningBinaryKind() == DebugTestConfig.RuntimeKind.CF;
}
protected final boolean isRunningArt() {
- return getCurrentlyRunningBinaryKind() == BinaryKind.DEX;
+ return getCurrentlyRunningBinaryKind() == DebugTestConfig.RuntimeKind.DEX;
+ }
+
+ protected final void runDebugTest(
+ DebugTestConfig config, String debuggeeClass, JUnit3Wrapper.Command... commands)
+ throws Throwable {
+ runInternal(config, debuggeeClass, Arrays.asList(commands));
}
protected final void runDebugTest(String debuggeeClass, JUnit3Wrapper.Command... commands)
throws Throwable {
- runDebugTest(
- DebuggeePath.makeDex(getDebuggeeDexD8()),
- Collections.<Path>emptyList(),
- debuggeeClass,
- Arrays.asList(commands));
- }
-
- protected final void runDebugTest(List<Path> extraPaths, String debuggeeClass,
- JUnit3Wrapper.Command... commands) throws Throwable {
- runDebugTest(
- DebuggeePath.makeDex(getDebuggeeDexD8()),
- extraPaths,
- debuggeeClass,
- Arrays.asList(commands));
+ runDebugTest(debuggeeClass, Arrays.asList(commands));
}
protected final void runDebugTest(String debuggeeClass, List<JUnit3Wrapper.Command> commands)
throws Throwable {
- runDebugTest(
- DebuggeePath.makeDex(getDebuggeeDexD8()),
- Collections.<Path>emptyList(),
- debuggeeClass,
- commands);
+ runInternal(new D8DebugTestResourcesConfig(temp), debuggeeClass, commands);
}
- protected final void runDebugTestJava8(String debuggeeClass, JUnit3Wrapper.Command... commands)
+ protected final void runDebugTest(
+ List<Path> extraPaths, String debuggeeClass, JUnit3Wrapper.Command... commands)
throws Throwable {
- runDebugTest(
- DebuggeePath.makeDex(getDebuggeeJava8DexD8()),
- Collections.<Path>emptyList(),
- debuggeeClass,
- Arrays.asList(commands));
- }
-
- protected final void runDebugTestJava8(String debuggeeClass, List<JUnit3Wrapper.Command> commands)
- throws Throwable {
- runDebugTest(
- DebuggeePath.makeDex(getDebuggeeJava8DexD8()),
- Collections.<Path>emptyList(),
- debuggeeClass,
- commands);
- }
-
- protected final void runDebugTestKotlin(String debuggeeClass, JUnit3Wrapper.Command... commands)
- throws Throwable {
- runDebugTest(
- DebuggeePath.makeDex(getDebuggeeKotlinDexD8()),
- Collections.<Path>emptyList(),
+ runInternal(
+ new D8DebugTestResourcesConfig(temp) {
+ @Override
+ public List<Path> getPaths() {
+ return new ImmutableList.Builder<Path>()
+ .addAll(super.getPaths())
+ .addAll(extraPaths)
+ .build();
+ }
+ },
debuggeeClass,
Arrays.asList(commands));
}
@@ -355,14 +251,13 @@
protected void runDebugTest(
DebuggeePath debuggeePath, String debuggeeClass, JUnit3Wrapper.Command... commands)
throws Throwable {
- runDebugTest(
- debuggeePath, Collections.<Path>emptyList(), debuggeeClass, Arrays.asList(commands));
+ runDebugTest(debuggeePath, ImmutableList.of(), debuggeeClass, Arrays.asList(commands));
}
protected void runDebugTest(
DebuggeePath debuggeePath, String debuggeeClass, List<JUnit3Wrapper.Command> commands)
throws Throwable {
- runDebugTest(debuggeePath, Collections.<Path>emptyList(), debuggeeClass, commands);
+ runDebugTest(debuggeePath, ImmutableList.of(), debuggeeClass, commands);
}
protected void runDebugTest(
@@ -380,6 +275,38 @@
String debuggeeClass,
List<JUnit3Wrapper.Command> commands)
throws Throwable {
+ DebugTestConfig debuggeeConfig;
+ if (debuggeePath.kind == DebugTestConfig.RuntimeKind.CF) {
+ debuggeeConfig =
+ new CfBaseDebugTestConfig() {
+ @Override
+ public List<Path> getPaths() {
+ return new ImmutableList.Builder<Path>()
+ .addAll(super.getPaths())
+ .addAll(extraPaths)
+ .add(debuggeePath.path)
+ .build();
+ }
+ };
+ } else {
+ debuggeeConfig =
+ new D8BaseDebugTestConfig(temp) {
+ @Override
+ public List<Path> getPaths() {
+ return new ImmutableList.Builder<Path>()
+ .addAll(super.getPaths())
+ .addAll(extraPaths)
+ .add(debuggeePath.path)
+ .build();
+ }
+ };
+ }
+ runInternal(debuggeeConfig, debuggeeClass, commands);
+ }
+
+ private void runInternal(
+ DebugTestConfig config, String debuggeeClass, List<JUnit3Wrapper.Command> commands)
+ throws Throwable {
// Skip test due to unsupported runtime.
Assume.assumeTrue("Skipping test " + testName.getMethodName() + " because ART is not supported",
ToolHelper.artSupported());
@@ -387,25 +314,19 @@
+ " because debug tests are not yet supported on Windows",
!ToolHelper.isWindows());
- String[] paths = new String[extraPaths.size() + 2];
- int indexPath = 0;
- ClassNameMapper classNameMapper = null;
- if (debuggeePath.kind == BinaryKind.CF) {
- paths[indexPath++] = JDWP_JAR.toString();
- } else {
- paths[indexPath++] = jdwpDexD8.toString();
- Path proguardMapPath = debuggeePath.path.resolveSibling(PROGUARD_MAP_FILENAME);
- if (Files.exists(proguardMapPath)) {
- classNameMapper = ClassNameMapper.mapperFromFile(proguardMapPath);
- }
- }
- paths[indexPath++] = debuggeePath.path.toString();
- for (Path extraPath : extraPaths) {
- paths[indexPath++] = extraPath.toString();
- }
+ ClassNameMapper classNameMapper =
+ config.getProguardMap() == null
+ ? null
+ : ClassNameMapper.mapperFromFile(config.getProguardMap());
- currentlyRunningBinaryKind = debuggeePath.kind;
- new JUnit3Wrapper(debuggeeClass, paths, commands, classNameMapper, isRunningArt()).runBare();
+ currentlyRunningBinaryKind = config.getRuntimeKind();
+ new JUnit3Wrapper(
+ debuggeeClass,
+ config.getPaths().stream().map(Path::toString).toArray(String[]::new),
+ commands,
+ classNameMapper,
+ isRunningArt())
+ .runBare();
}
protected final JUnit3Wrapper.Command run() {
diff --git a/src/test/java/com/android/tools/r8/debug/DebugTestConfig.java b/src/test/java/com/android/tools/r8/debug/DebugTestConfig.java
new file mode 100644
index 0000000..32df428
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debug/DebugTestConfig.java
@@ -0,0 +1,29 @@
+// Copyright (c) 2017, 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.debug;
+
+import java.nio.file.Path;
+import java.util.List;
+
+public abstract class DebugTestConfig {
+
+ public enum RuntimeKind {
+ CF,
+ DEX
+ }
+
+ public abstract RuntimeKind getRuntimeKind();
+
+ public abstract List<Path> getPaths();
+
+ public abstract Path getProguardMap();
+
+ public boolean isCfRuntime() {
+ return getRuntimeKind() == RuntimeKind.CF;
+ }
+
+ public boolean isDexRuntime() {
+ return getRuntimeKind() == RuntimeKind.DEX;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/debug/JasminDebugTest.java b/src/test/java/com/android/tools/r8/debug/JasminDebugTest.java
index 6f9c726..84af8f9 100644
--- a/src/test/java/com/android/tools/r8/debug/JasminDebugTest.java
+++ b/src/test/java/com/android/tools/r8/debug/JasminDebugTest.java
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.debug;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.D8Command;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.jasmin.JasminBuilder;
import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
@@ -13,6 +15,7 @@
import java.io.StringReader;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.junit.Rule;
@@ -22,7 +25,48 @@
// TODO(b/65474850) Should we build Jasmin at compile time or runtime ?
public class JasminDebugTest extends DebugTestBase {
- public static final boolean RUN_JAVA = false;
+ static class JasminTestConfig extends D8BaseDebugTestConfig {
+
+ public JasminTestConfig(TemporaryFolder temp, JasminBuilder builder) {
+ super(temp, compile(temp, builder));
+ }
+
+ private static Path compile(TemporaryFolder temp, JasminBuilder builder) {
+ try {
+ ImmutableList<ClassBuilder> classes = builder.getClasses();
+ File out = temp.newFolder();
+ List<Path> classFiles = new ArrayList<>(classes.size());
+ for (ClassBuilder clazz : classes) {
+ ClassFile file = new ClassFile();
+ file.readJasmin(new StringReader(clazz.toString()), clazz.name, false);
+ Path path = out.toPath().resolve(clazz.name + ".class");
+ Files.createDirectories(path.getParent());
+ try (OutputStream outputStream = Files.newOutputStream(path)) {
+ file.write(outputStream);
+ }
+ classFiles.add(path);
+ }
+ return compile(temp, classFiles);
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static Path compile(TemporaryFolder temp, List<Path> paths) throws Throwable {
+ int minSdk = ToolHelper.getMinApiLevelForDexVm(ToolHelper.getDexVm());
+ Path out = temp.newFolder().toPath().resolve("d8_jasmin.jar");
+ ToolHelper.runD8(
+ D8Command.builder()
+ .addProgramFiles(paths)
+ .setOutputPath(out)
+ .setMinApiLevel(minSdk)
+ .setMode(CompilationMode.DEBUG)
+ .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(minSdk)))
+ .build(),
+ null);
+ return out;
+ }
+ }
@Rule
public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
@@ -32,10 +76,8 @@
final String className = "UselessCheckCast";
final String sourcefile = className + ".j";
final String methodName = "test";
- List<Path> paths = getExtraPaths(getBuilderForUselessCheckcast(className, methodName));
runDebugTest(
- getDebuggeeDexD8OrCf(RUN_JAVA),
- paths,
+ new JasminTestConfig(temp, getBuilderForUselessCheckcast(className, methodName)),
className,
breakpoint(className, methodName),
run(),
@@ -81,27 +123,4 @@
return builder;
}
-
- private List<Path> getExtraPaths(JasminBuilder builder) throws Exception {
- ImmutableList<ClassBuilder> classes = builder.getClasses();
- List<Path> extraPaths = new ArrayList<>(classes.size());
- File out = temp.newFolder();
-
- for (ClassBuilder clazz : classes) {
- ClassFile file = new ClassFile();
- file.readJasmin(new StringReader(clazz.toString()), clazz.name, false);
- Path path = out.toPath().resolve(clazz.name + ".class");
- Files.createDirectories(path.getParent());
- try (OutputStream outputStream = Files.newOutputStream(path)) {
- file.write(outputStream);
- }
- if (RUN_JAVA) {
- extraPaths.add(path);
- } else {
- extraPaths.add(compileToDex(path, null));
- }
- }
-
- return extraPaths;
- }
}
diff --git a/src/test/java/com/android/tools/r8/debug/KotlinDebugTestBase.java b/src/test/java/com/android/tools/r8/debug/KotlinDebugTestBase.java
index a0a9c3f..50da158 100644
--- a/src/test/java/com/android/tools/r8/debug/KotlinDebugTestBase.java
+++ b/src/test/java/com/android/tools/r8/debug/KotlinDebugTestBase.java
@@ -4,16 +4,70 @@
package com.android.tools.r8.debug;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.D8Command;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.OutputMode;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import org.apache.harmony.jpda.tests.framework.jdwp.Frame.Variable;
import org.apache.harmony.jpda.tests.framework.jdwp.Location;
+import org.junit.BeforeClass;
+import org.junit.rules.TemporaryFolder;
/**
* A specialization for Kotlin-based tests which provides extra commands.
*/
public abstract class KotlinDebugTestBase extends DebugTestBase {
+ private static final Path DEBUGGEE_KOTLIN_JAR =
+ Paths.get(ToolHelper.BUILD_DIR, "test", "debug_test_resources_kotlin.jar");
+
+ protected static class KotlinD8Config extends D8BaseDebugTestConfig {
+
+ private static AndroidApp compiledResources = null;
+
+ private static synchronized AndroidApp getCompiledResources() throws Throwable {
+ if (compiledResources == null) {
+ int minSdk = ToolHelper.getMinApiLevelForDexVm(ToolHelper.getDexVm());
+ compiledResources =
+ ToolHelper.runD8(
+ D8Command.builder()
+ .addProgramFiles(DEBUGGEE_KOTLIN_JAR)
+ .setMinApiLevel(minSdk)
+ .setMode(CompilationMode.DEBUG)
+ .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(minSdk)))
+ .build());
+ }
+ return compiledResources;
+ }
+
+ public KotlinD8Config(TemporaryFolder temp) {
+ super(temp);
+ try {
+ Path out = temp.newFolder().toPath().resolve("d8_debug_test_resources_kotlin.jar");
+ getCompiledResources().write(out, OutputMode.Indexed);
+ addPaths(out);
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private static KotlinD8Config d8Config;
+
+ @BeforeClass
+ public static void setup() {
+ d8Config = new KotlinD8Config(temp);
+ }
+
+ protected KotlinD8Config getD8Config() {
+ return d8Config;
+ }
+
protected final JUnit3Wrapper.Command kotlinStepOver() {
return testBaseBeforeStep -> {
final JUnit3Wrapper.DebuggeeState debuggeeStateBeforeStep = testBaseBeforeStep
diff --git a/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java b/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java
index 8e9d145..cdba21b 100644
--- a/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java
+++ b/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java
@@ -7,7 +7,6 @@
import static org.junit.Assert.assertTrue;
import org.apache.harmony.jpda.tests.framework.jdwp.Value;
-import org.junit.Ignore;
import org.junit.Test;
// TODO check double-depth inline (an inline in another inline)
@@ -16,7 +15,9 @@
@Test
public void testStepOverInline() throws Throwable {
String methodName = "singleInline";
- runDebugTestKotlin("KotlinInline",
+ runDebugTest(
+ getD8Config(),
+ "KotlinInline",
breakpoint("KotlinInline", methodName),
run(),
inspect(s -> {
@@ -48,7 +49,9 @@
@Test
public void testStepIntoInline() throws Throwable {
String methodName = "singleInline";
- runDebugTestKotlin("KotlinInline",
+ runDebugTest(
+ getD8Config(),
+ "KotlinInline",
breakpoint("KotlinInline", methodName),
run(),
inspect(s -> {
@@ -84,7 +87,9 @@
@Test
public void testStepOutInline() throws Throwable {
String methodName = "singleInline";
- runDebugTestKotlin("KotlinInline",
+ runDebugTest(
+ getD8Config(),
+ "KotlinInline",
breakpoint("KotlinInline", methodName),
run(),
inspect(s -> {
@@ -121,7 +126,9 @@
@Test
public void testKotlinInline() throws Throwable {
final String inliningMethodName = "invokeInlinedFunctions";
- runDebugTestKotlin("KotlinInline",
+ runDebugTest(
+ getD8Config(),
+ "KotlinInline",
breakpoint("KotlinInline", inliningMethodName),
run(),
inspect(s -> {
diff --git a/src/test/java/com/android/tools/r8/debug/KotlinTest.java b/src/test/java/com/android/tools/r8/debug/KotlinTest.java
index 2baa426..5623d6d 100644
--- a/src/test/java/com/android/tools/r8/debug/KotlinTest.java
+++ b/src/test/java/com/android/tools/r8/debug/KotlinTest.java
@@ -14,7 +14,9 @@
// TODO(shertz) add more variables ?
@Test
public void testStepOver() throws Throwable {
- runDebugTestKotlin("KotlinApp",
+ runDebugTest(
+ getD8Config(),
+ "KotlinApp",
breakpoint("KotlinApp$Companion", "main"),
run(),
inspect(s -> {
@@ -44,7 +46,9 @@
@Test
public void testStepIntoAndOut() throws Throwable {
- runDebugTestKotlin("KotlinApp",
+ runDebugTest(
+ getD8Config(),
+ "KotlinApp",
breakpoint("KotlinApp$Companion", "main"),
run(),
inspect(s -> {
diff --git a/src/test/java/com/android/tools/r8/debug/LocalsTest.java b/src/test/java/com/android/tools/r8/debug/LocalsTest.java
index 76f8870..f240875 100644
--- a/src/test/java/com/android/tools/r8/debug/LocalsTest.java
+++ b/src/test/java/com/android/tools/r8/debug/LocalsTest.java
@@ -12,7 +12,6 @@
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants.Tag;
import org.apache.harmony.jpda.tests.framework.jdwp.Value;
import org.junit.Assert;
-import org.junit.Ignore;
import org.junit.Test;
/**
@@ -20,8 +19,6 @@
*/
public class LocalsTest extends DebugTestBase {
- private static final boolean RUN_JAVA = false;
-
public static final String SOURCE_FILE = "Locals.java";
@Test
@@ -726,6 +723,6 @@
commands.add(checkLocal("i", Value.createInt(0)));
commands.add(run());
- runDebugTest(getDebuggeeDexD8OrCf(RUN_JAVA), className, commands);
+ runDebugTest(className, commands);
}
}
diff --git a/src/test/java/com/android/tools/r8/debug/MinificationTest.java b/src/test/java/com/android/tools/r8/debug/MinificationTest.java
index 1e439c7..3b1985a 100644
--- a/src/test/java/com/android/tools/r8/debug/MinificationTest.java
+++ b/src/test/java/com/android/tools/r8/debug/MinificationTest.java
@@ -3,20 +3,20 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.debug;
-import com.android.tools.r8.CompilationException;
import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.ProguardRuleParserException;
-import com.android.tools.r8.utils.CompilationFailedException;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.origin.Origin;
import com.google.common.collect.ImmutableList;
-import java.io.IOException;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
-import java.util.concurrent.ExecutionException;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -24,22 +24,7 @@
@RunWith(Parameterized.class)
public class MinificationTest extends DebugTestBase {
- public static final String SOURCE_FILE = "Minified.java";
- private static final HashMap<Config, Path> debuggeePathMap = new HashMap<>();
-
- private static class Config {
- public final MinifyMode minificationMode;
- public final boolean writeProguardMap;
-
- Config(MinifyMode minificationMode, boolean writeProguardMap) {
- this.minificationMode = minificationMode;
- this.writeProguardMap = writeProguardMap;
- }
-
- public boolean minifiedNames() {
- return minificationMode.isMinify() && !writeProguardMap;
- }
- }
+ private static final String SOURCE_FILE = "Minified.java";
@Parameterized.Parameters(name = "minification: {0}, proguardMap: {1}")
public static Collection minificationControl() {
@@ -53,51 +38,68 @@
return builder.build();
}
- private final Config config;
+ @Rule
+ public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
- private synchronized DebuggeePath getDebuggeePath()
- throws IOException, CompilationException, ExecutionException, ProguardRuleParserException,
- CompilationFailedException {
- Path path = debuggeePathMap.get(config);
- if (path == null) {
- List<String> proguardConfigurations = Collections.<String>emptyList();
- if (config.minificationMode.isMinify()) {
- ImmutableList.Builder<String> builder = ImmutableList.builder();
- builder.add("-keep public class Minified { public static void main(java.lang.String[]); }");
- builder.add("-keepattributes SourceFile");
- builder.add("-keepattributes LineNumberTable");
- if (config.minificationMode == MinifyMode.AGGRESSIVE) {
- builder.add("-overloadaggressively");
- }
- proguardConfigurations = builder.build();
- }
- path =
- compileToDexViaR8(
- null,
- null,
- DEBUGGEE_JAR,
- proguardConfigurations,
- config.writeProguardMap,
- CompilationMode.DEBUG);
- debuggeePathMap.put(config, path);
- }
- return DebuggeePath.makeDex(path);
- }
+ private final MinifyMode minificationMode;
+ private final boolean writeProguardMap;
public MinificationTest(MinifyMode minificationMode, boolean writeProguardMap) throws Exception {
- config = new Config(minificationMode, writeProguardMap);
+ this.minificationMode = minificationMode;
+ this.writeProguardMap = writeProguardMap;
+ }
+
+ private boolean minifiedNames() {
+ return minificationMode.isMinify() && !writeProguardMap;
+ }
+
+ private DebugTestConfig getTestConfig() throws Throwable {
+ List<String> proguardConfigurations = Collections.emptyList();
+ if (minificationMode.isMinify()) {
+ ImmutableList.Builder<String> builder = ImmutableList.builder();
+ builder.add("-keep public class Minified { public static void main(java.lang.String[]); }");
+ builder.add("-keepattributes SourceFile");
+ builder.add("-keepattributes LineNumberTable");
+ if (minificationMode == MinifyMode.AGGRESSIVE) {
+ builder.add("-overloadaggressively");
+ }
+ proguardConfigurations = builder.build();
+ }
+
+ int minSdk = ToolHelper.getMinApiLevelForDexVm(ToolHelper.getDexVm());
+ Path dexOutputDir = temp.newFolder().toPath();
+ Path proguardMap = writeProguardMap ? dexOutputDir.resolve("proguard.map") : null;
+ R8Command.Builder builder =
+ R8Command.builder()
+ .addProgramFiles(DEBUGGEE_JAR)
+ .setOutputPath(dexOutputDir)
+ .setMinApiLevel(minSdk)
+ .setMode(CompilationMode.DEBUG)
+ .addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(minSdk)));
+ if (proguardMap != null) {
+ builder.setProguardMapOutput(proguardMap);
+ }
+ if (!proguardConfigurations.isEmpty()) {
+ builder.addProguardConfiguration(proguardConfigurations, Origin.unknown());
+ }
+ ToolHelper.runR8(builder.build());
+
+ D8BaseDebugTestConfig config =
+ new D8BaseDebugTestConfig(temp, dexOutputDir.resolve("classes.dex"));
+ config.setProguardMap(proguardMap);
+ return config;
}
@Test
public void testBreakInMainClass() throws Throwable {
final String className = "Minified";
- final String methodName = config.minifiedNames() ? "a" : "test";
+ final String methodName = minifiedNames() ? "a" : "test";
final String signature = "()V";
- final String innerClassName = config.minifiedNames() ? "a" : "Minified$Inner";
- final String innerMethodName = config.minifiedNames() ? "a" : "innerTest";
+ final String innerClassName = minifiedNames() ? "a" : "Minified$Inner";
+ final String innerMethodName = minifiedNames() ? "a" : "innerTest";
final String innerSignature = "()I";
runDebugTest(
- getDebuggeePath(),
+ getTestConfig(),
className,
breakpoint(className, methodName, signature),
run(),
@@ -115,11 +117,11 @@
@Test
public void testBreakInPossiblyRenamedClass() throws Throwable {
final String className = "Minified";
- final String innerClassName = config.minifiedNames() ? "a" : "Minified$Inner";
- final String innerMethodName = config.minifiedNames() ? "a" : "innerTest";
+ final String innerClassName = minifiedNames() ? "a" : "Minified$Inner";
+ final String innerMethodName = minifiedNames() ? "a" : "innerTest";
final String innerSignature = "()I";
runDebugTest(
- getDebuggeePath(),
+ getTestConfig(),
className,
breakpoint(innerClassName, innerMethodName, innerSignature),
run(),
diff --git a/src/test/java/com/android/tools/r8/debuginfo/DebugInfoTestBase.java b/src/test/java/com/android/tools/r8/debuginfo/DebugInfoTestBase.java
index 36f1b29..3e380fe 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/DebugInfoTestBase.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/DebugInfoTestBase.java
@@ -28,7 +28,7 @@
Paths.get(ToolHelper.BUILD_DIR, "test", "debuginfo_examples_dex.jar");
@Rule
- public TemporaryFolder temp = new TemporaryFolder();
+ public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
static AndroidApp compileWithD8(Class... classes) throws CompilationException, IOException,
CompilationFailedException {
diff --git a/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java b/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
index dfb3fd1..4b011a2 100644
--- a/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
+++ b/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
@@ -232,7 +232,7 @@
private static File d8Out = null;
@ClassRule
- public static TemporaryFolder temp = new TemporaryFolder();
+ public static TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
@BeforeClass
public static void compileLibraries() throws Exception {
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index 0fe9e75..1c55379 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -94,7 +94,8 @@
private static List<String> MANY_CLASSES;
@ClassRule
- public static TemporaryFolder generatedApplicationsFolder = new TemporaryFolder();
+ public static TemporaryFolder generatedApplicationsFolder =
+ ToolHelper.getTemporaryFolderForTest();
// Generate the test applications in a @BeforeClass method, as they are used by several tests.
@BeforeClass
diff --git a/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java b/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
index 41370d4..3b0a933 100644
--- a/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
+++ b/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
@@ -48,7 +48,7 @@
Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, "applymapping044" + FileUtils.JAR_EXTENSION);
@Rule
- public TemporaryFolder temp = new TemporaryFolder();
+ public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
private Path out;
diff --git a/src/test/java/com/android/tools/r8/regress/Regress37740372.java b/src/test/java/com/android/tools/r8/regress/Regress37740372.java
index 5258b31..1f13013 100644
--- a/src/test/java/com/android/tools/r8/regress/Regress37740372.java
+++ b/src/test/java/com/android/tools/r8/regress/Regress37740372.java
@@ -9,7 +9,10 @@
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.D8Command;
+import com.android.tools.r8.D8Command.Builder;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.origin.EmbeddedOrigin;
+import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.smali.SmaliTestBase;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DexInspector;
@@ -133,14 +136,16 @@
AndroidApp output =
ToolHelper.runD8(
D8Command.builder()
- .addClassProgramData(Base64.getDecoder().decode(javaLangObjectClassFile))
+ .addClassProgramData(Base64.getDecoder().decode(javaLangObjectClassFile),
+ EmbeddedOrigin.INSTANCE)
.build());
checkApplicationOnlyHasJavaLangObject(output);
// Build an application with the java.lang.Object stub from a dex file.
List<byte[]> dex = output.writeToMemory();
assertEquals(1, dex.size());
- checkApplicationOnlyHasJavaLangObject(
- ToolHelper.runD8(D8Command.builder().addDexProgramData(dex).build()));
+ Builder builder = D8Command.builder();
+ dex.forEach(data -> builder.addDexProgramData(data, Origin.unknown()));
+ checkApplicationOnlyHasJavaLangObject(ToolHelper.runD8(builder.build()));
}
}
diff --git a/src/test/java/com/android/tools/r8/rewrite/staticvalues/inlibraries/StaticLibraryValuesChangeTest.java b/src/test/java/com/android/tools/r8/rewrite/staticvalues/inlibraries/StaticLibraryValuesChangeTest.java
index 76c24f9..dd07b68 100644
--- a/src/test/java/com/android/tools/r8/rewrite/staticvalues/inlibraries/StaticLibraryValuesChangeTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/staticvalues/inlibraries/StaticLibraryValuesChangeTest.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.jasmin.JasminBuilder;
+import com.android.tools.r8.origin.EmbeddedOrigin;
import com.android.tools.r8.shaking.FilteredClassPath;
import com.android.tools.r8.smali.SmaliBuilder;
import com.android.tools.r8.utils.AndroidApp;
@@ -75,7 +76,7 @@
// Merge the compiled TestMain with the runtime version of LibraryClass.
builder = AndroidApp.builder(app);
- builder.addDexProgramData(runtimeLibrary.compile());
+ builder.addDexProgramData(runtimeLibrary.compile(), EmbeddedOrigin.INSTANCE);
String result = runOnArt(builder.build(), TestMain.class);
assertEquals("33", result);
}
diff --git a/src/test/java/com/android/tools/r8/smali/SmaliBuildTest.java b/src/test/java/com/android/tools/r8/smali/SmaliBuildTest.java
index 8e946b6..fa08ece 100644
--- a/src/test/java/com/android/tools/r8/smali/SmaliBuildTest.java
+++ b/src/test/java/com/android/tools/r8/smali/SmaliBuildTest.java
@@ -7,6 +7,7 @@
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.origin.EmbeddedOrigin;
import com.android.tools.r8.shaking.FilteredClassPath;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DexInspector;
@@ -60,7 +61,7 @@
);
AndroidApp originalApp = AndroidApp.builder()
- .addDexProgramData(builder.compile())
+ .addDexProgramData(builder.compile(), EmbeddedOrigin.INSTANCE)
.addLibraryFiles(FilteredClassPath.unfiltered(ToolHelper.getDefaultAndroidJar()))
.build();
diff --git a/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java b/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java
index e16b172..01b2af4 100644
--- a/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java
+++ b/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java
@@ -18,6 +18,7 @@
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.origin.EmbeddedOrigin;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.FilteredClassPath;
import com.android.tools.r8.shaking.ProguardConfiguration;
@@ -55,7 +56,7 @@
protected AndroidApp buildApplicationWithAndroidJar(SmaliBuilder builder) {
try {
return AndroidApp.builder()
- .addDexProgramData(builder.compile())
+ .addDexProgramData(builder.compile(), EmbeddedOrigin.INSTANCE)
.addLibraryFiles(FilteredClassPath.unfiltered(ToolHelper.getDefaultAndroidJar()))
.build();
} catch (IOException | RecognitionException | ExecutionException | DexOverflowException e) {
@@ -98,7 +99,7 @@
Path dexOutputDir = temp.newFolder().toPath();
R8Command command =
R8Command.builder()
- .addDexProgramData(builder.compile())
+ .addDexProgramData(builder.compile(), EmbeddedOrigin.INSTANCE)
.setOutputPath(dexOutputDir)
.setMode(CompilationMode.DEBUG)
.addLibraryFiles(Paths.get(ToolHelper.getDefaultAndroidJar()))
diff --git a/tests/api_usage_sample.jar b/tests/api_usage_sample.jar
index 51029b5..3b7d14a 100644
--- a/tests/api_usage_sample.jar
+++ b/tests/api_usage_sample.jar
Binary files differ
diff --git a/tools/archive.py b/tools/archive.py
index 20d057c..8e7436b 100755
--- a/tools/archive.py
+++ b/tools/archive.py
@@ -65,10 +65,15 @@
def Main():
if not 'BUILDBOT_BUILDERNAME' in os.environ:
raise Exception('You are not a bot, don\'t archive builds')
+ # Create maven release first which uses a build that exclude dependencies.
+ create_maven_release.main(["--out", utils.LIBS])
+
+ # Generate and copy the build that exclude dependencies.
+ gradle.RunGradleExcludeDeps([utils.R8])
+ shutil.copyfile(utils.R8_JAR, utils.R8_EXCLUDE_DEPS_JAR)
+
# Ensure all archived artifacts has been built before archiving.
gradle.RunGradle([utils.D8, utils.R8, utils.COMPATDX, utils.COMPATPROGUARD])
- create_maven_release.main(['--jar', utils.R8_JAR, "--out", utils.LIBS])
-
version = GetVersion()
is_master = IsMaster(version)
if is_master:
@@ -86,6 +91,7 @@
for file in [utils.D8_JAR,
utils.R8_JAR,
+ utils.R8_EXCLUDE_DEPS_JAR,
utils.COMPATDX_JAR,
utils.COMPATPROGUARD_JAR,
utils.MAVEN_ZIP]:
diff --git a/tools/create_maven_release.py b/tools/create_maven_release.py
index 85b558a..cc045a2 100755
--- a/tools/create_maven_release.py
+++ b/tools/create_maven_release.py
@@ -3,8 +3,9 @@
# 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.
-import hashlib
import argparse
+import gradle
+import hashlib
from os import makedirs
from os.path import join
from shutil import copyfile, make_archive, rmtree
@@ -14,13 +15,13 @@
import tempfile
import utils
-LICENSETEMPLATE = Template(
+DEPENDENCYTEMPLATE = Template(
"""
- <license>
- <name>$name</name>
- <url>$url</url>
- <distribution>repo</distribution>
- </license>""")
+ <dependency>
+ <groupId>$group</groupId>
+ <artifactId>$artifact</artifactId>
+ <version>$version</version>
+ </dependency>""")
POMTEMPLATE = Template(
"""<project
@@ -42,8 +43,10 @@
<name>BSD-3-Clause</name>
<url>https://opensource.org/licenses/BSD-3-Clause</url>
<distribution>repo</distribution>
- </license>$library_licenses
+ </license>
</licenses>
+ <dependencies>$dependencies
+ </dependencies>
<developers>
<developer>
<name>The Android Open Source Project</name>
@@ -62,19 +65,19 @@
def parse_options(argv):
result = argparse.ArgumentParser()
- result.add_argument('--jar', help='jar file to package')
result.add_argument('--out', help='directory in which to put the output zip file')
return result.parse_args(argv)
-def determine_version(jar):
- cmd = []
- cmd.append('java')
- cmd.extend(['-jar', jar]);
- cmd.append('--version')
- output = subprocess.check_output(cmd)
- version_string = output.split()[1]
- assert version_string.startswith("v")
- return version_string[1:]
+def determine_version():
+ version_file = join(
+ utils.SRC_ROOT, 'com', 'android', 'tools', 'r8', 'Version.java')
+ with open(version_file, 'r') as file:
+ for line in file:
+ if 'final String LABEL ' in line:
+ result = line[line.find('"v') + 2:]
+ result = result[:result.find('"')]
+ return result
+ raise Exception('Unable to determine version.')
def generate_library_licenses():
license_prefix = 'license: '
@@ -103,9 +106,76 @@
result += LICENSETEMPLATE.substitute(name=name, url=url)
return result
+
+# Generate the dependencies block for the pom file.
+#
+# We ask gradle to list all dependencies. In that output
+# we locate the runtimeClasspath block for 'main' which
+# looks something like:
+#
+# runtimeClasspath - Runtime classpath of source set 'main'.
+# +--- net.sf.jopt-simple:jopt-simple:4.6
+# +--- com.googlecode.json-simple:json-simple:1.1
+# +--- com.google.guava:guava:23.0
+# +--- it.unimi.dsi:fastutil:7.2.0
+# +--- org.ow2.asm:asm:6.0
+# +--- org.ow2.asm:asm-commons:6.0
+# | \--- org.ow2.asm:asm-tree:6.0
+# | \--- org.ow2.asm:asm:6.0
+# +--- org.ow2.asm:asm-tree:6.0 (*)
+# +--- org.ow2.asm:asm-analysis:6.0
+# | \--- org.ow2.asm:asm-tree:6.0 (*)
+# \--- org.ow2.asm:asm-util:6.0
+# \--- org.ow2.asm:asm-tree:6.0 (*)
+#
+# We filter out the repeats that are marked by '(*)'.
+#
+# For each remaining line, we remove the junk at the start
+# in chunks. As an example:
+#
+# ' | \--- org.ow2.asm:asm-tree:6.0 ' --strip-->
+# '| \--- org.ow2.asm:asm-tree:6.0' -->
+# '\--- org.ow2.asm:asm-tree:6.0' -->
+# 'org.ow2.asm:asm-tree:6.0'
+#
+# The end result is the dependency we are looking for:
+#
+# groupId: org.ow2.asm
+# artifact: asm-tree
+# version: 6.0
+def generate_dependencies():
+ dependencies = gradle.RunGradleGetOutput(['dependencies'])
+ dependency_lines = []
+ collect = False
+ for line in dependencies.splitlines():
+ if 'runtimeClasspath' in line and "'main'" in line:
+ collect = True
+ continue
+ if collect:
+ if not len(line) == 0:
+ if not '(*)' in line:
+ trimmed = line.strip()
+ while trimmed.find(' ') != -1:
+ trimmed = trimmed[trimmed.find(' ') + 1:].strip()
+ if not trimmed in dependency_lines:
+ dependency_lines.append(trimmed)
+ else:
+ break
+ result = ''
+ for dep in dependency_lines:
+ components = dep.split(':')
+ assert len(components) == 3
+ group = components[0]
+ artifact = components[1]
+ version = components[2]
+ result += DEPENDENCYTEMPLATE.substitute(
+ group=group, artifact=artifact, version=version)
+ return result
+
def write_pom_file(version, pom_file):
- library_licenses = generate_library_licenses()
- version_pom = POMTEMPLATE.substitute(version=version, library_licenses=library_licenses)
+ dependencies = generate_dependencies()
+ version_pom = POMTEMPLATE.substitute(
+ version=version, dependencies=dependencies)
with open(pom_file, 'w') as file:
file.write(version_pom)
@@ -131,13 +201,14 @@
def main(argv):
options = parse_options(argv)
- jar = options.jar
outdir = options.out
- if jar == None or outdir == None:
- print 'Need to supply --jar and --out.'
+ if outdir == None:
+ print 'Need to supply output dir with --out.'
exit(1)
+ # Build the R8 no deps artifact.
+ gradle.RunGradleExcludeDeps([utils.R8])
# Create directory structure for this version.
- version = determine_version(jar)
+ version = determine_version()
with utils.TempDir() as tmp_dir:
version_dir = join(
tmp_dir, 'com', 'google', 'android', 'tools', 'r8', version, 'r8')
@@ -147,7 +218,7 @@
write_pom_file(version, pom_file)
# Copy the jar to the output.
target_jar = join(version_dir, 'r8-' + version + '.jar')
- copyfile(jar, target_jar)
+ copyfile(utils.R8_JAR, target_jar)
# Create check sums.
write_md5_for(target_jar)
write_md5_for(pom_file)
diff --git a/tools/gradle.py b/tools/gradle.py
index 275c270..df80cc9 100755
--- a/tools/gradle.py
+++ b/tools/gradle.py
@@ -54,9 +54,12 @@
else:
print 'gradle.py: Shadow library present'
-def RunGradle(args, throw_on_failure=True):
+def EnsureDeps():
EnsureGradle()
EnsureShadow()
+
+def RunGradle(args, throw_on_failure=True):
+ EnsureDeps()
cmd = [GRADLE]
cmd.extend(args)
utils.PrintCmd(cmd)
@@ -66,6 +69,19 @@
raise
return return_value
+def RunGradleExcludeDeps(args, throw_on_failure=True):
+ EnsureDeps()
+ args.append('-Pexclude_deps')
+ RunGradle(args, throw_on_failure)
+
+def RunGradleGetOutput(args):
+ EnsureDeps()
+ cmd = [GRADLE]
+ cmd.extend(args)
+ utils.PrintCmd(cmd)
+ with utils.ChangedWorkingDirectory(utils.REPO_ROOT):
+ return subprocess.check_output(cmd)
+
def Main():
RunGradle(sys.argv[1:])
diff --git a/tools/utils.py b/tools/utils.py
index 40a62b8..cf01d3b 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -20,6 +20,7 @@
DEX_SEGMENTS_RESULT_PATTERN = re.compile('- ([^:]+): ([0-9]+)')
LIBS = os.path.join(REPO_ROOT, 'build', 'libs')
MAVEN_ZIP = os.path.join(LIBS, 'r8.zip')
+SRC_ROOT = os.path.join(REPO_ROOT, 'src', 'main', 'java')
D8 = 'd8'
R8 = 'r8'
@@ -28,6 +29,7 @@
D8_JAR = os.path.join(LIBS, 'd8.jar')
R8_JAR = os.path.join(LIBS, 'r8.jar')
+R8_EXCLUDE_DEPS_JAR = os.path.join(LIBS, 'r8-exclude-deps.jar')
COMPATDX_JAR = os.path.join(LIBS, 'compatdx.jar')
COMPATPROGUARD_JAR = os.path.join(LIBS, 'compatproguard.jar')