https://kotlinlang.org logo
#gradle
Title
# gradle
k

Konrad Sztenderski

02/19/2023, 9:27 PM
Hi, does anyone know why I am not able to compile my kotlin code targeting jvm 11 when using
kotlin-dsl
plugin. I have tried setting
jvmTarget
for
KotlinCompile
task:
Copy code
withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
    kotlinOptions.jvmTarget = "11"
}
or like this:
Copy code
kotlinDslPluginOptions {
    jvmTarget.set("11")
}
setting toolchain like this:
Copy code
kotlin.jvmToolchain {
    (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(11))
}
but when I add
kotlin-dsl
to plugins then code doesn't compile because of API I used from java 9, so it seems like it still uses jvm 8. Without
kotlin-dsl
everything builds fine.
c

Chris Lee

02/19/2023, 9:29 PM
The Kotlin DSL compiler unfortunately uses an afterEvaluate block to setup its options, thereby overriding what you set. If you wish to configure it you can use something like this:
Copy code
afterEvaluate {
            tasks.withType<KotlinCompile>().configureEach {
   }
}
Note: use of
afterEvaluate
is generally discouraged. This is a special case as it is the only way to override what the plugin does (ideally it should not be using afterEvaluate).
Also, note that with Gradle 8 the Kotlin DSL plugin uses the configured JVM toolchain directly.
e

ephemient

02/19/2023, 9:43 PM
also, as Gradle supports running on Java 8, consider making your plugins support running on Java 8 as well. that's why it's set up that way
k

Konrad Sztenderski

02/19/2023, 9:44 PM
In source code it looks like it should pick up the version I have configured:
Copy code
if (this@kotlinDslPluginOptions.jvmTarget.isPresent) {
    jvmTarget.set(JvmTarget.fromTarget(this@kotlinDslPluginOptions.jvmTarget.get()))
}
c

Chris Lee

02/19/2023, 9:55 PM
That source is Gradle 8, is that what you are using? Previous versions didn’t have that snippet.
k

Konrad Sztenderski

02/19/2023, 9:59 PM
I am using gradle 7.4.2 and it has similar code:
Copy code
it.kotlinOptions {
    jvmTarget = this@kotlinDslPluginOptions.jvmTarget.get()
    ...
}
And unfortunately configuring it in
afterEvaluate
doesn't help.
c

Chris Lee

02/19/2023, 10:00 PM
It does work using afterEvaluate. Will need to track down pre-Gradle 8 code snippet…
Prior to Gradle 8 this snippet can be used to set the JVM version for the Kotlin DSL plugin:
Copy code
configure<KotlinDslPluginOptions> {
    jvmTarget.value = "17"
}
Setting kotlinOptions can be done with this snippet:
Copy code
// afterEvaluate required as kotlin dsl plugin sets its defaults in afterEvaluate
// <https://github.com/gradle/gradle/blob/master/subprojects/kotlin-dsl-plugins/src/main/kotlin/org/gradle/kotlin/dsl/plugins/dsl/KotlinDslCompilerPlugins.kt#L43>
afterEvaluate {
    tasks.withType<KotlinCompile>().configureEach {
        kotlinOptions {
            
        }
    }
}
If you are only setting the JVM version (and not other Kotlin compiler options) then only the first snippet is needed.
k

Konrad Sztenderski

02/19/2023, 10:17 PM
When I set breakpoint here:
Copy code
jvmTarget = this@kotlinDslPluginOptions.jvmTarget.get()
then
jvmTarget
is set to "11" indeed but somehow my code still doesn't compile.
c

Chris Lee

02/19/2023, 10:17 PM
then this isn’t your issue. what is the error message you are encountering?
k

Konrad Sztenderski

02/19/2023, 10:20 PM
It is just
Unresolved reference: newDefaultInstance
and whole source code is:
Copy code
fun main(args: Array<String>) {
    TransformerFactory.newDefaultInstance()
}
newDefaultInstance
method is from java 9
c

Chris Lee

02/19/2023, 10:21 PM
hmmm. odd to see
fun main(args: Array<String>)
in a kotlin-dsl project, which is by definition creating a Gradle plugin, not otherwise executable Kotlin code.
e

ephemient

02/19/2023, 10:22 PM
jvmTarget does not affect which Java classpath you're compiling with, only what the target bytecode level is
your issue is something else
aha, I see what you're doing
c

Chris Lee

02/19/2023, 10:23 PM
are you creating a Gradle plugin? If not, you want
kotlin("jvm")
instead of
kotlin-dsl
.
e

ephemient

02/19/2023, 10:23 PM
the Gradle API JAR has its own copy of the java.xml module
you will not be able to use the JVM's own java.xml APIs in any Gradle plugin
(even if you fix the compile issue, it will not work at runtime)
k

Konrad Sztenderski

02/19/2023, 10:25 PM
I use both
kotlin("jvm")
and
kotlin-dsl
in gradle plugin source code. Previous code is only for testing against smaller source code.
e
c

Chris Lee

02/19/2023, 10:26 PM
while perhaps not related to this issue it’s problematic to use both kotlin(“jvm”) and kotlin-dsl. The former is for a Kotlin app/library, the latter is for a Gradle plugin. Using both together introduces a number of issues.
e

ephemient

02/19/2023, 10:26 PM
this is not a Kotlin issue, although earlier versions of Java did have a bug that made the compile work (even though it shouldn't)
this is an issue with anything that uses
dependencies { implementation(gradleApi()) }
(and also anything loaded into Gradle's classpath at runtime)
k

Konrad Sztenderski

02/19/2023, 10:40 PM
even when I got rid of
kotlin("jvm")
and left only
kotlin-dsl
it doesn't work
e

ephemient

02/19/2023, 10:41 PM
yes. it's not a Kotlin issue, it's a Gradle issue, as I said.
any
java.xml
API newer tha Java 8 is simply not going to work, regardless of which Java you're building or running Gradle with
k

Konrad Sztenderski

02/19/2023, 10:41 PM
ohh ok thank you guys
60 Views