Reland "Generate method lists for lint based on library desugar configuration"
This reverts commit 40fe34dfdddfa1bfeca659f76964d6f76cedcd43 and fixes the
build issue by generating the desugar configuration maven zip after an r8.jar
with dependencies has been built.
Bug: 134732760
Change-Id: Ice744eb738556e32c77932e24f95f6cb488209aa
diff --git a/src/main/java/com/android/tools/r8/GenerateLintFiles.java b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
new file mode 100644
index 0000000..2c63a69
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
@@ -0,0 +1,335 @@
+// 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 com.android.tools.r8.cf.code.CfConstNull;
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfThrow;
+import com.android.tools.r8.dex.ApplicationReader;
+import com.android.tools.r8.dex.Marker.Tool;
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.DexAnnotationSet;
+import com.android.tools.r8.graph.DexApplication;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexLibraryClass;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.graph.ParameterAnnotationsList;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfigurationParser;
+import com.android.tools.r8.jar.CfApplicationWriter;
+import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.Reporter;
+import com.android.tools.r8.utils.ThreadUtils;
+import com.android.tools.r8.utils.Timing;
+import com.google.common.collect.Sets;
+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.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.function.BiPredicate;
+import java.util.function.Predicate;
+
+public class GenerateLintFiles {
+
+ private static final String ANDROID_JAR_PATTERN = "third_party/android_jar/lib-v%d/android.jar";
+
+ private final DexItemFactory factory = new DexItemFactory();
+ private final Reporter reporter = new Reporter();
+ private final InternalOptions options = new InternalOptions(factory, reporter);
+
+ private final DesugaredLibraryConfiguration desugaredLibraryConfiguration;
+ private final String outputDirectory;
+
+ private final Set<DexMethod> parallelMethods = Sets.newIdentityHashSet();
+
+ private GenerateLintFiles(String desugarConfigurationPath, String outputDirectory) {
+ this.desugaredLibraryConfiguration =
+ readDesugaredLibraryConfiguration(desugarConfigurationPath);
+ this.outputDirectory =
+ outputDirectory.endsWith("/") ? outputDirectory : outputDirectory + File.separator;
+
+ DexType streamType = factory.createType(factory.createString("Ljava/util/stream/Stream;"));
+ DexMethod parallelMethod =
+ factory.createMethod(
+ factory.collectionType,
+ factory.createProto(streamType),
+ factory.createString("parallelStream"));
+ parallelMethods.add(parallelMethod);
+ for (String typePrefix : new String[] {"Base", "Double", "Int", "Long"}) {
+ streamType =
+ factory.createType(factory.createString("Ljava/util/stream/" + typePrefix + "Stream;"));
+ parallelMethod =
+ factory.createMethod(
+ streamType, factory.createProto(streamType), factory.createString("parallel"));
+ parallelMethods.add(parallelMethod);
+ }
+ }
+
+ private static Path getAndroidJarPath(AndroidApiLevel apiLevel) {
+ String jar = String.format(ANDROID_JAR_PATTERN, apiLevel.getLevel());
+ return Paths.get(jar);
+ }
+
+ private DesugaredLibraryConfiguration readDesugaredLibraryConfiguration(
+ String desugarConfigurationPath) {
+ return new DesugaredLibraryConfigurationParser(
+ factory, reporter, false, AndroidApiLevel.B.getLevel())
+ .parse(StringResource.fromFile(Paths.get(desugarConfigurationPath)));
+ }
+
+ private CfCode buildEmptyThrowingCfCode(DexMethod method) {
+ CfInstruction insn[] = {new CfConstNull(), new CfThrow()};
+ return new CfCode(
+ method.holder,
+ 1,
+ method.proto.parameters.size() + 1,
+ Arrays.asList(insn),
+ Collections.emptyList(),
+ Collections.emptyList());
+ }
+
+ private void addMethodsToHeaderJar(
+ DexApplication.Builder builder, DexClass clazz, List<DexEncodedMethod> methods) {
+ if (methods.size() == 0) {
+ return;
+ }
+
+ List<DexEncodedMethod> directMethods = new ArrayList<>();
+ List<DexEncodedMethod> virtualMethods = new ArrayList<>();
+ for (DexEncodedMethod method : methods) {
+ assert method.method.holder == clazz.type;
+ CfCode code = null;
+ if (!method.accessFlags.isAbstract() /*&& !method.accessFlags.isNative()*/) {
+ code = buildEmptyThrowingCfCode(method.method);
+ }
+ DexEncodedMethod throwingMethod =
+ new DexEncodedMethod(
+ method.method,
+ method.accessFlags,
+ DexAnnotationSet.empty(),
+ ParameterAnnotationsList.empty(),
+ code,
+ 50);
+ if (method.accessFlags.isStatic()) {
+ directMethods.add(throwingMethod);
+ } else {
+ virtualMethods.add(throwingMethod);
+ }
+ }
+
+ DexEncodedMethod[] directMethodsArray = new DexEncodedMethod[directMethods.size()];
+ DexEncodedMethod[] virtualMethodsArray = new DexEncodedMethod[virtualMethods.size()];
+ directMethods.toArray(directMethodsArray);
+ virtualMethods.toArray(virtualMethodsArray);
+ builder.addProgramClass(
+ new DexProgramClass(
+ clazz.type,
+ null,
+ Origin.unknown(),
+ clazz.accessFlags,
+ clazz.superType,
+ clazz.interfaces,
+ null,
+ null,
+ Collections.emptyList(),
+ null,
+ Collections.emptyList(),
+ DexAnnotationSet.empty(),
+ DexEncodedField.EMPTY_ARRAY,
+ DexEncodedField.EMPTY_ARRAY,
+ directMethodsArray,
+ virtualMethodsArray,
+ false));
+ }
+
+ private Map<DexClass, List<DexEncodedMethod>> collectSupportedMethods(
+ AndroidApiLevel compilationApiLevel, Predicate<DexEncodedMethod> supported)
+ throws IOException, ExecutionException {
+
+ // Read the android.jar for the compilation API level.
+ AndroidApp library =
+ AndroidApp.builder().addLibraryFiles(getAndroidJarPath(compilationApiLevel)).build();
+ DirectMappedDexApplication dexApplication =
+ new ApplicationReader(library, options, new Timing()).read().toDirect();
+
+ // collect all the methods that the library desugar configuration adds support for.
+ Map<DexClass, List<DexEncodedMethod>> supportedMethods = new LinkedHashMap<>();
+ for (DexLibraryClass clazz : dexApplication.libraryClasses()) {
+ String className = clazz.toSourceString();
+ // All the methods with the rewritten prefix are supported.
+ for (String prefix : desugaredLibraryConfiguration.getRewritePrefix().keySet()) {
+ if (clazz.accessFlags.isPublic() && className.startsWith(prefix)) {
+ for (DexEncodedMethod method : clazz.methods()) {
+ if (supported.test(method)) {
+ supportedMethods.computeIfAbsent(clazz, k -> new ArrayList<>()).add(method);
+ }
+ }
+ }
+ }
+
+ // All retargeted methods are supported.
+ for (DexEncodedMethod method : clazz.methods()) {
+ if (desugaredLibraryConfiguration
+ .getRetargetCoreLibMember()
+ .keySet()
+ .contains(method.method.name)) {
+ if (desugaredLibraryConfiguration
+ .getRetargetCoreLibMember()
+ .get(method.method.name)
+ .containsKey(clazz.type)) {
+ if (supported.test(method)) {
+ supportedMethods.computeIfAbsent(clazz, k -> new ArrayList<>()).add(method);
+ }
+ }
+ }
+ }
+ // All emulated interfaces methods are supported.
+ if (desugaredLibraryConfiguration.getEmulateLibraryInterface().containsKey(clazz.type)) {
+ for (DexEncodedMethod method : clazz.methods()) {
+ if (supported.test(method)) {
+ supportedMethods.computeIfAbsent(clazz, k -> new ArrayList<>()).add(method);
+ }
+ }
+ }
+ }
+
+ return supportedMethods;
+ }
+
+ private String lintBaseFileName(
+ AndroidApiLevel compilationApiLevel, AndroidApiLevel minApiLevel) {
+ return "desugared_apis_" + compilationApiLevel.getLevel() + "_" + minApiLevel.getLevel();
+ }
+
+ private Path lintFile(
+ AndroidApiLevel compilationApiLevel, AndroidApiLevel minApiLevel, String extension)
+ throws Exception {
+ Path directory =
+ Paths.get(outputDirectory + "compile_api_level_" + compilationApiLevel.getLevel());
+ Files.createDirectories(directory);
+ return Paths.get(
+ directory
+ + File.separator
+ + lintBaseFileName(compilationApiLevel, minApiLevel)
+ + extension);
+ }
+
+ private void writeLintFiles(
+ AndroidApiLevel compilationApiLevel,
+ AndroidApiLevel minApiLevel,
+ Map<DexClass, List<DexEncodedMethod>> supportedMethods)
+ throws Exception {
+ // Build a plain text file with the desugared APIs.
+ List<String> desugaredApisSignatures = new ArrayList<>();
+
+ DexApplication.Builder builder = DexApplication.builder(options, new Timing());
+ supportedMethods.forEach(
+ (clazz, methods) -> {
+ String classBinaryName =
+ DescriptorUtils.getClassBinaryNameFromDescriptor(clazz.type.descriptor.toString());
+ for (DexEncodedMethod method : methods) {
+ desugaredApisSignatures.add(
+ classBinaryName
+ + '/'
+ + method.method.name
+ + method.method.proto.toDescriptorString());
+ }
+
+ addMethodsToHeaderJar(builder, clazz, methods);
+ });
+ DexApplication app = builder.build();
+
+ // Write a plain text file with the desugared APIs.
+ FileUtils.writeTextFile(
+ lintFile(compilationApiLevel, minApiLevel, ".txt"), desugaredApisSignatures);
+
+ // Write a header jar with the desugared APIs.
+ AppInfo appInfo = new AppInfo(app);
+ AppView<?> appView = AppView.createForD8(appInfo, options);
+ CfApplicationWriter writer =
+ new CfApplicationWriter(
+ builder.build(),
+ appView,
+ options,
+ options.getMarker(Tool.L8),
+ GraphLense.getIdentityLense(),
+ NamingLens.getIdentityLens(),
+ null);
+ ClassFileConsumer consumer =
+ new ClassFileConsumer.ArchiveConsumer(
+ lintFile(compilationApiLevel, minApiLevel, FileUtils.JAR_EXTENSION));
+ writer.write(consumer, ThreadUtils.getExecutorService(options));
+ consumer.finished(options.reporter);
+ }
+
+ private void generateLintFiles(
+ AndroidApiLevel compilationApiLevel,
+ Predicate<AndroidApiLevel> generateForThisMinApiLevel,
+ BiPredicate<AndroidApiLevel, DexEncodedMethod> supportedForMinApiLevel)
+ throws Exception {
+ for (AndroidApiLevel value : AndroidApiLevel.values()) {
+ if (!generateForThisMinApiLevel.test(value)) {
+ continue;
+ }
+
+ Map<DexClass, List<DexEncodedMethod>> supportedMethods =
+ collectSupportedMethods(
+ compilationApiLevel, (method -> supportedForMinApiLevel.test(value, method)));
+ writeLintFiles(compilationApiLevel, value, supportedMethods);
+ }
+ }
+
+ private void run() throws Exception {
+ // Run over all the API levels that the desugared library can be compiled with.
+ for (int apiLevel = AndroidApiLevel.Q.getLevel();
+ apiLevel >= desugaredLibraryConfiguration.getRequiredCompilationApiLevel().getLevel();
+ apiLevel--) {
+ System.out.println("Generating lint files for compile API " + apiLevel);
+ generateLintFiles(
+ AndroidApiLevel.getAndroidApiLevel(apiLevel),
+ minApiLevel -> minApiLevel == AndroidApiLevel.L || minApiLevel == AndroidApiLevel.B,
+ (minApiLevel, method) -> {
+ assert minApiLevel == AndroidApiLevel.L || minApiLevel == AndroidApiLevel.B;
+ if (minApiLevel == AndroidApiLevel.L) {
+ return true;
+ }
+ assert minApiLevel == AndroidApiLevel.B;
+ return !parallelMethods.contains(method.method);
+ });
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (args.length != 2) {
+ System.out.println("Usage: GenerateLineFiles <desuage configuration> <output directory>");
+ System.exit(1);
+ }
+ new GenerateLintFiles(args[0], args[1]).run();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 1a97b26..b3a33f6 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -217,6 +217,7 @@
public final DexString serviceLoaderDescriptor = createString("Ljava/util/ServiceLoader;");
public final DexString listDescriptor = createString("Ljava/util/List;");
public final DexString setDescriptor = createString("Ljava/util/Set;");
+ public final DexString collectionDescriptor = createString("Ljava/util/Collection;");
public final DexString comparatorDescriptor = createString("Ljava/util/Comparator;");
public final DexString callableDescriptor = createString("Ljava/util/concurrent/Callable;");
public final DexString supplierDescriptor = createString("Ljava/util/function/Supplier;");
@@ -306,6 +307,7 @@
public final DexType serviceLoaderType = createType(serviceLoaderDescriptor);
public final DexType listType = createType(listDescriptor);
public final DexType setType = createType(setDescriptor);
+ public final DexType collectionType = createType(collectionDescriptor);
public final DexType comparatorType = createType(comparatorDescriptor);
public final DexType callableType = createType(callableDescriptor);
public final DexType supplierType = createType(supplierDescriptor);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfiguration.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfiguration.java
index d3dc54d..e1f2181 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfiguration.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfiguration.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.PrefixRewritingMapper.DesugarPrefixRewritingMapper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.Pair;
import com.google.common.collect.ImmutableList;
@@ -22,6 +23,7 @@
public class DesugaredLibraryConfiguration {
// TODO(b/134732760): should use DexString, DexType, DexMethod or so on when possible.
+ private final AndroidApiLevel requiredCompilationAPILevel;
private final boolean libraryCompilation;
private final Map<String, String> rewritePrefix;
private final Map<DexType, DexType> emulateLibraryInterface;
@@ -36,6 +38,7 @@
public static DesugaredLibraryConfiguration empty() {
return new DesugaredLibraryConfiguration(
+ AndroidApiLevel.B,
false,
ImmutableMap.of(),
ImmutableMap.of(),
@@ -46,6 +49,7 @@
}
public DesugaredLibraryConfiguration(
+ AndroidApiLevel requiredCompilationAPILevel,
boolean libraryCompilation,
Map<String, String> rewritePrefix,
Map<DexType, DexType> emulateLibraryInterface,
@@ -53,6 +57,7 @@
Map<DexType, DexType> backportCoreLibraryMember,
Map<DexType, DexType> customConversions,
List<Pair<DexType, DexString>> dontRewriteInvocation) {
+ this.requiredCompilationAPILevel = requiredCompilationAPILevel;
this.libraryCompilation = libraryCompilation;
this.rewritePrefix = rewritePrefix;
this.emulateLibraryInterface = emulateLibraryInterface;
@@ -68,6 +73,10 @@
: new DesugarPrefixRewritingMapper(rewritePrefix, factory);
}
+ public AndroidApiLevel getRequiredCompilationApiLevel() {
+ return requiredCompilationAPILevel;
+ }
+
public boolean isLibraryCompilation() {
return libraryCompilation;
}
@@ -100,6 +109,7 @@
private final DexItemFactory factory;
+ private AndroidApiLevel requiredCompilationAPILevel;
private boolean libraryCompilation = false;
private Map<String, String> rewritePrefix = new HashMap<>();
private Map<DexType, DexType> emulateLibraryInterface = new HashMap<>();
@@ -112,6 +122,11 @@
this.factory = dexItemFactory;
}
+ public Builder setRequiredCompilationAPILevel(AndroidApiLevel requiredCompilationAPILevel) {
+ this.requiredCompilationAPILevel = requiredCompilationAPILevel;
+ return this;
+ }
+
public Builder setProgramCompilation() {
libraryCompilation = false;
return this;
@@ -185,6 +200,7 @@
public DesugaredLibraryConfiguration build() {
return new DesugaredLibraryConfiguration(
+ requiredCompilationAPILevel,
libraryCompilation,
ImmutableMap.copyOf(rewritePrefix),
ImmutableMap.copyOf(emulateLibraryInterface),
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java
index 94467de..fbf3d1f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.StringResource;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.gson.JsonArray;
@@ -57,6 +58,10 @@
"Unsupported desugared library configuration version, please upgrade the D8/R8"
+ " compiler."));
}
+ int required_compilation_api_level =
+ jsonConfig.get("required_compilation_api_level").getAsInt();
+ configurationBuilder.setRequiredCompilationAPILevel(
+ AndroidApiLevel.getAndroidApiLevel(required_compilation_api_level));
JsonArray jsonFlags =
libraryCompilation
? jsonConfig.getAsJsonArray("library_flags")
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/InconsistentPrefixTest.java b/src/test/java/com/android/tools/r8/desugar/corelib/InconsistentPrefixTest.java
index de16ed5..843551e 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/InconsistentPrefixTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/InconsistentPrefixTest.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.jasmin.JasminBuilder;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.nio.file.Path;
@@ -39,6 +40,7 @@
options ->
options.desugaredLibraryConfiguration =
new DesugaredLibraryConfiguration(
+ AndroidApiLevel.B,
false,
x,
ImmutableMap.of(),
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/LintFilesTest.java b/src/test/java/com/android/tools/r8/desugar/corelib/LintFilesTest.java
new file mode 100644
index 0000000..87a6140
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/LintFilesTest.java
@@ -0,0 +1,94 @@
+// 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.desugar.corelib;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.GenerateLintFiles;
+import com.android.tools.r8.StringResource;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfigurationParser;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.Reporter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import org.junit.Assume;
+import org.junit.Test;
+
+public class LintFilesTest extends TestBase {
+
+ private void checkFileContent(AndroidApiLevel minApiLevel, Path lintFile) throws Exception {
+ // Just do some light probing in the generated lint files.
+ List<String> methods = FileUtils.readAllLines(lintFile);
+ assertTrue(methods.contains("java/util/List/spliterator()Ljava/util/Spliterator;"));
+ assertTrue(methods.contains("java/util/Optional/empty()Ljava/util/Optional;"));
+ assertTrue(methods.contains("java/util/OptionalInt/empty()Ljava/util/OptionalInt;"));
+ assertEquals(
+ minApiLevel == AndroidApiLevel.L,
+ methods.contains("java/util/Collection/parallelStream()Ljava/util/stream/Stream;"));
+ assertEquals(
+ minApiLevel == AndroidApiLevel.L,
+ methods.contains(
+ "java/util/stream/DoubleStream/parallel()Ljava/util/stream/DoubleStream;"));
+ assertEquals(
+ minApiLevel == AndroidApiLevel.L,
+ methods.contains("java/util/stream/IntStream/parallel()Ljava/util/stream/IntStream;"));
+ }
+
+ @Test
+ public void testFileContent() throws Exception {
+ // Test require r8.jar not r8lib.jar, as the class com.android.tools.r8.GenerateLintFiles in
+ // not kept.
+ Assume.assumeTrue(!ToolHelper.isTestingR8Lib());
+
+ Path directory = temp.newFolder().toPath();
+ GenerateLintFiles.main(
+ new String[] {ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING.toString(), directory.toString()});
+ InternalOptions options = new InternalOptions(new DexItemFactory(), new Reporter());
+ DesugaredLibraryConfiguration desugaredLibraryConfiguration =
+ new DesugaredLibraryConfigurationParser(
+ options.itemFactory, options.reporter, false, AndroidApiLevel.B.getLevel())
+ .parse(StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING));
+
+ for (AndroidApiLevel apiLevel : AndroidApiLevel.values()) {
+ if (apiLevel == AndroidApiLevel.R) {
+ // Skip API level 30 for now.
+ continue;
+ }
+
+ if (apiLevel.getLevel()
+ >= desugaredLibraryConfiguration.getRequiredCompilationApiLevel().getLevel()) {
+ Path compileApiLevelDirectory =
+ directory.resolve("compile_api_level_" + apiLevel.getLevel());
+ assertTrue(Files.exists(compileApiLevelDirectory));
+ for (AndroidApiLevel minApiLevel : AndroidApiLevel.values()) {
+ String desugaredApisBaseName =
+ "desugared_apis_" + apiLevel.getLevel() + "_" + minApiLevel.getLevel();
+ if (minApiLevel == AndroidApiLevel.L || minApiLevel == AndroidApiLevel.B) {
+ assertTrue(
+ Files.exists(compileApiLevelDirectory.resolve(desugaredApisBaseName + ".txt")));
+ assertTrue(
+ Files.exists(compileApiLevelDirectory.resolve(desugaredApisBaseName + ".jar")));
+ checkFileContent(
+ minApiLevel, compileApiLevelDirectory.resolve(desugaredApisBaseName + ".txt"));
+ } else {
+ assertFalse(
+ Files.exists(compileApiLevelDirectory.resolve(desugaredApisBaseName + ".txt")));
+ assertFalse(
+ Files.exists(compileApiLevelDirectory.resolve(desugaredApisBaseName + ".jar")));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/b135627418/B135627418.java b/src/test/java/com/android/tools/r8/memberrebinding/b135627418/B135627418.java
index a08b6ce..3353fd2 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/b135627418/B135627418.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/b135627418/B135627418.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.memberrebinding.b135627418.library.Drawable;
import com.android.tools.r8.memberrebinding.b135627418.library.DrawableWrapper;
import com.android.tools.r8.memberrebinding.b135627418.library.InsetDrawable;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -79,6 +80,7 @@
options ->
options.desugaredLibraryConfiguration =
new DesugaredLibraryConfiguration(
+ AndroidApiLevel.B,
false,
ImmutableMap.of(packageName + ".runtime", packageName + ".library"),
ImmutableMap.of(),
diff --git a/tools/archive.py b/tools/archive.py
index 1041b40..62e0e27 100755
--- a/tools/archive.py
+++ b/tools/archive.py
@@ -126,9 +126,6 @@
create_maven_release.generate_r8_maven_zip(utils.MAVEN_ZIP)
create_maven_release.generate_r8_maven_zip(
utils.MAVEN_ZIP_LIB, is_r8lib=True)
- # Create maven release of the desuage_jdk_libs configuration.
- create_maven_release.generate_desugar_configuration_maven_zip(
- utils.DESUGAR_CONFIGURATION_MAVEN_ZIP)
# Generate and copy a full build without dependencies.
gradle.RunGradleExcludeDeps([utils.R8, utils.R8_SRC])
@@ -149,6 +146,12 @@
utils.COMPATPROGUARDLIB,
'-Pno_internal'
])
+
+ # Create maven release of the desuage_jdk_libs configuration. This require
+ # an r8.jar with dependencies to have been built.
+ create_maven_release.generate_desugar_configuration_maven_zip(
+ utils.DESUGAR_CONFIGURATION_MAVEN_ZIP)
+
version = GetVersion()
is_master = IsMaster(version)
if is_master:
diff --git a/tools/create_maven_release.py b/tools/create_maven_release.py
index b4343f3..30c14c8 100755
--- a/tools/create_maven_release.py
+++ b/tools/create_maven_release.py
@@ -6,6 +6,7 @@
import argparse
import gradle
import hashlib
+import jdk
import json
from os import makedirs
from os.path import join
@@ -338,6 +339,19 @@
configuration_dir = join(tmp_dir, 'META-INF', 'desugar', 'd8')
makedirs(configuration_dir)
copyfile(configuration, join(configuration_dir, 'desugar.json'))
+
+ lint_dir = join(configuration_dir, 'lint')
+ makedirs(lint_dir)
+ cmd = [
+ jdk.GetJavaExecutable(),
+ '-cp',
+ utils.R8_JAR,
+ 'com.android.tools.r8.GenerateLintFiles',
+ configuration,
+ lint_dir]
+ utils.PrintCmd(cmd)
+ subprocess.check_call(cmd)
+
make_archive(destination, 'zip', tmp_dir)
move(destination + '.zip', destination)