gradle / gradle

Adaptable, fast automation for all
https://gradle.org
Apache License 2.0
16.99k stars 4.77k forks source link

Imports and extension functions cannot be used in Kotlin DSL plugins and buildscript blocks #9270

Open runningcode opened 6 years ago

runningcode commented 6 years ago

Imported functions and properties cannot be used inside of a buildscript { } block in a build.gradle.kts file. Extension functions also cannot be used.

If I define a function foo() inside buildSrc in the root source package, then function foo is usable in buildscript blocks in build.gradle.kts files.

However, if I move the function foo() in to package bar such that at the top of my build.gradle.kts file, I must now write import bar.foo, then this function cannot be used inside the builscript block of the build file, but it can be used in other parts of the file.

Expected behavior,

I expect to be able to use imported function declared in other packages inside buildscript blocks of build.gradle.kts files.

Context

This means that code and functions must be duplicated in order to be used inside buildscript blocks.

Steps to Reproduce (for bugs)

Sample repro project: https://github.com/runningcode/TripletBug/ using kotlin-dsl 0.17.5 with gradle 4.8

JLLeitschuh commented 6 years ago

Can you provide some code snippet examples?

runningcode commented 6 years ago

This build.gradle.kts from the linked github project has two examples: https://github.com/runningcode/TripletBug/blob/master/build.gradle.kts.

For example writing this code fails to compile inside the buildscript block, but works fine outside the buildscript block. ext["kotlin_version"] = "1.2.50"

The function notUsableInBuildscript() in that build.gradle.kts file doesn't compile when called inside the buildscript block but compiles elsewhere in the buildscript.

JLLeitschuh commented 6 years ago

Can you use a fully qualified version of the method and have it work? I think that this is failing because imports can only be satisfied after the buildscript block has been executed.

Functionally, what you'd need is a special set of imports specific to the buildscript block. Or maybe @bamboo and @eskatos can figure out some dark magic that will make this possible.

runningcode commented 6 years ago

A fully qualified version of the function notUsableInBuildscript() works. However, I can't get a fully qualified version of the extension property ext to work. I tried: org.gradle.kotlin.dsl.ext["kotlin_version"] = "1.2.50"

nico-mcalley commented 5 years ago

I just tried kotlin dsl for gradle. First thing that got me wondering was the maven-block inside the buildscript block. I tried to use the default java.net.URI class to set the url, but had to rewrite my script, because "java" is an extension? I know there is a workaround, but this is something that beginners have to fight with and its not a great experience.

bamboo commented 4 years ago

Moving to 7.0 as it's a potentially breaking change for scripts.

BjoernPetersen commented 3 years ago

It's already mentioned in the title, but I want to emphasize that the same issue exists in the plugins block (as demonstrated here: https://github.com/BjoernPetersen/gradle-import-bug-demo).

nuhkoca commented 3 years ago

Any update on this?

herrbert74 commented 3 years ago

It works in Groovy, so what kind of black magic is used there, that cannot be used in Kotlin DSL?

runningcode commented 3 years ago

@herrbert74 Groovy is a dynamic language. Kotlin is not.

mike192 commented 3 years ago

I'm facing the same issue. When is it going to be solved?

yueban commented 2 years ago

same issue here. it breaks the build system on kotlin dsl. Dependencies like kotlin have both library dependencies and plugin dependencies, so we must maintain two kotlin version values in separate files. One in buildSrc folder and another in root build.gradle.kts.

jonycorreia commented 2 years ago

one way to mitigate the issue is the following (build.gradle.kts):

import com.something.something.Versions

plugins {
    // buildSrc import issue: https://github.com/gradle/gradle/issues/9270
    val versions = com.something.something.Versions

    kotlin("jvm") version versions.kotlin
}

dependencies {
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${Versions.kotlin}")
}

In this case Versions is a kotlin object in the package com.something.something in the buildSrc folder

package com.something.something

object Versions {
    const val kotlin = "1.7.10" //https://github.com/JetBrains/kotlin/releases/latest
}
dan-lugg commented 4 months ago
plugins {
    // buildSrc import issue: https://github.com/gradle/gradle/issues/9270
    val versions = com.something.something.Versions

    kotlin("jvm") version versions.kotlin
}

I'm not happy that this fixes it, lol.

So, just to make sure I understand this, the issue is you can't use an import to pull Versions (or whatever reference from buildSrc) into the script and reference it in the plugins block?

Instead you must use the fully-qualified reference to the definition in buildSrc, in the plugins block.

user98392 commented 2 months ago

It's "by design" guys. https://github.com/gradle/kotlin-dsl-samples/issues/158#issuecomment-358374735