diff --git a/src/tools/android/java/com/android/tools/r8/CompatDxSupport.java b/src/tools/android/java/com/android/tools/r8/CompatDxSupport.java
index 31141b313f7dd2..e6a305b2a01c6e 100644
--- a/src/tools/android/java/com/android/tools/r8/CompatDxSupport.java
+++ b/src/tools/android/java/com/android/tools/r8/CompatDxSupport.java
@@ -13,8 +13,6 @@
// limitations under the License.
package com.android.tools.r8;
-import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.InternalOptions;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -25,30 +23,74 @@
public class CompatDxSupport {
public static void run(D8Command command, boolean minimalMainDex)
throws CompilationFailedException {
- AndroidApp app = command.getInputApp();
- InternalOptions options = command.getInternalOptions();
- // DX allows --multi-dex without specifying a main dex list for legacy devices.
- // That is broken, but for CompatDX we do the same to not break existing builds
- // that are trying to transition.
+ try {
+ // bazel can point to both an full r8.jar and to the shrunken r8.jar (r8lib.jar), as the
+ // r8.jar is currently referenced from the Android SDK build-tools, where different versions
+ // have either full or shrunken jar. From build-tools version 30.0.1 the shrunken jar is
+ // shipped. If the full jar is used some additional internal APIs are used for additional
+ // configuration of "check main dex" and "minimal main dex" flags which are not
+ // supported in the public D8 API.
+ Class> androidAppClass = Class.forName("com.android.tools.r8.utils.AndroidApp");
+ Class> internalOptionsClass = Class.forName("com.android.tools.r8.utils.InternalOptions");
+ runOnFullJar(command, minimalMainDex, androidAppClass, internalOptionsClass);
+ } catch (ClassNotFoundException e) {
+ D8.run(command);
+ }
+ }
+
+ public static void runOnFullJar(
+ D8Command command,
+ boolean minimalMainDex,
+ Class> androidAppClass,
+ Class> internalOptionsClass) {
+ Method getInputAppMethod;
+ Method getInternalOptionsMethod;
+ Method runForTestingMethod;
+ try {
+ getInputAppMethod = BaseCommand.class.getDeclaredMethod("getInputApp");
+ getInternalOptionsMethod = D8Command.class.getDeclaredMethod("getInternalOptions");
+ runForTestingMethod =
+ D8.class.getDeclaredMethod("runForTesting", androidAppClass, internalOptionsClass);
+ } catch (NoSuchMethodException e) {
+ throw new AssertionError("Unsupported r8.jar", e);
+ }
+
try {
// Use reflection for:
- // options.enableMainDexListCheck = false;
- // as bazel might link to an old r8.jar which does not have this field.
- Field enableMainDexListCheck = options.getClass().getField("enableMainDexListCheck");
+ // AndroidApp app = command.getInputApp();
+ // InternalOptions options = command.getInternalOptions();
+ // as bazel might link to a shrunken r8.jar which does not have these APIs.
+ Object app = getInputAppMethod.invoke(command);
+ Object options = getInternalOptionsMethod.invoke(command);
+ // DX allows --multi-dex without specifying a main dex list for legacy devices.
+ // That is broken, but for CompatDX we do the same to not break existing builds
+ // that are trying to transition.
try {
- enableMainDexListCheck.setBoolean(options, false);
- } catch (IllegalAccessException e) {
- throw new AssertionError(e);
+ Field enableMainDexListCheckField = internalOptionsClass.getField("enableMainDexListCheck");
+ // DX has a minimal main dex flag. In compat mode only do minimal main dex
+ // if the flag is actually set.
+ Field minimalMainDexField = internalOptionsClass.getField("minimalMainDex");
+ try {
+ // Use reflection for:
+ // options.enableMainDexListCheck = false;
+ // as bazel might link to an old r8.jar which does not have this field.
+ enableMainDexListCheckField.setBoolean(options, false);
+ // Use reflection for:
+ // options.minimalMainDex = minimalMainDex;
+ // as bazel might link to an old r8.jar which does not have this field.
+ minimalMainDexField.setBoolean(options, minimalMainDex);
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("Unsupported r8.jar", e);
+ }
+ } catch (NoSuchFieldException e) {
+ // Ignore if bazel is linking to an old r8.jar.
}
- } catch (NoSuchFieldException e) {
- // Ignore if bazel is linking to an old r8.jar.
- }
-
- // DX has a minimal main dex flag. In compat mode only do minimal main dex
- // if the flag is actually set.
- options.minimalMainDex = minimalMainDex;
- D8.runForTesting(app, options);
+ runForTestingMethod.invoke(null, app, options);
+ } catch (ReflectiveOperationException e) {
+ // This is an unsupported r8.jar.
+ throw new AssertionError("Unsupported r8.jar", e);
+ }
}
public static void enableDesugarBackportStatics(D8Command.Builder builder) {
@@ -61,7 +103,7 @@ public static void enableDesugarBackportStatics(D8Command.Builder builder) {
try {
enableDesugarBackportStatics.invoke(builder);
} catch (ReflectiveOperationException e) {
- throw new AssertionError(e);
+ throw new AssertionError("Unsupported r8.jar", e);
}
} catch (NoSuchMethodException e) {
// Ignore if bazel is linking to an old r8.jar.
diff --git a/src/tools/android/java/com/google/devtools/build/android/r8/CompatDx.java b/src/tools/android/java/com/google/devtools/build/android/r8/CompatDx.java
index 3adec8f9f79deb..7f0ad8f4bf0517 100644
--- a/src/tools/android/java/com/google/devtools/build/android/r8/CompatDx.java
+++ b/src/tools/android/java/com/google/devtools/build/android/r8/CompatDx.java
@@ -27,8 +27,6 @@
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.ProgramConsumer;
import com.android.tools.r8.Version;
-import com.android.tools.r8.errors.CompilationError;
-import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.utils.ArchiveResourceProvider;
@@ -523,11 +521,11 @@ private static void run(String[] args)
}
if (dexArgs.verboseDump) {
- throw new Unimplemented("verbose dump file not yet supported");
+ throw new CompatDxUnimplemented("verbose dump file not yet supported");
}
if (dexArgs.methodToDump != null) {
- throw new Unimplemented("method-dump not yet supported");
+ throw new CompatDxUnimplemented("method-dump not yet supported");
}
if (dexArgs.output != null) {
@@ -557,7 +555,7 @@ private static void run(String[] args)
}
if (dexArgs.incremental) {
- throw new Unimplemented("incremental merge not supported yet");
+ throw new CompatDxUnimplemented("incremental merge not supported yet");
}
if (dexArgs.forceJumbo && dexArgs.verbose) {
@@ -573,11 +571,11 @@ private static void run(String[] args)
}
if (dexArgs.optimizeList != null) {
- throw new Unimplemented("no support for optimize-method list");
+ throw new CompatDxUnimplemented("no support for optimize-method list");
}
if (dexArgs.noOptimizeList != null) {
- throw new Unimplemented("no support for dont-optimize-method list");
+ throw new CompatDxUnimplemented("no support for dont-optimize-method list");
}
if (dexArgs.statistics && dexArgs.verbose) {
@@ -647,7 +645,7 @@ private static void run(String[] args)
setMinimalMainDex.invoke(builder, dexArgs.minimalMainDex);
D8.run(builder.build());
} catch (ReflectiveOperationException e) {
- // Go through the support support code accessing the internals for the compilation.
+ // Go through the support code accessing the internals for the compilation.
CompatDxSupport.run(builder.build(), dexArgs.minimalMainDex);
}
} finally {
@@ -696,7 +694,7 @@ public SingleDexFileConsumer(DexIndexedConsumer consumer) {
public void accept(
int fileIndex, ByteDataView data, Set descriptors, DiagnosticsHandler handler) {
if (fileIndex > 0) {
- throw new CompilationError(
+ throw new CompatDxCompilationError(
"Compilation result could not fit into a single dex file. "
+ "Reduce the input-program size or run with --multi-dex enabled");
}
@@ -870,7 +868,7 @@ private void writeInputClassesToArchive(DiagnosticsHandler handler) throws IOExc
private static void processPath(Path path, List files) throws IOException {
if (!Files.exists(path)) {
- throw new CompilationError("File does not exist: " + path);
+ throw new CompatDxCompilationError("File does not exist: " + path);
}
if (Files.isDirectory(path)) {
processDirectory(path, files);
@@ -881,7 +879,7 @@ private static void processPath(Path path, List files) throws IOException
return;
}
if (FileUtils.isApkFile(path)) {
- throw new Unimplemented("apk files not yet supported: " + path);
+ throw new CompatDxUnimplemented("apk files not yet supported: " + path);
}
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/r8/CompatDxCompilationError.java b/src/tools/android/java/com/google/devtools/build/android/r8/CompatDxCompilationError.java
new file mode 100644
index 00000000000000..c7cbbeb3226215
--- /dev/null
+++ b/src/tools/android/java/com/google/devtools/build/android/r8/CompatDxCompilationError.java
@@ -0,0 +1,24 @@
+// Copyright 2020 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.android.r8;
+
+/** Compilation error in CompatDx */
+public class CompatDxCompilationError extends RuntimeException {
+
+ public CompatDxCompilationError() {}
+
+ public CompatDxCompilationError(String message) {
+ super(message);
+ }
+}
diff --git a/src/tools/android/java/com/google/devtools/build/android/r8/CompatDxUnimplemented.java b/src/tools/android/java/com/google/devtools/build/android/r8/CompatDxUnimplemented.java
new file mode 100644
index 00000000000000..e03d3269368c6c
--- /dev/null
+++ b/src/tools/android/java/com/google/devtools/build/android/r8/CompatDxUnimplemented.java
@@ -0,0 +1,24 @@
+// Copyright 2020 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.android.r8;
+
+/** Unimplemented in CompatDx */
+public class CompatDxUnimplemented extends RuntimeException {
+
+ public CompatDxUnimplemented() {}
+
+ public CompatDxUnimplemented(String message) {
+ super(message);
+ }
+}