Skip to content

Commit

Permalink
Kotlin version format fix in AGP
Browse files Browse the repository at this point in the history
  • Loading branch information
mvicsokolova authored and woainikk committed Jun 3, 2022
1 parent 7630ae6 commit 208754c
Showing 1 changed file with 70 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,25 @@ import org.jetbrains.kotlin.gradle.plugin.*
import java.io.*
import java.util.*
import java.util.concurrent.*
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool
import org.jetbrains.kotlin.gradle.targets.js.*
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
import org.jetbrains.kotlinx.atomicfu.gradle.*

private const val EXTENSION_NAME = "atomicfu"
private const val ORIGINAL_DIR_NAME = "originalClassesDir"
private const val COMPILE_ONLY_CONFIGURATION = "compileOnly"
private const val IMPLEMENTATION_CONFIGURATION = "implementation"
private const val TEST_IMPLEMENTATION_CONFIGURATION = "testImplementation"
private const val ENABLE_IR_TRANSFORMATION = "kotlinx.atomicfu.enableIrTransformation"

open class AtomicFUGradlePlugin : Plugin<Project> {
override fun apply(project: Project) = project.run {
val pluginVersion = rootProject.buildscript.configurations.findByName("classpath")
?.allDependencies?.find { it.name == "atomicfu-gradle-plugin" }?.version
extensions.add(EXTENSION_NAME, AtomicFUPluginExtension(pluginVersion))
if (rootProject.getBooleanProperty(ENABLE_IR_TRANSFORMATION) && isCompilerPluginAvailable()) {
plugins.apply(AtomicfuKotlinGradleSubplugin::class.java)
}
configureDependencies()
configureTasks()
}
Expand All @@ -50,6 +56,7 @@ private fun Project.configureDependencies() {
getAtomicfuDependencyNotation(Platform.JS, version)
)
dependencies.add(TEST_IMPLEMENTATION_CONFIGURATION, getAtomicfuDependencyNotation(Platform.JS, version))
addCompilerPluginDependency()
}
withPluginWhenEvaluatedDependencies("kotlin-multiplatform") { version ->
configureMultiplatformPluginDependencies(version)
Expand Down Expand Up @@ -79,6 +86,47 @@ private fun Project.configureTasks() {
}
}

private fun Project.isCompilerPluginAvailable(): Boolean {
// kotlinx-atomicfu compiler plugin is available for KGP >= 1.6.20
val kotlinVersion = getKotlinPluginVersion()
val (majorVersion, minorVersion) = kotlinVersion
.split('.')
.take(2)
.map { it.toInt() }
val patch = kotlinVersion.substringAfterLast('.').substringBefore('-').toInt()
return majorVersion == 1 && (minorVersion == 6 && patch >= 20 || minorVersion > 6)
}

private fun Project.getBooleanProperty(name: String) =
rootProject.findProperty(name)?.toString()?.toBooleanStrict() ?: false

private fun String.toBooleanStrict(): Boolean = when (this) {
"true" -> true
"false" -> false
else -> throw IllegalArgumentException("The string doesn't represent a boolean value: $this")
}

private fun Project.needsJsIrTransformation(target: KotlinTarget): Boolean =
config.transformJs && target.isJsIrTarget()

private fun KotlinTarget.isJsIrTarget() = (this is KotlinJsTarget && this.irTarget != null) || this is KotlinJsIrTarget

private fun Project.addCompilerPluginDependency() {
if (isCompilerPluginAvailable()) {
withKotlinTargets { target ->
if (needsJsIrTransformation(target)) {
target.compilations.forEach { kotlinCompilation ->
kotlinCompilation.dependencies {
// add atomicfu compiler plugin dependency
// to provide the `kotlinx-atomicfu-runtime` library used during compiler plugin transformation
compileOnly("org.jetbrains.kotlin:atomicfu:${getKotlinPluginVersion()}")
}
}
}
}
}
}

