All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmRun.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-Beta1
Show newest version
package org.jetbrains.kotlin.gradle.targets.jvm.tasks

import org.gradle.api.file.FileCollection
import org.gradle.api.plugins.JavaPluginExtension
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.gradle.jvm.toolchain.JavaToolchainService
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.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.getByType
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
 * `.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

    /**
     * ## 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.logger.warn("w: Target '$targetName': Unable to create run task '$taskName' as there is already such a task registered")
        return null
    }

    return registerKotlinJvmRun(taskName, mainCompilation)
}

private fun KotlinJvmTarget.registerKotlinJvmRun(taskName: String, compilation: KotlinJvmCompilation): KotlinJvmRunDslImpl {
    val mainClass = project.objects.property()
    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  Provider.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 '.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()
        )

        project.extensions.findByType(JavaToolchainService::class.java)?.let { toolchainService ->
            val toolchain = project.extensions.getByType(JavaPluginExtension::class.java).toolchain
            task.javaLauncher.convention(toolchainService.launcherFor(toolchain))
        }
    }

    @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,
    override val mainClass: Property,
) : 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)
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy