diff --git a/buildSrc/src/main/kotlin/Java9Modularity.kt b/buildSrc/src/main/kotlin/Java9Modularity.kt index 54a090167..a50c6fc91 100644 --- a/buildSrc/src/main/kotlin/Java9Modularity.kt +++ b/buildSrc/src/main/kotlin/Java9Modularity.kt @@ -3,12 +3,16 @@ */ import org.gradle.api.* +import org.gradle.api.file.* +import org.gradle.api.provider.* +import org.gradle.api.tasks.* import org.gradle.api.tasks.bundling.* import org.gradle.api.tasks.compile.* +import org.gradle.jvm.toolchain.* import org.gradle.kotlin.dsl.* +import org.gradle.process.* import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.plugin.mpp.* -import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.* import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.* import org.jetbrains.kotlin.gradle.targets.jvm.* import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -46,19 +50,17 @@ object Java9Modularity { kotlin.sourceSets.create(sourceSetName) { val sourceFile = this.kotlin.find { it.name == "module-info.java" } - val targetFile = compileKotlinTask.destinationDirectory.file("../module-info.class").get().asFile + val targetDirectory = compileKotlinTask.destinationDirectory.map { + it.dir("../${it.asFile.name}Module") + } // only configure the compilation if necessary if (sourceFile != null) { - // the default source set depends on this new source set - defaultSourceSet.dependsOn(this) - // register a new compile module task - val compileModuleTask = registerCompileModuleTask(compileModuleTaskName, compileKotlinTask, sourceFile, targetFile) + val compileModuleTask = registerCompileModuleTask(compileModuleTaskName, compileKotlinTask, sourceFile, targetDirectory) // add the resulting module descriptor to this target's artifact - artifactTask.dependsOn(compileModuleTask) - artifactTask.from(targetFile) { + artifactTask.from(compileModuleTask) { if (multiRelease) { into("META-INF/versions/9/") } @@ -73,39 +75,43 @@ object Java9Modularity { } } - private fun Project.registerCompileModuleTask(taskName: String, compileTask: KotlinCompile, sourceFile: File, targetFile: File) = + private fun Project.registerCompileModuleTask(taskName: String, compileTask: KotlinCompile, sourceFile: File, targetDirectory: Provider) = tasks.register(taskName, JavaCompile::class) { - // Also add the module-info.java source file to the Kotlin compile task; - // the Kotlin compiler will parse and check module dependencies, - // but it currently won't compile to a module-info.class file. - compileTask.source(sourceFile) - - // Configure the module compile task. - dependsOn(compileTask) source(sourceFile) - outputs.file(targetFile) classpath = files() - destinationDirectory.set(compileTask.destinationDirectory) - sourceCompatibility = JavaVersion.VERSION_1_9.toString() - targetCompatibility = JavaVersion.VERSION_1_9.toString() + destinationDirectory.set(targetDirectory) + javaCompiler.set( + this@registerCompileModuleTask.the().compilerFor { + languageVersion.set(JavaLanguageVersion.of(11)) + } + ) + options.release.set(9) + + options.compilerArgumentProviders.add(object : CommandLineArgumentProvider { + @get:CompileClasspath + val compileClasspath = compileTask.libraries - doFirst { - // Provide the module path to the compiler instead of using a classpath. - // The module path should be the same as the classpath of the compiler. - options.compilerArgs = listOf( - "--release", "9", - "--module-path", compileTask.libraries.asPath, + @get:CompileClasspath + val compiledClasses = compileTask.destinationDirectory + + @get:Input + val moduleName = sourceFile + .readLines() + .single { it.contains("module ") } + .substringAfter("module ") + .substringBefore(' ') + .trim() + + override fun asArguments() = mutableListOf( + // Provide the module path to the compiler instead of using a classpath. + // The module path should be the same as the classpath of the compiler. + "--module-path", + compileClasspath.asPath, + "--patch-module", + "$moduleName=${compiledClasses.get()}", "-Xlint:-requires-transitive-automatic" ) - } - - doLast { - // Move the compiled file out of the Kotlin compile task's destination dir, - // so it won't disturb Gradle's caching mechanisms. - val compiledFile = destinationDirectory.file(targetFile.name).get().asFile - targetFile.parentFile.mkdirs() - compiledFile.renameTo(targetFile) - } + }) } } diff --git a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/CharsetReader.kt b/formats/json/jvmMain/src/kotlinx/serialization/json/internal/CharsetReader.kt index 61fc79109..f5bf0cf6b 100644 --- a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/CharsetReader.kt +++ b/formats/json/jvmMain/src/kotlinx/serialization/json/internal/CharsetReader.kt @@ -20,20 +20,7 @@ internal class CharsetReader( .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) byteBuffer = ByteBuffer.wrap(ByteArrayPool8k.take()) - // An explicit cast is needed here due to an API change in Java 9, see #2218. - // - // In Java 8 and earlier, the `flip` method was final in `Buffer`, and returned a `Buffer`. - // In Java 9 and later, the method was opened, and `ByteFuffer` overrides it, returning a `ByteBuffer`. - // - // You could observe this by decompiling this call with `javap`: - // Compiled with Java 8 it produces `INVOKEVIRTUAL java/nio/ByteBuffer.flip ()Ljava/nio/Buffer;` - // Compiled with Java 9+ it produces `INVOKEVIRTUAL java/nio/ByteBuffer.flip ()Ljava/nio/ByteBuffer;` - // - // This causes a `NoSuchMethodError` when running a class, compiled with a newer Java version, on Java 8. - // - // To mitigate that, `--bootclasspath` / `--release` options were introduced in `javac`, but there are no - // counterparts for these options in `kotlinc`, so an explicit cast is required. - (byteBuffer as Buffer).flip() // Make empty + byteBuffer.flip() // Make empty } @Suppress("NAME_SHADOWING") @@ -105,7 +92,7 @@ internal class CharsetReader( if (bytesRead < 0) return bytesRead byteBuffer.position(position + bytesRead) } finally { - (byteBuffer as Buffer).flip() // see the `init` block in this class for the reasoning behind the cast + byteBuffer.flip() } return byteBuffer.remaining() } diff --git a/gradle/configure-source-sets.gradle b/gradle/configure-source-sets.gradle index 6356668f5..64cfffa4b 100644 --- a/gradle/configure-source-sets.gradle +++ b/gradle/configure-source-sets.gradle @@ -2,14 +2,15 @@ * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(8)) + } +} + kotlin { jvm { withJava() - configure([compilations.main, compilations.test]) { - kotlinOptions { - jvmTarget = '1.8' - } - } } js { diff --git a/settings.gradle b/settings.gradle index 01d4ea62f..ed5256ee9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,6 +2,10 @@ * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0' +} + rootProject.name = 'kotlinx-serialization' include ':kotlinx-serialization-core'