JVM: Add D8 check that class files can be dexed with D8.
This change adds D8 in addition to Dx which is being deprecated. At some point after the official Dx deprecation, we should remove the Dx checker. Moving to D8 has the additional benefit that D8 can dex code using java 8 features without using a separate desugaring tool.
This commit is contained in:
committed by
Alexander Udalov
parent
222ceb7698
commit
73aa36ca59
@@ -534,8 +534,15 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
||||
);
|
||||
classFileFactory = generationState.getFactory();
|
||||
|
||||
if (verifyWithDex() && DxChecker.RUN_DX_CHECKER) {
|
||||
// Some names are not allowed in the dex file format and the VM will reject the program
|
||||
// if they are used. Therefore, a few tests cannot be dexed as they use such names that
|
||||
// are valid on the JVM but not on the Android Runtime.
|
||||
boolean ignoreDexing = myFiles.getPsiFiles().stream().anyMatch(
|
||||
it -> InTextDirectivesUtils.isDirectiveDefined(it.getText(), "IGNORE_DEXING")
|
||||
);
|
||||
if (verifyWithDex() && DxChecker.RUN_DX_CHECKER && !ignoreDexing) {
|
||||
DxChecker.check(classFileFactory);
|
||||
D8Checker.check(classFileFactory);
|
||||
}
|
||||
}
|
||||
catch (TestsCompiletimeError e) {
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.android.tools.r8.*;
|
||||
import com.android.tools.r8.origin.PathOrigin;
|
||||
import com.android.tools.r8.utils.AndroidApiLevel;
|
||||
import com.intellij.concurrency.IdeaForkJoinWorkerThreadFactory;
|
||||
import kotlin.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFile;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class D8Checker {
|
||||
|
||||
private D8Checker() {
|
||||
}
|
||||
|
||||
public static void check(ClassFileFactory outputFiles) {
|
||||
runD8(builder -> {
|
||||
for (OutputFile file : ClassFileUtilsKt.getClassFiles(outputFiles)) {
|
||||
byte[] bytes = file.asByteArray();
|
||||
builder.addClassProgramData(bytes, new PathOrigin(Paths.get(file.getRelativePath())));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void checkFilesWithD8(Collection<Pair<byte[], String>> classFiles) {
|
||||
runD8(builder -> {
|
||||
classFiles.forEach(pair -> {
|
||||
builder.addClassProgramData(pair.getFirst(), new PathOrigin(Paths.get(pair.getSecond())));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static void runD8(Consumer<D8Command.Builder> addInput) {
|
||||
ProgramConsumer ignoreOutputConsumer = new DexIndexedConsumer.ForwardingConsumer(null);
|
||||
D8Command.Builder builder = D8Command.builder()
|
||||
.setMinApiLevel(28)
|
||||
.setMode(CompilationMode.DEBUG)
|
||||
.setProgramConsumer(ignoreOutputConsumer);
|
||||
addInput.accept(builder);
|
||||
try {
|
||||
D8.run(builder.build(), Executors.newSingleThreadExecutor());
|
||||
}
|
||||
catch (CompilationFailedException e) {
|
||||
Assert.fail(generateExceptionMessage(e));
|
||||
}
|
||||
}
|
||||
|
||||
private static String generateExceptionMessage(Throwable e) {
|
||||
StringWriter writer = new StringWriter();
|
||||
try (PrintWriter printWriter = new PrintWriter(writer)) {
|
||||
e.printStackTrace(printWriter);
|
||||
String stackTrace = writer.toString();
|
||||
return stackTrace;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user