[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
This commit is contained in:
Yahor Berdnikau
2023-07-27 19:56:04 +02:00
committed by Space Team
parent 8154f7ab37
commit 94013b1ff2
8 changed files with 110 additions and 22 deletions
+1
View File
@@ -6,6 +6,7 @@
<trusted-artifacts> <trusted-artifacts>
<trust version="211.7442.40" file="ivy-211.7442.40.xml"/> <trust version="211.7442.40" file="ivy-211.7442.40.xml"/>
<trust version="212.4746.92" file="ivy-212.4746.92.xml"/> <trust version="212.4746.92" file="ivy-212.4746.92.xml"/>
<trust group="org.jetbrains.kotlin" name="kotlin-stdlib-common" version="1.4.0" reason="Cannot declare new component explicitly before bootstrap due to verification-metadata test considering it redundant"/>
<trust file=".*-javadoc[.]jar" regex="true"/> <trust file=".*-javadoc[.]jar" regex="true"/>
<trust file=".*-sources[.]jar" regex="true"/> <trust file=".*-sources[.]jar" regex="true"/>
<trust file=".*[.]module" regex="true"/> <trust file=".*[.]module" regex="true"/>
@@ -16,6 +16,8 @@ import java.nio.file.Path
import java.util.* import java.util.*
import java.util.stream.Stream import java.util.stream.Stream
import kotlin.io.path.appendText import kotlin.io.path.appendText
import kotlin.io.path.createDirectories
import kotlin.io.path.writeText
import kotlin.streams.asStream import kotlin.streams.asStream
import kotlin.streams.toList import kotlin.streams.toList
import kotlin.test.assertFalse import kotlin.test.assertFalse
@@ -30,7 +32,26 @@ class KotlinSpecificDependenciesIT : KGPBaseTest() {
fun testStdlibByDefaultJvm(gradleVersion: GradleVersion) { fun testStdlibByDefaultJvm(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) { project("simpleProject", gradleVersion) {
removeDependencies(buildGradle) 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 buildJdk = jdkVersion.location
) { ) {
removeDependencies(buildGradle) 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 @JvmGradlePluginTests
@DisplayName("KT-41642: adding stdlib should not resolve dependencies eagerly") @DisplayName("KT-41642: adding stdlib should not resolve dependencies eagerly")
@GradleTest @GradleTest
@@ -106,7 +106,7 @@ class PublishingIT : KGPBaseTest() {
) { ) {
assertTasksExecuted(":compileKotlin", ":compileTestKotlin") assertTasksExecuted(":compileKotlin", ":compileTestKotlin")
val pomLines = projectPath.resolve("build/publications/myLibrary/pom-default.xml").readLines() val pomLines = projectPath.resolve("build/publications/myLibrary/pom-default.xml").readLines()
val stdlibVersionLineNumber = pomLines.indexOfFirst { "<artifactId>kotlin-stdlib-jdk8</artifactId>" in it } + 1 val stdlibVersionLineNumber = pomLines.indexOfFirst { "<artifactId>kotlin-stdlib</artifactId>" in it } + 1
val versionLine = pomLines[stdlibVersionLineNumber] val versionLine = pomLines[stdlibVersionLineNumber]
assertTrue { "<version>${buildOptions.kotlinVersion}</version>" in versionLine } assertTrue { "<version>${buildOptions.kotlinVersion}</version>" in versionLine }
} }
@@ -40,17 +40,27 @@ internal fun Project.configureStdlibDefaultDependency(
) { ) {
when (topLevelExtension) { when (topLevelExtension) {
is KotlinJsProjectExtension -> topLevelExtension.registerTargetObserver { target -> is KotlinJsProjectExtension -> topLevelExtension.registerTargetObserver { target ->
target?.addStdlibDependency(configurations, dependencies, coreLibrariesVersion) target?.addStdlibDependency(
configurations,
dependencies,
coreLibrariesVersion,
false,
)
} }
is KotlinSingleTargetExtension<*> -> topLevelExtension is KotlinSingleTargetExtension<*> -> topLevelExtension
.target .target
.addStdlibDependency(configurations, dependencies, coreLibrariesVersion) .addStdlibDependency(
configurations,
dependencies,
coreLibrariesVersion,
false
)
is KotlinMultiplatformExtension -> topLevelExtension is KotlinMultiplatformExtension -> topLevelExtension
.targets .targets
.configureEach { target -> .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( private fun KotlinTarget.addStdlibDependency(
configurations: ConfigurationContainer, configurations: ConfigurationContainer,
dependencies: DependencyHandler, dependencies: DependencyHandler,
coreLibrariesVersion: Provider<String> coreLibrariesVersion: Provider<String>,
isMppProject: Boolean,
) { ) {
compilations.configureEach { compilation -> compilations.configureEach { compilation ->
compilation.allKotlinSourceSets.forEach { kotlinSourceSet -> compilation.allKotlinSourceSets.forEach { kotlinSourceSet ->
@@ -122,9 +133,20 @@ private fun KotlinTarget.addStdlibDependency(
// Check if stdlib is directly added to SourceSet // Check if stdlib is directly added to SourceSet
if (isStdlibAddedByUser(configurations, stdlibModules, kotlinSourceSet)) return@withDependencies 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 val stdlibModule = compilation
.platformType .platformType
.stdlibPlatformType(this, kotlinSourceSet) .stdlibPlatformType(this, kotlinSourceSet, stdlibVersion >= kotlin1920Version)
?: return@withDependencies ?: return@withDependencies
// Check if stdlib module is added to SourceSets hierarchy // 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( internal fun isStdlibAddedByUser(
configurations: ConfigurationContainer, configurations: ConfigurationContainer,
stdlibModules: Set<String>, stdlibModules: Set<String>,
@@ -166,29 +193,31 @@ internal fun isStdlibAddedByUser(
internal fun KotlinPlatformType.stdlibPlatformType( internal fun KotlinPlatformType.stdlibPlatformType(
kotlinTarget: KotlinTarget, kotlinTarget: KotlinTarget,
kotlinSourceSet: KotlinSourceSet kotlinSourceSet: KotlinSourceSet,
isVersionWithGradleMetadata: Boolean
): String? = when (this) { ): 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 -> { KotlinPlatformType.androidJvm -> {
if (kotlinTarget is KotlinAndroidTarget && if (kotlinTarget is KotlinAndroidTarget &&
kotlinSourceSet.androidSourceSetInfoOrNull?.androidSourceSetName == AndroidBaseSourceSetName.Main.name 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 { } else {
null 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.wasm -> KOTLIN_STDLIB_WASM_MODULE_NAME
KotlinPlatformType.native -> null KotlinPlatformType.native -> null
KotlinPlatformType.common -> // there's no platform compilation that the source set is default for 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 androidTestVariants = setOf(AndroidVariantType.UnitTest, AndroidVariantType.InstrumentedTest)
private val kotlin180Version = SemVer(1.toBigInteger(), 8.toBigInteger(), 0.toBigInteger()) 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 { private fun KotlinSourceSet.isRelatedToAndroidTestSourceSet(): Boolean {
val androidVariant = androidSourceSetInfoOrNull?.androidVariantType ?: return false val androidVariant = androidSourceSetInfoOrNull?.androidVariantType ?: return false
@@ -150,8 +150,6 @@ class IdeJvmAndAndroidDependencyResolutionTest {
val stdlibVersion = project.getKotlinPluginVersion() val stdlibVersion = project.getKotlinPluginVersion()
val stdlibDependencies = listOf( val stdlibDependencies = listOf(
binaryCoordinates("org.jetbrains.kotlin:kotlin-stdlib:${stdlibVersion}"), 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"), binaryCoordinates("org.jetbrains:annotations:13.0"),
) )
@@ -44,7 +44,7 @@ class IdeOriginalMetadataDependencyResolverTest {
for (sourceSet in stdlibCommonSourceSets) { for (sourceSet in stdlibCommonSourceSets) {
IdeOriginalMetadataDependencyResolver.resolve(sourceSet).assertMatches( IdeOriginalMetadataDependencyResolver.resolve(sourceSet).assertMatches(
binaryCoordinates("org.jetbrains.kotlin:kotlin-stdlib-common:${kotlin.coreLibrariesVersion}") binaryCoordinates("org.jetbrains.kotlin:kotlin-stdlib:common:${kotlin.coreLibrariesVersion}")
) )
} }
} }
@@ -235,11 +235,9 @@ class IdeStdlibResolutionTest {
} }
private fun commonStdlibDependency(kotlin: KotlinMultiplatformExtension) = 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( 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}"), binaryCoordinates("org.jetbrains.kotlin:kotlin-stdlib:${kotlin.coreLibrariesVersion}"),
) )
@@ -56,13 +56,12 @@ class WasmDependencyResolutionSmokeTest {
consumer.kotlinIdeMultiplatformImport.resolveDependencies("commonMain").assertMatches( consumer.kotlinIdeMultiplatformImport.resolveDependencies("commonMain").assertMatches(
regularSourceDependency(":producer/commonMain"), regularSourceDependency(":producer/commonMain"),
binaryCoordinates(Regex(".*stdlib-common.*")) binaryCoordinates(Regex(".*stdlib.*"))
) )
consumer.kotlinIdeMultiplatformImport.resolveDependencies("wasmJsMain").assertMatches( consumer.kotlinIdeMultiplatformImport.resolveDependencies("wasmJsMain").assertMatches(
dependsOnDependency(":consumer/commonMain"), dependsOnDependency(":consumer/commonMain"),
projectArtifactDependency(type = Regular, ":producer", FilePathRegex(".*/producer-wasm-js.klib")), projectArtifactDependency(type = Regular, ":producer", FilePathRegex(".*/producer-wasm-js.klib")),
binaryCoordinates(Regex(".*stdlib-wasm.*"))
) )
consumer.kotlinIdeMultiplatformImport.resolveDependencies("wasmJsTest").assertMatches( consumer.kotlinIdeMultiplatformImport.resolveDependencies("wasmJsTest").assertMatches(
@@ -70,7 +69,6 @@ class WasmDependencyResolutionSmokeTest {
friendSourceDependency(":consumer/wasmJsMain"), friendSourceDependency(":consumer/wasmJsMain"),
dependsOnDependency(":consumer/commonTest"), dependsOnDependency(":consumer/commonTest"),
projectArtifactDependency(type = Regular, ":producer", FilePathRegex(".*/producer-wasm-js.klib")), projectArtifactDependency(type = Regular, ":producer", FilePathRegex(".*/producer-wasm-js.klib")),
binaryCoordinates(Regex(".*stdlib-wasm.*"))
) )
} }
} }