elect
elect

Reputation: 7190

Using ProjectDelegate `gradle` within the `plugins` DSL

As titled, this:

plugins {
   if (gradle.gradleVersion < "6.0")
      id("ru.vyarus.quality").version("4.3.0")
}

returns:

Unresolved reference: gradle

gradle is also marked as an error, and hovering the mouse above I get:

'val Build_gradle.gradle: Gradle' can't be called in this context by implicit receiver. Use the explicit one if necessary

Googling around, I tried specifying the receiver:

plugins {
   if (this@Build_gradle.gradle.gradleVersion < "6.0")
      id("ru.vyarus.quality").version("4.3.0")
}

But it fires:

Unresolved reference: getGradle

Is there a way? (other than declaring an outside variable just for that)

Upvotes: 1

Views: 570

Answers (1)

Nicolas
Nicolas

Reputation: 7081

From Limitations of the plugins DSL:

This requires that plugins be specified in a way that Gradle can easily and quickly extract, before executing the rest of the build script. It also requires that the definition of plugins to use be somewhat static.

The plugins {} block does not support arbitrary code. It is constrained, in order to be idempotent (produce the same result every time) and side effect free (safe for Gradle to execute at any time).

In fact, your build script is evaluated against CompiledKotlinPluginsBlock for the plugins block, and CompiledKotlinBuildScript for the rest. So this@Build_gradle doesn't always refer to the same object. You can see this by printing the superclass at different places:

println(this@Build_gradle::class.java.superclass)

And as it turns out CompiledKotlinPluginsBlock doesn't have a getGradle() method.

It's great to know why that happens, but finding a solution wasn't so easy. You can't add a variable outside of plugins {} because it won't be reachable. One way would be to have a static field in your buildSrc folder, but it would be weird needing it only for that.

Here's something I found that works. In your root build.gradle.kts add:

plugins {
    id("ru.vyarus.quality") version "4.3.0" apply false
}

project(":yourModule") {
    if (gradle.gradleVersion < "6.0") {
        apply(plugin = "ru.vyarus.qualit")
    }
}

I wish it didn't need the old apply(plugin = way, but that's the only solution I found. You don't need anything special in your module's plugins {}.

Upvotes: 1

Related Questions