Vampire
07/17/2023, 2:25 PM--release for the KotlinCompile task and / or set the Java Toolchain for a specific KotlinCompile task like for Java-centric tasks like JavaCompile?
I tried to provide a better and future-proof solution for #2218 of kotlinx.serialization (https://github.com/Kotlin/kotlinx.serialization/issues/2218).
For that I set the java { toolchain { ... } } to Java 8 and just set the specific JavaCompile task that compiles the module-info.java file to Java 11 toolchain with --release 9. (Because there is no Java 9 toolchain for certain macOS architectures.
But the consequence of this is, that the KotlinCompile tasks ignore the module-info.class files. Before, the KotlinCompile task considered the module-info.class files of compile dependencies, so if you for example remove the exports kotlinx.serialization; from `core`'s module-info.java, the compilation of formats/json failed due to the missing exports in core. Now as Java 8 is used as toolchain, the module-info.class of core is ignored and the compilation succeeds and would then only fail at runtime when using JPMS.
So a solution would probably either need to use a Java 11 toolchain for the KotlinCompile task, but somehow being able to specify --release 8, so that the compilation happens against the correct Java 8 API. Alternatively, another KotlinCompile task would be necessary - for exampled hooked to the check lifecycle task - that compiles all files again but with Java 11, so that for the real build it compiles against the Java 8 API, but as a verification for the JPMS configuration it is compiled again with Java 11.
Using a Java 11 toolchain with jvmTarget 8 is not a proper solution as that is basically what is done now. Actually in this specific case it would work as the API that has changed here was changed in Java 13. But there might be other cases now or in the future, so it should really compile against the proper Java 8 API like the --release option is doing for JavaCompile.Sam
07/17/2023, 2:34 PM-Xjdk-release option; does that help? https://kotlinlang.org/docs/compiler-reference.html#xjdk-release-versionVampire
07/17/2023, 2:35 PMfreeCompilerArgs, thanks.Vampire
07/17/2023, 4:18 PM--release, but unfortunately not sufficiently.
If I add that arg to the current build setup, core does not compile anymore as it says maaaany symbols declared in module kotlin.stdlib which is not depended on and unnamed module which is not read.
And if I add it to the setup I changed it to, changing the toolcahin to 11 (or 17 to eventually reproduce the problematic outcome) and setting jvmTarget and -Xjdk-release to 1.8, now produces the intended bytecode, but still does does not complain about the module-info problem πmbonnin
07/18/2023, 10:09 AMVampire
07/18/2023, 10:12 AMVampire
07/18/2023, 10:24 AMmbonnin
07/18/2023, 10:24 AMkotlin {
    jvm("java11")
    jvm("java8")
}
tasks.withType<KotlinJvmCompile>().configureEach {
    if (name.contains("Java8")) {
        compilerOptions.jvmTarget.set(JvmTarget.JVM_1_8)
    } else {
        compilerOptions.jvmTarget.set(JvmTarget.JVM_11)
    }
}
This works for membonnin
07/18/2023, 10:25 AMVampire
07/18/2023, 10:26 AMVampire
07/18/2023, 10:26 AMtapchicoma
07/18/2023, 10:29 AMKotlinApiPlugin plugin which exposes methods to create KotlinJvmCompile taskVampire
07/18/2023, 6:12 PMProject#plugins shouldn't be used?
apply<KotlinBaseApiPlugin>()
val verifyModuleTaskName = "verify${compileModuleTaskName.removePrefix("compile").capitalize()}"
val verifyModuleTask = plugins.findPlugin(KotlinBaseApiPlugin::class)!!.registerKotlinJvmCompileTask(verifyModuleTaskName)
verifyModuleTask {
    group = VERIFICATION_GROUP
    libraries.from(compileKotlinTask.libraries)
    source(compileKotlinTask.sources)
    source(moduleInfoSourceFile)
    kotlinOptions {
        jvmTarget = "9"
        freeCompilerArgs += "-Xjdk-release=9"
    }
}
tasks.named("check") {
    dependsOn(verifyModuleTask)
}
Besides that it complains about missing value of ownModuleName.
So assuming above might be correct, what else would I need to set for it to get it going?tapchicoma
07/18/2023, 6:36 PMcompileKotlinTask compilerOptions.moduleName (ownModuleName could be the same as moduleName)Vampire
07/18/2023, 6:37 PMVampire
07/18/2023, 6:37 PMmoduleName.set(verifyModuleTaskName), but that didn't make the error go awayVampire
07/18/2023, 6:38 PMmoduleName.set(compileKotlinTask.moduleName) also does not helpVampire
07/18/2023, 6:39 PMVampire
07/18/2023, 6:40 PMkotlinOptions {
    moduleName = compileKotlinTask.moduleName.get()
}
also does not change a thingtapchicoma
07/18/2023, 6:43 PMownModuleName.set(compileKotlinTask.compilerOptions.moduleName)tapchicoma
07/18/2023, 6:44 PMKotlinJvmTask.moduleName is deprecated in favor of KotlinJvmTask.compilerOptions.moduleNameVampire
07/18/2023, 6:44 PMownModuleName, neither on the task, nor the optionstapchicoma
07/19/2023, 8:06 AMVampire
07/19/2023, 8:07 AMVampire
07/19/2023, 8:08 AMVampire
07/19/2023, 8:08 AMtapchicoma
07/19/2023, 8:09 AMtapchicoma
07/19/2023, 8:12 AMownModuleName is not a part of public api in KotlinJvmCompile task. Unfortunately in this case you need to fallback to use our internal org.jetbrains.kotlin.gradle.tasks.KotlinCompile implementationVampire
07/19/2023, 8:16 AMtapchicoma
07/19/2023, 8:17 AMownModuleName is scheduled to be removed in 2.0. Though this is good point that created task could not be used as is. Could you open an issue?Vampire
07/19/2023, 8:55 AMVampire
07/19/2023, 9:04 AMVampire
07/19/2023, 2:22 PMapply<KotlinBaseApiPlugin>()
val verifyModuleTaskName = "verify${compileModuleTaskName.removePrefix("compile").capitalize()}"
val verifyModuleTask = plugins.findPlugin(KotlinBaseApiPlugin::class)!!.registerKotlinJvmCompileTask(verifyModuleTaskName)
verifyModuleTask {
    group = VERIFICATION_GROUP
    libraries.from(compileKotlinTask.libraries)
    source(compileKotlinTask.sources)
    source(sourceFile)
    destinationDirectory.set(temporaryDir)
    moduleName.set(compileKotlinTask.moduleName)
    multiPlatformEnabled.set(compileKotlinTask.multiPlatformEnabled)
    kotlinOptions {
        jvmTarget = "9"
        freeCompilerArgs += "-Xjdk-release=9"
    }
    this as KotlinCompile
    ownModuleName.set(compileKotlinTask.moduleName)
}
tasks.named("check") {
    dependsOn(verifyModuleTask)
}
And if yes, how do I make it work? π
Because now I get several
e: file///.../kotlinx.serialization/formats/json/commonMain/src/kotlinx/serialization/json/Json.kt69:6 Declaration annotated with '@OptionalExpectation' can only be used in common module sourcesComparing the `--info`output of
compileKotlinTask and verifyKotlinJvmModule suggests they are compiling the same files, except for the additional module info file.Vampire
07/19/2023, 2:23 PMtapchicoma
07/19/2023, 2:32 PMVampire
07/19/2023, 2:33 PMVampire
07/19/2023, 2:33 PMtapchicoma
07/19/2023, 2:44 PMinternal.... So following hack may work:
verifyModuleTask {
    @Suppress("INVISIBLE_MEMBER")
    commonSourceSet.from(compileKotlinTask.commonSourceSet)
    multiplatformEnabled.set(true)
}Vampire
07/19/2023, 2:58 PMapply<KotlinBaseApiPlugin>()
val verifyModuleTaskName = "verify${compileModuleTaskName.removePrefix("compile").capitalize()}"
val verifyModuleTask = plugins.findPlugin(KotlinBaseApiPlugin::class)!!.registerKotlinJvmCompileTask(verifyModuleTaskName)
verifyModuleTask {
    group = VERIFICATION_GROUP
    libraries.from(compileKotlinTask.libraries)
    source(compileKotlinTask.sources)
    source(sourceFile)
    destinationDirectory.set(temporaryDir)
    moduleName.set(compileKotlinTask.moduleName)
    multiPlatformEnabled.set(compileKotlinTask.multiPlatformEnabled)
    kotlinOptions {
        jvmTarget = "9"
        freeCompilerArgs += "-Xjdk-release=9"
    }
    this as KotlinCompile
    ownModuleName.set(compileKotlinTask.moduleName)
    @Suppress("INVISIBLE_MEMBER")
    commonSourceSet.from(compileKotlinTask.commonSourceSet)
}
tasks.named("check") {
    dependsOn(verifyModuleTask)
}
It detects if I remove exports kotlinx.serialization; from core and it detects if I remove requires transitive kotlinx.serialization.core; from formats/json.Vampire
07/19/2023, 2:58 PMinternal at will πVampire
07/19/2023, 3:06 PMcommonSourceSet requirement be a separate issue, is it intended, or can it be considered part of KT-60541?tapchicoma
07/19/2023, 3:07 PMVampire
07/19/2023, 3:10 PMVampire
07/19/2023, 3:10 PMVampire
07/19/2023, 3:16 PMVampire
07/19/2023, 3:30 PMVampire
07/19/2023, 3:36 PMtapchicoma
07/19/2023, 3:57 PMkotlin-android plugin. We will consider fixing it πVampire
07/19/2023, 9:00 PMtapchicoma
07/20/2023, 8:28 AMKotlinCompile.incremental = falseVampire
07/20/2023, 8:35 AMVampire
07/20/2023, 9:22 AMincremental, just changing `core`'s module-info.java does not make the task out-of-date, it stays UP-TO-DATE and only forcing --rerun makes it run and fail accordingly.
And with incremental, just changing `format/json`'s module-info.java, the task does execute, but does not fail although it should, due to the incrementality. Using --rerun again makes the task run non-incrementally and fail properl.y
So two more bugs I'd say, that changes in the module-info.class of dependencies does not make the task out-of-date and the task needs to run non-incrementally automatically if the compiled module-info.java changes. Will create those too.Vampire
07/20/2023, 9:22 AMmodule-info.class in dependency not making the task out-of-date?tapchicoma
07/20/2023, 9:27 AMtapchicoma
07/20/2023, 9:27 AMDefaultTaskVampire
07/20/2023, 9:28 AMtapchicoma
07/20/2023, 10:21 AMsource(kotlinCompileTask.javaSources) so task with track changes in .java filestapchicoma
07/20/2023, 10:23 AMsource(..) separate sources into 3 task inputs: sources (.kt, .kts files), javaSources (.java files),  scriptSources (custom Kotlin script files)Vampire
07/20/2023, 11:21 AMkotlinCompileTask in my case does not contain the module-info.java anyway.
I already add the module-info.java to the new task as the is the main purpose of the task.
The --info output also says that the module-info.java is compiled along.
It just does not make the Kotlin files recompiled when only the module-info.java changes.
And I would not expect that change to care about the module-info.class files in the dependencies anyway.Vampire
07/20/2023, 11:22 AMincremental = false for the incrementality problem and for the module-info.class in the dependencies
inputs.files(
    libraries.asFileTree.elements.map { libs ->
        libs
            .filter { it.asFile.exists() }
            .map {
                zipTree(it.asFile).filter { it.name == "module-info.class" }
            }
    }
).withPropertyName("modularInfosOfLibraries")Vampire
07/20/2023, 11:23 AMVampire
07/20/2023, 11:25 AMsource(compileKotlinTask.javaSources) to be sure in case there are other Java files in that source task.
But I don't see compileKotlinTask.scriptSourcesVampire
07/20/2023, 11:26 AMinternal in KotlinCompile, so
@Suppress("INVISIBLE_MEMBER")
source(compileKotlinTask.scriptSources)Vampire
07/20/2023, 1:44 PM