3

I was working with Maven before Gradle and Maven has such things like dependencyManagement and pluginManagement what allows to keep all versions "DRY" in one place with help of "properties".

Gradle supports project properties, so I can declare versions like:

buildscript {
    ext.kotlin_version = '1.1.61'

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

But this approach cannot be applied to plugins {} DSL. I cannot write something like this:

plugins {
    id 'org.jetbrains.kotlin:kotlin-gradle-plugin' version $kotlin_version
}

As according to docs:

values must be literal (e.g. constant strings, not variables)

Is there a way to workaround this limitation?

Community
  • 1
  • 1
Alex L.
  • 53
  • 4
  • your IDE may not like it but you can actually do: `val kotlin_version: String by rootProject.ext' inside the plugin block just fine, also you'd want to do `version kotlin_version` (no `$` symbol) – Matt Kerr Jan 09 '20 at 00:10

2 Answers2

1

The latest versions of Gradle allows you to define your versions in a property file, map that version in a pluginManagement block, and then omit the version from all downstream plugin blocks. The pluginManagement block does not have the only-constant restriction.

In fact, once you use this approach, it is a compile time error to even try to declare a version downstream.

After using this approach, there is a good chance you can completely omit your buildscript.

gradle.properties

kotlinVersion=1.3.50

settings.gradle

pluginManagement {
    resolutionStrategy {
        eachPlugin {
            if (requested.id.id == "org.jetbrains.kotlin.jvm") {
                useVersion(kotlinVersion)
            }
        }
    }
}

build.gradle

plugins {
    id("org.jetbrains.kotlin.jvm")
}

If you are into kotlinscript, get your version from a delegate:

settings.gradle.kts

val kotlinVersion: String by settings
pluginManagement {
    resolutionStrategy {
        eachPlugin {
            if (requested.id.id == "org.jetbrains.kotlin.jvm") {
                useVersion(kotlinVersion)
            }
        }
    }
}

Of course, you do not need the properties file. You can just hard code the version in your gradle.settings. But by having the property, you can then declare dependencies to the stdlib using it.

Steven Spungin
  • 27,002
  • 5
  • 88
  • 78
  • way more cumbersome than simply doing `buildscript { extra.set("kotlinVersion", "1.3.61") } plugins { kotlin("jvm") version rootProject.extra["kotlinVersion"] }` – Matt Kerr Jan 09 '20 at 00:11
0

I think you can put the ext closure in a separate properties.gradle, and then reference the properties twice in buildscript as well as project build (buildscript block is evaluated at the very beginning, before any other part of groovy script).

For example, in $projectRoot/gradle/properties.gradle as below:

ext {
  kotlinVersion = '1.1.61' // NOTE, the naming convention is better with kotlinVersion instead of kotlin_version
}

And your $projectRoot/build.gradle would look like this:

buildscript {
  apply from: "gradle/properties.gradle"

  repositories {
      jcenter()
  }

  dependencies {
    println "In buildscript, kotlinVersion is $kotlinVersion"
  }
}

apply plugin: 'java'
apply from: "gradle/properties.gradle"

repositories {
    jcenter()
}

dependencies {
    println "In project, kotlinVersion is $kotlinVersion"
}

When you run ./gradlew dependencies, it would show you the populated versions:

> Configure project : 
In buildscript, kotlinVersion is 1.1.61
In project, kotlinVersion is 1.1.61
chenrui
  • 8,910
  • 3
  • 33
  • 43
  • 2
    This doesn't solve the issue with `plugins {}` DSL. I cannot write: `plugins { id 'org.jetbrains.kotlin:kotlin-gradle-plugin' version $kotlinVersion }` – Alex L. Jan 01 '18 at 15:38
  • @AlexL. There is no way that you can put a variable in a `plugins {}`, it has to be string literal. – chenrui Jan 01 '18 at 15:39
  • Maybe I need to think different. I do not want to copy/paste version and keep it in two places. May be is there something like constants? – Alex L. Jan 01 '18 at 15:43
  • yes, I guess the approach I provided may be the best viable choice. – chenrui Jan 01 '18 at 16:59
  • Re "best viable choice", showing how to output $kotlinVersion to the command-line doesn't seem to move the user closer to using that when specifying a plugin version. – Glen Mazza Jan 08 '23 at 12:02