Qi Chen
Qi Chen

Reputation: 158

Unresolved reference: KotlinCompilerVersion in build.gradle.kts

In build.gradle.kts file, I include this code on the top line. Then I use KotlinCompilerVesion.VERSION below.

import org.jetbrains.kotlin.config.KotlinCompilerVersion

Some code works fine, but some code failed:

It seems like only plugins block can not enable this import.

Here works fine:

dependencies {
    Implementation(kotlin("stdlib-jdk7", KotlinCompilerVersion.VERSION))
    Implementation(kotlin("test", KotlinCompilerVersion.VERSION))
}

Here always wrong:

plugins {
    id("com.android.application")
    kotlin("android")
    kotlin("android.extensions")

    /*
    * Error: Unresolved reference: KotlinCompilerVersion
    */
    id("kotlinx-serialization") version KotlinCompilerVersion.VERSION

    /*
    * Error: Unresolved reference: KotlinCompilerVersion
    */
    id("kotlinx-serialization") version "$KotlinCompilerVersion.VERSION"

    /*
    * Error: Unresolved reference: KotlinCompilerVersion
    */
    id("kotlinx-serialization") version "${KotlinCompilerVersion.VERSION}"
}

How can I use it correctly in here, without declare an ext.xxxVersion var?

Upvotes: 8

Views: 9938

Answers (2)

Mo Beigi
Mo Beigi

Reputation: 1765

Local variable in plugin block

One solution is to define a local object in the plugin {} block. This can reduce duplication within the block itself.

    plugins {
val PluginVersions =
    object {
        val SPRING_BOOT = "3.2.2"
        val SPRING_DEPENDENCY_MANAGEMENT = "1.1.4"
        val KOTLIN = "1.9.22"
        val KTFMT = "0.17.0"
    }

war
id("org.springframework.boot") version PluginVersions.SPRING_BOOT
id("io.spring.dependency-management") version PluginVersions.SPRING_DEPENDENCY_MANAGEMENT
kotlin("jvm") version PluginVersions.KOTLIN
kotlin("plugin.spring") version PluginVersions.KOTLIN
kotlin("plugin.serialization") version PluginVersions.KOTLIN
id("com.ncorti.ktfmt.gradle") version PluginVersions.KTFMT

}

Gradle version catalog

You can also use the Gradle version catalog which lets you make a gradle/libs.versions.toml file which can be referenced from your build.gradle.kts file. It seems to be best practice for version management (especially if you share versions across multiple Gradle projects). However, personally I feel it makes the build.gradle.kts look like ugly with an overload of references and aliases everywhere.

buildSrc folder

The contents of the buildSrc are available inside the plugin {} block. So if you add a basic buildSrc/build.gradle.kts folder with:

repositories { mavenCentral() }

plugins { `kotlin-dsl` }

And a buildSrc/main/kotlin/Versions.kt file with:

object Versions {
    const val SPRING = "3.2.2"
    const val SPRING_DEPENDENCY_MANAGEMENT = "1.1.4"
    const val KOTLIN = "1.9.22"
}

You will be able to access the object inside the plugins {} block.

Upvotes: 0

mig4
mig4

Reputation: 371

Yes, the syntax of the plugins DSL is limited because Gradle parses it before parsing the rest of the file, which requires the definition to be static (no references to variables, constants, etc., pretty much no code is allowed). See Limitations of the plugins DSL for details.

The way I handle defining Kotlin version only once is by actually using the version I specify in the plugins block as canonical in other sections of the file (I picked this up from this blog post by Simon Wirtz) like so:

import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper

val kotlinVersion = plugins.getPlugin(KotlinPluginWrapper::class.java)
        .kotlinPluginVersion

plugins {
    kotlin("jvm") version "1.3.30"
}

dependencies {
    implementation(platform(kotlin("bom", kotlinVersion)))
    implementation(kotlin("stdlib-jdk8"))
}

But yeah, in the plugins block it needs to be static and unfortunately repeated if needed.


Update: I actually just learned it's possible to use constants in the plugins DSL, but they must be defined before Gradle parses the build.gradle.kts file, i.e. from buildSrc. I noticed this in the fuel library. In essence, create buildSrc/build.gradle.kts with the following contents:

plugins {
    `kotlin-dsl`
}

repositories {
    jcenter()
}

Then create buildSrc/src/main/kotlin/Constants.kt with the following contents:

object Kotlin {
    const val version = "1.3.30"
}

And then you'll be able to use the following in your main build.gradle.kts:

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

Upvotes: 6

Related Questions