Use Library Configuration JSON
- allow to use a JSON file instead of the
SpecialLibraryConfiguration hardcoded hack.
- Add a parser for library configuration.
- Add test to check SpecialLibraryConfiguration
against JSON parsed configuration.
- Move LibraryConfiguration to its own structure.
Bug:134732760
Change-Id: Iaa9979055b6a5d1cf05a5b9c4b796e267d1e1d0b
diff --git a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
index 05c4147..9918583 100644
--- a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
@@ -3,7 +3,12 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8;
+import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unreachable;
+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.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.FileUtils;
@@ -33,7 +38,6 @@
private final boolean enableDesugaring;
private final boolean includeClassesChecksum;
private final boolean optimizeMultidexForLinearAlloc;
- private String specialLibraryConfiguration;
private final BiPredicate<String, Long> dexClassChecksumFilter;
BaseCompilerCommand(boolean printHelp, boolean printVersion) {
@@ -58,7 +62,6 @@
Reporter reporter,
boolean enableDesugaring,
boolean optimizeMultidexForLinearAlloc,
- String specialLibraryConfiguration,
boolean includeClassesChecksum,
BiPredicate<String, Long> dexClassChecksumFilter) {
super(app);
@@ -71,7 +74,6 @@
this.reporter = reporter;
this.enableDesugaring = enableDesugaring;
this.optimizeMultidexForLinearAlloc = optimizeMultidexForLinearAlloc;
- this.specialLibraryConfiguration = specialLibraryConfiguration;
this.includeClassesChecksum = includeClassesChecksum;
this.dexClassChecksumFilter = dexClassChecksumFilter;
}
@@ -132,10 +134,6 @@
return reporter;
}
- public String getSpecialLibraryConfiguration() {
- return specialLibraryConfiguration;
- }
-
/**
* Base builder for compilation commands.
*
@@ -156,7 +154,7 @@
private CompilationMode mode;
private int minApiLevel = 0;
private boolean disableDesugaring = false;
- private String specialLibraryConfiguration;
+ private List<StringResource> desugaredLibraryConfigurationResources = new ArrayList<>();
private boolean includeClassesChecksum = false;
private boolean lookupLibraryBeforeProgram = true;
private boolean optimizeMultidexForLinearAlloc = false;
@@ -225,8 +223,8 @@
* Get the program consumer.
*
* @return The currently set program consumer, null if no program consumer or output
- * path-and-mode is set, e.g., neither {@link #setProgramConsumer} nor
- * {@link #setOutput} have been called.
+ * path-and-mode is set, e.g., neither {@link #setProgramConsumer} nor {@link #setOutput}
+ * have been called.
*/
public ProgramConsumer getProgramConsumer() {
return programConsumer;
@@ -429,14 +427,54 @@
return disableDesugaring;
}
- /** Special library configuration */
- public B addSpecialLibraryConfiguration(String configuration) {
- this.specialLibraryConfiguration = configuration;
+ /** Desugared library configuration */
+ // Configuration "default" is for testing only and support will be dropped.
+ public B addDesugaredLibraryConfiguration(String configuration) {
+ this.desugaredLibraryConfigurationResources.add(
+ StringResource.fromString(configuration, Origin.unknown()));
return self();
}
- public String getSpecialLibraryConfiguration() {
- return specialLibraryConfiguration;
+ /** Desugared library configuration */
+ public B addDesugaredLibraryConfiguration(StringResource configuration) {
+ this.desugaredLibraryConfigurationResources.add(configuration);
+ return self();
+ }
+
+ DesugaredLibraryConfiguration getDesugaredLibraryConfiguration(
+ DexItemFactory factory, boolean libraryCompilation, int minAPILevel) {
+ if (desugaredLibraryConfigurationResources.isEmpty()) {
+ return DesugaredLibraryConfiguration.empty();
+ }
+ if (desugaredLibraryConfigurationResources.size() > 1) {
+ throw new CompilationError("Only one desugared library configuration is supported.");
+ }
+ StringResource desugaredLibraryConfigurationResource =
+ desugaredLibraryConfigurationResources.get(0);
+
+ // TODO(b/134732760): Remove the following once the default testing hack is not supported
+ // anymore.
+ try {
+ if (desugaredLibraryConfigurationResource.getString().equals("default")) {
+ if (libraryCompilation) {
+ return DesugaredLibraryConfigurationForTesting
+ .configureLibraryDesugaringForLibraryCompilation(minAPILevel);
+ }
+ return DesugaredLibraryConfigurationForTesting
+ .configureLibraryDesugaringForProgramCompilation(minAPILevel);
+ }
+ } catch (ResourceException e) {
+ throw new RuntimeException(e);
+ }
+
+ DesugaredLibraryConfigurationParser libraryParser =
+ new DesugaredLibraryConfigurationParser(
+ factory, getReporter(), libraryCompilation, getMinApiLevel());
+ return libraryParser.parse(desugaredLibraryConfigurationResource);
+ }
+
+ boolean hasDesugaredLibraryConfiguration(){
+ return desugaredLibraryConfigurationResources.size() == 1;
}
/** Encodes checksum for each class when generating dex files. */
@@ -482,12 +520,11 @@
}
reporter.error(builder.toString());
}
- if (specialLibraryConfiguration != null) {
+ if (!desugaredLibraryConfigurationResources.isEmpty()) {
reporter.warning(
- new StringDiagnostic("Special library configuration is still work in progress"));
+ new StringDiagnostic("Desugared library configuration is still work in progress"));
}
super.validate();
}
}
-
}
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 4d23aef..4eca620 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.errors.DexFileOverflowDiagnostic;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
@@ -79,26 +80,34 @@
super(app);
}
- /** Add dex program-data. */
+ /**
+ * Add dex program-data.
+ */
@Override
public Builder addDexProgramData(byte[] data, Origin origin) {
guard(() -> getAppBuilder().addDexProgramData(data, origin));
return self();
}
- /** Add classpath file resources. These have @Override to ensure binary compatibility. */
+ /**
+ * Add classpath file resources. These have @Override to ensure binary compatibility.
+ */
@Override
public Builder addClasspathFiles(Path... files) {
return super.addClasspathFiles(files);
}
- /** Add classpath file resources. */
+ /**
+ * Add classpath file resources.
+ */
@Override
public Builder addClasspathFiles(Collection<Path> files) {
return super.addClasspathFiles(files);
}
- /** Add classfile resources provider for class-path resources. */
+ /**
+ * Add classfile resources provider for class-path resources.
+ */
@Override
public Builder addClasspathResourceProvider(ClassFileResourceProvider provider) {
return super.addClasspathResourceProvider(provider);
@@ -125,7 +134,9 @@
return self();
}
- /** Get the consumer that will receive dependency information for desugaring. */
+ /**
+ * Get the consumer that will receive dependency information for desugaring.
+ */
public DesugarGraphConsumer getDesugarGraphConsumer() {
return desugarGraphConsumer;
}
@@ -174,14 +185,8 @@
+ " and above");
}
}
- if (getSpecialLibraryConfiguration() != null) {
- if (getDisableDesugaring()) {
- reporter.error("Using special library configuration requires desugaring to be enabled");
- }
- if (!getSpecialLibraryConfiguration().equals("default")) {
- reporter
- .error("D8 currently requires the special library configuration to be \"default\"");
- }
+ if (hasDesugaredLibraryConfiguration() && getDisableDesugaring()) {
+ reporter.error("Using desugared library configuration requires desugaring to be enabled");
}
super.validate();
}
@@ -194,6 +199,10 @@
intermediate |= getProgramConsumer() instanceof DexFilePerClassFileConsumer;
+ DexItemFactory factory = new DexItemFactory();
+ DesugaredLibraryConfiguration libraryConfiguration =
+ getDesugaredLibraryConfiguration(factory, false, getMinApiLevel());
+
return new D8Command(
getAppBuilder().build(),
getMode(),
@@ -204,11 +213,12 @@
!getDisableDesugaring(),
intermediate,
isOptimizeMultidexForLinearAlloc(),
- getSpecialLibraryConfiguration(),
getIncludeClassesChecksum(),
getDexClassChecksumFilter(),
getDesugarGraphConsumer(),
- desugaredLibraryKeepRuleConsumer);
+ desugaredLibraryKeepRuleConsumer,
+ libraryConfiguration,
+ factory);
}
}
@@ -217,6 +227,8 @@
private final boolean intermediate;
private final DesugarGraphConsumer desugarGraphConsumer;
private final StringConsumer desugaredLibraryKeepRuleConsumer;
+ private final DesugaredLibraryConfiguration libraryConfiguration;
+ private final DexItemFactory factory;
public static Builder builder() {
return new Builder();
@@ -268,11 +280,12 @@
boolean enableDesugaring,
boolean intermediate,
boolean optimizeMultidexForLinearAlloc,
- String specialLibraryConfiguration,
boolean encodeChecksum,
BiPredicate<String, Long> dexClassChecksumFilter,
DesugarGraphConsumer desugarGraphConsumer,
- StringConsumer desugaredLibraryKeepRuleConsumer) {
+ StringConsumer desugaredLibraryKeepRuleConsumer,
+ DesugaredLibraryConfiguration libraryConfiguration,
+ DexItemFactory factory) {
super(
inputApp,
mode,
@@ -282,12 +295,13 @@
diagnosticsHandler,
enableDesugaring,
optimizeMultidexForLinearAlloc,
- specialLibraryConfiguration,
encodeChecksum,
dexClassChecksumFilter);
this.intermediate = intermediate;
this.desugarGraphConsumer = desugarGraphConsumer;
this.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
+ this.libraryConfiguration = libraryConfiguration;
+ this.factory = factory;
}
private D8Command(boolean printHelp, boolean printVersion) {
@@ -295,15 +309,13 @@
intermediate = false;
desugarGraphConsumer = null;
desugaredLibraryKeepRuleConsumer = null;
- }
-
- private void configureLibraryDesugaring(InternalOptions options) {
- SpecialLibraryConfiguration.configureLibraryDesugaringForProgramCompilation(options);
+ libraryConfiguration = null;
+ factory = null;
}
@Override
InternalOptions getInternalOptions() {
- InternalOptions internal = new InternalOptions(new DexItemFactory(), getReporter());
+ InternalOptions internal = new InternalOptions(factory, getReporter());
assert !internal.debug;
internal.debug = getMode() == CompilationMode.DEBUG;
internal.programConsumer = getProgramConsumer();
@@ -342,15 +354,7 @@
internal.enableInheritanceClassInDexDistributor = isOptimizeMultidexForLinearAlloc();
// TODO(134732760): This is still work in progress.
- assert internal.rewritePrefix.isEmpty();
- assert internal.emulateLibraryInterface.isEmpty();
- assert internal.retargetCoreLibMember.isEmpty();
- assert internal.backportCoreLibraryMembers.isEmpty();
- assert internal.dontRewriteInvocations.isEmpty();
- if (getSpecialLibraryConfiguration() != null) {
- configureLibraryDesugaring(internal);
- }
-
+ internal.libraryConfiguration = libraryConfiguration;
internal.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
return internal;
diff --git a/src/main/java/com/android/tools/r8/SpecialLibraryConfiguration.java b/src/main/java/com/android/tools/r8/DesugaredLibraryConfigurationForTesting.java
similarity index 76%
rename from src/main/java/com/android/tools/r8/SpecialLibraryConfiguration.java
rename to src/main/java/com/android/tools/r8/DesugaredLibraryConfigurationForTesting.java
index 8f9bb7c..90d232b 100644
--- a/src/main/java/com/android/tools/r8/SpecialLibraryConfiguration.java
+++ b/src/main/java/com/android/tools/r8/DesugaredLibraryConfigurationForTesting.java
@@ -4,19 +4,18 @@
package com.android.tools.r8;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.List;
import java.util.Map;
// TODO(134732760): This is still work in progress.
-// The SpecialLibraryConfiguration is a set of flags for experimentation
+// The DesugaredLibraryConfigurationForTesting is a set of flags for experimentation
// with the desugared JDK libraries which should be replaced by a D8/R8
// API level flag --coreLibraryDescriptor
-public class SpecialLibraryConfiguration {
+public class DesugaredLibraryConfigurationForTesting {
private static Map<String, String> buildPrefixRewritingForProgramCompilationAllAndroid() {
return ImmutableMap.<String, String>builder()
@@ -184,51 +183,67 @@
.build();
}
- public static void configureLibraryDesugaringForProgramCompilation(InternalOptions options) {
+ public static DesugaredLibraryConfiguration configureLibraryDesugaringForProgramCompilation(
+ int minApiLevel) {
// TODO(b/134732760): Make assertions in D8/R8 commands.
- if (options.minApiLevel >= AndroidApiLevel.O.getLevel()) {
- options.reporter.warning(
- new StringDiagnostic(
- "Desugaring core libraries for Android O and over is possible but not required."));
+ if (minApiLevel >= AndroidApiLevel.O.getLevel()) {
+ return DesugaredLibraryConfiguration.empty();
}
- options.coreLibraryCompilation = false;
- if (options.minApiLevel < AndroidApiLevel.N.getLevel()) {
- if (options.minApiLevel < AndroidApiLevel.M.getLevel()) {
- options.rewritePrefix = buildPrefixRewritingForProgramCompilationAllAndroid();
+ Map<String, String> rewritePrefix;
+ Map<String, String> retargetCoreLibMember;
+ Map<String, String> emulateLibraryInterface = ImmutableMap.of();
+ List<String> dontRewriteInvocations = ImmutableList.of();
+ if (minApiLevel < AndroidApiLevel.N.getLevel()) {
+ if (minApiLevel < AndroidApiLevel.M.getLevel()) {
+ rewritePrefix = buildPrefixRewritingForProgramCompilationAllAndroid();
} else {
- options.rewritePrefix = buildPrefixRewritingForProgramCompilationAndroidOPlus();
+ rewritePrefix = buildPrefixRewritingForProgramCompilationAndroidOPlus();
}
- options.retargetCoreLibMember =
- buildRetargetCoreLibraryMemberForProgramCompilationAllAndroid();
- options.emulateLibraryInterface = buildEmulateLibraryInterface();
- options.dontRewriteInvocations = buildDontRewriteInvocations();
+ retargetCoreLibMember = buildRetargetCoreLibraryMemberForProgramCompilationAllAndroid();
+ emulateLibraryInterface = buildEmulateLibraryInterface();
+ dontRewriteInvocations = buildDontRewriteInvocations();
} else {
- options.rewritePrefix = buildPrefixRewritingForProgramCompilationAndroidNPlus();
- options.retargetCoreLibMember =
- buildRetargetCoreLibraryMemberForProgramCompilationAndroidNPlus();
+ rewritePrefix = buildPrefixRewritingForProgramCompilationAndroidNPlus();
+ retargetCoreLibMember = buildRetargetCoreLibraryMemberForProgramCompilationAndroidNPlus();
}
+ return new DesugaredLibraryConfiguration(
+ false,
+ rewritePrefix,
+ emulateLibraryInterface,
+ retargetCoreLibMember,
+ ImmutableMap.of(),
+ dontRewriteInvocations);
}
- public static void configureLibraryDesugaringForLibraryCompilation(InternalOptions options) {
+ public static DesugaredLibraryConfiguration configureLibraryDesugaringForLibraryCompilation(
+ int minApiLevel) {
// TODO(b/134732760): Make assertions in L8 commands.
- if (options.minApiLevel >= AndroidApiLevel.O.getLevel()) {
- options.reporter.warning(
- new StringDiagnostic(
- "Desugaring core libraries for Android O and over is possible but not required."));
+ if (minApiLevel >= AndroidApiLevel.O.getLevel()) {
+ return DesugaredLibraryConfiguration.empty();
}
- options.coreLibraryCompilation = true;
- options.backportCoreLibraryMembers = buildBackportCoreLibraryMembers();
- if (options.minApiLevel < AndroidApiLevel.N.getLevel()) {
- options.retargetCoreLibMember = buildRetargetCoreLibraryMemberForCoreLibCompilation();
- options.dontRewriteInvocations = buildDontRewriteInvocations();
- options.emulateLibraryInterface = buildEmulateLibraryInterface();
- if (options.minApiLevel < AndroidApiLevel.M.getLevel()) {
- options.rewritePrefix = buildPrefixRewritingForCoreLibCompilationAllAndroid();
+ Map<String, String> rewritePrefix;
+ Map<String, String> retargetCoreLibMember = ImmutableMap.of();
+ Map<String, String> emulateLibraryInterface = ImmutableMap.of();
+ List<String> dontRewriteInvocations = ImmutableList.of();
+ Map<String, String> backportCoreLibraryMembers = buildBackportCoreLibraryMembers();
+ if (minApiLevel < AndroidApiLevel.N.getLevel()) {
+ retargetCoreLibMember = buildRetargetCoreLibraryMemberForCoreLibCompilation();
+ dontRewriteInvocations = buildDontRewriteInvocations();
+ emulateLibraryInterface = buildEmulateLibraryInterface();
+ if (minApiLevel < AndroidApiLevel.M.getLevel()) {
+ rewritePrefix = buildPrefixRewritingForCoreLibCompilationAllAndroid();
} else {
- options.rewritePrefix = buildPrefixRewritingForCoreLibCompilationAndroidOPlus();
+ rewritePrefix = buildPrefixRewritingForCoreLibCompilationAndroidOPlus();
}
} else {
- options.rewritePrefix = buildPrefixRewritingForCoreLibCompilationAndroidNPlus();
+ rewritePrefix = buildPrefixRewritingForCoreLibCompilationAndroidNPlus();
}
+ return new DesugaredLibraryConfiguration(
+ true,
+ rewritePrefix,
+ emulateLibraryInterface,
+ retargetCoreLibMember,
+ backportCoreLibraryMembers,
+ dontRewriteInvocations);
}
}
diff --git a/src/main/java/com/android/tools/r8/L8.java b/src/main/java/com/android/tools/r8/L8.java
index cc8f925..1c72b43 100644
--- a/src/main/java/com/android/tools/r8/L8.java
+++ b/src/main/java/com/android/tools/r8/L8.java
@@ -26,7 +26,9 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
-/** The L8 compiler. */
+/**
+ * The L8 compiler.
+ */
@Keep
public class L8 {
@@ -107,6 +109,10 @@
DexApplication app = new ApplicationReader(inputApp, options, timing).read(executor);
app = new L8TreePruner(options).prune(app);
+ if (app.classes().size() == 0) {
+ // TODO(b/134732760): report error instead of fatalError.
+ throw options.reporter.fatalError("Empty desugared library.");
+ }
AppInfo appInfo = new AppInfo(app);
AppView<?> appView = AppView.createForL8(appInfo, options);
@@ -119,15 +125,15 @@
assert appView.appInfo() == appInfo;
new CfApplicationWriter(
- app,
- appView,
- options,
- options.getMarker(Tool.L8),
- null,
- GraphLense.getIdentityLense(),
- PrefixRewritingNamingLens.createPrefixRewritingNamingLens(
- options, converter.getAdditionalRewritePrefix()),
- null)
+ app,
+ appView,
+ options,
+ options.getMarker(Tool.L8),
+ null,
+ GraphLense.getIdentityLense(),
+ PrefixRewritingNamingLens.createPrefixRewritingNamingLens(
+ options, converter.getAdditionalRewritePrefix()),
+ null)
.write(options.getClassFileConsumer(), executor);
options.printWarnings();
} catch (ExecutionException e) {
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index 4933163..a22cd4d 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.errors.DexFileOverflowDiagnostic;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
@@ -23,6 +24,8 @@
private final D8Command d8Command;
private final R8Command r8Command;
+ private final com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration libraryConfiguration;
+ private final DexItemFactory factory;
boolean isShrinking() {
return r8Command != null;
@@ -45,7 +48,8 @@
StringConsumer mainDexListConsumer,
int minApiLevel,
Reporter diagnosticsHandler,
- String specialLibraryConfiguration) {
+ DesugaredLibraryConfiguration libraryConfiguration,
+ DexItemFactory factory) {
super(
inputApp,
mode,
@@ -55,21 +59,20 @@
diagnosticsHandler,
true,
false,
- specialLibraryConfiguration,
false,
(name, checksum) -> true);
this.d8Command = d8Command;
this.r8Command = r8Command;
+ this.libraryConfiguration = libraryConfiguration;
+ this.factory = factory;
}
private L8Command(boolean printHelp, boolean printVersion) {
super(printHelp, printVersion);
r8Command = null;
d8Command = null;
- }
-
- private void configureLibraryDesugaring(InternalOptions options) {
- SpecialLibraryConfiguration.configureLibraryDesugaringForLibraryCompilation(options);
+ libraryConfiguration = null;
+ factory = null;
}
protected static class DefaultL8DiagnosticsHandler implements DiagnosticsHandler {
@@ -98,7 +101,7 @@
@Override
InternalOptions getInternalOptions() {
- InternalOptions internal = new InternalOptions(new DexItemFactory(), getReporter());
+ InternalOptions internal = new InternalOptions(factory, getReporter());
assert !internal.debug;
internal.debug = getMode() == CompilationMode.DEBUG;
assert internal.mainDexListConsumer == null;
@@ -134,13 +137,7 @@
internal.enableInheritanceClassInDexDistributor = false;
// TODO(134732760): This is still work in progress.
- assert internal.rewritePrefix.isEmpty();
- assert internal.emulateLibraryInterface.isEmpty();
- assert internal.retargetCoreLibMember.isEmpty();
- assert internal.backportCoreLibraryMembers.isEmpty();
- assert internal.dontRewriteInvocations.isEmpty();
- assert getSpecialLibraryConfiguration().equals("default");
- configureLibraryDesugaring(internal);
+ internal.libraryConfiguration = libraryConfiguration;
return internal;
}
@@ -187,10 +184,8 @@
@Override
void validate() {
Reporter reporter = getReporter();
- if (getSpecialLibraryConfiguration() == null) {
- reporter.error("L8 requires a special library configuration");
- } else if (!getSpecialLibraryConfiguration().equals("default")) {
- reporter.error("L8 currently requires the special library configuration to be \"default\"");
+ if (!hasDesugaredLibraryConfiguration()){
+ reporter.error("L8 requires a desugared library configuration");
}
if (getProgramConsumer() instanceof ClassFileConsumer) {
reporter.error("L8 does not support compiling to class files");
@@ -216,6 +211,10 @@
setMode(defaultCompilationMode());
}
+ DexItemFactory factory = new DexItemFactory();
+ DesugaredLibraryConfiguration libraryConfiguration =
+ getDesugaredLibraryConfiguration(factory, true, getMinApiLevel());
+
R8Command r8Command = null;
D8Command d8Command = null;
@@ -265,7 +264,8 @@
getMainDexListConsumer(),
getMinApiLevel(),
getReporter(),
- getSpecialLibraryConfiguration());
+ libraryConfiguration,
+ factory);
}
}
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index b4d0411..7050e40 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.errors.DexFileOverflowDiagnostic;
import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.origin.StandardOutOrigin;
@@ -283,7 +284,6 @@
* Set a consumer for receiving the proguard configuration information.
*
* <p>Note that any subsequent calls to this method will replace the previous setting.
- *
* @param proguardConfigurationConsumer
*/
public Builder setProguardConfigurationConsumer(StringConsumer proguardConfigurationConsumer) {
@@ -293,8 +293,6 @@
/**
* Set a consumer for receiving kept-graph events.
- *
- * @param graphConsumer
*/
public Builder setKeptGraphConsumer(GraphConsumer graphConsumer) {
this.keptGraphConsumer = graphConsumer;
@@ -303,8 +301,6 @@
/**
* Set a consumer for receiving kept-graph events for the content of the main-dex output.
- *
- * @param graphConsumer
*/
public Builder setMainDexKeptGraphConsumer(GraphConsumer graphConsumer) {
this.mainDexKeptGraphConsumer = graphConsumer;
@@ -398,14 +394,8 @@
if (getProgramConsumer() instanceof ClassFileConsumer && isMinApiLevelSet()) {
reporter.error("R8 does not support --min-api when compiling to class files");
}
- if (getSpecialLibraryConfiguration() != null) {
- if (getDisableDesugaring()) {
- reporter.error("Using special library configuration requires desugaring to be enabled");
- }
- if (!getSpecialLibraryConfiguration().equals("default")) {
- reporter
- .error("R8 currently requires the special library configuration to be \"default\"");
- }
+ if (hasDesugaredLibraryConfiguration() && getDisableDesugaring()) {
+ reporter.error("Using desugared library configuration requires desugaring to be enabled");
}
super.validate();
}
@@ -432,6 +422,9 @@
mainDexKeepRules = parser.getConfig().getRules();
}
+ DesugaredLibraryConfiguration libraryConfiguration =
+ getDesugaredLibraryConfiguration(factory, false, getMinApiLevel());
+
ProguardConfigurationParser parser =
new ProguardConfigurationParser(factory, reporter, allowTestProguardOptions);
if (!proguardConfigs.isEmpty()) {
@@ -472,17 +465,17 @@
}
};
- getAppBuilder().getProgramResourceProviders()
- .stream()
+ getAppBuilder().getProgramResourceProviders().stream()
.map(ProgramResourceProvider::getDataResourceProvider)
.filter(Objects::nonNull)
- .forEach(dataResourceProvider -> {
- try {
- dataResourceProvider.accept(embeddedProguardConfigurationVisitor);
- } catch (ResourceException e) {
- reporter.error(new ExceptionDiagnostic(e));
- }
- });
+ .forEach(
+ dataResourceProvider -> {
+ try {
+ dataResourceProvider.accept(embeddedProguardConfigurationVisitor);
+ } catch (ResourceException e) {
+ reporter.error(new ExceptionDiagnostic(e));
+ }
+ });
if (disableTreeShaking) {
configurationBuilder.disableShrinking();
@@ -526,10 +519,10 @@
mainDexKeptGraphConsumer,
syntheticProguardRulesConsumer,
isOptimizeMultidexForLinearAlloc(),
- getSpecialLibraryConfiguration(),
getIncludeClassesChecksum(),
getDexClassChecksumFilter(),
- desugaredLibraryKeepRuleConsumer);
+ desugaredLibraryKeepRuleConsumer,
+ libraryConfiguration);
return command;
}
@@ -610,6 +603,7 @@
private final GraphConsumer mainDexKeptGraphConsumer;
private final Consumer<List<ProguardConfigurationRule>> syntheticProguardRulesConsumer;
private final StringConsumer desugaredLibraryKeepRuleConsumer;
+ private final DesugaredLibraryConfiguration libraryConfiguration;
/** Get a new {@link R8Command.Builder}. */
public static Builder builder() {
@@ -681,10 +675,10 @@
GraphConsumer mainDexKeptGraphConsumer,
Consumer<List<ProguardConfigurationRule>> syntheticProguardRulesConsumer,
boolean optimizeMultidexForLinearAlloc,
- String specialLibraryConfiguration,
boolean encodeChecksum,
BiPredicate<String, Long> dexClassChecksumFilter,
- StringConsumer desugaredLibraryKeepRuleConsumer) {
+ StringConsumer desugaredLibraryKeepRuleConsumer,
+ com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration libraryConfiguration) {
super(
inputApp,
mode,
@@ -694,7 +688,6 @@
reporter,
enableDesugaring,
optimizeMultidexForLinearAlloc,
- specialLibraryConfiguration,
encodeChecksum,
dexClassChecksumFilter);
assert proguardConfiguration != null;
@@ -714,6 +707,7 @@
this.mainDexKeptGraphConsumer = mainDexKeptGraphConsumer;
this.syntheticProguardRulesConsumer = syntheticProguardRulesConsumer;
this.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
+ this.libraryConfiguration = libraryConfiguration;
}
private R8Command(boolean printHelp, boolean printVersion) {
@@ -733,6 +727,7 @@
mainDexKeptGraphConsumer = null;
syntheticProguardRulesConsumer = null;
desugaredLibraryKeepRuleConsumer = null;
+ libraryConfiguration = null;
}
/** Get the enable-tree-shaking state. */
@@ -761,12 +756,13 @@
// shaking for removing the lambda classes which should be revised later.
internal.enableLambdaMerging = getEnableTreeShaking();
assert !internal.ignoreMissingClasses;
- internal.ignoreMissingClasses = proguardConfiguration.isIgnoreWarnings()
- // TODO(70706667): We probably only want this in Proguard compatibility mode.
- || (forceProguardCompatibility
- && !proguardConfiguration.isOptimizing()
- && !internal.isShrinking()
- && !internal.isMinifying());
+ internal.ignoreMissingClasses =
+ proguardConfiguration.isIgnoreWarnings()
+ // TODO(70706667): We probably only want this in Proguard compatibility mode.
+ || (forceProguardCompatibility
+ && !proguardConfiguration.isOptimizing()
+ && !internal.isShrinking()
+ && !internal.isMinifying());
assert !internal.verbose;
internal.mainDexKeepRules = mainDexKeepRules;
@@ -847,24 +843,12 @@
internal.enableInheritanceClassInDexDistributor = isOptimizeMultidexForLinearAlloc();
// TODO(134732760): This is still work in progress.
- assert internal.rewritePrefix.isEmpty();
- assert internal.emulateLibraryInterface.isEmpty();
- assert internal.retargetCoreLibMember.isEmpty();
- assert internal.backportCoreLibraryMembers.isEmpty();
- assert internal.dontRewriteInvocations.isEmpty();
- if (getSpecialLibraryConfiguration() != null) {
- configureLibraryDesugaring(internal);
- }
-
+ internal.libraryConfiguration = libraryConfiguration;
internal.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
return internal;
}
- private void configureLibraryDesugaring(InternalOptions options) {
- SpecialLibraryConfiguration.configureLibraryDesugaringForProgramCompilation(options);
- }
-
private static StringConsumer wrapStringConsumer(
StringConsumer optionConsumer, boolean optionsFlag, Path optionFile) {
if (optionsFlag) {
diff --git a/src/main/java/com/android/tools/r8/dex/CodeToKeep.java b/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
index 6f3ff04..37c9e12 100644
--- a/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
+++ b/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
@@ -21,8 +21,9 @@
public abstract class CodeToKeep {
static CodeToKeep createCodeToKeep(InternalOptions options, NamingLens namingLens) {
- if ((!namingLens.hasPrefixRewritingLogic() && options.emulateLibraryInterface.isEmpty())
- || options.coreLibraryCompilation) {
+ if ((!namingLens.hasPrefixRewritingLogic()
+ && options.libraryConfiguration.getEmulateLibraryInterface().isEmpty())
+ || options.isDesugaredLibraryCompilation()) {
return new NopCodeToKeep();
}
return new DesugaredLibraryCodeToKeep(namingLens, options);
@@ -49,7 +50,8 @@
// Any class implementing one interface should implement the other one.
// Interface method desugaring should have created the types if emulatedLibraryInterfaces
// are set.
- for (String rewrittenName : options.emulateLibraryInterface.values()) {
+ for (String rewrittenName :
+ options.libraryConfiguration.getEmulateLibraryInterface().values()) {
DexString descriptor =
options.itemFactory.lookupString(DescriptorUtils.javaTypeToDescriptor(rewrittenName));
assert descriptor != null;
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index 0dac6a9..6ab56d3 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -222,7 +222,7 @@
// A consumer can manage the generated keep rules.
if (options.desugaredLibraryKeepRuleConsumer != null && !desugaredLibraryCodeToKeep.isNop()) {
- assert !options.coreLibraryCompilation;
+ assert !options.isDesugaredLibraryCompilation();
desugaredLibraryCodeToKeep.generateKeepRules(options);
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 7ef077a..4cc9ee8 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -690,7 +690,7 @@
|| (arity == dexCode.getDebugInfo().parameters.length);
} else {
// TODO(b/134732760): Patch Cf debug info.
- assert appView.options().coreLibraryCompilation;
+ assert appView.options().isDesugaredLibraryCompilation();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 0cbef69..2b446b3 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -201,7 +201,7 @@
.map(prefix -> "L" + DescriptorUtils.getPackageBinaryNameFromJavaType(prefix))
.map(options.itemFactory::createString)
.collect(Collectors.toList());
- if (options.coreLibraryCompilation) {
+ if (options.isDesugaredLibraryCompilation()) {
// Specific L8 Settings.
// BackportedMethodRewriter is needed for retarget core library members and backports.
// InterfaceMethodRewriter is needed for emulated interfaces.
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index f4905df..b581486 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -79,13 +79,14 @@
this.converter = converter;
this.factory = appView.dexItemFactory();
this.rewritableMethods = new RewritableMethods(appView);
- for (String coreLibMember : appView.options().backportCoreLibraryMembers.keySet()) {
+ Map<String, String> backportCoreLibraryMembers =
+ appView.options().libraryConfiguration.getBackportCoreLibraryMember();
+ for (String coreLibMember : backportCoreLibraryMembers.keySet()) {
DexType extraCoreLibMemberType =
factory.createType(DescriptorUtils.javaTypeToDescriptor(coreLibMember));
DexType coreLibMemberType =
factory.createType(
- DescriptorUtils.javaTypeToDescriptor(
- appView.options().backportCoreLibraryMembers.get(coreLibMember)));
+ DescriptorUtils.javaTypeToDescriptor(backportCoreLibraryMembers.get(coreLibMember)));
this.backportCoreLibraryMembers.put(extraCoreLibMemberType, coreLibMemberType);
}
}
@@ -251,7 +252,7 @@
initializeAndroidOMethodProviders(factory);
}
- if (options.rewritePrefix.containsKey("java.util.Optional")
+ if (options.libraryConfiguration.getRewritePrefix().containsKey("java.util.Optional")
|| options.minApiLevel >= AndroidApiLevel.N.getLevel()) {
// These are currently not implemented at any API level in Android.
// They however require the Optional class to be present, either through
@@ -264,7 +265,7 @@
initializeJava9MethodProviders(factory);
initializeJava11MethodProviders(factory);
- if (!options.retargetCoreLibMember.isEmpty()) {
+ if (!options.libraryConfiguration.getRetargetCoreLibMember().isEmpty()) {
initializeRetargetCoreLibraryMembers(appView);
}
}
@@ -1075,7 +1076,8 @@
String unqualifiedName =
DescriptorUtils.getUnqualifiedClassNameFromDescriptor(clazz.toString());
// Avoid duplicate class names between core lib dex file and program dex files.
- String coreLibUtilitySuffix = appView.options().coreLibraryCompilation ? "$corelib" : "";
+ String coreLibUtilitySuffix =
+ appView.options().isDesugaredLibraryCompilation() ? "$corelib" : "";
String descriptor =
UTILITY_CLASS_DESCRIPTOR_PREFIX
+ '$'
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index 6833067..e23772f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -80,7 +80,7 @@
boolean desugaredLibraryLookup =
superClass != null
&& superClass.isLibraryClass()
- && appView.options().emulateLibraryInterface.size() > 0;
+ && appView.options().libraryConfiguration.getEmulateLibraryInterface().size() > 0;
if (clazz.interfaces.isEmpty() && !desugaredLibraryLookup) {
// Since superclass has already been processed and it has all missing methods
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
new file mode 100644
index 0000000..c98378a
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfiguration.java
@@ -0,0 +1,142 @@
+// 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.ir.desugar;
+
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.utils.Reporter;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class DesugaredLibraryConfiguration {
+
+ // TODO(b/134732760): should use DexString, DexType, DexMethod or so on when possible.
+ private final boolean libraryCompilation;
+ private final Map<String, String> rewritePrefix;
+ private final Map<String, String> emulateLibraryInterface;
+ private final Map<String, String> retargetCoreLibMember;
+ private final Map<String, String> backportCoreLibraryMember;
+ private final List<String> dontRewriteInvocation;
+
+ public static Builder builder(DexItemFactory dexItemFactory, Reporter reporter) {
+ return new Builder(dexItemFactory, reporter);
+ }
+
+ public static DesugaredLibraryConfiguration empty() {
+ return new DesugaredLibraryConfiguration(
+ false,
+ ImmutableMap.of(),
+ ImmutableMap.of(),
+ ImmutableMap.of(),
+ ImmutableMap.of(),
+ ImmutableList.of());
+ }
+
+ public DesugaredLibraryConfiguration(
+ boolean libraryCompilation,
+ Map<String, String> rewritePrefix,
+ Map<String, String> emulateLibraryInterface,
+ Map<String, String> retargetCoreLibMember,
+ Map<String, String> backportCoreLibraryMember,
+ List<String> dontRewriteInvocation) {
+ this.libraryCompilation = libraryCompilation;
+ this.rewritePrefix = rewritePrefix;
+ this.emulateLibraryInterface = emulateLibraryInterface;
+ this.retargetCoreLibMember = retargetCoreLibMember;
+ this.backportCoreLibraryMember = backportCoreLibraryMember;
+ this.dontRewriteInvocation = dontRewriteInvocation;
+ }
+
+ public boolean isLibraryCompilation() {
+ return libraryCompilation;
+ }
+
+ public Map<String, String> getRewritePrefix() {
+ return rewritePrefix;
+ }
+
+ public Map<String, String> getEmulateLibraryInterface() {
+ return emulateLibraryInterface;
+ }
+
+ public Map<String, String> getRetargetCoreLibMember() {
+ return retargetCoreLibMember;
+ }
+
+ public Map<String, String> getBackportCoreLibraryMember() {
+ return backportCoreLibraryMember;
+ }
+
+ public List<String> getDontRewriteInvocation() {
+ return dontRewriteInvocation;
+ }
+
+ public static class Builder {
+
+ private final DexItemFactory factory;
+ private final Reporter reporter;
+
+ private boolean libraryCompilation = false;
+ private Map<String, String> rewritePrefix = new HashMap<>();
+ private Map<String, String> emulateLibraryInterface = new HashMap<>();
+ private Map<String, String> retargetCoreLibMember = new HashMap<>();
+ private Map<String, String> backportCoreLibraryMember = new HashMap<>();
+ private List<String> dontRewriteInvocation = new ArrayList<>();
+
+ public Builder(DexItemFactory dexItemFactory, Reporter reporter) {
+ this.factory = dexItemFactory;
+ this.reporter = reporter;
+ }
+
+ public Builder setProgramCompilation() {
+ libraryCompilation = false;
+ return this;
+ }
+
+ public Builder setLibraryCompilation() {
+ libraryCompilation = true;
+ return this;
+ }
+
+ public Builder putRewritePrefix(String prefix, String rewrittenPrefix) {
+ rewritePrefix.put(prefix, rewrittenPrefix);
+ return this;
+ }
+
+ public Builder putEmulateLibraryInterface(
+ String emulateLibraryItf, String rewrittenEmulateLibraryItf) {
+ emulateLibraryInterface.put(emulateLibraryItf, rewrittenEmulateLibraryItf);
+ return this;
+ }
+
+ public Builder putRetargetCoreLibMember(String retarget, String rewrittenRetarget) {
+ retargetCoreLibMember.put(retarget, rewrittenRetarget);
+ return this;
+ }
+
+ public Builder putBackportCoreLibraryMember(String backport, String rewrittenBackport) {
+ backportCoreLibraryMember.put(backport, rewrittenBackport);
+ return this;
+ }
+
+ public Builder addDontRewriteInvocation(String dontRewriteInvocation) {
+ this.dontRewriteInvocation.add(dontRewriteInvocation);
+ return this;
+ }
+
+ public DesugaredLibraryConfiguration build() {
+ return new DesugaredLibraryConfiguration(
+ libraryCompilation,
+ ImmutableMap.copyOf(rewritePrefix),
+ ImmutableMap.copyOf(emulateLibraryInterface),
+ ImmutableMap.copyOf(retargetCoreLibMember),
+ ImmutableMap.copyOf(backportCoreLibraryMember),
+ ImmutableList.copyOf(dontRewriteInvocation));
+ }
+ }
+}
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
new file mode 100644
index 0000000..73ddfa2
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java
@@ -0,0 +1,110 @@
+// 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.ir.desugar;
+
+import com.android.tools.r8.StringResource;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.utils.Reporter;
+import com.android.tools.r8.utils.StringDiagnostic;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import java.util.Map;
+
+public class DesugaredLibraryConfigurationParser {
+
+ private static final int MAX_SUPPORTED_VERSION = 1;
+
+ private final DesugaredLibraryConfiguration.Builder configurationBuilder;
+ private final Reporter reporter;
+ private final boolean libraryCompilation;
+ private final int minAPILevel;
+
+ public DesugaredLibraryConfigurationParser(
+ DexItemFactory dexItemFactory,
+ Reporter reporter,
+ boolean libraryCompilation,
+ int minAPILevel) {
+ this.reporter = reporter;
+ this.configurationBuilder = DesugaredLibraryConfiguration.builder(dexItemFactory, reporter);
+ this.minAPILevel = minAPILevel;
+ this.libraryCompilation = libraryCompilation;
+ if (libraryCompilation) {
+ configurationBuilder.setLibraryCompilation();
+ } else {
+ configurationBuilder.setProgramCompilation();
+ }
+ }
+
+ public DesugaredLibraryConfiguration parse(StringResource stringResource) {
+ String jsonConfigString;
+ try {
+ jsonConfigString = stringResource.getString();
+ } catch (Exception e) {
+ throw reporter.fatalError(
+ new StringDiagnostic("Cannot access desugared library configuration."));
+ }
+ JsonParser parser = new JsonParser();
+ JsonObject jsonConfig = parser.parse(jsonConfigString).getAsJsonObject();
+
+ int version = jsonConfig.get("configuration_format_version").getAsInt();
+ if (version > MAX_SUPPORTED_VERSION) {
+ throw reporter.fatalError(
+ new StringDiagnostic(
+ "Unsupported desugared library configuration version, please upgrade the D8/R8"
+ + " compiler."));
+ }
+ JsonArray jsonFlags =
+ libraryCompilation
+ ? jsonConfig.getAsJsonArray("library_flags")
+ : jsonConfig.getAsJsonArray("program_flags");
+ for (JsonElement jsonFlagSet : jsonFlags) {
+ int api_level_below_or_equal =
+ jsonFlagSet.getAsJsonObject().get("api_level_below_or_equal").getAsInt();
+ if (minAPILevel > api_level_below_or_equal) {
+ continue;
+ }
+ parseFlags(jsonFlagSet.getAsJsonObject());
+ }
+ return configurationBuilder.build();
+ }
+
+ private void parseFlags(JsonObject jsonFlagSet) {
+ if (jsonFlagSet.has("rewrite_prefix")) {
+ for (Map.Entry<String, JsonElement> rewritePrefix :
+ jsonFlagSet.get("rewrite_prefix").getAsJsonObject().entrySet()) {
+ configurationBuilder.putRewritePrefix(
+ rewritePrefix.getKey(), rewritePrefix.getValue().getAsString());
+ }
+ }
+ if (jsonFlagSet.has("retarget_lib_member")) {
+ for (Map.Entry<String, JsonElement> retarget :
+ jsonFlagSet.get("retarget_lib_member").getAsJsonObject().entrySet()) {
+ configurationBuilder.putRetargetCoreLibMember(
+ retarget.getKey(), retarget.getValue().getAsString());
+ }
+ }
+ if (jsonFlagSet.has("backport")) {
+ for (Map.Entry<String, JsonElement> backport :
+ jsonFlagSet.get("backport").getAsJsonObject().entrySet()) {
+ configurationBuilder.putBackportCoreLibraryMember(
+ backport.getKey(), backport.getValue().getAsString());
+ }
+ }
+ if (jsonFlagSet.has("emulate_interface")) {
+ for (Map.Entry<String, JsonElement> itf :
+ jsonFlagSet.get("emulate_interface").getAsJsonObject().entrySet()) {
+ configurationBuilder.putEmulateLibraryInterface(itf.getKey(), itf.getValue().getAsString());
+ }
+ }
+ if (jsonFlagSet.has("dont_rewrite")) {
+ JsonArray dontRewrite = jsonFlagSet.get("dont_rewrite").getAsJsonArray();
+ for (JsonElement rewrite : dontRewrite) {
+ configurationBuilder.addDontRewriteInvocation(rewrite.getAsString());
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index a4fb48b..437d78d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -147,13 +147,14 @@
}
private void initializeEmulatedInterfaceVariables() {
- for (String interfaceName : options.emulateLibraryInterface.keySet()) {
+ Map<String, String> emulateLibraryInterface =
+ options.libraryConfiguration.getEmulateLibraryInterface();
+ for (String interfaceName : emulateLibraryInterface.keySet()) {
DexType interfaceType =
factory.createType(DescriptorUtils.javaTypeToDescriptor(interfaceName));
DexType rewrittenType =
factory.createType(
- DescriptorUtils.javaTypeToDescriptor(
- options.emulateLibraryInterface.get(interfaceName)));
+ DescriptorUtils.javaTypeToDescriptor(emulateLibraryInterface.get(interfaceName)));
emulatedInterfaces.put(interfaceType, rewrittenType);
addRewritePrefix(interfaceType, rewrittenType.toSourceString());
DexClass emulatedInterfaceClass = appView.definitionFor(interfaceType);
@@ -164,10 +165,10 @@
}
}
}
- if (appView.options().coreLibraryCompilation) {
+ if (appView.options().isDesugaredLibraryCompilation()) {
options.populateRetargetCoreLibMember(factory, retargetCoreMember);
}
- for (String dontRewrite : options.dontRewriteInvocations) {
+ for (String dontRewrite : options.libraryConfiguration.getDontRewriteInvocation()) {
int index = dontRewrite.lastIndexOf('#');
if (index <= 0 || index >= dontRewrite.length() - 1) {
throw new CompilationError(
@@ -382,7 +383,7 @@
// Outside of core libraries, only library classes are rewritten. In core libraries,
// some classes are present both as program and library class, and definitionFor
// answers the program class so this is not true.
- if (!appView.options().coreLibraryCompilation && !dexClass.isLibraryClass()) {
+ if (!appView.options().isDesugaredLibraryCompilation() && !dexClass.isLibraryClass()) {
continue;
}
// We always rewrite interfaces, but classes are rewritten only if they are not already
@@ -548,11 +549,11 @@
}
private boolean isInDesugaredLibrary(DexClass clazz) {
- assert clazz.isLibraryClass() || options.coreLibraryCompilation;
+ assert clazz.isLibraryClass() || options.isDesugaredLibraryCompilation();
if (emulatedInterfaces.containsKey(clazz.type)) {
return true;
}
- return clazz.type.rewritingPrefixIn(options.rewritePrefix) != null;
+ return clazz.type.rewritingPrefixIn(options.libraryConfiguration.getRewritePrefix()) != null;
}
private boolean dontRewrite(DexMethod method) {
@@ -902,7 +903,9 @@
if (clazz.isInterface()) {
DexType newType = inferEmulatedInterfaceName(clazz);
if (newType != null
- && clazz.type.rewritingPrefixIn(appView.options().rewritePrefix) == null) {
+ && clazz.type.rewritingPrefixIn(
+ appView.options().libraryConfiguration.getRewritePrefix())
+ == null) {
// We do not rewrite if it is already going to be rewritten using the a rewritingPrefix.
addRewritePrefix(clazz.type, newType.toString());
renameEmulatedInterfaces(clazz, newType);
@@ -982,7 +985,7 @@
Flavor flavour,
ExecutorService executorService)
throws ExecutionException {
- if (appView.options().coreLibraryCompilation) {
+ if (appView.options().isDesugaredLibraryCompilation()) {
generateEmulateInterfaceLibrary(builder);
}
duplicateEmulatedInterfaces();
@@ -1004,7 +1007,7 @@
appInfo.addSynthesizedClass(synthesizedClass);
}
- if (appView.options().coreLibraryCompilation) {
+ if (appView.options().isDesugaredLibraryCompilation()) {
renameEmulatedInterfaces();
}
@@ -1086,7 +1089,8 @@
// Companion/Emulated interface classes for desugared library won't be missing,
// they are in the desugared library.
if (prefixRewritingInterfaces.containsKey(missing.toString())
- || missing.rewritingPrefixIn(appView.options().rewritePrefix) != null) {
+ || missing.rewritingPrefixIn(appView.options().libraryConfiguration.getRewritePrefix())
+ != null) {
return;
}
DexMethod method = appView.graphLense().getOriginalMethodSignature(referencedFrom);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index 550eb37..5b58d86 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -519,7 +519,7 @@
// The only case where we do Lambda desugaring with Cf to Cf is in L8.
// If the compilation is not coreLibraryCompilation, then the assertion
// implMethodHolder != null may fail, hence the assertion.
- assert rewriter.converter.appView.options().coreLibraryCompilation;
+ assert rewriter.converter.appView.options().isDesugaredLibraryCompilation();
DexMethod implMethod = descriptor.implHandle.asMethod();
DexClass implMethodHolder = definitionFor(implMethod.holder);
if (implMethodHolder == null) {
@@ -527,7 +527,8 @@
.converter
.appView
.options()
- .backportCoreLibraryMembers
+ .libraryConfiguration
+ .getBackportCoreLibraryMember()
.containsKey(implMethod.holder.toString());
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
index 3dbb5d0..d359630 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
@@ -280,11 +280,14 @@
knownLambdaClasses,
lambdaClassType,
new LambdaClass(this, accessedFrom, lambdaClassType, descriptor));
- if (appView.options().coreLibraryCompilation) {
+ if (appView.options().isDesugaredLibraryCompilation()) {
Pair<String, String> rewriting =
- accessedFrom.rewritingPrefixIn(appView.options().rewritePrefix);
+ accessedFrom.rewritingPrefixIn(
+ appView.options().libraryConfiguration.getRewritePrefix());
if (rewriting == null) {
- rewriting = accessedFrom.rewritingPrefixIn(appView.options().emulateLibraryInterface);
+ rewriting =
+ accessedFrom.rewritingPrefixIn(
+ appView.options().libraryConfiguration.getEmulateLibraryInterface());
}
if (rewriting != null) {
addRewritingPrefix(rewriting, lambdaClassType);
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index 71def8b..abe34ca 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -116,7 +116,7 @@
}
String markerString = marker.toString();
for (DexProgramClass clazz : application.classes()) {
- if (clazz.getSynthesizedFrom().isEmpty() || options.coreLibraryCompilation) {
+ if (clazz.getSynthesizedFrom().isEmpty() || options.isDesugaredLibraryCompilation()) {
writeClass(clazz, consumer, markerString);
} else {
throw new Unimplemented("No support for synthetics in the Java bytecode backend.");
@@ -205,7 +205,7 @@
// In this case bridges have been introduced for the Cf back-end,
// which do not have class file version.
assert options.testing.enableForceNestBasedAccessDesugaringForTest
- || options.coreLibraryCompilation;
+ || options.isDesugaredLibraryCompilation();
return 0;
}
return method.getClassFileVersion();
diff --git a/src/main/java/com/android/tools/r8/naming/PrefixRewritingNamingLens.java b/src/main/java/com/android/tools/r8/naming/PrefixRewritingNamingLens.java
index 6b24a34..914176e 100644
--- a/src/main/java/com/android/tools/r8/naming/PrefixRewritingNamingLens.java
+++ b/src/main/java/com/android/tools/r8/naming/PrefixRewritingNamingLens.java
@@ -42,7 +42,8 @@
public static NamingLens createPrefixRewritingNamingLens(
InternalOptions options, Map<String, String> additionalRewritePrefix, NamingLens namingLens) {
- if (options.rewritePrefix.isEmpty() && additionalRewritePrefix.isEmpty()) {
+ if (options.libraryConfiguration.getRewritePrefix().isEmpty()
+ && additionalRewritePrefix.isEmpty()) {
return namingLens;
}
return new PrefixRewritingNamingLens(namingLens, options, additionalRewritePrefix);
@@ -59,7 +60,7 @@
descriptorPrefixRewriting.put(
"L" + DescriptorUtils.getBinaryNameFromJavaType(from),
"L" + DescriptorUtils.getBinaryNameFromJavaType(to));
- options.rewritePrefix.forEach(lambda);
+ options.libraryConfiguration.getRewritePrefix().forEach(lambda);
additionalRewritePrefix.forEach(lambda);
// Run over all types and remap types with matching prefixes.
// TODO(134732760): Use a more efficient data structure (prefix tree/trie).
@@ -169,7 +170,7 @@
// If compiling the program using a desugared library, nothing needs to be printed.
// If compiling the desugared library, the mapping needs to be printed.
// When debugging the program, both mapping files need to be merged.
- if (options.coreLibraryCompilation) {
+ if (options.isDesugaredLibraryCompilation()) {
classRenaming.keySet().forEach(consumer);
}
namingLens.forAllRenamedTypes(consumer);
diff --git a/src/main/java/com/android/tools/r8/shaking/L8TreePruner.java b/src/main/java/com/android/tools/r8/shaking/L8TreePruner.java
index 5c7deb1..0b6531e 100644
--- a/src/main/java/com/android/tools/r8/shaking/L8TreePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/L8TreePruner.java
@@ -36,14 +36,16 @@
}
private void initializeEmulatedInterfaces() {
- for (String rewrittenName : options.emulateLibraryInterface.keySet()) {
+ for (String rewrittenName :
+ options.libraryConfiguration.getEmulateLibraryInterface().keySet()) {
emulatedInterfaces.add(
options.itemFactory.createType(DescriptorUtils.javaTypeToDescriptor(rewrittenName)));
}
}
private void initializeBackports() {
- for (String backportName : options.backportCoreLibraryMembers.keySet()) {
+ for (String backportName :
+ options.libraryConfiguration.getBackportCoreLibraryMember().keySet()) {
backports.add(
options.itemFactory.createType(DescriptorUtils.javaTypeToDescriptor(backportName)));
}
@@ -56,7 +58,7 @@
}
List<DexProgramClass> toKeep = new ArrayList<>();
for (DexProgramClass aClass : app.classes()) {
- if (aClass.type.rewritingPrefixIn(options.rewritePrefix) != null
+ if (aClass.type.rewritingPrefixIn(options.libraryConfiguration.getRewritePrefix()) != null
|| emulatedInterfaces.contains(aClass.type)
|| interfaceImplementsEmulatedInterface(aClass, typeMap)) {
toKeep.add(aClass);
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 6c01902..51ea8a0 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -32,6 +32,7 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.ir.optimize.Inliner;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.Position;
@@ -43,7 +44,6 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.io.IOException;
@@ -307,8 +307,13 @@
throw new UnsupportedOperationException("Cannot find internal output mode.");
}
+ public boolean isDesugaredLibraryCompilation() {
+ return libraryConfiguration.isLibraryCompilation();
+ }
+
public boolean shouldKeepStackMapTable() {
- return coreLibraryCompilation || getProguardConfiguration().getKeepAttributes().stackMapTable;
+ return isDesugaredLibraryCompilation()
+ || getProguardConfiguration().getKeepAttributes().stackMapTable;
}
public boolean isGeneratingDex() {
@@ -439,15 +444,9 @@
*/
public boolean enableInheritanceClassInDexDistributor = true;
- public boolean coreLibraryCompilation = false;
- public Map<String, String> rewritePrefix = ImmutableMap.of();
- public Map<String, String> emulateLibraryInterface = ImmutableMap.of();
- public Map<String, String> retargetCoreLibMember = ImmutableMap.of();
- public Map<String, String> backportCoreLibraryMembers = ImmutableMap.of();
- public List<String> dontRewriteInvocations = ImmutableList.of();
-
public void populateRetargetCoreLibMember(
DexItemFactory factory, Map<DexString, Map<DexType, DexType>> dest) {
+ Map<String, String> retargetCoreLibMember = libraryConfiguration.getRetargetCoreLibMember();
for (String inputString : retargetCoreLibMember.keySet()) {
int index = inputString.lastIndexOf('#');
if (index <= 0 || index >= inputString.length() - 1) {
@@ -606,6 +605,10 @@
// If non-null, configuration must be passed to the consumer.
public StringConsumer configurationConsumer = null;
+ // If null, no desugaring of library is performed.
+ // If non null it contains flags describing library desugaring.
+ public DesugaredLibraryConfiguration libraryConfiguration = DesugaredLibraryConfiguration.empty();
+
// If null, no keep rules are recorded.
// If non null it records desugared library APIs used by the program.
public StringConsumer desugaredLibraryKeepRuleConsumer = null;
@@ -1011,6 +1014,7 @@
new ProguardIfRuleEvaluationData();
public static class ProguardIfRuleEvaluationData {
+
public int numberOfProguardIfRuleClassEvaluations = 0;
public int numberOfProguardIfRuleMemberEvaluations = 0;
}
diff --git a/src/test/java/com/android/tools/r8/D8CommandTest.java b/src/test/java/com/android/tools/r8/D8CommandTest.java
index 870d7c8..ec83a9b 100644
--- a/src/test/java/com/android/tools/r8/D8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/D8CommandTest.java
@@ -531,10 +531,10 @@
public void warnForSpecialLibraryConfiguration() throws Throwable {
Path emptyZip = temp.getRoot().toPath().resolve("empty.zip");
DiagnosticsChecker.checkWarningsContains(
- "Special library configuration is still work in progress",
+ "Desugared library configuration is still work in progress",
handler ->
D8Command.builder(handler)
- .addSpecialLibraryConfiguration("default")
+ .addDesugaredLibraryConfiguration("default")
.setOutput(emptyZip, OutputMode.DexIndexed)
.build());
}
diff --git a/src/test/java/com/android/tools/r8/D8TestBuilder.java b/src/test/java/com/android/tools/r8/D8TestBuilder.java
index cb1a8c4..39b9024 100644
--- a/src/test/java/com/android/tools/r8/D8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/D8TestBuilder.java
@@ -71,7 +71,7 @@
if (minAPILevel.getLevel() < AndroidApiLevel.O.getLevel()) {
// Use P to mimic current Android Studio.
builder.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P));
- builder.addSpecialLibraryConfiguration("default");
+ builder.addDesugaredLibraryConfiguration("default");
builder.setDesugaredLibraryKeepRuleConsumer(keepRuleConsumer);
}
return self();
diff --git a/src/test/java/com/android/tools/r8/L8CommandTest.java b/src/test/java/com/android/tools/r8/L8CommandTest.java
index ca080de..b40d689 100644
--- a/src/test/java/com/android/tools/r8/L8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/L8CommandTest.java
@@ -30,7 +30,7 @@
verifyEmptyCommand(
L8Command.builder()
.setProgramConsumer(DexIndexedConsumer.emptyConsumer())
- .addSpecialLibraryConfiguration("default")
+ .addDesugaredLibraryConfiguration("default")
.build());
}
@@ -50,7 +50,7 @@
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(ToolHelper.getDesugarJDKLibs())
.setMinApiLevel(20)
- .addSpecialLibraryConfiguration("default")
+ .addDesugaredLibraryConfiguration("default")
.setOutput(output, OutputMode.DexIndexed)
.build());
Collection<Marker> markers = ExtractMarker.extractMarkerFromDexFile(output);
@@ -97,32 +97,21 @@
}
@Test(expected = CompilationFailedException.class)
- public void specialLibraryConfgurationRequired() throws Throwable {
+ public void specialLibraryConfigurationRequired() throws Throwable {
DiagnosticsChecker.checkErrorsContains(
- "L8 requires a special library configuration",
+ "L8 requires a desugared library configuration",
(handler) ->
prepareBuilder(handler).setProgramConsumer(ClassFileConsumer.emptyConsumer()).build());
}
- @Test(expected = CompilationFailedException.class)
- public void specialLibraryConfigurationMustBeDefault() throws Throwable {
- DiagnosticsChecker.checkErrorsContains(
- "L8 currently requires the special library configuration to be \"default\"",
- (handler) ->
- prepareBuilder(handler)
- .addSpecialLibraryConfiguration("not default")
- .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
- .build());
- }
-
@Test
public void warnForSpecialLibraryConfiguration() throws Throwable {
DiagnosticsChecker.checkWarningsContains(
- "Special library configuration is still work in progress",
+ "Desugared library configuration is still work in progress",
handler ->
prepareBuilder(handler)
.setProgramConsumer(DexIndexedConsumer.emptyConsumer())
- .addSpecialLibraryConfiguration("default")
+ .addDesugaredLibraryConfiguration("default")
.build());
}
}
diff --git a/src/test/java/com/android/tools/r8/R8CommandTest.java b/src/test/java/com/android/tools/r8/R8CommandTest.java
index 68aea3d..57d278e 100644
--- a/src/test/java/com/android/tools/r8/R8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/R8CommandTest.java
@@ -17,7 +17,6 @@
import com.android.tools.r8.origin.EmbeddedOrigin;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.ZipUtils;
import com.google.common.collect.ImmutableList;
@@ -89,8 +88,7 @@
@Test
public void desugaredLibraryKeepRuleConsumer() throws Exception {
- Box<String> holder = new Box<>("");
- StringConsumer stringConsumer = (string, handler) -> holder.set(holder.get() + string);
+ StringConsumer stringConsumer = StringConsumer.emptyConsumer();
D8Command command =
D8Command.builder()
.setProgramConsumer(DexIndexedConsumer.emptyConsumer())
@@ -639,18 +637,6 @@
"Missing parameter", handler -> parse(handler, "--output"));
}
- @Test(expected = CompilationFailedException.class)
- public void specialLibraryConfgurationMustBeDefault() throws Throwable {
- DiagnosticsChecker.checkErrorsContains(
- "R8 currently requires the special library configuration to be \"default\"",
- handler ->
- R8.run(
- R8Command.builder(handler)
- .addSpecialLibraryConfiguration("not default")
- .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
- .build()));
- }
-
private R8Command parse(String... args) throws CompilationFailedException {
return R8Command.parse(args, EmbeddedOrigin.INSTANCE).build();
}
diff --git a/src/test/java/com/android/tools/r8/R8TestBuilder.java b/src/test/java/com/android/tools/r8/R8TestBuilder.java
index d141a70..fbbf170 100644
--- a/src/test/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8TestBuilder.java
@@ -332,7 +332,7 @@
if (minAPILevel.getLevel() < AndroidApiLevel.O.getLevel()) {
// Use P to mimic current Android Studio.
builder.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P));
- builder.addSpecialLibraryConfiguration("default");
+ builder.addDesugaredLibraryConfiguration("default");
builder.setDesugaredLibraryKeepRuleConsumer(keepRuleConsumer);
}
return self();
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java b/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
index 5be195a..a5f8124 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
@@ -74,7 +74,7 @@
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(ToolHelper.getDesugarJDKLibs())
.addProgramFiles(additionalProgramFiles)
- .addSpecialLibraryConfiguration("default")
+ .addDesugaredLibraryConfiguration("default")
.setMinApiLevel(apiLevel.getLevel())
.setOutput(desugaredLib, OutputMode.DexIndexed);
if (shrink) {
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/DesugaredLibraryContentTest.java b/src/test/java/com/android/tools/r8/desugar/corelib/DesugaredLibraryContentTest.java
index 8304f36..9b210df 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/DesugaredLibraryContentTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/DesugaredLibraryContentTest.java
@@ -18,6 +18,7 @@
import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Assume;
import java.nio.file.Path;
import java.util.ArrayList;
import org.junit.Test;
@@ -40,12 +41,14 @@
@Test
public void testDesugaredLibraryContent() throws Exception {
+ Assume.assumeTrue(requiresAnyCoreLibDesugaring(parameters));
CodeInspector inspector = new CodeInspector(buildDesugaredLibrary(parameters.getApiLevel()));
assertCorrect(inspector);
}
@Test
public void testDesugaredLibraryContentWithCoreLambdaStubsAsProgram() throws Exception {
+ Assume.assumeTrue(requiresAnyCoreLibDesugaring(parameters));
ArrayList<Path> coreLambdaStubs = new ArrayList<>();
coreLambdaStubs.add(ToolHelper.getCoreLambdaStubs());
CodeInspector inspector =
@@ -56,6 +59,7 @@
@Test
public void testDesugaredLibraryContentWithCoreLambdaStubsAsLibrary() throws Exception {
+ Assume.assumeTrue(requiresAnyCoreLibDesugaring(parameters));
TestDiagnosticMessagesImpl diagnosticsHandler = new TestDiagnosticMessagesImpl();
Path desugaredLib = temp.newFolder().toPath().resolve("desugar_jdk_libs_dex.zip");
L8Command.Builder l8Builder =
@@ -63,7 +67,7 @@
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(ToolHelper.getDesugarJDKLibs())
.addLibraryFiles(ToolHelper.getCoreLambdaStubs())
- .addSpecialLibraryConfiguration("default")
+ .addDesugaredLibraryConfiguration("default")
.setMinApiLevel(parameters.getApiLevel().getLevel())
.setOutput(desugaredLib, OutputMode.DexIndexed);
ToolHelper.runL8(l8Builder.build(), options -> {});
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/DisableDesugarTest.java b/src/test/java/com/android/tools/r8/desugar/corelib/DisableDesugarTest.java
index c6c7c00..ca2ff2b 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/DisableDesugarTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/DisableDesugarTest.java
@@ -37,11 +37,11 @@
messages.assertWarningsCount(1);
assertThat(
messages.getWarnings().get(0).getDiagnosticMessage(),
- containsString("Special library configuration is still work in progress"));
+ containsString("Desugared library configuration is still work in progress"));
messages.assertErrorsCount(1);
assertThat(
messages.getErrors().get(0).getDiagnosticMessage(),
- containsString("Using special library configuration requires desugaring to be enabled"));
+ containsString("Using desugared library configuration requires desugaring to be enabled"));
}
@Test
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/JavaUtilOptionalTest.java b/src/test/java/com/android/tools/r8/desugar/corelib/JavaUtilOptionalTest.java
index 46f6418..7c13e5c 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/JavaUtilOptionalTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/JavaUtilOptionalTest.java
@@ -82,10 +82,10 @@
.addInnerClasses(JavaUtilOptionalTest.class)
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
- .enableCoreLibraryDesugaring()
+ .enableCoreLibraryDesugaring(parameters.getApiLevel())
.compile()
.inspect(this::checkRewrittenInvokes)
- .addRunClasspathFiles(buildDesugaredLibrary(parameters.getApiLevel()))
+ .addDesugaredCoreLibraryRunClassPath(this::buildDesugaredLibrary, parameters.getApiLevel())
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutput(expectedOutput);
}
@@ -95,11 +95,10 @@
testForD8()
.addProgramFiles(
Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION))
- .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel())
.compile()
- .addRunClasspathFiles(buildDesugaredLibrary(parameters.getApiLevel()))
+ .addDesugaredCoreLibraryRunClassPath(this::buildDesugaredLibrary, parameters.getApiLevel())
.run(parameters.getRuntime(), "backport.OptionalBackportJava9Main")
.assertSuccess();
}
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/JsonCompatibilityTest.java b/src/test/java/com/android/tools/r8/desugar/corelib/JsonCompatibilityTest.java
new file mode 100644
index 0000000..7051374
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/JsonCompatibilityTest.java
@@ -0,0 +1,110 @@
+// 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.assertTrue;
+
+import com.android.tools.r8.DesugaredLibraryConfigurationForTesting;
+import com.android.tools.r8.StringResource;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfigurationParser;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.Reporter;
+import java.nio.file.Paths;
+import java.util.Map;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class JsonCompatibilityTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDexRuntimes().withAllApiLevels().build();
+ }
+
+ public JsonCompatibilityTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testCompatibilityProgram() {
+ InternalOptions options1 = new InternalOptions(new DexItemFactory(), new Reporter());
+ options1.minApiLevel = parameters.getApiLevel().getLevel();
+ options1.libraryConfiguration =
+ DesugaredLibraryConfigurationForTesting.configureLibraryDesugaringForProgramCompilation(
+ parameters.getApiLevel().getLevel());
+
+ DexItemFactory factory = new DexItemFactory();
+ Reporter reporter = new Reporter();
+ InternalOptions options2 = new InternalOptions(factory, reporter);
+ options2.minApiLevel = parameters.getApiLevel().getLevel();
+ options2.libraryConfiguration =
+ new DesugaredLibraryConfigurationParser(
+ factory, reporter, false, parameters.getApiLevel().getLevel())
+ .parse(
+ StringResource.fromFile(
+ Paths.get(
+ "src/test/java/com/android/tools/r8/desugar/corelib/desugar_jdk_libs.json")));
+
+ assertConfigurationEquals(options1.libraryConfiguration, options2.libraryConfiguration);
+ }
+
+ @Test
+ public void testCompatibilityLibrary() {
+ InternalOptions options1 = new InternalOptions(new DexItemFactory(), new Reporter());
+ options1.minApiLevel = parameters.getApiLevel().getLevel();
+ options1.libraryConfiguration =
+ DesugaredLibraryConfigurationForTesting.configureLibraryDesugaringForLibraryCompilation(
+ parameters.getApiLevel().getLevel());
+
+ DexItemFactory factory = new DexItemFactory();
+ Reporter reporter = new Reporter();
+ InternalOptions options2 = new InternalOptions(factory, reporter);
+ options2.minApiLevel = parameters.getApiLevel().getLevel();
+ options2.libraryConfiguration =
+ new DesugaredLibraryConfigurationParser(
+ factory, reporter, true, parameters.getApiLevel().getLevel())
+ .parse(
+ StringResource.fromFile(
+ Paths.get(
+ "src/test/java/com/android/tools/r8/desugar/corelib/desugar_jdk_libs.json")));
+
+ assertConfigurationEquals(options1.libraryConfiguration, options2.libraryConfiguration);
+ }
+
+ private void assertConfigurationEquals(
+ com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration libraryConfiguration1,
+ com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration libraryConfiguration2) {
+ assertDictEquals(
+ libraryConfiguration1.getRewritePrefix(), libraryConfiguration2.getRewritePrefix());
+ assertDictEquals(
+ libraryConfiguration1.getEmulateLibraryInterface(),
+ libraryConfiguration2.getEmulateLibraryInterface());
+ assertDictEquals(
+ libraryConfiguration1.getBackportCoreLibraryMember(),
+ libraryConfiguration2.getBackportCoreLibraryMember());
+ assertDictEquals(
+ libraryConfiguration1.getRetargetCoreLibMember(),
+ libraryConfiguration2.getRetargetCoreLibMember());
+ assertEquals(
+ libraryConfiguration1.getDontRewriteInvocation().size(),
+ libraryConfiguration1.getDontRewriteInvocation().size());
+ }
+
+ private void assertDictEquals(Map<String, String> map1, Map<String, String> map2) {
+ assertEquals(map1.size(), map2.size());
+ for (String key : map1.keySet()) {
+ assertTrue(map2.containsKey(key) && map1.get(key).equals(map2.get(key)));
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/LongestPrefixlTest.java b/src/test/java/com/android/tools/r8/desugar/corelib/LongestPrefixlTest.java
index f66628d..15e9f41 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/LongestPrefixlTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/LongestPrefixlTest.java
@@ -8,8 +8,11 @@
import static org.hamcrest.MatcherAssert.assertThat;
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.BooleanUtils;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import java.nio.file.Path;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -40,7 +43,16 @@
testForD8()
.addProgramFiles(inputJar)
- .addOptionsModification(options -> options.rewritePrefix = x)
+ .addOptionsModification(
+ options ->
+ options.libraryConfiguration =
+ new DesugaredLibraryConfiguration(
+ false,
+ x,
+ ImmutableMap.of(),
+ ImmutableMap.of(),
+ ImmutableMap.of(),
+ ImmutableList.of()))
.compile()
.inspect(
inspector -> {
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/MergingJ$Test.java b/src/test/java/com/android/tools/r8/desugar/corelib/MergingJ$Test.java
index bdce532..d9255fe 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/MergingJ$Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/MergingJ$Test.java
@@ -56,7 +56,7 @@
L8Command.builder()
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(ToolHelper.getDesugarJDKLibs())
- .addSpecialLibraryConfiguration("default")
+ .addDesugaredLibraryConfiguration("default")
.setMinApiLevel(AndroidApiLevel.B.getLevel())
.setOutput(outputDex, OutputMode.DexIndexed)
.build());
@@ -71,7 +71,7 @@
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(JDK_11_JAVA_BASE_EXTENSION_COMPILED_FILES)
.addClasspathFiles(ToolHelper.getDesugarJDKLibs())
- .addSpecialLibraryConfiguration("default")
+ .addDesugaredLibraryConfiguration("default")
.setMinApiLevel(AndroidApiLevel.B.getLevel())
.setOutput(outputCf, OutputMode.DexIndexed)
.build());
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/NeverMergeCoreLibDesugarClasses.java b/src/test/java/com/android/tools/r8/desugar/corelib/NeverMergeCoreLibDesugarClasses.java
index 421a101..352fccf 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/NeverMergeCoreLibDesugarClasses.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/NeverMergeCoreLibDesugarClasses.java
@@ -65,6 +65,7 @@
@Test
public void testDesugaredCoreLibrary() throws Exception {
+ Assume.assumeTrue(parameters.getApiLevel().getLevel() < 26);
try {
testForD8()
.addInnerClasses(NeverMergeCoreLibDesugarClasses.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/desugar_jdk_libs.json b/src/test/java/com/android/tools/r8/desugar/corelib/desugar_jdk_libs.json
index cb63a44..af89cd4 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/desugar_jdk_libs.json
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/desugar_jdk_libs.json
@@ -9,13 +9,6 @@
"java.time.": "j$.time.",
"java.util.Desugar": "j$.util.Desugar"
},
- "retarget_lib_member": {
- "java.util.Calendar#toInstant": "java.util.DesugarCalendar",
- "java.util.Date#from": "java.util.DesugarDate",
- "java.util.Date#toInstant": "java.util.DesugarDate",
- "java.util.GregorianCalendar#from": "java.util.DesugarGregorianCalendar",
- "java.util.GregorianCalendar#toZonedDateTime": "java.util.DesugarGregorianCalendar"
- },
"backport": {
"java.lang.Double8": "java.lang.Double",
"java.lang.Integer8": "java.lang.Integer",
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 5935d18..8f90064 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
@@ -12,6 +12,7 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
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;
@@ -19,6 +20,7 @@
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.InvokeInstructionSubject;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -75,8 +77,14 @@
.setMinApi(parameters.getRuntime())
.addOptionsModification(
options ->
- options.rewritePrefix =
- ImmutableMap.of(packageName + ".runtime", packageName + ".library"))
+ options.libraryConfiguration =
+ new DesugaredLibraryConfiguration(
+ false,
+ ImmutableMap.of(packageName + ".runtime", packageName + ".library"),
+ ImmutableMap.of(),
+ ImmutableMap.of(),
+ ImmutableMap.of(),
+ ImmutableList.of()))
.compile();
testForR8(parameters.getBackend())