private enum class Platform(val suffix: String) {
JVM("-jvm"),
JS("-js"),
Expand Down Expand Up @@ -130,9 +178,9 @@ fun Project.withKotlinTargets(fn: (KotlinTarget) -> Unit) {
extensions.findByType(KotlinProjectExtension::class.java)?.let { kotlinExtension ->
val targetsExtension = (kotlinExtension as? ExtensionAware)?.extensions?.findByName("targets")
@Suppress("UNCHECKED_CAST")
val targets = targetsExtension as NamedDomainObjectContainer<KotlinTarget>
val targets = targetsExtension as? NamedDomainObjectContainer<KotlinTarget>
// find all compilations given sourceSet belongs to
targets.all { target -> fn(target) }
targets?.all { target -> fn(target) }
}
}

Expand Down Expand Up @@ -181,7 +229,10 @@ private fun Project.configureTransformationForTarget(target: KotlinTarget) {
)
}
KotlinPlatformType.js -> {
if (!config.transformJs) return@compilations // skip when transformation is turned off
// skip when js transformation is not needed or when IR is transformed
if (!config.transformJs || (needsJsIrTransformation(target))) {
return@compilations
}
project.createJsTransformTask(compilation).configureJsTask(
compilation.compileAllTaskName,
transformedClassesDir,
Expand All @@ -195,7 +246,7 @@ private fun Project.configureTransformationForTarget(target: KotlinTarget) {
classesDirs.setFrom(transformedClassesDir)
classesDirs.builtBy(transformTask)
(tasks.findByName(target.artifactsTaskName) as? Jar)?.apply {
setupJarManifest(multiRelease = config.variant.toVariant() == Variant.BOTH)
setupJarManifest(multiRelease = config.jvmVariant.toJvmVariant() == JvmVariant.BOTH)
}
// test should compile and run against original production binaries
if (compilationType == CompilationType.TEST) {
Expand All @@ -206,28 +257,15 @@ private fun Project.configureTransformationForTarget(target: KotlinTarget) {
Callable { originalDirsByCompilation[mainCompilation]!! }
)

// KGP >= 1.7.0 has breaking changes in task hierarchy:
// https://youtrack.jetbrains.com/issue/KT-32805#focus=Comments-27-5915479.0-0
val (majorVersion, minorVersion) = getKotlinPluginVersion()
.split('.')
.take(2)
.map { it.toInt() }
if (majorVersion == 1 && minorVersion < 7) {
(tasks.findByName(compilation.compileKotlinTaskName) as? AbstractCompile)?.classpath =
originalMainClassesDirs + compilation.compileDependencyFiles - mainCompilation.output.classesDirs
} else {
(tasks.findByName(compilation.compileKotlinTaskName) as? AbstractKotlinCompileTool<*>)
?.libraries
?.setFrom(
originalMainClassesDirs + compilation.compileDependencyFiles - mainCompilation.output.classesDirs
)
}
(tasks.findByName(compilation.compileKotlinTaskName) as? AbstractCompile)?.classpath =
originalMainClassesDirs + compilation.compileDependencyFiles - mainCompilation.output.classesDirs

(tasks.findByName("${target.name}${compilation.name.capitalize()}") as? Test)?.classpath =
originalMainClassesDirs + (compilation as KotlinCompilationToRunnableFiles).runtimeDependencyFiles - mainCompilation.output.classesDirs

val kotlinOptions = compilation.kotlinOptions
compilation.compileKotlinTask.doFirst {
compilation.kotlinOptions.addFriendPaths(originalMainClassesDirs)
kotlinOptions.addFriendPaths(originalMainClassesDirs)
}
}
}
Expand All @@ -246,7 +284,8 @@ fun Project.sourceSetsByCompilation(): Map<KotlinSourceSet, List<KotlinCompilati
}

fun Project.configureMultiplatformPluginDependencies(version: String) {
if (rootProject.findProperty("kotlin.mpp.enableGranularSourceSetsMetadata").toString().toBoolean()) {
if (rootProject.getBooleanProperty("kotlin.mpp.enableGranularSourceSetsMetadata")) {
addCompilerPluginDependency()
val mainConfigurationName = project.extensions.getByType(KotlinMultiplatformExtension::class.java).sourceSets
.getByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
.compileOnlyConfigurationName
Expand All @@ -270,6 +309,7 @@ fun Project.configureMultiplatformPluginDependencies(version: String) {
}
} else {
sourceSetsByCompilation().forEach { (sourceSet, compilations) ->
addCompilerPluginDependency()
val platformTypes = compilations.map { it.platformType }.toSet()
val compilationNames = compilations.map { it.compilationName }.toSet()
if (compilationNames.size != 1)
Expand All @@ -282,8 +322,7 @@ fun Project.configureMultiplatformPluginDependencies(version: String) {
KotlinPlatformType.common -> Platform.MULTIPLATFORM
KotlinPlatformType.jvm, KotlinPlatformType.androidJvm -> Platform.JVM
KotlinPlatformType.js -> Platform.JS
KotlinPlatformType.native -> Platform.NATIVE
else -> TODO()
KotlinPlatformType.native, KotlinPlatformType.wasm -> Platform.NATIVE
}
val configurationName = when {
// impl dependency for native (there is no transformation)
Expand Down Expand Up @@ -318,7 +357,7 @@ fun Project.configureJvmTransformation(
//now transformTask is responsible for compiling this source set into the classes directory
sourceSet.compiledBy(transformTask)
(tasks.findByName(sourceSet.jarTaskName) as? Jar)?.apply {
setupJarManifest(multiRelease = config.variant.toVariant() == Variant.BOTH)
setupJarManifest(multiRelease = config.jvmVariant.toJvmVariant() == JvmVariant.BOTH)
}
// test should compile and run against original production binaries
if (compilationType == CompilationType.TEST) {
Expand All @@ -344,7 +383,7 @@ fun Project.configureJvmTransformation(
}
}

fun String.toVariant(): Variant = enumValueOf(toUpperCase(Locale.US))
fun String.toJvmVariant(): JvmVariant = enumValueOf(toUpperCase(Locale.US))

fun Project.createJvmTransformTask(compilation: KotlinCompilation<*>): AtomicFUTransformTask =
tasks.create(
Expand Down Expand Up @@ -373,7 +412,7 @@ fun AtomicFUTransformTask.configureJvmTask(
classPath = classpath
inputFiles = originalClassesDir
outputDir = transformedClassesDir
variant = config.variant
jvmVariant = config.jvmVariant
verbose = config.verbose
}

Expand Down Expand Up @@ -405,7 +444,7 @@ class AtomicFUPluginExtension(pluginVersion: String?) {
var dependenciesVersion = pluginVersion
var transformJvm = true
var transformJs = true
var variant: String = "FU"
var jvmVariant: String = "FU"
var verbose: Boolean = false
}

Expand All @@ -423,7 +462,7 @@ open class AtomicFUTransformTask : ConventionTask() {
lateinit var classPath: FileCollection

@Input
var variant = "FU"
var jvmVariant = "FU"
@Input
var verbose = false

Expand All @@ -432,7 +471,7 @@ open class AtomicFUTransformTask : ConventionTask() {
val cp = classPath.files.map { it.absolutePath }
inputFiles.files.forEach { inputDir ->
AtomicFUTransformer(cp, inputDir, outputDir).let { t ->
t.variant = variant.toVariant()
t.jvmVariant = jvmVariant.toJvmVariant()
t.verbose = verbose
t.transform()
}
Expand Down

0 comments on commit 208754c

Please sign in to comment.