Revert "Lookup in library classes before program classes"
This reverts commit d62e2d5b59aaaa5ba06fec796670297a29896853.
Reason for revert: Failure on Android Platform build. b/120884788#comment6
Change-Id: Icc0503085dc1688087bc243ff712c478cbb4fb04
diff --git a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
index a5d9143..fbfb968 100644
--- a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.DataResourceProvider;
import com.android.tools.r8.graph.LazyLoadedDexApplication.AllClasses;
import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.utils.ProgramClassCollection;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -130,9 +131,9 @@
super(application);
// As a side-effect, this will force-load all classes.
AllClasses allClasses = application.loadAllClasses();
+ assert application.programClasses().equals(allClasses.getProgramClasses());
libraryClasses = allClasses.getLibraryClasses();
classpathClasses = allClasses.getClasspathClasses();
- replaceProgramClasses(allClasses.getProgramClasses());
}
private Builder(DirectMappedDexApplication application) {
@@ -149,10 +150,15 @@
@Override
public DexApplication build() {
// Rebuild the map. This will fail if keys are not unique.
+ // TODO(zerny): It seems weird that we have conflict resolution here.
+ ImmutableList<DexProgramClass> newProgramClasses =
+ ImmutableList.copyOf(
+ ProgramClassCollection.create(
+ programClasses, ProgramClassCollection::resolveClassConflictImpl)
+ .getAllClasses());
// TODO(zerny): Consider not rebuilding the map if no program classes are added.
- Map<DexType, DexClass> allClasses =
- new IdentityHashMap<>(
- programClasses.size() + classpathClasses.size() + libraryClasses.size());
+ Map<DexType, DexClass> allClasses = new IdentityHashMap<>(
+ newProgramClasses.size() + classpathClasses.size() + libraryClasses.size());
// Note: writing classes in reverse priority order, so a duplicate will be correctly ordered.
// There should never be duplicates and that is asserted in the addAll subroutine.
addAll(allClasses, libraryClasses);
@@ -161,7 +167,7 @@
return new DirectMappedDexApplication(
proguardMap,
allClasses,
- ImmutableList.copyOf(programClasses),
+ newProgramClasses,
classpathClasses,
libraryClasses,
ImmutableList.copyOf(dataResourceProviders),
diff --git a/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java b/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
index b037db7..a58b9ac 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
@@ -60,16 +60,13 @@
@Override
public DexClass definitionFor(DexType type) {
assert type.isClassType() : "Cannot lookup definition for type: " + type;
- DexClass clazz = null;
- if (libraryClasses != null) {
- clazz = libraryClasses.get(type);
- }
- if (clazz == null) {
- clazz = programClasses.get(type);
- }
+ DexClass clazz = programClasses.get(type);
if (clazz == null && classpathClasses != null) {
clazz = classpathClasses.get(type);
}
+ if (clazz == null && libraryClasses != null) {
+ clazz = libraryClasses.get(type);
+ }
return clazz;
}
@@ -92,24 +89,16 @@
LibraryClassCollection libraryClassesLoader,
ClasspathClassCollection classpathClassesLoader,
ProgramClassCollection programClassesLoader) {
- int expectedMaxSize = 0;
-
- // Force-load library classes.
- Map<DexType, DexLibraryClass> allLibraryClasses = null;
- if (libraryClassesLoader != null) {
- libraryClassesLoader.forceLoad(type -> true);
- allLibraryClasses = libraryClassesLoader.getAllClassesInMap();
- expectedMaxSize += allLibraryClasses.size();
- }
-
- // Program classes should be fully loaded.
+ // Collect loaded classes in the precedence order program classes, class path classes and
+ // library classes.
+ // TODO(b/120884788): Change library priority.
assert programClassesLoader != null;
- assert programClassesLoader.isFullyLoaded();
+ // Program classes are supposed to be loaded, but force-loading them is no-op.
programClassesLoader.forceLoad(type -> true);
Map<DexType, DexProgramClass> allProgramClasses = programClassesLoader.getAllClassesInMap();
- expectedMaxSize += allProgramClasses.size();
+ int expectedMaxSize = allProgramClasses.size();
+ programClasses = ImmutableList.copyOf(allProgramClasses.values());
- // Force-load classpath classes.
Map<DexType, DexClasspathClass> allClasspathClasses = null;
if (classpathClassesLoader != null) {
classpathClassesLoader.forceLoad(type -> true);
@@ -117,36 +106,16 @@
expectedMaxSize += allClasspathClasses.size();
}
+ Map<DexType, DexLibraryClass> allLibraryClasses = null;
+ if (libraryClassesLoader != null) {
+ libraryClassesLoader.forceLoad(type -> true);
+ allLibraryClasses = libraryClassesLoader.getAllClassesInMap();
+ expectedMaxSize += allLibraryClasses.size();
+ }
- // Collect loaded classes in the precedence order library classes, program classes and
- // class path classes.
// Note: using hash map for building as the immutable builder does not support contains.
Map<DexType, DexClass> prioritizedClasses = new IdentityHashMap<>(expectedMaxSize);
- if (allLibraryClasses != null) {
- ImmutableList.Builder<DexLibraryClass> builder = ImmutableList.builder();
- allLibraryClasses.forEach(
- (type, clazz) -> {
- if (!prioritizedClasses.containsKey(type)) {
- prioritizedClasses.put(type, clazz);
- builder.add(clazz);
- }
- });
- libraryClasses = builder.build();
- } else {
- libraryClasses = ImmutableList.of();
- }
-
- {
- ImmutableList.Builder<DexProgramClass> builder = ImmutableList.builder();
- allProgramClasses.forEach(
- (type, clazz) -> {
- if (!prioritizedClasses.containsKey(type)) {
- prioritizedClasses.put(type, clazz);
- builder.add(clazz);
- }
- });
- programClasses = builder.build();
- }
+ prioritizedClasses.putAll(allProgramClasses);
if (allClasspathClasses != null) {
ImmutableList.Builder<DexClasspathClass> builder = ImmutableList.builder();
@@ -162,10 +131,20 @@
classpathClasses = ImmutableList.of();
}
+ if (allLibraryClasses != null) {
+ ImmutableList.Builder<DexLibraryClass> builder = ImmutableList.builder();
+ allLibraryClasses.forEach(
+ (type, clazz) -> {
+ if (!prioritizedClasses.containsKey(type)) {
+ prioritizedClasses.put(type, clazz);
+ builder.add(clazz);
+ }
+ });
+ libraryClasses = builder.build();
+ } else {
+ libraryClasses = ImmutableList.of();
+ }
allClasses = Collections.unmodifiableMap(prioritizedClasses);
-
- assert prioritizedClasses.size()
- == libraryClasses.size() + classpathClasses.size() + programClasses.size();
}
public Map<DexType, DexClass> getAllClasses() {
diff --git a/src/main/java/com/android/tools/r8/utils/ClassMap.java b/src/main/java/com/android/tools/r8/utils/ClassMap.java
index 416b389..d8366df 100644
--- a/src/main/java/com/android/tools/r8/utils/ClassMap.java
+++ b/src/main/java/com/android/tools/r8/utils/ClassMap.java
@@ -163,10 +163,10 @@
ClassProvider<T> classProvider;
// Cache value of class provider, as it might change concurrently.
- if (isFullyLoaded()) {
+ classProvider = this.classProvider.get();
+ if (classProvider == null) {
return;
}
- classProvider = this.classProvider.get();
// Collects the types which might be represented in fully loaded class map.
knownClasses = Sets.newIdentityHashSet();
@@ -224,10 +224,6 @@
}
}
- public boolean isFullyLoaded() {
- return this.classProvider.get() == null;
- }
-
// Supplier implementing a thread-safe loader for a class loaded from a
// class provider. Helps avoid synchronizing on the whole class map
// when loading a class.
diff --git a/src/test/java/com/android/tools/r8/JunitAvailabilityInHostArtTest.java b/src/test/java/com/android/tools/r8/JunitAvailabilityInHostArtTest.java
deleted file mode 100644
index 9e82042..0000000
--- a/src/test/java/com/android/tools/r8/JunitAvailabilityInHostArtTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2019, 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 static org.hamcrest.CoreMatchers.containsString;
-import static org.junit.Assume.assumeTrue;
-
-import com.android.tools.r8.ToolHelper.DexVm;
-import com.android.tools.r8.utils.StringUtils;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-@RunWith(Parameterized.class)
-public class JunitAvailabilityInHostArtTest extends TestBase {
-
- private final TestParameters parameters;
-
- @Parameterized.Parameters(name = "{0}")
- public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimes().withAllApiLevels().build();
- }
-
- public JunitAvailabilityInHostArtTest(TestParameters parameters) {
- this.parameters = parameters;
- }
-
- // It of the Art host VMs only 5.1.1 and 6.0.1 have junit.framework.Assert present at runtime.
- private void checkResult(TestRunResult<?> result) {
- if (parameters.getRuntime().isDex()
- && ((parameters.getRuntime().asDex().getVm() == DexVm.ART_6_0_1_HOST)
- || (parameters.getRuntime().asDex().getVm() == DexVm.ART_5_1_1_HOST))) {
- result.assertSuccessWithOutput(StringUtils.lines("class junit.framework.Assert"));
- } else {
- result.assertFailureWithErrorThatMatches(containsString("ClassNotFoundException"));
- }
- }
-
- @Test
- public void test() throws Exception {
- testForR8(parameters.getBackend())
- .addInnerClasses(JunitAvailabilityInHostArtTest.class)
- .addKeepMainRule(TestClass.class)
- .setMinApi(parameters.getRuntime())
- .compile()
- .run(parameters.getRuntime(), TestClass.class)
- .apply(this::checkResult);
- }
-
- @Test
- public void testD8() throws Exception {
- assumeTrue("Only run D8 for Dex backend", parameters.getBackend() == Backend.DEX);
- testForD8()
- .addInnerClasses(JunitAvailabilityInHostArtTest.class)
- .setMinApi(parameters.getRuntime())
- .compile()
- .run(parameters.getRuntime(), TestClass.class)
- .apply(this::checkResult);
- }
-
- static class TestClass {
-
- public static void main(String[] args) throws Exception {
- System.out.println(Class.forName("junit.framework.Assert"));
- }
- }
-
- static class A {}
-}
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
index 67a4573..afba9d9 100644
--- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -764,7 +764,6 @@
.match(TestCondition
.runtimes(DexVm.Version.V4_0_4, DexVm.Version.V4_4_4, DexVm.Version.V5_1_1,
DexVm.Version.V6_0_1));
- // TODO(herhut): Change to V8_0_0 once we have a new art VM.
private static final TestCondition beforeAndroidO =
TestCondition.match(TestCondition.runtimesUpTo(DexVm.Version.V7_0_0));
// TODO(herhut): Change to V8_0_0 once we have a new art VM.
@@ -913,26 +912,6 @@
CompilerUnderTest.D8_AFTER_R8CF),
TestCondition.runtimes(DexVm.Version.V4_0_4, DexVm.Version.V4_4_4))))
.put("979-const-method-handle", beforeAndroidP)
- // Missing class junit.framework.Assert (see JunitAvailabilityInHostArtTest).
- .put(
- "021-string2",
- TestCondition.or(
- TestCondition.match(
- TestCondition.compilers(CompilerUnderTest.D8_AFTER_R8CF),
- TestCondition.runtimesFrom(DexVm.Version.V7_0_0)),
- TestCondition.match(
- TestCondition.compilers(CompilerUnderTest.D8_AFTER_R8CF),
- TestCondition.runtimes(DexVm.Version.V4_0_4, DexVm.Version.V4_4_4))))
- // Missing class junit.framework.Assert (see JunitAvailabilityInHostArtTest).
- .put(
- "082-inline-execute",
- TestCondition.or(
- TestCondition.match(
- TestCondition.compilers(CompilerUnderTest.D8_AFTER_R8CF),
- TestCondition.runtimesFrom(DexVm.Version.V7_0_0)),
- TestCondition.match(
- TestCondition.compilers(CompilerUnderTest.D8_AFTER_R8CF),
- TestCondition.runtimes(DexVm.Version.V4_0_4, DexVm.Version.V4_4_4))))
.build();
// Tests where code generation fails.
@@ -954,6 +933,9 @@
.put("974-verify-interface-super", TestCondition.match(TestCondition.R8DEX_COMPILER))
// R8 generates too large code in Goto.bigGoto(). b/74327727
.put("003-omnibus-opcodes", TestCondition.match(TestCondition.D8_AFTER_R8CF_COMPILER))
+ // Contains a subset of JUnit which collides with library definitions of JUnit.
+ .put("021-string2", TestCondition.match(TestCondition.D8_AFTER_R8CF_COMPILER))
+ .put("082-inline-execute", TestCondition.match(TestCondition.D8_AFTER_R8CF_COMPILER))
.build();
// Tests that are invalid dex files and on which R8/D8 fails and that is OK.
diff --git a/src/test/java/com/android/tools/r8/classlookup/LibraryClassExtendsProgramClassTest.java b/src/test/java/com/android/tools/r8/classlookup/LibraryClassExtendsProgramClassTest.java
index 1dd5afd..0b5a60b 100644
--- a/src/test/java/com/android/tools/r8/classlookup/LibraryClassExtendsProgramClassTest.java
+++ b/src/test/java/com/android/tools/r8/classlookup/LibraryClassExtendsProgramClassTest.java
@@ -4,32 +4,19 @@
package com.android.tools.r8.classlookup;
-import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assume.assumeTrue;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.jasmin.JasminBuilder;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.AndroidApiLevel;
import java.util.List;
import org.junit.BeforeClass;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-// This test used to test R8 errors/warnings when library class extends program class. Before
-// the change fixing b/120884788, that could easily happen as lookup would lookup in program
-// classes before library classes, and the Android library included parts of JUnit, which could
-// also easily end up as program classes when JUnit was used by a program.
-//
-// Now that library classes are looked up before program classes these JUnit classes will be
-// found in the library and the ones in program will be ignored and not end up in the output.
-//
-// For a D8 compilation any class passed as input will end up in the output.
-@RunWith(Parameterized.class)
public class LibraryClassExtendsProgramClassTest extends TestBase {
private static List<byte[]> junitClasses;
@@ -41,65 +28,51 @@
junitClasses = builder.buildClasses();
}
- private final TestParameters parameters;
-
- @Parameterized.Parameters(name = "{0}")
- public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimes().withAllApiLevels().build();
- }
-
- public LibraryClassExtendsProgramClassTest(TestParameters parameters) {
- this.parameters = parameters;
- }
-
- private void checkClassesInResult(CodeInspector inspector) {
- if (parameters.getBackend() == Backend.DEX) {
- noClassesInResult(inspector);
- } else {
- testCaseClassInResult(inspector);
+ @Test
+ public void testFullModeError() {
+ try {
+ testForR8(Backend.DEX)
+ .setMinApi(AndroidApiLevel.O)
+ .addProgramClassFileData(junitClasses)
+ .addKeepAllClassesRule()
+ .compile();
+ fail("Succeeded in full mode");
+ } catch (Throwable t) {
+ assertTrue(t instanceof CompilationFailedException);
}
}
- private void noClassesInResult(CodeInspector inspector) {
- assertEquals(0, inspector.allClasses().size());
- }
-
- private void testCaseClassInResult(CodeInspector inspector) {
- assertEquals(1, inspector.allClasses().size());
- assertThat(inspector.clazz("junit.framework.TestCase"), isPresent());
- }
-
@Test
- public void testFullMode() throws Exception {
- testForR8(parameters.getBackend())
- .setMinApi(parameters.getApiLevel())
+ public void testCompatibilityModeWarning() throws Exception {
+ R8TestCompileResult result = testForR8Compat(Backend.DEX)
+ .setMinApi(AndroidApiLevel.O)
.addProgramClassFileData(junitClasses)
.addKeepAllClassesRule()
.compile()
- .inspect(this::checkClassesInResult)
- .assertNoMessages();
+ .assertOnlyWarnings();
+
+ String[] libraryClassesExtendingTestCase = new String[]{
+ "android.test.InstrumentationTestCase",
+ "android.test.AndroidTestCase",
+ "android.test.suitebuilder.TestSuiteBuilder$FailedToCreateTests"
+ };
+
+ for (String name : libraryClassesExtendingTestCase) {
+ result
+ .assertWarningMessageThatMatches(
+ containsString(
+ "Library class " + name + " extends program class junit.framework.TestCase"));
+ }
}
@Test
- public void testCompatibilityMode() throws Exception {
- testForR8Compat(parameters.getBackend())
- .setMinApi(parameters.getApiLevel())
+ public void testWithDontWarn() throws Exception {
+ testForR8(Backend.DEX)
+ .setMinApi(AndroidApiLevel.O)
.addProgramClassFileData(junitClasses)
.addKeepAllClassesRule()
+ .addKeepRules("-dontwarn android.test.**")
.compile()
- .inspect(this::checkClassesInResult)
.assertNoMessages();
}
-
- @Test
- public void testD8() throws Exception {
- assumeTrue("Only run D8 for Dex backend", parameters.getBackend() == Backend.DEX);
- testForD8()
- .setMinApi(parameters.getApiLevel())
- .addProgramClassFileData(junitClasses)
- .compile()
- .inspect(this::testCaseClassInResult)
- .assertNoMessages();
- }
-
}
diff --git a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
index 46583c9..9f25230 100644
--- a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
+++ b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
@@ -19,7 +19,6 @@
import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.utils.AndroidApiLevel;
@@ -36,7 +35,6 @@
import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
import com.android.tools.r8.utils.codeinspector.FoundFieldSubject;
import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
-import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closer;
import java.io.File;
@@ -139,18 +137,6 @@
R8Command.Builder builder = R8Command.builder(reporter);
builder.addProgramFiles(ListUtils.map(inputs, Paths::get));
if (pgConfs != null) {
- // Sanitize libraries for apps relying on the Proguard behaviour of lookup in program
- // classes before library classes. See tools/sanitize_libraries.py for more information.
- Path sanitizedLibrary = temp.getRoot().toPath().resolve("sanitized_lib.jar");
- Path sanitizedPgConf = temp.getRoot().toPath().resolve("sanitized.config");
- List<String> command = new ImmutableList.Builder<String>()
- .add("tools/sanitize_libraries.py")
- .add(sanitizedLibrary.toString())
- .add(sanitizedPgConf.toString())
- .addAll(pgConfs)
- .build();
- ProcessResult result = ToolHelper.runProcess(new ProcessBuilder(command));
- assert result.exitCode == 0;
builder.addProguardConfigurationFiles(
pgConfs.stream().map(Paths::get).collect(Collectors.toList()));
} else {
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java
index 4374d0e..62c6bc8 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java
@@ -7,7 +7,9 @@
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.utils.AndroidApp;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
public class R8GMSCoreV10TreeShakeJarVerificationTest
extends R8GMSCoreTreeShakeJarVerificationTest {
diff --git a/src/test/java/com/android/tools/r8/maindexlist/b72312389/B72312389.java b/src/test/java/com/android/tools/r8/maindexlist/b72312389/B72312389.java
index 056eaad..c1741c9 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/b72312389/B72312389.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/b72312389/B72312389.java
@@ -4,11 +4,12 @@
package com.android.tools.r8.maindexlist.b72312389;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import com.android.tools.r8.BaseCommand;
import com.android.tools.r8.CompatProguardCommandBuilder;
+import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.Diagnostic;
import com.android.tools.r8.DiagnosticsHandler;
@@ -57,7 +58,7 @@
.addMainDexRules(keepInstrumentationTestCaseRules, Origin.unknown())
.build();
List<String> mainDexList = GenerateMainDexList.run(command);
- assertFalse(mainDexList.contains("junit/framework/TestCase.class"));
+ assertTrue(mainDexList.contains("junit/framework/TestCase.class"));
diagnostics.assertEmpty();
}
@@ -85,9 +86,9 @@
.build();
CodeInspector inspector = new CodeInspector(ToolHelper.runR8(command));
assertTrue(inspector.clazz("instrumentationtest.InstrumentationTest").isPresent());
- assertFalse(mainDexList.content.contains("junit/framework/TestCase.class"));
- assertEquals(
- 0,
+ assertTrue(mainDexList.content.contains("junit/framework/TestCase.class"));
+ // TODO(72794301): Two copies of this message is a bit over the top.
+ assertEquals(2,
diagnostics.countLibraryClassExtensdProgramClassWarnings(
"android.test.InstrumentationTestCase", "junit.framework.TestCase"));
}
@@ -101,8 +102,12 @@
.addMainDexRules(keepInstrumentationTestCaseRules, Origin.unknown())
.setProgramConsumer(DexIndexedConsumer.emptyConsumer())
.build();
- R8.run(command);
- diagnostics.assertEmpty();
+ try {
+ R8.run(command);
+ fail();
+ } catch (CompilationFailedException e) {
+ // Expected, as library class extending program class is an error for R8.
+ }
}
private static class CollectingDiagnosticHandler implements DiagnosticsHandler {
diff --git a/tools/run_on_app.py b/tools/run_on_app.py
index b8bd0ed..a480214 100755
--- a/tools/run_on_app.py
+++ b/tools/run_on_app.py
@@ -15,7 +15,6 @@
import gmscore_data
import golem
import nest_data
-from sanitize_libraries import SanitizeLibraries
import toolhelper
import utils
import youtube_data
@@ -302,14 +301,9 @@
if options.compiler == 'r8':
if 'pgconf' in values and not options.k:
- sanitized_lib_path = os.path.join(
- os.path.abspath(outdir), 'sanitized_lib.jar')
- sanitized_pgconf_path = os.path.join(
- os.path.abspath(outdir), 'sanitized.config')
- SanitizeLibraries(
- sanitized_lib_path, sanitized_pgconf_path, values['pgconf'])
- args.extend(['--pg-conf', sanitized_pgconf_path])
- app_provided_pg_conf = True
+ for pgconf in values['pgconf']:
+ args.extend(['--pg-conf', pgconf])
+ app_provided_pg_conf = True
if options.k:
args.extend(['--pg-conf', options.k])
if 'maindexrules' in values:
diff --git a/tools/sanitize_libraries.py b/tools/sanitize_libraries.py
deleted file mode 100755
index e67a06e..0000000
--- a/tools/sanitize_libraries.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2019, 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.
-from __future__ import print_function
-import os
-import sys
-import zipfile
-
-# Proguard lookup program classes before library classes. In R8 this is
-# not the behaviour (it used to be) R8 will check library classes before
-# program classes. Some apps have duplicate classes in the library and program.
-# To make these apps work with R8 simulate program classes before library
-# classes by creating a new library jar which have all the provided library
-# classes which are not also in program classes.
-def SanitizeLibraries(sanitized_lib_path, sanitized_pgconf_path, pgconfs):
-
- injars = []
- libraryjars = []
-
- with open(sanitized_pgconf_path, 'w') as sanitized_pgconf:
- for pgconf in pgconfs:
- pgconf_dirname = os.path.abspath(os.path.dirname(pgconf))
- first_library_jar = True
- with open(pgconf) as pgconf_file:
- for line in pgconf_file:
- trimmed = line.strip()
- if trimmed.startswith('-injars'):
- # Collect -injars and leave them in the configuration.
- injar = os.path.join(
- pgconf_dirname, trimmed[len('-injars'):].strip())
- injars.append(injar)
- sanitized_pgconf.write('-injars {}\n'.format(injar))
- elif trimmed.startswith('-libraryjars'):
- # Collect -libraryjars and replace them with the sanitized library.
- libraryjar = os.path.join(
- pgconf_dirname, trimmed[len('-libraryjars'):].strip())
- libraryjars.append(libraryjar)
- if first_library_jar:
- sanitized_pgconf.write(
- '-libraryjars {}\n'.format(sanitized_lib_path))
- first_library_jar = False
- sanitized_pgconf.write('# {}'.format(line))
- else:
- sanitized_pgconf.write(line)
-
- program_entries = set()
- library_entries = set()
-
- for injar in injars:
- with zipfile.ZipFile(injar, 'r') as injar_zf:
- for zipinfo in injar_zf.infolist():
- program_entries.add(zipinfo.filename)
-
- with zipfile.ZipFile(sanitized_lib_path, 'w') as output_zf:
- for libraryjar in libraryjars:
- with zipfile.ZipFile(libraryjar, 'r') as input_zf:
- for zipinfo in input_zf.infolist():
- if (not zipinfo.filename in program_entries
- and not zipinfo.filename in library_entries):
- library_entries.add(zipinfo.filename)
- output_zf.writestr(zipinfo, input_zf.read(zipinfo))
-
- return sanitized_pgconf_path
-
-def main(argv):
- if (len(argv) < 3):
- print("Wrong number of arguments!")
- print("Usage: sanitize_libraries.py " +
- "<sanitized_lib> <sanitized_pgconf> (<existing_pgconf)+")
- return 1
- else:
- SanitizeLibraries(argv[0], argv[1], argv[2:])
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv[1:]))
diff --git a/tools/utils.py b/tools/utils.py
index 9bd7711..4e658cc 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -337,18 +337,16 @@
return exit_code == 0
class TempDir(object):
- def __init__(self, prefix='', delete=True):
+ def __init__(self, prefix=''):
self._temp_dir = None
self._prefix = prefix
- self._delete = delete
def __enter__(self):
self._temp_dir = tempfile.mkdtemp(self._prefix)
return self._temp_dir
def __exit__(self, *_):
- if self._delete:
- shutil.rmtree(self._temp_dir, ignore_errors=True)
+ shutil.rmtree(self._temp_dir, ignore_errors=True)
class ChangedWorkingDirectory(object):
def __init__(self, working_directory, quiet=False):