14b13a2f17
* Replace pcollections with ClassValue/ConcurrentHashMap-based caches * Do not store weak references, instead cache strong references and count on ClassValue to unload the corresponding classloader if necessary * ConcurrentHashMap does not rely on WeakReference as it's only selected on Android where classloader leaks don't exist * Update reflect/scripting JDK requirement to Java 8 in order to proceed #KT-53454 #KT-50705 Merge-request: KT-MR-6788 Merged-by: Vsevolod Tolstopyatov <qwwdfsad@gmail.com>
253 lines
8.0 KiB
Kotlin
253 lines
8.0 KiB
Kotlin
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
|
import com.github.jengelman.gradle.plugins.shadow.transformers.CacheableTransformer
|
|
import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer
|
|
import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext
|
|
import kotlinx.metadata.jvm.KmModuleVisitor
|
|
import kotlinx.metadata.jvm.KotlinModuleMetadata
|
|
import org.gradle.kotlin.dsl.support.serviceOf
|
|
import shadow.org.apache.tools.zip.ZipEntry
|
|
import shadow.org.apache.tools.zip.ZipOutputStream
|
|
|
|
description = "Kotlin Full Reflection Library"
|
|
|
|
buildscript {
|
|
dependencies {
|
|
classpath("org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0")
|
|
}
|
|
}
|
|
|
|
plugins {
|
|
`java-library`
|
|
}
|
|
|
|
configureJavaOnlyToolchain(JdkMajorVersion.JDK_1_8)
|
|
|
|
publish()
|
|
|
|
val core = "$rootDir/core"
|
|
val relocatedCoreSrc = "$buildDir/core-relocated"
|
|
|
|
val proguardDeps by configurations.creating
|
|
val proguardAdditionalInJars by configurations.creating
|
|
|
|
val embedded by configurations
|
|
embedded.isTransitive = false
|
|
|
|
configurations.getByName("compileOnly").extendsFrom(embedded)
|
|
|
|
dependencies {
|
|
api(kotlinStdlib())
|
|
|
|
proguardDeps(kotlinStdlib())
|
|
proguardAdditionalInJars(project(":kotlin-annotations-jvm"))
|
|
|
|
embedded(project(":kotlin-reflect-api"))
|
|
embedded(project(":core:metadata"))
|
|
embedded(project(":core:metadata.jvm"))
|
|
embedded(project(":core:compiler.common"))
|
|
embedded(project(":core:compiler.common.jvm"))
|
|
embedded(project(":core:deserialization.common"))
|
|
embedded(project(":core:deserialization.common.jvm"))
|
|
embedded(project(":core:descriptors"))
|
|
embedded(project(":core:descriptors.jvm"))
|
|
embedded(project(":core:deserialization"))
|
|
embedded(project(":core:descriptors.runtime"))
|
|
embedded(project(":core:util.runtime"))
|
|
embedded("javax.inject:javax.inject:1")
|
|
embedded(protobufLite())
|
|
|
|
compileOnly("org.jetbrains:annotations:13.0")
|
|
}
|
|
|
|
@CacheableTransformer
|
|
class KotlinModuleShadowTransformer(private val logger: Logger) : Transformer {
|
|
@Suppress("ArrayInDataClass")
|
|
private data class Entry(val path: String, val bytes: ByteArray)
|
|
private val data = mutableListOf<Entry>()
|
|
|
|
override fun getName() = "KotlinModuleShadowTransformer"
|
|
|
|
override fun canTransformResource(element: FileTreeElement): Boolean =
|
|
element.path.substringAfterLast(".") == KOTLIN_MODULE
|
|
|
|
override fun transform(context: TransformerContext) {
|
|
fun relocate(content: String): String =
|
|
context.relocators.fold(content) { acc, relocator -> relocator.applyToSourceContent(acc) }
|
|
|
|
val metadata = KotlinModuleMetadata.read(context.`is`.readBytes())
|
|
?: error("Not a .kotlin_module file: ${context.path}")
|
|
val writer = KotlinModuleMetadata.Writer()
|
|
logger.info("Transforming ${context.path}")
|
|
metadata.accept(object : KmModuleVisitor(writer) {
|
|
override fun visitPackageParts(fqName: String, fileFacades: List<String>, multiFileClassParts: Map<String, String>) {
|
|
assert(multiFileClassParts.isEmpty()) { multiFileClassParts } // There are no multi-file class parts in core
|
|
super.visitPackageParts(relocate(fqName), fileFacades.map(::relocate), multiFileClassParts)
|
|
}
|
|
})
|
|
data += Entry(context.path, writer.write().bytes)
|
|
}
|
|
|
|
override fun hasTransformedResource(): Boolean =
|
|
data.isNotEmpty()
|
|
|
|
override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) {
|
|
for ((path, bytes) in data) {
|
|
os.putNextEntry(ZipEntry(path))
|
|
os.write(bytes)
|
|
}
|
|
data.clear()
|
|
}
|
|
|
|
companion object {
|
|
const val KOTLIN_MODULE = "kotlin_module"
|
|
}
|
|
}
|
|
|
|
val reflectShadowJar by task<ShadowJar> {
|
|
archiveClassifier.set("shadow")
|
|
configurations = listOf(embedded)
|
|
|
|
exclude("**/*.proto")
|
|
exclude("org/jetbrains/annotations/Nls*.class")
|
|
|
|
if (kotlinBuildProperties.relocation) {
|
|
mergeServiceFiles()
|
|
transform(KotlinModuleShadowTransformer(logger))
|
|
relocate("org.jetbrains.kotlin", "kotlin.reflect.jvm.internal.impl")
|
|
relocate("javax.inject", "kotlin.reflect.jvm.internal.impl.javax.inject")
|
|
}
|
|
}
|
|
|
|
val stripMetadata by tasks.registering {
|
|
dependsOn(reflectShadowJar)
|
|
val inputJar = provider { reflectShadowJar.get().outputs.files.singleFile }
|
|
val outputJar = fileFrom(base.libsDirectory.asFile.get(), "${base.archivesName.get()}-$version-stripped.jar")
|
|
|
|
inputs.file(inputJar).withNormalizer(ClasspathNormalizer::class.java)
|
|
|
|
outputs.file(outputJar)
|
|
outputs.cacheIf { true }
|
|
|
|
doLast {
|
|
stripMetadata(
|
|
logger = logger,
|
|
classNamePattern = "kotlin/reflect/jvm/internal/impl/.*",
|
|
inFile = inputJar.get(),
|
|
outFile = outputJar,
|
|
preserveFileTimestamps = false
|
|
)
|
|
}
|
|
}
|
|
|
|
val proguard by task<CacheableProguardTask> {
|
|
dependsOn(stripMetadata)
|
|
|
|
injars(mapOf("filter" to "!META-INF/versions/**"), stripMetadata.get().outputs.files)
|
|
injars(mapOf("filter" to "!META-INF/**,!**/*.kotlin_builtins"), proguardAdditionalInJars)
|
|
outjars(fileFrom(base.libsDirectory.asFile.get(), "${base.archivesName.get()}-$version-proguard.jar"))
|
|
|
|
javaLauncher.set(project.getToolchainLauncherFor(chooseJdk18ForJpsBuild(JdkMajorVersion.JDK_1_8)))
|
|
libraryjars(mapOf("filter" to "!META-INF/versions/**"), proguardDeps)
|
|
libraryjars(
|
|
project.files(
|
|
javaLauncher.map {
|
|
firstFromJavaHomeThatExists(
|
|
"jre/lib/rt.jar",
|
|
"../Classes/classes.jar",
|
|
jdkHome = it.metadata.installationPath.asFile
|
|
)
|
|
}
|
|
)
|
|
)
|
|
|
|
configuration("$core/reflection.jvm/reflection.pro")
|
|
}
|
|
|
|
val relocateCoreSources by task<Copy> {
|
|
val relocatedCoreSrc = relocatedCoreSrc
|
|
val fs = serviceOf<FileSystemOperations>()
|
|
doFirst {
|
|
fs.delete {
|
|
delete(relocatedCoreSrc)
|
|
}
|
|
}
|
|
|
|
from("$core/descriptors/src")
|
|
from("$core/descriptors.common/src")
|
|
from("$core/descriptors.jvm/src")
|
|
from("$core/descriptors.runtime/src")
|
|
from("$core/deserialization/src")
|
|
from("$core/deserialization/deserialization.common/src")
|
|
from("$core/util.runtime/src")
|
|
|
|
exclude("META-INF/services/**")
|
|
|
|
into(relocatedCoreSrc)
|
|
includeEmptyDirs = false
|
|
|
|
eachFile {
|
|
path = path.replace("org/jetbrains/kotlin", "kotlin/reflect/jvm/internal/impl")
|
|
}
|
|
|
|
filter { line ->
|
|
line.replace("org.jetbrains.kotlin", "kotlin.reflect.jvm.internal.impl")
|
|
}
|
|
filter(org.apache.tools.ant.filters.FixCrLfFilter::class, "eol" to org.apache.tools.ant.filters.FixCrLfFilter.CrLf.newInstance("lf"))
|
|
|
|
outputs.cacheIf { true }
|
|
}
|
|
|
|
noDefaultJar()
|
|
|
|
java {
|
|
withSourcesJar()
|
|
}
|
|
|
|
configurePublishedComponent {
|
|
addVariantsFromConfiguration(configurations[JavaPlugin.SOURCES_ELEMENTS_CONFIGURATION_NAME]) { }
|
|
}
|
|
|
|
val sourcesJar = tasks.named<Jar>("sourcesJar") {
|
|
archiveClassifier.set("sources")
|
|
|
|
dependsOn(relocateCoreSources)
|
|
from(relocatedCoreSrc)
|
|
from("$core/reflection.jvm/src")
|
|
}
|
|
|
|
addArtifact("archives", sourcesJar)
|
|
addArtifact("sources", sourcesJar)
|
|
|
|
val intermediate = when {
|
|
kotlinBuildProperties.proguard -> proguard
|
|
kotlinBuildProperties.relocation -> stripMetadata
|
|
else -> reflectShadowJar
|
|
}
|
|
|
|
val result by task<Jar> {
|
|
dependsOn(intermediate)
|
|
from {
|
|
zipTree(intermediate.get().singleOutputFile())
|
|
}
|
|
from(zipTree(provider { reflectShadowJar.get().archiveFile.get().asFile })) {
|
|
include("META-INF/versions/**")
|
|
}
|
|
callGroovy("manifestAttributes", manifest, project, "Main", true)
|
|
}
|
|
|
|
javadocJar()
|
|
|
|
dexMethodCount {
|
|
dependsOn(result)
|
|
jarFile = result.get().outputs.files.single()
|
|
ownPackages.set(listOf("kotlin.reflect"))
|
|
}
|
|
|
|
artifacts {
|
|
listOf("archives", "runtimeElements").forEach { configurationName ->
|
|
add(configurationName, provider { result.get().outputs.files.singleFile }) {
|
|
builtBy(result)
|
|
}
|
|
}
|
|
}
|