From 94013b1ff2bf72380126cf7d2782523009d943fc Mon Sep 17 00:00:00 2001 From: Yahor Berdnikau Date: Thu, 27 Jul 2023 19:56:04 +0200 Subject: [PATCH] [Gradle] Updated logic to add stdlib default dependency published with Gradle metadata Since Kotlin 1.9.20, Kotlin stdlib is published with Gradle metadata, which allows Gradle itself to select proper dependency subtypes. Now stdlib in MPP projects is only added to common dependencies. The default artifact for JVM was changed from 'kotlin-stdlib-jdk8' to 'kotlin-stdlib'. ^KT-59000 Fixed --- gradle/verification-metadata.xml | 1 + .../gradle/KotlinSpecificDependenciesIT.kt | 68 ++++++++++++++++++- .../jetbrains/kotlin/gradle/PublishingIT.kt | 2 +- .../internal/stdlibDependencyManagement.kt | 49 ++++++++++--- ...deJvmAndAndroidDependencyResolutionTest.kt | 2 - ...eOriginalMetadataDependencyResolverTest.kt | 2 +- .../tcs/IdeStdlibResolutionTest.kt | 4 +- .../tcs/WasmDependencyResolutionSmokeTest.kt | 4 +- 8 files changed, 110 insertions(+), 22 deletions(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index f12745e7188..7358f3ec36d 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -6,6 +6,7 @@ + diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt index 8b090396784..01f0ce4280c 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt @@ -16,6 +16,8 @@ import java.nio.file.Path import java.util.* import java.util.stream.Stream import kotlin.io.path.appendText +import kotlin.io.path.createDirectories +import kotlin.io.path.writeText import kotlin.streams.asStream import kotlin.streams.toList import kotlin.test.assertFalse @@ -30,7 +32,26 @@ class KotlinSpecificDependenciesIT : KGPBaseTest() { fun testStdlibByDefaultJvm(gradleVersion: GradleVersion) { project("simpleProject", gradleVersion) { removeDependencies(buildGradle) - checkTaskCompileClasspath("compileKotlin", listOf("kotlin-stdlib")) + checkTaskCompileClasspath("compileKotlin", listOf("kotlin-stdlib"), listOf("kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8")) + } + } + + @GradleTest + @DisplayName("JVM: add pre-1.9.20 kotlin-stdlib dependency") + @JvmGradlePluginTests + fun testStdlibByDefaultPre1920Jvm(gradleVersion: GradleVersion) { + project("simpleProject", gradleVersion) { + removeDependencies(buildGradle) + + buildGradle.appendText( + //language=groovy + """ + | + |kotlin.coreLibrariesVersion = "1.9.0" + """.trimMargin() + ) + + checkTaskCompileClasspath("compileKotlin", listOf("kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8")) } } @@ -115,7 +136,11 @@ class KotlinSpecificDependenciesIT : KGPBaseTest() { buildJdk = jdkVersion.location ) { removeDependencies(buildGradle) - checkTaskCompileClasspath("compileDebugKotlin", listOf("kotlin-stdlib")) + checkTaskCompileClasspath( + "compileDebugKotlin", + listOf("kotlin-stdlib"), + listOf("kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8") + ) } } @@ -216,6 +241,45 @@ class KotlinSpecificDependenciesIT : KGPBaseTest() { } } + @MppGradlePluginTests + @DisplayName("Stdlib should be added into compilation not depending on common") + @GradleTest + fun testStdlibAddedIntoCompilationNotUsingCommon(gradleVersion: GradleVersion) { + project("hierarchical-all-native", gradleVersion) { + buildGradleKts.modify { + it.substringBefore("kotlin {") + .plus( + """ + | + |kotlin { + | js() + | jvm("standalone") { + | compilations.register("jvmAllAlone") + | } + |} + """.trimMargin() + ) + } + + kotlinSourcesDir("standaloneJvmAllAlone").also { + it.createDirectories() + it.resolve("main.kt").writeText( + """ + |fun main() { + | println("Hello") + |} + """.trimIndent() + ) + } + + checkTaskCompileClasspath( + "compileJvmAllAloneKotlinStandalone", + listOf("kotlin-stdlib"), + isBuildGradleKts = true + ) + } + } + @JvmGradlePluginTests @DisplayName("KT-41642: adding stdlib should not resolve dependencies eagerly") @GradleTest diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/PublishingIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/PublishingIT.kt index 67d61baee6a..3994e34729f 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/PublishingIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/PublishingIT.kt @@ -106,7 +106,7 @@ class PublishingIT : KGPBaseTest() { ) { assertTasksExecuted(":compileKotlin", ":compileTestKotlin") val pomLines = projectPath.resolve("build/publications/myLibrary/pom-default.xml").readLines() - val stdlibVersionLineNumber = pomLines.indexOfFirst { "kotlin-stdlib-jdk8" in it } + 1 + val stdlibVersionLineNumber = pomLines.indexOfFirst { "kotlin-stdlib" in it } + 1 val versionLine = pomLines[stdlibVersionLineNumber] assertTrue { "${buildOptions.kotlinVersion}" in versionLine } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/stdlibDependencyManagement.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/stdlibDependencyManagement.kt index f34f475c17d..bb77b1d414a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/stdlibDependencyManagement.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/stdlibDependencyManagement.kt @@ -40,17 +40,27 @@ internal fun Project.configureStdlibDefaultDependency( ) { when (topLevelExtension) { is KotlinJsProjectExtension -> topLevelExtension.registerTargetObserver { target -> - target?.addStdlibDependency(configurations, dependencies, coreLibrariesVersion) + target?.addStdlibDependency( + configurations, + dependencies, + coreLibrariesVersion, + false, + ) } is KotlinSingleTargetExtension<*> -> topLevelExtension .target - .addStdlibDependency(configurations, dependencies, coreLibrariesVersion) + .addStdlibDependency( + configurations, + dependencies, + coreLibrariesVersion, + false + ) is KotlinMultiplatformExtension -> topLevelExtension .targets .configureEach { target -> - target.addStdlibDependency(configurations, dependencies, coreLibrariesVersion) + target.addStdlibDependency(configurations, dependencies, coreLibrariesVersion, true) } } } @@ -102,7 +112,8 @@ private fun Configuration.alignStdlibJvmVariantVersions( private fun KotlinTarget.addStdlibDependency( configurations: ConfigurationContainer, dependencies: DependencyHandler, - coreLibrariesVersion: Provider + coreLibrariesVersion: Provider, + isMppProject: Boolean, ) { compilations.configureEach { compilation -> compilation.allKotlinSourceSets.forEach { kotlinSourceSet -> @@ -122,9 +133,20 @@ private fun KotlinTarget.addStdlibDependency( // Check if stdlib is directly added to SourceSet if (isStdlibAddedByUser(configurations, stdlibModules, kotlinSourceSet)) return@withDependencies + val requestedStdlibVersion = coreLibrariesVersion.get() + val stdlibVersion = SemVer.fromGradleRichVersion(requestedStdlibVersion) + + // Since 1.9.20 in MPP projects, we should add stdlib only for common dependencies + // except standalone compilations which as not using 'common' + if (isMppProject && + stdlibVersion >= kotlin1920Version && + compilation.platformType != KotlinPlatformType.common && + kotlinSourceSet.hasDependencyOnCommon() + ) return@withDependencies + val stdlibModule = compilation .platformType - .stdlibPlatformType(this, kotlinSourceSet) + .stdlibPlatformType(this, kotlinSourceSet, stdlibVersion >= kotlin1920Version) ?: return@withDependencies // Check if stdlib module is added to SourceSets hierarchy @@ -146,6 +168,11 @@ private fun KotlinTarget.addStdlibDependency( } } +internal fun KotlinSourceSet.hasDependencyOnCommon(): Boolean = dependsOn + .any { sourceSet -> + sourceSet.internal.compilations.any { it.platformType == KotlinPlatformType.common } + } + internal fun isStdlibAddedByUser( configurations: ConfigurationContainer, stdlibModules: Set, @@ -166,29 +193,31 @@ internal fun isStdlibAddedByUser( internal fun KotlinPlatformType.stdlibPlatformType( kotlinTarget: KotlinTarget, - kotlinSourceSet: KotlinSourceSet + kotlinSourceSet: KotlinSourceSet, + isVersionWithGradleMetadata: Boolean ): String? = when (this) { - KotlinPlatformType.jvm -> KOTLIN_STDLIB_MODULE_NAME + KotlinPlatformType.jvm -> if (isVersionWithGradleMetadata) KOTLIN_STDLIB_MODULE_NAME else KOTLIN_STDLIB_JDK8_MODULE_NAME KotlinPlatformType.androidJvm -> { if (kotlinTarget is KotlinAndroidTarget && kotlinSourceSet.androidSourceSetInfoOrNull?.androidSourceSetName == AndroidBaseSourceSetName.Main.name ) { - KOTLIN_ANDROID_JVM_STDLIB_MODULE_NAME + if (isVersionWithGradleMetadata) KOTLIN_ANDROID_JVM_STDLIB_MODULE_NAME else KOTLIN_STDLIB_JDK8_MODULE_NAME } else { null } } - KotlinPlatformType.js -> KOTLIN_STDLIB_MODULE_NAME + KotlinPlatformType.js -> if (isVersionWithGradleMetadata) KOTLIN_STDLIB_MODULE_NAME else KOTLIN_STDLIB_JS_MODULE_NAME KotlinPlatformType.wasm -> KOTLIN_STDLIB_WASM_MODULE_NAME KotlinPlatformType.native -> null KotlinPlatformType.common -> // there's no platform compilation that the source set is default for - KOTLIN_STDLIB_MODULE_NAME + if (isVersionWithGradleMetadata) KOTLIN_STDLIB_MODULE_NAME else KOTLIN_STDLIB_COMMON_MODULE_NAME } private val androidTestVariants = setOf(AndroidVariantType.UnitTest, AndroidVariantType.InstrumentedTest) private val kotlin180Version = SemVer(1.toBigInteger(), 8.toBigInteger(), 0.toBigInteger()) +private val kotlin1920Version = SemVer(1.toBigInteger(), 9.toBigInteger(), 20.toBigInteger()) private fun KotlinSourceSet.isRelatedToAndroidTestSourceSet(): Boolean { val androidVariant = androidSourceSetInfoOrNull?.androidVariantType ?: return false diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeJvmAndAndroidDependencyResolutionTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeJvmAndAndroidDependencyResolutionTest.kt index b245a9766b1..be29ef0aec1 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeJvmAndAndroidDependencyResolutionTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeJvmAndAndroidDependencyResolutionTest.kt @@ -150,8 +150,6 @@ class IdeJvmAndAndroidDependencyResolutionTest { val stdlibVersion = project.getKotlinPluginVersion() val stdlibDependencies = listOf( binaryCoordinates("org.jetbrains.kotlin:kotlin-stdlib:${stdlibVersion}"), - binaryCoordinates("org.jetbrains.kotlin:kotlin-stdlib-jdk7:${stdlibVersion}"), - binaryCoordinates("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${stdlibVersion}"), binaryCoordinates("org.jetbrains:annotations:13.0"), ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeOriginalMetadataDependencyResolverTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeOriginalMetadataDependencyResolverTest.kt index 2d804420a24..00b0e064f8e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeOriginalMetadataDependencyResolverTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeOriginalMetadataDependencyResolverTest.kt @@ -44,7 +44,7 @@ class IdeOriginalMetadataDependencyResolverTest { for (sourceSet in stdlibCommonSourceSets) { IdeOriginalMetadataDependencyResolver.resolve(sourceSet).assertMatches( - binaryCoordinates("org.jetbrains.kotlin:kotlin-stdlib-common:${kotlin.coreLibrariesVersion}") + binaryCoordinates("org.jetbrains.kotlin:kotlin-stdlib:common:${kotlin.coreLibrariesVersion}") ) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeStdlibResolutionTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeStdlibResolutionTest.kt index 536fb0f8558..db93782a81c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeStdlibResolutionTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeStdlibResolutionTest.kt @@ -235,11 +235,9 @@ class IdeStdlibResolutionTest { } private fun commonStdlibDependency(kotlin: KotlinMultiplatformExtension) = - binaryCoordinates("org.jetbrains.kotlin:kotlin-stdlib:${kotlin.coreLibrariesVersion}:commonMain") + binaryCoordinates("org.jetbrains.kotlin:kotlin-stdlib:commonMain:${kotlin.coreLibrariesVersion}") private fun jvmStdlibDependencies(kotlin: KotlinMultiplatformExtension) = listOf( -// binaryCoordinates("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin.coreLibrariesVersion}"), -// binaryCoordinates("org.jetbrains.kotlin:kotlin-stdlib-jdk7:${kotlin.coreLibrariesVersion}"), binaryCoordinates("org.jetbrains.kotlin:kotlin-stdlib:${kotlin.coreLibrariesVersion}"), ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/WasmDependencyResolutionSmokeTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/WasmDependencyResolutionSmokeTest.kt index ef6072c197d..9847324cf00 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/WasmDependencyResolutionSmokeTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/WasmDependencyResolutionSmokeTest.kt @@ -56,13 +56,12 @@ class WasmDependencyResolutionSmokeTest { consumer.kotlinIdeMultiplatformImport.resolveDependencies("commonMain").assertMatches( regularSourceDependency(":producer/commonMain"), - binaryCoordinates(Regex(".*stdlib-common.*")) + binaryCoordinates(Regex(".*stdlib.*")) ) consumer.kotlinIdeMultiplatformImport.resolveDependencies("wasmJsMain").assertMatches( dependsOnDependency(":consumer/commonMain"), projectArtifactDependency(type = Regular, ":producer", FilePathRegex(".*/producer-wasm-js.klib")), - binaryCoordinates(Regex(".*stdlib-wasm.*")) ) consumer.kotlinIdeMultiplatformImport.resolveDependencies("wasmJsTest").assertMatches( @@ -70,7 +69,6 @@ class WasmDependencyResolutionSmokeTest { friendSourceDependency(":consumer/wasmJsMain"), dependsOnDependency(":consumer/commonTest"), projectArtifactDependency(type = Regular, ":producer", FilePathRegex(".*/producer-wasm-js.klib")), - binaryCoordinates(Regex(".*stdlib-wasm.*")) ) } }