[Gradle] Implement KotlinJvmTarget.mainRun (KotlinJvmRun)
This task will also automatically support the use case of a 'carrier' task for the IDE. The IDE can use this task to execute generic main methods, providing a -P<taskName>.mainClass property ^KT-58661 Verification Pending
This commit is contained in:
committed by
Space Team
parent
432c781ff7
commit
e0389a0a87
+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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.mpp
|
||||||
|
|
||||||
|
import org.gradle.util.GradleVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.testbase.*
|
||||||
|
import kotlin.io.path.appendText
|
||||||
|
|
||||||
|
@MppGradlePluginTests
|
||||||
|
class MppJvmRunIT : KGPBaseTest() {
|
||||||
|
|
||||||
|
@GradleTest
|
||||||
|
fun `test jvmRun`(version: GradleVersion) {
|
||||||
|
project("mppRunJvm", version) {
|
||||||
|
build("jvmRun", "-PmainClass=JvmMainKt") {
|
||||||
|
assertOutputContains("Jvm: OK!")
|
||||||
|
assertOutputContains("Executed: JvmMain")
|
||||||
|
}
|
||||||
|
|
||||||
|
build("jvmRun", "-PmainClass=CommonMainKt") {
|
||||||
|
assertOutputContains("Jvm: OK!")
|
||||||
|
assertOutputContains("Executed: CommonMain")
|
||||||
|
}
|
||||||
|
|
||||||
|
// No mainClass provided!
|
||||||
|
buildAndFail("jvmRun")
|
||||||
|
|
||||||
|
/* Provided mainClass in buildscript */
|
||||||
|
projectPath.resolve("multiplatform").resolve("build.gradle.kts").appendText(
|
||||||
|
"""
|
||||||
|
kotlin {
|
||||||
|
jvm().mainRun {
|
||||||
|
mainClass.set("JvmMainKt")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
build("jvmRun") {
|
||||||
|
assertOutputContains("Jvm: OK!")
|
||||||
|
assertOutputContains("Executed: JvmMain")
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overwrite buildscript mainClass via property */
|
||||||
|
build("jvmRun", "-PmainClass=CommonMainKt") {
|
||||||
|
assertOutputContains("Jvm: OK!")
|
||||||
|
assertOutputContains("Executed: CommonMain")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GradleTestVersions(minVersion = TestVersions.Gradle.G_7_4)
|
||||||
|
@GradleTest
|
||||||
|
fun `test - jvmRun - works with Gradle configuration cache`(version: GradleVersion) {
|
||||||
|
project("mppRunJvm", version, buildOptions = defaultBuildOptions.copy(configurationCache = true)) {
|
||||||
|
build("jvmRun", "-DmainClass=JvmMainKt") {
|
||||||
|
assertOutputContains("Jvm: OK!")
|
||||||
|
assertOutputContains("Executed: JvmMain")
|
||||||
|
assertConfigurationCacheStored()
|
||||||
|
}
|
||||||
|
|
||||||
|
build("jvmRun", "-DmainClass=CommonMainKt") {
|
||||||
|
assertOutputContains("Jvm: OK!")
|
||||||
|
assertOutputContains("Executed: CommonMain")
|
||||||
|
assertConfigurationCacheReused()
|
||||||
|
}
|
||||||
|
|
||||||
|
build("jvmRun", "-DmainClass=JvmMainKt") {
|
||||||
|
assertOutputContains("Jvm: OK!")
|
||||||
|
assertOutputContains("Executed: JvmMain")
|
||||||
|
assertConfigurationCacheReused()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
object Jvm {
|
||||||
|
operator fun invoke() = runBlocking {
|
||||||
|
withContext(Dispatchers.Default) {
|
||||||
|
println("Jvm: OK!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform")
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
jvm()
|
||||||
|
sourceSets.getByName("jvmMain").dependencies {
|
||||||
|
implementation(project(":jvm"))
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
fun main() {
|
||||||
|
Jvm.invoke()
|
||||||
|
println("Executed: CommonMain")
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
fun main() {
|
||||||
|
Jvm.invoke()
|
||||||
|
println("Executed: JvmMain")
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
dependencyResolutionManagement {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
include(":multiplatform")
|
||||||
|
include(":jvm")
|
||||||
+8
@@ -178,4 +178,12 @@ object KotlinToolingDiagnostics {
|
|||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object KotlinJvmMainRunTaskConflict : ToolingDiagnosticFactory(WARNING) {
|
||||||
|
operator fun invoke(targetName: String, taskName: String) = build(
|
||||||
|
"""
|
||||||
|
Target '$targetName': Unable to create run task '$taskName' as there is already such a task registered
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-2
@@ -6,10 +6,13 @@
|
|||||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.jetbrains.kotlin.gradle.plugin.*
|
import org.jetbrains.kotlin.gradle.plugin.AbstractKotlinTargetConfigurator
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset
|
||||||
|
|
||||||
abstract class KotlinOnlyTargetPreset<R : KotlinOnlyTarget<T>, T : KotlinCompilation<*>>(
|
abstract class KotlinOnlyTargetPreset<R : KotlinOnlyTarget<T>, T : KotlinCompilation<*>>(
|
||||||
protected val project: Project
|
protected val project: Project,
|
||||||
) : KotlinTargetPreset<R> {
|
) : KotlinTargetPreset<R> {
|
||||||
|
|
||||||
protected abstract fun createKotlinTargetConfigurator(): AbstractKotlinTargetConfigurator<R>
|
protected abstract fun createKotlinTargetConfigurator(): AbstractKotlinTargetConfigurator<R>
|
||||||
|
|||||||
+53
-3
@@ -18,6 +18,7 @@ import org.gradle.api.tasks.testing.Test
|
|||||||
import org.gradle.jvm.tasks.Jar
|
import org.gradle.jvm.tasks.Jar
|
||||||
import org.gradle.language.jvm.tasks.ProcessResources
|
import org.gradle.language.jvm.tasks.ProcessResources
|
||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
|
||||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||||
import org.jetbrains.kotlin.gradle.plugin.*
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.JavaSourceSetsAccessor
|
import org.jetbrains.kotlin.gradle.plugin.internal.JavaSourceSetsAccessor
|
||||||
@@ -25,20 +26,69 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmCompilation
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.internal
|
import org.jetbrains.kotlin.gradle.plugin.mpp.internal
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.copyAttributes
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.copyAttributes
|
||||||
|
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.tasks.withType
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.Future
|
||||||
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.future
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||||
import java.util.concurrent.Callable
|
import java.util.concurrent.Callable
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.reflect.full.functions
|
import kotlin.reflect.full.functions
|
||||||
|
|
||||||
abstract class KotlinJvmTarget @Inject constructor(
|
abstract class KotlinJvmTarget @Inject constructor(
|
||||||
project: Project
|
project: Project,
|
||||||
) : KotlinOnlyTarget<KotlinJvmCompilation>(project, KotlinPlatformType.jvm),
|
) : KotlinOnlyTarget<KotlinJvmCompilation>(project, KotlinPlatformType.jvm),
|
||||||
KotlinTargetWithTests<JvmClasspathTestRunSource, KotlinJvmTestRun> {
|
KotlinTargetWithTests<JvmClasspathTestRunSource, KotlinJvmTestRun> {
|
||||||
|
|
||||||
override lateinit var testRuns: NamedDomainObjectContainer<KotlinJvmTestRun>
|
override lateinit var testRuns: NamedDomainObjectContainer<KotlinJvmTestRun>
|
||||||
|
|
||||||
|
internal val mainRun: Future<KotlinJvmRunDslImpl?> = project.future { registerMainRunTask() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ### ⚠️ KotlinJvmTarget 'mainRun' is experimental
|
||||||
|
* The [KotlinJvmTarget], by default, creates a 'run' task called {targetName}Run, which will allows simple
|
||||||
|
* execution of the targets 'main' code.
|
||||||
|
*
|
||||||
|
* e.g.
|
||||||
|
* ```kotlin
|
||||||
|
* // build.gradle.kts
|
||||||
|
* kotlin {
|
||||||
|
* jvm().mainRun {
|
||||||
|
* mainClass.set("FooKt")
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // src/jvmMain/Foo
|
||||||
|
* fun main() {
|
||||||
|
* println("Hello from foo")
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* will be executable using
|
||||||
|
* ```text
|
||||||
|
* ./gradlew jvmRun
|
||||||
|
* > "Hello from foo"
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ### Running a different 'mainClass' from CLI:
|
||||||
|
* The execution of the main code allows providing a different 'mainClass' via CLI. *
|
||||||
|
* It accepts System Properties and Gradle Properties. However, when Gradle Configuration Cache is used,
|
||||||
|
* System Properties are the preferred way.
|
||||||
|
*
|
||||||
|
* ```text
|
||||||
|
* ./gradlew jvmRun -DmainClass="BarKt"
|
||||||
|
* ^
|
||||||
|
* Will execute the 'src/jvmMain/kotlin/Bar' main method.
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
@ExperimentalKotlinGradlePluginApi
|
||||||
|
fun mainRun(configure: KotlinJvmRunDsl.() -> Unit) = project.launch {
|
||||||
|
mainRun.await()?.configure()
|
||||||
|
}
|
||||||
|
|
||||||
var withJavaEnabled = false
|
var withJavaEnabled = false
|
||||||
private set
|
private set
|
||||||
|
|
||||||
@@ -106,7 +156,7 @@ abstract class KotlinJvmTarget @Inject constructor(
|
|||||||
|
|
||||||
private fun setupJavaSourceSetSourcesAndResources(
|
private fun setupJavaSourceSetSourcesAndResources(
|
||||||
javaSourceSet: SourceSet,
|
javaSourceSet: SourceSet,
|
||||||
compilation: KotlinJvmCompilation
|
compilation: KotlinJvmCompilation,
|
||||||
) {
|
) {
|
||||||
javaSourceSet.java.setSrcDirs(listOf("src/${compilation.defaultSourceSet.name}/java"))
|
javaSourceSet.java.setSrcDirs(listOf("src/${compilation.defaultSourceSet.name}/java"))
|
||||||
compilation.defaultSourceSet.kotlin.srcDirs(javaSourceSet.java.sourceDirectories)
|
compilation.defaultSourceSet.kotlin.srcDirs(javaSourceSet.java.sourceDirectories)
|
||||||
@@ -153,7 +203,7 @@ abstract class KotlinJvmTarget @Inject constructor(
|
|||||||
|
|
||||||
private fun setupDependenciesCrossInclusionForJava(
|
private fun setupDependenciesCrossInclusionForJava(
|
||||||
compilation: KotlinJvmCompilation,
|
compilation: KotlinJvmCompilation,
|
||||||
javaSourceSet: SourceSet
|
javaSourceSet: SourceSet,
|
||||||
) {
|
) {
|
||||||
// Make sure Kotlin compilation dependencies appear in the Java source set classpaths:
|
// Make sure Kotlin compilation dependencies appear in the Java source set classpaths:
|
||||||
|
|
||||||
|
|||||||
+162
@@ -0,0 +1,162 @@
|
|||||||
|
package org.jetbrains.kotlin.gradle.targets.jvm.tasks
|
||||||
|
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.tasks.JavaExec
|
||||||
|
import org.gradle.api.tasks.TaskProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
|
||||||
|
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.await
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.KotlinJvmMainRunTaskConflict
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnostic
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.internal.configurationTimePropertiesAccessor
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.internal.usedAtConfigurationTime
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.internal
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.property
|
||||||
|
import org.jetbrains.kotlin.tooling.core.UnsafeApi
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run task for executing Kotlin/Jvm code.
|
||||||
|
* Shall be configured using the [KotlinJvmRunDsl]
|
||||||
|
*
|
||||||
|
* ### IDE carrier task:
|
||||||
|
* This task can act as 'carrier' task for IDE run gutters:
|
||||||
|
* It accepts configurable 'mainClass' when a Gradle property is provided as
|
||||||
|
* `<taskName>.mainClass=...`
|
||||||
|
*
|
||||||
|
* e.g.
|
||||||
|
* ```
|
||||||
|
* ./gradlew runJvm // <- executes the mainClass that is configured by default by the user
|
||||||
|
* ./gradlew runJvm -PrunJvm.mainClass="FooKt" // <- executes FooKt.main
|
||||||
|
* ./gradlew runJvm -PmainClass="FooKt" // <- excutes FooKt.main
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
@InternalKotlinGradlePluginApi
|
||||||
|
open class KotlinJvmRun : JavaExec()
|
||||||
|
|
||||||
|
@ExperimentalKotlinGradlePluginApi
|
||||||
|
interface KotlinJvmRunDsl {
|
||||||
|
/**
|
||||||
|
* ## See [JavaExec.mainClass]
|
||||||
|
*/
|
||||||
|
val mainClass: Property<String>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## See [JavaExec.args]
|
||||||
|
*/
|
||||||
|
fun args(vararg args: Any)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## See [JavaExec.args]
|
||||||
|
*/
|
||||||
|
fun args(args: Iterable<*>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## See [JavaExec.setArgs]
|
||||||
|
*/
|
||||||
|
fun setArgs(args: Iterable<*>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## See [JavaExec.classpath]
|
||||||
|
*/
|
||||||
|
fun classpath(vararg paths: Any)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## See [JavaExec.setClasspath]
|
||||||
|
*/
|
||||||
|
fun setClasspath(classpath: FileCollection)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the runtime classpath of the given [compilation] to this run task
|
||||||
|
*/
|
||||||
|
fun classpath(compilation: KotlinCompilation<*>)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal suspend fun KotlinJvmTarget.registerMainRunTask(): KotlinJvmRunDslImpl? {
|
||||||
|
/* Await all inputs from user */
|
||||||
|
KotlinPluginLifecycle.Stage.FinaliseDsl.await()
|
||||||
|
val mainCompilation = compilations.findByName("main") ?: return null
|
||||||
|
val taskName = lowerCamelCaseName(targetName, "run")
|
||||||
|
|
||||||
|
if (taskName in project.tasks.names) {
|
||||||
|
/* Proper warning tbd */
|
||||||
|
project.reportDiagnostic(KotlinJvmMainRunTaskConflict(targetName = name, taskName = taskName))
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return registerKotlinJvmRun(taskName, mainCompilation)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KotlinJvmTarget.registerKotlinJvmRun(taskName: String, compilation: KotlinJvmCompilation): KotlinJvmRunDslImpl {
|
||||||
|
val mainClass = project.objects.property<String>()
|
||||||
|
val taskProvider = project.tasks.register(taskName, KotlinJvmRun::class.java)
|
||||||
|
|
||||||
|
/* Convenience helper for telling older Gradle versions, that this provider is used at configuration time */
|
||||||
|
val configurationTimePropertiesAccessor = project.configurationTimePropertiesAccessor
|
||||||
|
fun <T> Provider<T>.usedAtConfigurationTime() = usedAtConfigurationTime(configurationTimePropertiesAccessor)
|
||||||
|
|
||||||
|
taskProvider.configure { task ->
|
||||||
|
task.group = "run"
|
||||||
|
task.description = "Jvm Run task for target '${compilation.target.name}' and compilation '${compilation.name}'. " +
|
||||||
|
"This task can act as carrier for the IDE to execute jvm based code"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See [KotlinJvmRun]: This task will respect the '<taskName>.mainClass' property over
|
||||||
|
* the DSL configuration
|
||||||
|
*/
|
||||||
|
task.mainClass.value(
|
||||||
|
project.providers.gradleProperty("$taskName.mainClass").usedAtConfigurationTime()
|
||||||
|
.orElse(project.providers.gradleProperty("mainClass").usedAtConfigurationTime())
|
||||||
|
.orElse(project.providers.systemProperty("$taskName.mainClass").usedAtConfigurationTime())
|
||||||
|
.orElse(project.providers.systemProperty("mainClass").usedAtConfigurationTime())
|
||||||
|
.orElse(mainClass).usedAtConfigurationTime()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(UnsafeApi::class)
|
||||||
|
return KotlinJvmRunDslImpl(taskProvider, mainClass)
|
||||||
|
.also { dsl -> dsl.classpath(compilation) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use [registerKotlinJvmRun] to create an instance
|
||||||
|
*/
|
||||||
|
internal class KotlinJvmRunDslImpl @UnsafeApi constructor(
|
||||||
|
val task: TaskProvider<KotlinJvmRun>,
|
||||||
|
override val mainClass: Property<String>,
|
||||||
|
) : KotlinJvmRunDsl {
|
||||||
|
|
||||||
|
override fun args(vararg args: Any) {
|
||||||
|
task.configure { it.args(*args) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun args(args: Iterable<*>) {
|
||||||
|
task.configure { it.args(args) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setArgs(args: Iterable<*>) {
|
||||||
|
task.configure { it.setArgs(args) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun classpath(vararg paths: Any) {
|
||||||
|
task.configure { it.classpath(*paths) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setClasspath(classpath: FileCollection) {
|
||||||
|
task.configure { it.setClasspath(classpath) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun classpath(compilation: KotlinCompilation<*>) {
|
||||||
|
task.configure {
|
||||||
|
it.classpath(compilation.output.allOutputs)
|
||||||
|
it.classpath(compilation.internal.configurations.runtimeDependencyConfiguration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+165
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* 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.unitTests
|
||||||
|
|
||||||
|
import org.gradle.api.tasks.JavaExec
|
||||||
|
import org.jetbrains.kotlin.gradle.dependencyResolutionTests.mavenCentralCacheRedirector
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.configurationResult
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.launch
|
||||||
|
import org.jetbrains.kotlin.gradle.util.*
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
class KotlinJvmRunTest {
|
||||||
|
@Test
|
||||||
|
fun `test - simple jvm target`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||||
|
val kotlin = project.multiplatformExtension
|
||||||
|
assertNotNull(kotlin.jvm())
|
||||||
|
project.configurationResult.await()
|
||||||
|
|
||||||
|
val task = project.tasks.findByName("jvmRun") ?: fail("Missing 'jvmRun' run task")
|
||||||
|
if (task !is JavaExec) fail("Expected $task to implement '${JavaExec::class}'")
|
||||||
|
assertNoDiagnostics()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test - mainClass - set via DSL`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||||
|
val kotlin = project.multiplatformExtension
|
||||||
|
val mainRun = assertNotNull(kotlin.jvm().mainRun.await())
|
||||||
|
val mainRunTask = mainRun.task.get()
|
||||||
|
|
||||||
|
assertNull(
|
||||||
|
mainRunTask.mainClass.orNull,
|
||||||
|
"Expected mainClass to be null: No mainClass set via DSL or property"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Set mainClass via DSL
|
||||||
|
mainRun.mainClass.set("Foo")
|
||||||
|
assertEquals("Foo", mainRunTask.mainClass.orNull)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test - args`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||||
|
val kotlin = project.multiplatformExtension
|
||||||
|
val task = assertNotNull(kotlin.jvm().mainRun.await()).task.get()
|
||||||
|
|
||||||
|
/* Set properties using 'args()' */
|
||||||
|
kotlin.jvm().mainRun {
|
||||||
|
args("first", "second")
|
||||||
|
args(listOf("third", "fourth"))
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
assertEquals(listOf("first", "second", "third", "fourth"), task.args)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Set property using .setArgs */
|
||||||
|
kotlin.jvm().mainRun {
|
||||||
|
setArgs(listOf("1", "2"))
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
assertEquals(listOf("1", "2"), task.args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test - classpath - contains main compilation output by default`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||||
|
repositories.mavenLocal()
|
||||||
|
repositories.mavenCentralCacheRedirector()
|
||||||
|
|
||||||
|
val kotlin = project.multiplatformExtension
|
||||||
|
val mainRunTask = assertNotNull(kotlin.jvm().mainRun.await()).task.get()
|
||||||
|
val mainCompilation = kotlin.jvm().compilations.main
|
||||||
|
|
||||||
|
configurationResult.await()
|
||||||
|
|
||||||
|
mainCompilation.output.allOutputs.files.ifEmpty { fail("Expected some file in 'allOutputs'") }
|
||||||
|
if (!mainRunTask.classpath.files.containsAll(mainCompilation.output.allOutputs.files)) {
|
||||||
|
fail("Missing output from main compilation in '$mainRunTask'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test - classpath - contains main compilation runtime dependencies`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||||
|
repositories.mavenLocal()
|
||||||
|
repositories.mavenCentralCacheRedirector()
|
||||||
|
|
||||||
|
val kotlin = project.multiplatformExtension
|
||||||
|
|
||||||
|
kotlin.jvm().compilations.main.defaultSourceSet.dependencies {
|
||||||
|
implementation(project.files("implementation.jar"))
|
||||||
|
compileOnly(project.files("compileOnly.jar"))
|
||||||
|
runtimeOnly(project.files("runtimeOnly.jar"))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
configurationResult.await()
|
||||||
|
val mainRunTask = assertNotNull(kotlin.jvm().mainRun.await()?.task?.get())
|
||||||
|
|
||||||
|
if (project.file("implementation.jar") !in mainRunTask.classpath) {
|
||||||
|
fail("Missing file from 'implementation' scope")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (project.file("runtimeOnly.jar") !in mainRunTask.classpath) {
|
||||||
|
fail("Missing file from 'runtimeOnly' scope")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (project.file("compileOnly.jar") in mainRunTask.classpath) {
|
||||||
|
fail("Unexpected file from 'compileOnly' scope")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test - classpath - add file`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||||
|
repositories.mavenLocal()
|
||||||
|
repositories.mavenCentralCacheRedirector()
|
||||||
|
val kotlin = project.multiplatformExtension
|
||||||
|
kotlin.jvm().mainRun { classpath(file("custom.jar")) }
|
||||||
|
|
||||||
|
configurationResult.await()
|
||||||
|
|
||||||
|
val task = assertNotNull(kotlin.jvm().mainRun.await()).task.get()
|
||||||
|
if (file("custom.jar") !in task.classpath.files) {
|
||||||
|
fail("Missing custom.jar in classpath")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.classpath.files.size <= 1) {
|
||||||
|
fail("Expected more files in classpath than just custom.jar")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test - setClasspath`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||||
|
repositories.mavenLocal()
|
||||||
|
repositories.mavenCentralCacheRedirector()
|
||||||
|
val kotlin = project.multiplatformExtension
|
||||||
|
kotlin.jvm().mainRun {
|
||||||
|
setClasspath(project.files("a.jar", "b.jar"))
|
||||||
|
}
|
||||||
|
|
||||||
|
project.configurationResult.await()
|
||||||
|
assertEquals(
|
||||||
|
project.files("a.jar", "b.jar").files,
|
||||||
|
kotlin.jvm().mainRun.await()?.task?.get()?.classpath?.files
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test - jvmRun task is already registered`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||||
|
val kotlin = multiplatformExtension
|
||||||
|
kotlin.jvm()
|
||||||
|
tasks.register("jvmRun")
|
||||||
|
configurationResult.await()
|
||||||
|
checkDiagnostics("jvmRunTask-conflict")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
[KotlinJvmMainRunTaskConflict | WARNING] Target 'jvm': Unable to create run task 'jvmRun' as there is already such a task registered
|
||||||
Reference in New Issue
Block a user