[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>
<trust version="211.7442.40" file="ivy-211.7442.40.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=".*-sources[.]jar" regex="true"/>
<trust file=".*[.]module" regex="true"/>
@@ -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
@@ -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 { "<artifactId>kotlin-stdlib-jdk8</artifactId>" in it } + 1
val stdlibVersionLineNumber = pomLines.indexOfFirst { "<artifactId>kotlin-stdlib</artifactId>" in it } + 1
val versionLine = pomLines[stdlibVersionLineNumber]
assertTrue { "<version>${buildOptions.kotlinVersion}</version>" in versionLine }
}
@@ -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<String>
coreLibrariesVersion: Provider<String>,
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<String>,
@@ -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
@@ -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"),
)
@@ -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}")
)
}
}
@@ -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}"),
)
@@ -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.*"))
)
}
}