[Gradle] jvm().withJava(): Fix Zombie compilation instance returned from create()
^KT-60462 Verification Pending
This commit is contained in:
committed by
Space Team
parent
0945968751
commit
0feecebc07
+1
-1
@@ -286,4 +286,4 @@ internal abstract class AbstractKotlinPlugin(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -15,7 +15,6 @@ import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.api.tasks.bundling.Jar
|
||||
import org.jetbrains.kotlin.gradle.plugin.internal.JavaSourceSetsAccessor
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaCompilation
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||
@@ -41,7 +40,7 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
|
||||
protected val javaSourceSet: SourceSet?
|
||||
get() = when (val compilation = compilationInfo.safeAs<KotlinCompilationInfo.TCS>()?.origin) {
|
||||
is KotlinWithJavaCompilation<*, *> -> compilation.javaSourceSet
|
||||
is KotlinJvmCompilation -> compilation.javaSourceSet.getOrNull()
|
||||
is KotlinJvmCompilation -> compilation.javaSourceSet
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
||||
+8
-9
@@ -19,9 +19,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationI
|
||||
import org.jetbrains.kotlin.gradle.plugin.variantImplementationFactory
|
||||
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
|
||||
import org.jetbrains.kotlin.gradle.utils.LenientFuture
|
||||
import org.jetbrains.kotlin.gradle.utils.future
|
||||
import org.jetbrains.kotlin.gradle.utils.lenient
|
||||
import javax.inject.Inject
|
||||
|
||||
open class KotlinJvmCompilation @Inject internal constructor(
|
||||
@@ -67,17 +64,19 @@ open class KotlinJvmCompilation @Inject internal constructor(
|
||||
* will be enabled after call to this method.
|
||||
*/
|
||||
internal val compileJavaTaskProviderSafe: Provider<JavaCompile> = target.project.providers
|
||||
.provider { javaSourceSet.getOrNull() }
|
||||
.provider { javaSourceSet }
|
||||
.flatMap { javaSourceSet ->
|
||||
@Suppress("RedundantRequireNotNullCall") // IDE and CLI disagree here
|
||||
checkNotNull(javaSourceSet)
|
||||
project.tasks.named(javaSourceSet.compileJavaTaskName, JavaCompile::class.java)
|
||||
}
|
||||
|
||||
internal val javaSourceSet: LenientFuture<SourceSet> = target.project.future {
|
||||
target.withJavaEnabledFuture.await()
|
||||
target.project.javaSourceSets.maybeCreate(compilationName)
|
||||
}.lenient
|
||||
internal val javaSourceSet
|
||||
get() = if (target.withJavaEnabled) maybeCreateJavaSourceSet() else null
|
||||
|
||||
internal fun maybeCreateJavaSourceSet(): SourceSet {
|
||||
check(target.withJavaEnabled)
|
||||
return target.project.javaSourceSets.maybeCreate(compilationName)
|
||||
}
|
||||
|
||||
override val processResourcesTaskName: String
|
||||
get() = compilation.processResourcesTaskName ?: error("Missing 'processResourcesTaskName'")
|
||||
|
||||
+1
-3
@@ -6,12 +6,10 @@
|
||||
@file:Suppress("PackageDirectoryMismatch") // Old package for compatibility
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinJvmCompilationAssociator
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.KotlinCompilationImplFactory
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.KotlinJvmCompilerOptionsFactory
|
||||
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
|
||||
import org.jetbrains.kotlin.gradle.utils.*
|
||||
|
||||
open class KotlinJvmCompilationFactory internal constructor(
|
||||
override val target: KotlinJvmTarget
|
||||
|
||||
+4
-10
@@ -34,9 +34,8 @@ import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmRunDsl
|
||||
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmRunDslImpl
|
||||
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.registerMainRunTask
|
||||
import org.jetbrains.kotlin.gradle.tasks.withType
|
||||
import org.jetbrains.kotlin.gradle.utils.*
|
||||
import org.jetbrains.kotlin.gradle.utils.CompletableFuture
|
||||
import org.jetbrains.kotlin.gradle.utils.Future
|
||||
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||
import org.jetbrains.kotlin.gradle.utils.findAppliedAndroidPluginIdOrNull
|
||||
import org.jetbrains.kotlin.gradle.utils.future
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
@@ -95,13 +94,6 @@ abstract class KotlinJvmTarget @Inject constructor(
|
||||
mainRun.await()?.configure()
|
||||
}
|
||||
|
||||
/**
|
||||
* Future that will complete once [withJava] is called and java support for this target
|
||||
* was established.
|
||||
*/
|
||||
internal val withJavaEnabledFuture: Future<Unit> get() = withJavaEnabledFutureImpl
|
||||
private val withJavaEnabledFutureImpl = CompletableFuture<Unit>()
|
||||
|
||||
var withJavaEnabled = false
|
||||
private set
|
||||
|
||||
@@ -184,7 +176,9 @@ abstract class KotlinJvmTarget @Inject constructor(
|
||||
disableJavaPluginTasks(javaSourceSets)
|
||||
}
|
||||
|
||||
withJavaEnabledFutureImpl.complete(Unit)
|
||||
compilations.all { compilation ->
|
||||
compilation.maybeCreateJavaSourceSet()
|
||||
}
|
||||
}
|
||||
|
||||
private fun disableJavaPluginTasks(javaSourceSet: SourceSetContainer) {
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
@file:Suppress("FunctionName")
|
||||
|
||||
package org.jetbrains.kotlin.gradle.regressionTests
|
||||
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmCompilation
|
||||
import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP
|
||||
import org.jetbrains.kotlin.gradle.util.runLifecycleAwareTest
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertNull
|
||||
import kotlin.test.assertSame
|
||||
|
||||
class KT60462WithJavaZombieCompilationTest {
|
||||
|
||||
/**
|
||||
* Regression was introduced by:
|
||||
*
|
||||
* ```
|
||||
* [Gradle] Ensure java source sets being created eagerly for 'withJava' Sebastian Sellmair* 07.07.23, 20:49
|
||||
* 817e3de8f546e34974b89fef0f4f93b425e7e607
|
||||
* ```
|
||||
*
|
||||
* The commit was ensuring that jvm compilations will create their associated java source sets
|
||||
* as eager as possible. The solution chosen in the commit was that already the construction of the compilation
|
||||
* will spawn a coroutine that waits for the `withJavaEnabled` callback to create the java source set.
|
||||
*
|
||||
* However, a buildscript like
|
||||
*
|
||||
* ```kotlin
|
||||
* kotlin {
|
||||
* jvm().withJava()
|
||||
* val customCompilation = jvm().compilations.create("custom")
|
||||
* // ^
|
||||
* // Zombie
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* would therefore try to create the java source set right in the constructor call of the 'custom' compilation.
|
||||
* This would have triggered a listener on `javaSourceSets.all {}` which would ensure that all
|
||||
* java source sets have a corresponding kotlin compilation created.
|
||||
*
|
||||
* Since the current stack is currently inside the constructor of the first compilation, the
|
||||
* used `compilations.maybeCreate` would trigger the creation of another custom compilation.
|
||||
*
|
||||
* The initial buildscript call creating the initial custom compilation will therefore return a Zombie instance
|
||||
* ```kotlin
|
||||
* kotlin {
|
||||
* val customCompilation = jvm().compilations.create("custom")
|
||||
* customCompilation != jvm().compilations.getByName("custom")
|
||||
* // ^ ^
|
||||
* // Zombie Real instance created by the javaSourceSets.all listener
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@Test
|
||||
fun `test - custom compilation`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||
multiplatformExtension.jvm().apply {
|
||||
withJava()
|
||||
|
||||
var instanceUsedForConfigureBlock: KotlinJvmCompilation? = null
|
||||
|
||||
val instanceReturnedFromCreate = compilations.create("custom") { instance ->
|
||||
assertNull(instanceUsedForConfigureBlock)
|
||||
instanceUsedForConfigureBlock = instance
|
||||
}
|
||||
|
||||
val instanceReturnedFromGet = compilations.getByName("custom")
|
||||
|
||||
assertSame(instanceReturnedFromCreate, instanceUsedForConfigureBlock)
|
||||
assertSame(instanceReturnedFromGet, instanceUsedForConfigureBlock)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user