From 46a92bed88a8437ec453e65bc322797e1cac25b6 Mon Sep 17 00:00:00 2001 From: Filipp Zhinkin Date: Mon, 10 Nov 2025 13:16:41 -0500 Subject: [PATCH] Generate unique Automatic-Module-Name for metadata JARs Fixes #2901 --- buildSrc/src/main/kotlin/Java9Modularity.kt | 24 +++++++++++++++++++++ core/build.gradle.kts | 2 ++ formats/cbor/build.gradle.kts | 2 ++ formats/json-io/build.gradle.kts | 4 ++-- formats/json-okio/build.gradle.kts | 4 ++-- formats/json/build.gradle.kts | 3 ++- formats/properties/build.gradle.kts | 2 ++ formats/protobuf/build.gradle.kts | 2 ++ 8 files changed, 38 insertions(+), 5 deletions(-) diff --git a/buildSrc/src/main/kotlin/Java9Modularity.kt b/buildSrc/src/main/kotlin/Java9Modularity.kt index abe933bb30..23b7434eb9 100644 --- a/buildSrc/src/main/kotlin/Java9Modularity.kt +++ b/buildSrc/src/main/kotlin/Java9Modularity.kt @@ -241,4 +241,28 @@ object Java9Modularity { ) }) } + + /** + * For multiplatform Gradle modules, generate and set `Automatic-Module-Name` in metadata JAR's manifest. + * + * Generated automatic (JPMS) module name has the following format: + * `. artifact_disambiguating_module`. + * + * For multiplatform projects, a metadata artifact is the one without a platform-specific suffix, + * and it always depends on corresponding `-jvm` artifact (for convenience on build systems other than Gradle). + * For a JVM project depending on such an artifact and using JPMS, it may result in the automatic module name clash + * with a module provided by the `-jvm` artifact. By explicitly setting a non-clashing automatic module name in + * metadata JAR's manifest, we're mitigating this issue. + */ + fun Project.configureMetadataJarAutomaticModuleName() { + val kotlin = extensions.findByType() ?: return + val moduleName = project.name.replace('-', '.') + ".artifact_disambiguating_module" + tasks.withType().named(kotlin.metadata().artifactsTaskName) { + manifest { + attributes( + "Automatic-Module-Name" to moduleName, + ) + } + } + } } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index b3d885ee26..ff75803aa7 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,4 +1,5 @@ import Java9Modularity.configureJava9ModuleInfo +import Java9Modularity.configureMetadataJarAutomaticModuleName import org.jetbrains.kotlin.gradle.targets.js.ir.* /* @@ -69,6 +70,7 @@ tasks.withType().named(kotlin.jvm().artifactsTaskName) { } configureJava9ModuleInfo() +configureMetadataJarAutomaticModuleName() tasks.withType().configureEach { compilerOptions.freeCompilerArgs.add("-Xwasm-enable-array-range-checks") diff --git a/formats/cbor/build.gradle.kts b/formats/cbor/build.gradle.kts index 5b3c7ff5eb..879040fef2 100644 --- a/formats/cbor/build.gradle.kts +++ b/formats/cbor/build.gradle.kts @@ -1,4 +1,5 @@ import Java9Modularity.configureJava9ModuleInfo +import Java9Modularity.configureMetadataJarAutomaticModuleName /* * Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. @@ -36,3 +37,4 @@ kotlin { } configureJava9ModuleInfo() +configureMetadataJarAutomaticModuleName() diff --git a/formats/json-io/build.gradle.kts b/formats/json-io/build.gradle.kts index 334241fa09..bf6d7b856c 100644 --- a/formats/json-io/build.gradle.kts +++ b/formats/json-io/build.gradle.kts @@ -2,8 +2,7 @@ * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ import Java9Modularity.configureJava9ModuleInfo -import org.jetbrains.dokka.gradle.* -import java.net.* +import Java9Modularity.configureMetadataJarAutomaticModuleName plugins { kotlin("multiplatform") @@ -32,6 +31,7 @@ kotlin { } project.configureJava9ModuleInfo() +project.configureMetadataJarAutomaticModuleName() dokka.dokkaSourceSets.configureEach { externalDocumentationLinks.register("kotlinx-io") { diff --git a/formats/json-okio/build.gradle.kts b/formats/json-okio/build.gradle.kts index 1d165755a9..40093bcedc 100644 --- a/formats/json-okio/build.gradle.kts +++ b/formats/json-okio/build.gradle.kts @@ -2,8 +2,7 @@ * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ import Java9Modularity.configureJava9ModuleInfo -import org.jetbrains.dokka.gradle.* -import java.net.* +import Java9Modularity.configureMetadataJarAutomaticModuleName plugins { kotlin("multiplatform") @@ -33,6 +32,7 @@ kotlin { } project.configureJava9ModuleInfo() +project.configureMetadataJarAutomaticModuleName() dokka.dokkaSourceSets.configureEach { externalDocumentationLinks.register("okio") { diff --git a/formats/json/build.gradle.kts b/formats/json/build.gradle.kts index 2ef589ac19..a2670894a2 100644 --- a/formats/json/build.gradle.kts +++ b/formats/json/build.gradle.kts @@ -1,5 +1,5 @@ import Java9Modularity.configureJava9ModuleInfo -import org.jetbrains.kotlin.gradle.tasks.* +import Java9Modularity.configureMetadataJarAutomaticModuleName /* * Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. @@ -53,3 +53,4 @@ kotlin { } configureJava9ModuleInfo() +configureMetadataJarAutomaticModuleName() diff --git a/formats/properties/build.gradle.kts b/formats/properties/build.gradle.kts index 20c8ea9c94..a2acc2e114 100644 --- a/formats/properties/build.gradle.kts +++ b/formats/properties/build.gradle.kts @@ -1,4 +1,5 @@ import Java9Modularity.configureJava9ModuleInfo +import Java9Modularity.configureMetadataJarAutomaticModuleName /* * Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. @@ -36,3 +37,4 @@ kotlin { } configureJava9ModuleInfo() +configureMetadataJarAutomaticModuleName() diff --git a/formats/protobuf/build.gradle.kts b/formats/protobuf/build.gradle.kts index b4692919fe..0fd4b87049 100644 --- a/formats/protobuf/build.gradle.kts +++ b/formats/protobuf/build.gradle.kts @@ -2,6 +2,7 @@ * Copyright 2017-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ import Java9Modularity.configureJava9ModuleInfo +import Java9Modularity.configureMetadataJarAutomaticModuleName plugins { kotlin("multiplatform") @@ -34,3 +35,4 @@ kotlin { } configureJava9ModuleInfo() +configureMetadataJarAutomaticModuleName()