diff --git a/build.gradle b/build.gradle index 2b00f602e3..f6c4cf31c7 100644 --- a/build.gradle +++ b/build.gradle @@ -177,6 +177,7 @@ configure(subprojects.findAll { !sourceless.contains(it.name) && it.name != core apply plugin: "bom-conventions" apply plugin: "java-modularity-conventions" +apply plugin: "version-file-conventions" if (build_snapshot_train) { println "Hacking test tasks, removing stress and flaky tests" @@ -252,40 +253,6 @@ configure(subprojects.findAll { !unpublished.contains(it.name) }) { } } } - - def thisProject = it - if (thisProject.name in sourceless) { - return - } - - def versionFileTask = thisProject.tasks.register("versionFileTask") { - def name = thisProject.name.replace("-", "_") - def versionFile = thisProject.layout.buildDirectory.file("${name}.version") - it.outputs.file(versionFile) - - it.doLast { - versionFile.get().asFile.text = version.toString() - } - } - - List jarTasks - if (isMultiplatform(it)) { - jarTasks = ["jvmJar"] - } else if (it.name == "kotlinx-coroutines-debug") { - // We shadow debug module instead of just packaging it - jarTasks = ["shadowJar"] - } else { - jarTasks = ["jar"] - } - - for (name in jarTasks) { - thisProject.tasks.named(name, Jar) { - it.dependsOn versionFileTask - it.from(versionFileTask) { - into("META-INF") - } - } - } } // Report Kotlin compiler version when building project diff --git a/buildSrc/src/main/kotlin/VersionFile.kt b/buildSrc/src/main/kotlin/VersionFile.kt new file mode 100644 index 0000000000..ef0ef0faa1 --- /dev/null +++ b/buildSrc/src/main/kotlin/VersionFile.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +import org.gradle.api.* +import org.gradle.api.tasks.* + +/** + * Adds 'module_name.version' file to the project's JAR META-INF + * for the better toolability. See #2941 + */ +object VersionFile { + fun registerVersionFileTask(project: Project): TaskProvider { + val versionFile = project.layout.buildDirectory.file("${project.name.replace('-', '_')}.version") + val version = project.version.toString() + return project.tasks.register("versionFileTask") { + outputs.file(versionFile) + doLast { + versionFile.get().asFile.writeText(version) + } + } + } + + fun fromVersionFile(target: AbstractCopyTask, versionFileTask: TaskProvider) { + target.from(versionFileTask) { + into("META-INF") + } + } +} diff --git a/buildSrc/src/main/kotlin/version-file-conventions.gradle.kts b/buildSrc/src/main/kotlin/version-file-conventions.gradle.kts new file mode 100644 index 0000000000..587e184b30 --- /dev/null +++ b/buildSrc/src/main/kotlin/version-file-conventions.gradle.kts @@ -0,0 +1,17 @@ +import org.gradle.api.tasks.bundling.* + +configure(subprojects.filter { !unpublished.contains(it.name) && it.name !in sourceless }) { + val project = this + val jarTaskName = when { + project.name == "kotlinx-coroutines-debug" -> { + project.apply(plugin = "com.github.johnrengelman.shadow") + "shadowJar" + } + isMultiplatform -> "jvmJar" + else -> "jar" + } + val versionFileTask = VersionFile.registerVersionFileTask(project) + tasks.withType(Jar::class.java).named(jarTaskName) { + VersionFile.fromVersionFile(this, versionFileTask) + } +} diff --git a/gradle/publish.gradle b/gradle/publish.gradle index f3b1561dde..9984ae8e70 100644 --- a/gradle/publish.gradle +++ b/gradle/publish.gradle @@ -2,8 +2,6 @@ * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -import org.gradle.util.VersionNumber - // Configures publishing of Maven artifacts to Maven Central apply plugin: 'maven-publish' @@ -15,10 +13,6 @@ def isMultiplatform = project.name == "kotlinx-coroutines-core" || project.name def isBom = project.name == "kotlinx-coroutines-bom" if (!isBom) { - if (project.name == "kotlinx-coroutines-debug") { - apply plugin: "com.github.johnrengelman.shadow" - } - // empty xxx-javadoc.jar task javadocJar(type: Jar) { archiveClassifier = 'javadoc' diff --git a/kotlinx-coroutines-debug/build.gradle b/kotlinx-coroutines-debug/build.gradle deleted file mode 100644 index 42d0b8d0f0..0000000000 --- a/kotlinx-coroutines-debug/build.gradle +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -apply plugin: "com.github.johnrengelman.shadow" - -// apply plugin to use autocomplete for Kover DSL -apply plugin: 'org.jetbrains.kotlinx.kover' - -configurations { - shadowDeps // shaded dependencies, not included into the resulting .pom file - compileOnly.extendsFrom(shadowDeps) - runtimeOnly.extendsFrom(shadowDeps) -} - -dependencies { - compileOnly "junit:junit:$junit_version" - compileOnly "org.junit.jupiter:junit-jupiter-api:$junit5_version" - testImplementation "org.junit.jupiter:junit-jupiter-engine:$junit5_version" - testImplementation "org.junit.platform:junit-platform-testkit:1.7.0" - shadowDeps "net.bytebuddy:byte-buddy:$byte_buddy_version" - shadowDeps "net.bytebuddy:byte-buddy-agent:$byte_buddy_version" - compileOnly "io.projectreactor.tools:blockhound:$blockhound_version" - testImplementation "io.projectreactor.tools:blockhound:$blockhound_version" - testImplementation "com.google.code.gson:gson:2.8.6" - api "net.java.dev.jna:jna:$jna_version" - api "net.java.dev.jna:jna-platform:$jna_version" -} - -java { - /* This is needed to be able to run JUnit5 tests. Otherwise, Gradle complains that it can't find the - JVM1.6-compatible version of the `junit-jupiter-api` artifact. */ - disableAutoTargetJvm() -} - -// This is required for BlockHound tests to work, see https://github.com/Kotlin/kotlinx.coroutines/issues/3701 -tasks.withType(Test).configureEach { - if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_13)) { - jvmArgs += ["-XX:+AllowRedefinitionToAddDeleteMethods"] - } -} - -jar { - setEnabled(false) -} - -def shadowJarTask = shadowJar { - classifier null - // Shadow only byte buddy, do not package kotlin stdlib - configurations = [project.configurations.shadowDeps] - relocate('net.bytebuddy', 'kotlinx.coroutines.repackaged.net.bytebuddy') - - manifest { - attributes "Premain-Class": "kotlinx.coroutines.debug.AgentPremain" - attributes "Can-Redefine-Classes": "true" - } -} - -configurations { - artifacts { - add("apiElements", shadowJarTask) - add("runtimeElements", shadowJarTask) - } -} - -koverReport { - filters { - excludes { - // Never used, safety mechanism - classes("kotlinx.coroutines.debug.internal.NoOpProbesKt") - } - } -} diff --git a/kotlinx-coroutines-debug/build.gradle.kts b/kotlinx-coroutines-debug/build.gradle.kts new file mode 100644 index 0000000000..ed8b918b8a --- /dev/null +++ b/kotlinx-coroutines-debug/build.gradle.kts @@ -0,0 +1,113 @@ +/* + * Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +import com.github.jengelman.gradle.plugins.shadow.tasks.* +import java.net.* +import java.nio.file.* + +plugins { + id("com.github.johnrengelman.shadow") + id("org.jetbrains.kotlinx.kover") // apply plugin to use autocomplete for Kover DSL +} + +configurations { + val shadowDeps by creating + compileOnly.configure { + extendsFrom(shadowDeps) + } + runtimeOnly.configure { + extendsFrom(shadowDeps) + } +} + +val junit_version by properties +val junit5_version by properties +val byte_buddy_version by properties +val blockhound_version by properties +val jna_version by properties + +dependencies { + compileOnly("junit:junit:$junit_version") + compileOnly("org.junit.jupiter:junit-jupiter-api:$junit5_version") + testImplementation("org.junit.jupiter:junit-jupiter-engine:$junit5_version") + testImplementation("org.junit.platform:junit-platform-testkit:1.7.0") + add("shadowDeps", "net.bytebuddy:byte-buddy:$byte_buddy_version") + add("shadowDeps", "net.bytebuddy:byte-buddy-agent:$byte_buddy_version") + compileOnly("io.projectreactor.tools:blockhound:$blockhound_version") + testImplementation("io.projectreactor.tools:blockhound:$blockhound_version") + testImplementation("com.google.code.gson:gson:2.8.6") + api("net.java.dev.jna:jna:$jna_version") + api("net.java.dev.jna:jna-platform:$jna_version") +} + +java { + /* This is needed to be able to run JUnit5 tests. Otherwise, Gradle complains that it can't find the + JVM1.6-compatible version of the `junit-jupiter-api` artifact. */ + disableAutoTargetJvm() +} + +// This is required for BlockHound tests to work, see https://github.com/Kotlin/kotlinx.coroutines/issues/3701 +tasks.withType().configureEach { + if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_13)) { + jvmArgs("-XX:+AllowRedefinitionToAddDeleteMethods") + } +} + +val jar by tasks.existing(Jar::class) { + enabled = false +} + +val shadowJar by tasks.existing(ShadowJar::class) { + // Shadow only byte buddy, do not package kotlin stdlib + configurations = listOf(project.configurations["shadowDeps"]) + relocate("net.bytebuddy", "kotlinx.coroutines.repackaged.net.bytebuddy") + /* These classifiers are both set to `null` to trick Gradle into thinking that this jar file is both the + artifact from the `jar` task and the one from `shadowJar`. Without this, Gradle complains that the artifact + from the `jar` task is not present when the compilaton finishes, even if the file with this name exists. */ + archiveClassifier.convention(null as String?) + archiveClassifier.set(null as String?) + archiveBaseName.set(jar.flatMap { it.archiveBaseName }) + archiveVersion.set(jar.flatMap { it.archiveVersion }) + manifest { + attributes( + mapOf( + "Premain-Class" to "kotlinx.coroutines.debug.AgentPremain", + "Can-Redefine-Classes" to "true", + "Multi-Release" to "true" + ) + ) + } + // add module-info.class to the META-INF/versions/9/ directory. + dependsOn(tasks.compileModuleInfoJava) + doLast { + // We can't do that directly with the shadowJar task because it doesn't support replacing existing files. + val zipPath = this@existing.outputs.files.singleFile.toPath() + val zipUri = URI.create("jar:${zipPath.toUri()}") + val moduleInfoFilePath = tasks.compileModuleInfoJava.get().outputs.files.asFileTree.matching { + include("module-info.class") + }.singleFile.toPath() + FileSystems.newFileSystem(zipUri, emptyMap()).use { fs -> + val moduleInfoFile = fs.getPath("META-INF/versions/9/module-info.class") + Files.copy(moduleInfoFilePath, moduleInfoFile, StandardCopyOption.REPLACE_EXISTING) + } + } +} + +configurations { + // shadowJar is already part of the `shadowRuntimeElements` and `shadowApiElements`, but the other subprojects + // that depend on `kotlinx-coroutines-debug` look at `runtimeElements` and `apiElements`. + artifacts { + add("apiElements", shadowJar) + add("runtimeElements", shadowJar) + } +} + +koverReport { + filters { + excludes { + // Never used, safety mechanism + classes("kotlinx.coroutines.debug.internal.NoOpProbesKt") + } + } +}