Build: Use only @Exported & whitelisted classes for tools.jar api
This makes it stable between JDK vendors and versions
This commit is contained in:
+34
-38
@@ -1,8 +1,5 @@
|
|||||||
import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated
|
import org.jetbrains.org.objectweb.asm.*
|
||||||
import org.jetbrains.org.objectweb.asm.ClassReader
|
|
||||||
import org.jetbrains.org.objectweb.asm.ClassReader.SKIP_CODE
|
import org.jetbrains.org.objectweb.asm.ClassReader.SKIP_CODE
|
||||||
import org.jetbrains.org.objectweb.asm.ClassVisitor
|
|
||||||
import org.jetbrains.org.objectweb.asm.ClassWriter
|
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||||
import java.util.zip.ZipFile
|
import java.util.zip.ZipFile
|
||||||
|
|
||||||
@@ -20,11 +17,9 @@ val runtimeElements by configurations.creating {
|
|||||||
|
|
||||||
val JDK_18: String by rootProject.extra
|
val JDK_18: String by rootProject.extra
|
||||||
val toolsJarFile = toolsJarFile(jdkHome = File(JDK_18)) ?: error("Couldn't find tools.jar in $JDK_18")
|
val toolsJarFile = toolsJarFile(jdkHome = File(JDK_18)) ?: error("Couldn't find tools.jar in $JDK_18")
|
||||||
|
val usedInternalApiPackages = listOf(
|
||||||
// tools.jar from JDK has different public api on different platforms which makes impossible to reuse caches
|
"com/sun/tools/javac" // Used in KAPT
|
||||||
// for tasks which depend on it. Since we can't compile against those classes & stay cross-platform anyway,
|
)
|
||||||
// we may just exclude them from compile classpath. Since method bodies are not required for compilation
|
|
||||||
// strip them out to remove noise between different versions.
|
|
||||||
|
|
||||||
val toolsJarStubs by tasks.registering {
|
val toolsJarStubs by tasks.registering {
|
||||||
inputs.file(toolsJarFile)
|
inputs.file(toolsJarFile)
|
||||||
@@ -33,6 +28,7 @@ val toolsJarStubs by tasks.registering {
|
|||||||
outputs.dir(outDir)
|
outputs.dir(outDir)
|
||||||
|
|
||||||
doLast {
|
doLast {
|
||||||
|
outDir.deleteRecursively()
|
||||||
val zipFile = ZipFile(toolsJarFile)
|
val zipFile = ZipFile(toolsJarFile)
|
||||||
zipFile.stream()
|
zipFile.stream()
|
||||||
.filter { it.name.endsWith(".class") }
|
.filter { it.name.endsWith(".class") }
|
||||||
@@ -40,12 +36,37 @@ val toolsJarStubs by tasks.registering {
|
|||||||
zipFile.getInputStream(zipEntry).use { entryStream ->
|
zipFile.getInputStream(zipEntry).use { entryStream ->
|
||||||
val classReader = ClassReader(entryStream)
|
val classReader = ClassReader(entryStream)
|
||||||
val classWriter = ClassWriter( 0)
|
val classWriter = ClassWriter( 0)
|
||||||
|
var isExported = false
|
||||||
classReader.accept(object : ClassVisitor(API_VERSION, classWriter) {
|
classReader.accept(object : ClassVisitor(API_VERSION, classWriter) {
|
||||||
|
override fun visit(
|
||||||
|
version: Int,
|
||||||
|
access: Int,
|
||||||
|
name: String?,
|
||||||
|
signature: String?,
|
||||||
|
superName: String?,
|
||||||
|
interfaces: Array<out String>?
|
||||||
|
) {
|
||||||
|
val isPublic = access and ACC_PUBLIC != 0
|
||||||
|
if (isPublic && usedInternalApiPackages.any { name?.startsWith(it) == true }) {
|
||||||
|
isExported = true
|
||||||
|
}
|
||||||
|
|
||||||
|
super.visit(version, access, name, signature, superName, interfaces)
|
||||||
|
}
|
||||||
|
override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor {
|
||||||
|
if (descriptor == "Ljdk/Exported;") {
|
||||||
|
isExported = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.visitAnnotation(descriptor, visible)
|
||||||
|
}
|
||||||
}, SKIP_CODE)
|
}, SKIP_CODE)
|
||||||
val result = File(outDir, zipEntry.name)
|
|
||||||
result.ensureParentDirsCreated()
|
if (isExported) {
|
||||||
result.writeBytes(classWriter.toByteArray())
|
val result = File(outDir, zipEntry.name)
|
||||||
|
result.parentFile.mkdirs()
|
||||||
|
result.writeBytes(classWriter.toByteArray())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,32 +75,7 @@ val toolsJarStubs by tasks.registering {
|
|||||||
val jar = tasks.register<Jar>("jar") {
|
val jar = tasks.register<Jar>("jar") {
|
||||||
dependsOn(toolsJarStubs)
|
dependsOn(toolsJarStubs)
|
||||||
from {
|
from {
|
||||||
fileTree(toolsJarStubs.get().outputs.files.singleFile).matching {
|
fileTree(toolsJarStubs.get().outputs.files.singleFile)
|
||||||
exclude("META-INF/**")
|
|
||||||
|
|
||||||
exclude("sun/tools/attach/LinuxAttachProvider.class")
|
|
||||||
exclude("sun/tools/attach/LinuxVirtualMachine*")
|
|
||||||
|
|
||||||
exclude("sun/tools/attach/BsdAttachProvider.class")
|
|
||||||
exclude("sun/tools/attach/BsdVirtualMachine*")
|
|
||||||
|
|
||||||
exclude("sun/tools/attach/WindowsAttachProvider.class")
|
|
||||||
exclude("sun/tools/attach/WindowsVirtualMachine*")
|
|
||||||
|
|
||||||
// Windows only classes
|
|
||||||
exclude("com/sun/tools/jdi/SharedMemoryAttachingConnector$1.class")
|
|
||||||
exclude("com/sun/tools/jdi/SharedMemoryAttachingConnector.class")
|
|
||||||
exclude("com/sun/tools/jdi/SharedMemoryConnection.class")
|
|
||||||
exclude("com/sun/tools/jdi/SharedMemoryListeningConnector$1.class")
|
|
||||||
exclude("com/sun/tools/jdi/SharedMemoryListeningConnector.class")
|
|
||||||
exclude("com/sun/tools/jdi/SharedMemoryTransportService${'$'}SharedMemoryListenKey.class")
|
|
||||||
exclude("com/sun/tools/jdi/SharedMemoryTransportService.class")
|
|
||||||
exclude("com/sun/tools/jdi/SharedMemoryTransportServiceCapabilities.class")
|
|
||||||
exclude("com/sun/tools/jdi/SunSDK.class")
|
|
||||||
|
|
||||||
// Deprecated class which has differences in api between versions
|
|
||||||
exclude("com/sun/tools/javadoc/JavaScriptScanner.class")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user