ext in buildscript can not be recognised by Gradle Kotlin DSL

GradleKotlinbuild.gradleGradle Kotlin-Dsl

Gradle Problem Overview


In these days, I am trying to write some codes to experience the Spring reactive features and kotlin extension in Spring 5, and I also prepared a gradle Kotlin DSL build.gradle.kt to configure the gradle build.

The build.gradle.kt is converted from Spring Boot template codes generated by http://start.spring.io.

But the ext in the buildscript can not be detected by Gradle.

buildscript {
  ext { }
}

The ext will cause Gradle build error.

To make the variables in classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") and compile("org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlinVersion") work, I added the variables in the hard way.

val kotlinVersion = "1.1.4"
val springBootVersion = "2.0.0.M3"

But I have to declare them in global top location and duplicate them in the buildscript.

Code: https://github.com/hantsy/spring-reactive-sample/blob/master/kotlin-gradle/build.gradle.kts

Is there a graceful approach to make ext work?

Update: There are some ugly approaches:

  1. From Gradle Kotlin DSL example, https://github.com/gradle/kotlin-dsl/tree/master/samples/project-properties, declares the properties in gradel.properties.

     kotlinVersion = 1.1.4
     springBootVersion = 2.0.0.M3
    

    And use it in build.gradle.kts.

     buildScript{
        val kotlinVersion by project
     
     }
      val kotlinVersion by project //another declare out of buildscript block.
    
  2. Similar with above declare them in buildScript block:

     buildScript{
        extra["kotlinVersion"] = "1.1.4"
        extra["springBootVersion"] = "2.0.0.M3"
        val kotlinVersion: String by extra
     
     }
      val kotlinVersion: String by extra//another declare out of buildscript block.
    

How can I avoid the duplication of val kotlinVersion: String by extra?

Gradle Solutions


Solution 1 - Gradle

With Kotlin DSL ext has been changed to extra and it can be used under buildscript.

Eg :-

buildscript {
    // Define versions in a single place
    extra.apply{
        set("minSdkVersion", 26)
        set("targetSdkVersion", 27)
    }
}

Solution 2 - Gradle

It is possible to use constants defined in .kt file in .gradle.kts files.

create buildSrc folder in root folder of your project

create buildSrc/build.gradle.kts file with the following content

plugins {
    `kotlin-dsl`
}

repositories {
    mavenCentral()
}

create file buildSrc/src/main/kotlin/Constants.kt with the following content

object Constants {
    const val kotlinVersion = "1.3.70"
    const val targetSdkVersion = 28
}

Synchronize. Now you may reference created constants in various .gradle.kts files like this

...
classpath(kotlin("gradle-plugin", version = Constants.kotlinVersion))
...

...
targetSdkVersion(Constants.targetSdkVersion)
...

Solution 3 - Gradle

What is working for me is using ext in allprojects instead of buildscript, so in your top-level build.gradle.kts

allprojects {
  ext {
    set("supportLibraryVersion", "26.0.1")
  }
}

then you can use it in build.gradle.kts files in modules like this:

val supportLibraryVersion = ext.get("supportLibraryVersion") as String

Solution 4 - Gradle

None of these answers felt clear to me. So here's my explanation:

/build.gradle.kts:

buildscript {
    extra.apply {
        set("compose_version", "1.0.3")
    }
    ...
}

/app/build.gradle.kts:

val composeVersion = rootProject.extra["compose_version"]
implementation("androidx.compose.ui:ui:$composeVersion")
implementation("androidx.compose.material:material:$composeVersion")

Solution 5 - Gradle

There is a new possibility with Kotlin we can use:

object DependencyVersions {
    const val JETTY_VERSION = "9.4.12.v20180830"
}

dependencies{
    implementation("org.eclipse.jetty:jettyserver:${DependencyVersions.JETTY_VERSION}")
}

Here, DependencyVersions is a name I chose. You can choose another name, like "MyProjectVariables". This is a way to avoid using the extra or ext properties.

Solution 6 - Gradle

Global properties in kotlin-gradle-dsl:
https://stackoverflow.com/a/53594357/3557894


Kotlin version is embedded into kotlin-gradle-dsl.
You can use dependecies with embedded version as follows:

implementation(embeddedKotlin("stdlib-jdk7"))

classpath(embeddedKotlin("gradle-plugin"))

Solution 7 - Gradle

val junitVersion by extra("4.13.2")
testImplementation("junit:junit:$junitVersion")

Solution 8 - Gradle

It's a possibility to define global properties within gradle.properties:

xyzVersion=1.0.0

And then use them in your module's build.gradle.kts:

val xyzVersion: String by project

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHantsyView Question on Stackoverflow
Solution 1 - GradleShashi BhushanView Answer on Stackoverflow
Solution 2 - GradleEugene PopovichView Answer on Stackoverflow
Solution 3 - Gradlekamil zychView Answer on Stackoverflow
Solution 4 - GradleBlundellView Answer on Stackoverflow
Solution 5 - GradlePer Christian HendenView Answer on Stackoverflow
Solution 6 - GradlenuamehasView Answer on Stackoverflow
Solution 7 - Gradle顾小兔View Answer on Stackoverflow
Solution 8 - GradlesergiosuaView Answer on Stackoverflow