Raise a compilation error when compiling with machine spec
Bug: b/247730422
Change-Id: Iaf7ac1b61616afc8a3ce8939b8150ffe2b8db583
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibrarySpecificationParser.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibrarySpecificationParser.java
index 83ee3ec..4bb5379 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibrarySpecificationParser.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibrarySpecificationParser.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.ir.desugar.desugaredlibrary;
import com.android.tools.r8.StringResource;
+import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser;
import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecificationParser;
@@ -20,6 +21,7 @@
public static final String CONFIGURATION_FORMAT_VERSION_KEY = "configuration_format_version";
private static final int MIN_HUMAN_CONFIGURATION_FORMAT_VERSION = 100;
+ private static final int MIN_MACHINE_CONFIGURATION_FORMAT_VERSION = 200;
public static DesugaredLibrarySpecification parseDesugaredLibrarySpecification(
StringResource stringResource,
@@ -27,26 +29,8 @@
Reporter reporter,
boolean libraryCompilation,
int minAPILevel) {
- Origin origin = stringResource.getOrigin();
- assert origin != null;
- String jsonConfigString;
- JsonObject jsonConfig;
- try {
- jsonConfigString = stringResource.getString();
- JsonParser parser = new JsonParser();
- jsonConfig = parser.parse(jsonConfigString).getAsJsonObject();
- } catch (Exception e) {
- throw reporter.fatalError(new ExceptionDiagnostic(e, origin));
- }
-
- if (isHumanSpecification(jsonConfig, reporter, origin)) {
- return new HumanDesugaredLibrarySpecificationParser(
- dexItemFactory, reporter, libraryCompilation, minAPILevel)
- .parse(origin, jsonConfigString, jsonConfig);
- }
- return new LegacyDesugaredLibrarySpecificationParser(
- dexItemFactory, reporter, libraryCompilation, minAPILevel)
- .parse(origin, jsonConfigString, jsonConfig);
+ return parseDesugaredLibrarySpecificationforTesting(
+ stringResource, dexItemFactory, reporter, libraryCompilation, minAPILevel, flags -> {});
}
public static DesugaredLibrarySpecification parseDesugaredLibrarySpecificationforTesting(
@@ -67,18 +51,53 @@
} catch (Exception e) {
throw reporter.fatalError(new ExceptionDiagnostic(e, origin));
}
+ // Machine Specification is the shippable format released in Maven. D8/R8 has to be *very*
+ // backward compatible to any machine specification, and raise proper error messages for
+ // compatibility issues. The format is also exhaustive (Very limited pattern matching, if any).
+ // It can hardly be written by hand and is always generated.
+ if (isMachineSpecification(jsonConfig, reporter, origin)) {
+ throw new CompilationError(
+ "Unsupported desugared library configuration version, please upgrade the D8/R8 compiler."
+ + " See https://developer.android.com/studio/build/library-desugaring-versions.");
+ }
+ // Human Specification is the easy to write format for developers and allows one to widely use
+ // pattern matching. This format is mainly used for development and to generate the machine
+ // specification. D8/R8 is *not* backward compatible with any previous version of human
+ // specification, which is therefore not suited to be shipped for external users. It can be
+ // shipped to internal users where we can easily update the D8/R8 compiler and the
+ // desugared library specification at the same time.
if (isHumanSpecification(jsonConfig, reporter, origin)) {
return new HumanDesugaredLibrarySpecificationParser(
dexItemFactory, reporter, libraryCompilation, minAPILevel)
.parse(origin, jsonConfigString, jsonConfig, topLevelFlagsAmender);
}
+ // Legacy specification is the legacy format, as was shipped desugared library JDK8 or JDK11
+ // legacy. Hopefully the day will come where this format is no longer supported, and the other
+ // formats shall always be preferred.
return new LegacyDesugaredLibrarySpecificationParser(
dexItemFactory, reporter, libraryCompilation, minAPILevel)
.parse(origin, jsonConfigString, jsonConfig, topLevelFlagsAmender);
}
+ public static boolean isMachineSpecification(
+ JsonObject jsonConfig, Reporter reporter, Origin origin) {
+ ensureConfigurationFormatVersion(jsonConfig, reporter, origin);
+
+ int formatVersion = jsonConfig.get(CONFIGURATION_FORMAT_VERSION_KEY).getAsInt();
+ return formatVersion >= MIN_MACHINE_CONFIGURATION_FORMAT_VERSION;
+ }
+
public static boolean isHumanSpecification(
JsonObject jsonConfig, Reporter reporter, Origin origin) {
+ ensureConfigurationFormatVersion(jsonConfig, reporter, origin);
+
+ int formatVersion = jsonConfig.get(CONFIGURATION_FORMAT_VERSION_KEY).getAsInt();
+ return formatVersion >= MIN_HUMAN_CONFIGURATION_FORMAT_VERSION
+ && formatVersion < MIN_MACHINE_CONFIGURATION_FORMAT_VERSION;
+ }
+
+ private static void ensureConfigurationFormatVersion(
+ JsonObject jsonConfig, Reporter reporter, Origin origin) {
if (!jsonConfig.has(CONFIGURATION_FORMAT_VERSION_KEY)) {
throw reporter.fatalError(
new StringDiagnostic(
@@ -87,8 +106,5 @@
+ "'",
origin));
}
-
- return jsonConfig.get(CONFIGURATION_FORMAT_VERSION_KEY).getAsInt()
- >= MIN_HUMAN_CONFIGURATION_FORMAT_VERSION;
}
}