简体   繁体   中英

Why I cannot access project properties in "plugins" section of build.gradle.kts with Gradle Kotlin DSL (5.0)?

Gradle 5.0, Kotlin DSL

Create gradle.properties file:

kotlinVersion=1.3.10

Create build.gradle.kts file:

val kotlinVersion: String by project

println(kotlinVersion) // works

plugins {
    kotlin("jvm").version(kotlinVersion)
    //                    ^ Unresolved reference: kotlinVersion

}

repositories {
    jcenter()
}

tasks.register("compute") {
    doLast {
        println(kotlinVersion) // works
    }
}

Run gradle compute , then change

kotlin("jvm").version(kotlinVersion)

to

kotlin("jvm").version("1.3.10")

and run again. Everything works.

Am I just doing something wrong? Or is it some sort of limitation or a bug?

I just wanted to move the Kotlin version out of the build script, so I could play with changing it later (eg via command line, ... -PkotlinVersion=1.3.0 ) and also to keep it the same both for dependencies and plugins.

I typically use the buildSrc directory to define objects that represent versions or properties that I wish to reuse, especially when I have multiple projects or multiple dependencies that stay lock-step with versioning. I put together a little example projecthere that demonstrates usage.

In buildSrc/src/main/kotlin/Versions.kt I have:

object Versions {
    // Library versions
    val Kotlin = "1.3.10"
    val logback = "1.2.3"

    // Plugin versions
    object Plugins {
        // Can be changed if we want to use a version other than one matching the library version
        val Kotlin = Versions.Kotlin
    }
}

And I use it elsewhere like so:

plugins {
    kotlin("jvm") version Versions.Plugins.Kotlin
}

// snip...

dependencies {
    compile(kotlin("stdlib-jdk8"))
    compile(group = "ch.qos.logback", name = "logback-classic", version = Versions.logback)
}

These are statically defined in the Versions.kt file, but you could also read them from the environment, or a file, or properties. The real key is that your buildSrc is evaluated before everything else, so it's available for all of the other phases in your build script (At least all the ones I've tried!) .

The plugins block is evaluated separately from the rest of the build script, because the set of plugins you're using determines the classpath (and the name resolution scope) for the rest of the build script. Because of that, declarations outside of the plugins block cannot be used inside that block.

As @yole said in his answer, the plugins { ... } block is a special construct that is evaluated before the rest of the build script and has limited access to the Gradle model.

One way to pass a property and use it in the plugins { ... } DSL is to use system properties :

val kotlinVersion = System.getProperty("kotlinVersion")?.toString() 
    ?: error("Add a 'kotlinVersion' system property or pass -DkotlinVersion=...")
id("org.jetbrains.kotlin.multiplatform").version(kotlinVersion)

The way to pass a system property via command line is -DkotlinVersion=1.3.0 .

可以通过以下方式访问属性:

project.properties["kotlinVersion"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM