For describing Gradle build scripts, we can use Kotlin via build.gradle.kts
files. It's a common problem to globally define the Kotlin version to be used, both in the dependencies
and also in the build plugin
section (It's rather uncommon to have different versions in use for the given case).
Consider the following code (Gradle 4.3.1):
plugins {
var pluginVersion = "1.2.30"
kotlin("jvm").version(kotlinVersion)
// more
}
var dependencyVersion = "1.2.30"
dependencies {
compile(kotlin("stdlib", kotlinVersion))
compile(kotlin("reflect", kotlinVersion))
testCompile(kotlin("test", kotlinVersion))
// more
}
As you can see, the kotlin version
(1.2.30 in this case) is defined twice: dependencyVersion
and pluginVersion
, which very often does not differ. Due to DSL restrictions, it is impossible to access the pluginVersion
from outside the plugins
block or access the dependencyVersion
from within the plugins
block.
How can the version string, "1.2.30"
be extracted to a single place?
In later versions of Gradle you no longer need to specify the version of your kotlin(stdlib|reflect|test)
dependencies, the Kotlin plugin will automatically configure them for you.
As for extracting the dependency to a single place, there are two main patterns:
- define the constants you want to share in an object within
buildSrc/src/main/kotlin/
and use that object in your build script, code from buildSrc
is available to the whole script including the plugins
block
use a system property, you can define a system property in gradle.properties
by prefixing its name with systemProp.
and you can access system properties via System.getProperties()
, for example:
// build.gradle.kts
plugins {
val kotlinVersion by System.getProperties()
println("Kotlin version is $kotlinVersion")
}
// gradle.properties
systemProp.kotlinVersion=1.2.20
You can extract the version from the plugin class:
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper
plugins {
kotlin("jvm") version "1.2.0"
}
val kotlinVersion = plugins.getPlugin(KotlinPluginWrapper::class.java).kotlinPluginVersion
There's a workaround available, which searches the version defined for the kotlin plugin and assignes this one to the outer variable. The following demonstrates this:
val kotlinVersion: String? by extra {
buildscript.configurations["classpath"]
.resolvedConfiguration.firstLevelModuleDependencies
.find { it.moduleName == "kotlin-gradle-plugin" }?.moduleVersion
}
plugins {
kotlin("jvm").version("1.2.30")
//more
}
The variable kotlinVersion
can then be used in the dependencies
without further trouble.