Temp
diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt
index 6364478..25e0cac 100644
--- a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt
+++ b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt
@@ -56,9 +56,7 @@
/**
* Represents a compilation output compiled for the Wasm Kotlin platform.
*/
- wasm,
-
- unknown;
+ wasm;
/**
* @suppress
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts
index 75add62..b858447 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts
@@ -108,6 +108,7 @@
// AGP classes for buildScriptInjection's
testImplementation(libs.android.gradle.plugin.gradle.api) { isTransitive = false }
+ testImplementation(libs.android.gradle.plugin.gradle) { isTransitive = false }
testImplementation(project(path = ":examples:annotation-processor-example"))
testImplementation(kotlinStdlib("jdk8"))
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGenerateSourceSets.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGenerateSourceSets.kt
index 4c222f0..3770266 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGenerateSourceSets.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGenerateSourceSets.kt
@@ -5,8 +5,11 @@
package org.jetbrains.kotlin.gradle.testbase
+import org.intellij.lang.annotations.Language
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import java.io.Serializable
+import java.security.MessageDigest
+import java.util.Base64
data class SourceSetIdentifier(
val name: String,
@@ -45,4 +48,20 @@
}
}
)
+}
+
+fun KotlinSourceSet.compileSource(
+ @Language("kotlin")
+ sourceContent: String
+) {
+ val identifier = name
+ val identifierPath = project.layout.buildDirectory.dir("consume_${identifier}")
+ kotlin.srcDir(
+ project.tasks.create("consumeSourceIn_${identifier}") { task ->
+ task.outputs.dir(identifierPath)
+ task.doLast {
+ identifierPath.get().asFile.resolve("consumeSourceIn_${identifier}.kt").writeText(sourceContent)
+ }
+ }
+ )
}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGradleBuildInjection.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGradleBuildInjection.kt
index 84cafbf..44bd192 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGradleBuildInjection.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGradleBuildInjection.kt
@@ -109,11 +109,14 @@
* query anything from relevant tasks since they have executed. However, we have to disable CC, so that the returning closure can reach
* out for configuration entities.
*/
- fun buildAndReturn(evaluationTask: String = "tasks"): T {
+ fun buildAndReturn(
+ evaluationTask: String = "tasks",
+ deriveBuildOptions: TestProject.() -> BuildOptions = { buildOptions },
+ ): T {
gradleProject.build(
evaluationTask,
"-P${injectionLoadProperty}=true",
- buildOptions = gradleProject.buildOptions.copy(
+ buildOptions = gradleProject.deriveBuildOptions().copy(
configurationCache = BuildOptions.ConfigurationCacheValue.DISABLED,
)
)
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/uklibs/UklibConsumptionIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/uklibs/UklibConsumptionIT.kt
new file mode 100644
index 0000000..9aa442f
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/uklibs/UklibConsumptionIT.kt
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.gradle.uklibs
+
+import org.gradle.api.Project
+import org.gradle.api.artifacts.component.ModuleComponentIdentifier
+import org.gradle.api.file.Directory
+import org.gradle.api.initialization.resolve.RepositoriesMode
+import org.gradle.api.internal.GradleInternal
+import org.gradle.api.plugins.ExtraPropertiesExtension
+import org.gradle.api.publish.PublishingExtension
+import org.gradle.api.internal.project.*
+import org.gradle.util.GradleVersion
+import org.jetbrains.kotlin.gradle.artifacts.UklibResolutionStrategy
+import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
+import org.jetbrains.kotlin.gradle.internal.properties.nativeProperties
+import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
+import org.jetbrains.kotlin.gradle.testbase.*
+import org.jetbrains.kotlin.internal.compilerRunner.native.nativeCompilerClasspath
+import org.junit.jupiter.api.DisplayName
+import java.io.File
+import java.io.FileOutputStream
+import java.io.Serializable
+import java.net.URLClassLoader
+import kotlin.test.assertEquals
+import java.io.PrintStream
+
+@MppGradlePluginTests
+@DisplayName("Smoke test uklib consumption")
+class UklibConsumptionIT : KGPBaseTest() {
+
+ @GradleTestVersions
+ @GradleTest
+ fun `uklib consumption smoke - in kotlin compilations of a symmetric consumer and producer projects - with all metadata compilations`(
+ version: GradleVersion
+ ) {
+ val symmetricTargets: KotlinMultiplatformExtension.() -> Unit = @JvmSerializableLambda {
+ linuxArm64()
+ iosArm64()
+ iosX64()
+ jvm()
+ js()
+ wasmJs()
+ wasmWasi()
+ }
+ val publisher = publishUklib(version) @JvmSerializableLambda {
+ symmetricTargets()
+ sourceSets.all {
+ it.compileSource(
+ "object Producer_${it.name}"
+ )
+ }
+ }
+
+ val producerConsumerVisibility = mapOf(
+ "common" to listOf(
+ "Producer_commonMain",
+ ),
+ "native" to listOf(
+ "Producer_commonMain",
+ "Producer_nativeMain",
+ ),
+ "apple" to listOf(
+ "Producer_commonMain",
+ "Producer_nativeMain",
+ "Producer_appleMain",
+ ),
+ "ios" to listOf(
+ "Producer_commonMain",
+ "Producer_nativeMain",
+ "Producer_appleMain",
+ "Producer_iosMain"
+ ),
+ "linux" to listOf(
+ "Producer_commonMain",
+ "Producer_nativeMain",
+ "Producer_linuxMain",
+ ),
+ "jvm" to listOf(
+ "Producer_commonMain",
+ "Producer_jvmMain",
+ ),
+ "js" to listOf(
+ "Producer_commonMain",
+ "Producer_jsMain",
+ ),
+ "wasmJs" to listOf(
+ "Producer_commonMain",
+ "Producer_wasmJsMain",
+ ),
+ "wasmWasi" to listOf(
+ "Producer_commonMain",
+ "Producer_wasmWasiMain"
+ ),
+ "iosArm64" to listOf(
+ "Producer_commonMain",
+ "Producer_nativeMain",
+ "Producer_appleMain",
+ "Producer_iosArm64Main",
+ ),
+ "iosX64" to listOf(
+ "Producer_commonMain",
+ "Producer_nativeMain",
+ "Producer_appleMain",
+ "Producer_iosX64Main",
+ ),
+ "linuxArm64" to listOf(
+ "Producer_commonMain",
+ "Producer_nativeMain",
+ "Producer_linuxMain",
+ "Producer_linuxArm64Main",
+ ),
+ ).flatMap {
+ listOf(
+ it.key + "Main" to it.value,
+ it.key + "Test" to it.value,
+ )
+ }.toMap()
+
+ project(
+ "buildScriptInjectionGroovy",
+ version,
+ dependencyManagement = DependencyManagement.DefaultDependencyManagement(
+ gradleRepositoriesMode = RepositoriesMode.PREFER_PROJECT,
+ )
+ ) {
+ transferDependencyResolutionRepositoriesIntoProjectRepositories()
+ buildScriptInjection {
+ project.propertiesExtension.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_UKLIB_RESOLUTION_STRATEGY, UklibResolutionStrategy.AllowResolvingUklibs.propertyName)
+
+ project.plugins.apply("org.jetbrains.kotlin.multiplatform")
+
+ project.repositories.maven {
+ it.setUrl(publisher.repository)
+
+ // Prevent Gradle from reading Gradle metadata
+ it.metadataSources {
+ it.mavenPom()
+ it.ignoreGradleMetadataRedirection()
+ }
+ }
+
+ with(kotlinMultiplatform) {
+ symmetricTargets()
+
+ sourceSets.all {
+ val producerTypes = producerConsumerVisibility[it.name] ?: error("Missing producer declaration for ${it.name}")
+ val arguments = producerTypes.map { "${it}: ${it}" }.joinToString(", ")
+ it.compileSource(
+ """
+ fun consumeIn_${it.name}(${arguments}) {}
+ """.trimIndent()
+ )
+ }
+
+ sourceSets.commonMain.dependencies {
+ implementation("${publisher.group}:${publisher.name}:${publisher.version}")
+ }
+ }
+ }
+
+ // FIXME: Maybe just nuke Gradle metadata?
+ val resolvedProducerIosArm64Variant = buildScriptReturn {
+ (project.gradle as GradleInternal).services.get(ProjectStateRegistry::class.java).allowUncontrolledAccessToAnyProject {
+ val selectedVariant = kotlinMultiplatform.iosArm64().compilations.getByName("main")
+ .configurations.compileDependencyConfiguration
+ .incoming.artifacts.artifacts.single {
+ val identifier = (it.id.componentIdentifier as? ModuleComponentIdentifier) ?: return@single false
+ identifier.group == publisher.group
+ && identifier.module == publisher.name
+ && identifier.version == publisher.version
+ }.variant
+ selectedVariant.attributes.keySet().map {
+ it.toString() to selectedVariant.attributes.getAttribute(it).toString()
+ }.toMap()
+ }
+ }.buildAndReturn()
+
+ // Make sure that we are actually resolving uklib from metadataSources configuration
+ assertEquals(
+ resolvedProducerIosArm64Variant["uklibDestination"],
+ "ios_arm64",
+ )
+
+ // FIXME: Test metadata compilations
+ build("build")
+
+ data class KlibsToCheck(
+ val iosArm64Klib: File,
+ val commonMainKlib: File,
+ ) : Serializable
+
+ val klibs = buildScriptReturn {
+ KlibsToCheck(
+ kotlinMultiplatform.iosArm64().compilations.getByName("main").compileTaskProvider.flatMap { it.outputFile }.get(),
+ kotlinMultiplatform.metadata().compilations.getByName("commonMain").output.classesDirs.singleFile,
+ )
+ }.buildAndReturn()
+
+ assertEquals(
+ """
+ /consumeIn_appleMain|consumeIn_appleMain(Producer_commonMain;Producer_nativeMain;Producer_appleMain){}[0]
+ /consumeIn_commonMain|consumeIn_commonMain(Producer_commonMain){}[0]
+ /consumeIn_iosArm64Main|consumeIn_iosArm64Main(Producer_commonMain;Producer_nativeMain;Producer_appleMain;Producer_iosArm64Main){}[0]
+ /consumeIn_iosMain|consumeIn_iosMain(Producer_commonMain;Producer_nativeMain;Producer_appleMain;Producer_iosMain){}[0]
+ /consumeIn_nativeMain|consumeIn_nativeMain(Producer_commonMain;Producer_nativeMain){}[0]
+
+ """.trimIndent(),
+ dumpKlibMetadataSignatures(klibs.iosArm64Klib),
+ )
+
+ assertEquals(
+ """
+ /consumeIn_commonMain|consumeIn_commonMain(Producer_commonMain){}[0]
+
+ """.trimIndent(),
+ dumpKlibMetadataSignatures(klibs.commonMainKlib),
+ )
+ }
+ }
+
+ private fun TestProject.dumpKlibMetadataSignatures(klib: File): String {
+ val dumpName = "dump_${klib.name}"
+ // FIXME: This path is not actually unique
+ val outputFile = projectPath.resolve(dumpName).toFile()
+ outputFile.createNewFile()
+
+ buildScriptInjection {
+ project.tasks.register(dumpName) {
+ val inputs = project.objects.nativeCompilerClasspath(
+ project.nativeProperties.actualNativeHomeDirectory,
+ project.nativeProperties.shouldUseEmbeddableCompilerJar,
+ )
+ it.inputs.files(inputs)
+ val nativePath = project.nativeProperties.actualNativeHomeDirectory
+ it.doLast {
+ // FIXME: Why does App class loader loads compiler classes and why is this crutch needed ???
+ System.setProperty("kotlin.native.home", nativePath.get().path)
+ URLClassLoader(inputs.map { it.toURI().toURL() }.toTypedArray()).use { classLoader ->
+ val entryPoint = Class.forName("org.jetbrains.kotlin.cli.klib.Main", true, classLoader)
+ .declaredMethods
+ .single { it.name == "exec" }
+
+ val stdout = PrintStream(FileOutputStream(outputFile))
+ val stderr = System.err
+
+ val args: Array<String> = arrayOf(
+ "dump-metadata-signatures", klib.path,
+ "-test-mode", "true",
+ )
+
+ assert(entryPoint.invoke(null, stdout, stderr, args) as Int == 0)
+ }
+ }
+ }
+ }
+
+ build(dumpName)
+
+ return outputFile.readText()
+ }
+
+ data class PublisherProject(
+ val repository: File,
+ val group: String,
+ val name: String,
+ val version: String,
+ ) : Serializable
+
+ private fun publishUklib(
+ gradleVersion: GradleVersion,
+ publisherConfiguration: KotlinMultiplatformExtension.() -> Unit,
+ ): PublisherProject {
+ val publisherGroup = "foo"
+ val publisherVersion = "1.0"
+ val publisherName = "producer"
+ var publicationRepoPath: File? = null
+ project(
+ "buildScriptInjectionGroovy",
+ gradleVersion,
+ projectPathAdditionalSuffix = publisherName,
+ ) {
+ val publicationRepo: Project.() -> Directory = @JvmSerializableLambda { project.layout.projectDirectory.dir("repo") }
+ buildScriptInjection {
+ project.propertiesExtension.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_PUBLISH_UKLIB, true.toString())
+
+ project.plugins.apply("org.jetbrains.kotlin.multiplatform")
+ project.plugins.apply("maven-publish")
+
+ project.group = publisherGroup
+ project.version = publisherVersion
+
+ with(kotlinMultiplatform) {
+ publisherConfiguration()
+ }
+
+ val publishingExtension = project.extensions.getByType(PublishingExtension::class.java)
+ publishingExtension.repositories.maven {
+ it.url = project.uri(project.publicationRepo())
+ }
+ }
+
+ build("publishAllPublicationsToMavenRepository")
+
+ publicationRepoPath = buildScriptReturn {
+ project.publicationRepo().asFile
+ }.buildAndReturn()
+ }
+ return PublisherProject(
+ publicationRepoPath!!,
+ publisherGroup,
+ publisherName,
+ publisherVersion,
+ )
+ }
+}
+
+val Project.propertiesExtension: ExtraPropertiesExtension
+ get() = extensions.getByType(ExtraPropertiesExtension::class.java)
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/uklibs/UklibPublicationIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/uklibs/UklibPublicationIT.kt
new file mode 100644
index 0000000..4177af3
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/uklibs/UklibPublicationIT.kt
@@ -0,0 +1,351 @@
+/*
+ * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.gradle.uklibs
+
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.decodeFromStream
+import org.gradle.api.Project
+import org.gradle.api.file.Directory
+import org.gradle.api.publish.PublishingExtension
+import org.gradle.util.GradleVersion
+import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
+import org.jetbrains.kotlin.gradle.mpp.resources.unzip
+import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.*
+import org.jetbrains.kotlin.gradle.testbase.*
+import org.junit.jupiter.api.DisplayName
+import java.io.File
+import java.io.FileInputStream
+import java.io.Serializable
+import java.nio.file.Path
+import kotlin.io.path.createDirectory
+import kotlin.io.path.listDirectoryEntries
+import kotlin.io.path.name
+import kotlin.test.assertEquals
+import com.android.build.gradle.BaseExtension
+import org.gradle.api.NamedDomainObjectContainer
+import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
+import org.jetbrains.kotlin.gradle.dsl.HasConfigurableKotlinCompilerOptions
+import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
+import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions
+import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
+import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
+import org.jetbrains.kotlin.gradle.plugin.mpp.external.*
+
+@OptIn(ExternalKotlinTargetApi::class)
+@MppGradlePluginTests
+@DisplayName("Smoke test uklib artifact publication")
+class UklibPublicationIT : KGPBaseTest() {
+
+ @GradleTest
+ fun `uklib contents - produces expected umanifest, platform and metadata artifacts`(
+ gradleVersion: GradleVersion
+ ) {
+ val publisher = publishUklib(
+ gradleVersion = gradleVersion,
+ ) @JvmSerializableLambda {
+ linuxArm64()
+ linuxX64()
+ iosArm64()
+ iosX64()
+ jvm()
+ js()
+ wasmJs()
+ wasmWasi()
+ }
+
+ val expectedFragments = listOf(
+ Fragment(identifier="appleMain", targets=listOf("ios_arm64", "ios_x64")),
+ Fragment(identifier="commonMain", targets=listOf("ios_arm64", "ios_x64", "js_ir", "jvm", "linux_arm64", "linux_x64", "wasm_js", "wasm_wasi")),
+ Fragment(identifier="iosArm64Main", targets=listOf("ios_arm64")),
+ Fragment(identifier="iosMain", targets=listOf("ios_arm64", "ios_x64")),
+ Fragment(identifier="iosX64Main", targets=listOf("ios_x64")),
+ Fragment(identifier="jsMain", targets=listOf("js_ir")),
+ Fragment(identifier="jvmMain", targets=listOf("jvm")),
+ Fragment(identifier="linuxArm64Main", targets=listOf("linux_arm64")),
+ Fragment(identifier="linuxMain", targets=listOf("linux_arm64", "linux_x64")),
+ Fragment(identifier="linuxX64Main", targets=listOf("linux_x64")),
+ Fragment(identifier="nativeMain", targets=listOf("ios_arm64", "ios_x64", "linux_arm64", "linux_x64")),
+ Fragment(identifier="wasmJsMain", targets=listOf("wasm_js")),
+ Fragment(identifier="wasmWasiMain", targets=listOf("wasm_wasi")),
+ )
+
+ assertEquals(
+ Umanifest(expectedFragments),
+ publisher.umanifest,
+ )
+ assertEquals(
+ expectedFragments.map { it.identifier }.toSet(),
+ publisher.uklibContents.listDirectoryEntries().map {
+ it.name
+ }.filterNot { it == Uklib.UMANIFEST_FILE_NAME }.toSet(),
+ )
+ }
+
+ @GradleTest
+ fun `uklib contents - produces single platform fragment - when metadata compilations are redundant`(
+ gradleVersion: GradleVersion,
+ ) {
+ val publisher = publishUklib(
+ gradleVersion = gradleVersion
+ ) @JvmSerializableLambda {
+ iosArm64()
+ }
+
+ val expectedFragments = listOf(
+ Fragment(identifier="iosArm64Main", targets=listOf("ios_arm64")),
+ )
+
+ assertEquals(
+ Umanifest(expectedFragments),
+ publisher.umanifest,
+ )
+ assertEquals(
+ expectedFragments.map { it.identifier }.toSet(),
+ publisher.uklibContents.listDirectoryEntries().map {
+ it.name
+ }.filterNot { it == Uklib.UMANIFEST_FILE_NAME }.toSet(),
+ )
+ }
+
+ // FIXME: This should be an error or we need to introduce refines edges
+ @GradleTest
+ fun `uklib contents - bamboo metadata publication`(
+ gradleVersion: GradleVersion
+ ) {
+ val publisher = publishUklib(
+ gradleVersion = gradleVersion
+ ) @JvmSerializableLambda {
+ iosArm64()
+ iosX64()
+ }
+
+ val expectedFragments = listOf(
+ Fragment(identifier="appleMain", targets=listOf("ios_arm64", "ios_x64")),
+ Fragment(identifier="commonMain", targets=listOf("ios_arm64", "ios_x64")),
+ Fragment(identifier="iosArm64Main", targets=listOf("ios_arm64")),
+ Fragment(identifier="iosMain", targets=listOf("ios_arm64", "ios_x64")),
+ Fragment(identifier="iosX64Main", targets=listOf("ios_x64")),
+ Fragment(identifier="nativeMain", targets=listOf("ios_arm64", "ios_x64")),
+ )
+
+ assertEquals(
+ Umanifest(expectedFragments),
+ publisher.umanifest,
+ )
+ assertEquals(
+ expectedFragments.map { it.identifier }.toSet(),
+ publisher.uklibContents.listDirectoryEntries().map {
+ it.name
+ }.filterNot { it == Uklib.UMANIFEST_FILE_NAME }.toSet(),
+ )
+ }
+
+ @GradleAndroidTest
+ fun `uklib publication - with AGP`(
+ gradleVersion: GradleVersion,
+ agpVersion: String,
+ ) {
+ val publisher = publishUklib(
+ template = "buildScriptInjectionGroovyWithAGP",
+ gradleVersion = gradleVersion,
+ agpVersion = agpVersion,
+ ) @JvmSerializableLambda {
+ project.plugins.apply("com.android.library")
+ iosArm64()
+ androidTarget()
+
+ with(project.extensions.getByType(BaseExtension::class.java)) {
+ compileSdkVersion(23)
+ namespace = "kotlin.multiplatform.projects"
+ }
+ }
+
+ val expectedFragments = listOf(
+ Fragment(identifier="commonMain", targets=listOf("android", "ios_arm64")),
+ Fragment(identifier="iosArm64Main", targets=listOf("ios_arm64")),
+ )
+
+ assertEquals(
+ Umanifest(expectedFragments),
+ publisher.umanifest,
+ )
+ assertEquals(
+ expectedFragments.map { it.identifier }.toSet(),
+ publisher.uklibContents.listDirectoryEntries().map {
+ it.name
+ }.filterNot { it == Uklib.UMANIFEST_FILE_NAME }.toSet(),
+ )
+ }
+
+ // FIXME: Lift this to FT
+ @GradleTest
+ fun `uklib publication - with externalTarget`(
+ gradleVersion: GradleVersion
+ ) {
+ project(
+ "buildScriptInjectionGroovy",
+ gradleVersion,
+ ) {
+ val publicationRepo: Project.() -> Directory = @JvmSerializableLambda{ project.layout.projectDirectory.dir("repo") }
+ buildScriptInjection {
+ // FIXME: Enable cross compilation
+ project.propertiesExtension.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_PUBLISH_UKLIB, true.toString())
+
+ project.plugins.apply("org.jetbrains.kotlin.multiplatform")
+ project.plugins.apply("maven-publish")
+
+ project.group = "foo"
+ project.version = "1.0"
+
+ with(kotlinMultiplatform) {
+ class FakeCompilation(delegate: Delegate) : DecoratedExternalKotlinCompilation(delegate) {
+ @Suppress("UNCHECKED_CAST", "DEPRECATION")
+ override val compilerOptions: HasCompilerOptions<KotlinJvmCompilerOptions>
+ get() = super.compilerOptions as HasCompilerOptions<KotlinJvmCompilerOptions>
+ }
+
+ class FakeTarget(delegate: Delegate) : DecoratedExternalKotlinTarget(delegate),
+ HasConfigurableKotlinCompilerOptions<KotlinJvmCompilerOptions> {
+
+ @Suppress("UNCHECKED_CAST")
+ override val compilations: NamedDomainObjectContainer<FakeCompilation>
+ get() = super.compilations as NamedDomainObjectContainer<FakeCompilation>
+
+ override val compilerOptions: KotlinJvmCompilerOptions
+ get() = super.compilerOptions as KotlinJvmCompilerOptions
+ }
+
+ fun ExternalKotlinTargetDescriptorBuilder<FakeTarget>.defaults() {
+ targetName = "fake"
+ platformType = KotlinPlatformType.jvm
+ targetFactory = ExternalKotlinTargetDescriptor.TargetFactory(::FakeTarget)
+ }
+
+ fun ExternalKotlinCompilationDescriptorBuilder<FakeCompilation>.defaults(
+ kotlin: KotlinMultiplatformExtension,
+ name: String = KotlinCompilation.MAIN_COMPILATION_NAME,
+ ) {
+ compilationName = name
+ compilationFactory = ExternalKotlinCompilationDescriptor.CompilationFactory(::FakeCompilation)
+ defaultSourceSet = kotlin.sourceSets.maybeCreate(name)
+ }
+
+ iosArm64()
+ iosX64()
+ val kotlin = this
+ createExternalKotlinTarget {
+ defaults()
+ }.createCompilation { defaults(kotlin) }
+
+ sourceSets.all {
+ it.addIdentifierClass(SourceSetIdentifier(it.name))
+ }
+ }
+
+ val publishingExtension = project.extensions.getByType(PublishingExtension::class.java)
+ publishingExtension.repositories.maven {
+ it.url = project.uri(project.publicationRepo())
+ }
+ }
+
+ buildAndFail("publishAllPublicationsToMavenRepository") {
+ assertOutputContains("FIXME: This is explicitly unsupported")
+ }
+ }
+ }
+
+ @kotlinx.serialization.Serializable
+ data class Fragment(
+ val identifier: String,
+ val targets: List<String>,
+ )
+ @kotlinx.serialization.Serializable
+ data class Umanifest(
+ val fragments: List<Fragment>,
+ )
+
+ data class UklibProducer(
+ val uklibContents: Path,
+ val umanifest: Umanifest,
+ ) : Serializable
+
+ private fun publishUklib(
+ template: String = "buildScriptInjectionGroovy",
+ gradleVersion: GradleVersion,
+ agpVersion: String? = null,
+ publisherConfiguration: KotlinMultiplatformExtension.() -> Unit,
+ ): UklibProducer {
+ val publisherGroup = "foo"
+ val publisherVersion = "1.0"
+ val publisherName = "producer"
+ var repository: File? = null
+ project(
+ template,
+ gradleVersion,
+ projectPathAdditionalSuffix = publisherName,
+ ) {
+ val publicationRepo: Project.() -> Directory = @JvmSerializableLambda{ project.layout.projectDirectory.dir("repo") }
+ buildScriptInjection {
+ // FIXME: Enable cross compilation
+ project.propertiesExtension.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_PUBLISH_UKLIB, true.toString())
+
+ project.plugins.apply("org.jetbrains.kotlin.multiplatform")
+ project.plugins.apply("maven-publish")
+
+ project.group = publisherGroup
+ project.version = publisherVersion
+
+ with(kotlinMultiplatform) {
+ // Add a source to all source sets
+ publisherConfiguration()
+
+ sourceSets.all {
+ it.addIdentifierClass(SourceSetIdentifier(it.name))
+ }
+ }
+
+ val publishingExtension = project.extensions.getByType(PublishingExtension::class.java)
+ publishingExtension.repositories.maven {
+ it.url = project.uri(project.publicationRepo())
+ }
+ }
+
+ build(
+ "publishAllPublicationsToMavenRepository",
+ buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion),
+ )
+
+ repository = buildScriptReturn {
+ project.publicationRepo().asFile
+ }.buildAndReturn(
+ deriveBuildOptions = { defaultBuildOptions.copy(androidVersion = agpVersion) }
+ )
+ }
+
+ val uklibPath = repository!!
+ .resolve(publisherGroup).resolve(publisherName).resolve(publisherVersion)
+ .resolve("${publisherName}-${publisherVersion}.uklib").toPath()
+
+ assertFileExists(uklibPath)
+
+ val uklibContents = repository!!.resolve("uklibContents").toPath()
+ uklibContents.createDirectory()
+ unzip(
+ uklibPath,
+ uklibContents,
+ ""
+ )
+
+ return UklibProducer(
+ uklibContents = uklibContents,
+ umanifest = Json.decodeFromStream<Umanifest>(
+ FileInputStream(uklibContents.resolve("umanifest").toFile())
+ )
+ )
+ }
+
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/gradleRunningUtils.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/gradleRunningUtils.kt
index e682538..a65373a 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/gradleRunningUtils.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/gradleRunningUtils.kt
@@ -9,7 +9,7 @@
class ProcessRunResult(
private val cmd: List<String>,
- private val workingDir: File,
+ private val workingDir: File?,
val exitCode: Int,
val output: String,
val stdErr: String,
@@ -20,20 +20,22 @@
override fun toString(): String = """
Executing process was ${if (isSuccessful) "successful" else "unsuccessful"}
Command: ${cmd.joinToString()}
- Working directory: ${workingDir.absolutePath}
+ Working directory: ${workingDir?.absolutePath}
Exit code: $exitCode
"""
}
fun runProcess(
cmd: List<String>,
- workingDir: File,
+ workingDir: File?,
environmentVariables: Map<String, String> = mapOf(),
redirectErrorStream: Boolean = true,
): ProcessRunResult {
val builder = ProcessBuilder(cmd)
builder.environment().putAll(environmentVariables)
- builder.directory(workingDir)
+ workingDir?.let {
+ builder.directory(it)
+ }
// redirectErrorStream merges stdout and stderr, so it can be gotten from process.inputStream
builder.redirectErrorStream(redirectErrorStream)
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/buildScriptInjectionGroovyWithAGP/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/buildScriptInjectionGroovyWithAGP/build.gradle
new file mode 100644
index 0000000..ab3f872
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/buildScriptInjectionGroovyWithAGP/build.gradle
@@ -0,0 +1,4 @@
+plugins {
+ id("org.jetbrains.kotlin.multiplatform") apply false
+ id("com.android.library") apply false
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/build.gradle.kts
new file mode 100644
index 0000000..7bb3986
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/build.gradle.kts
@@ -0,0 +1,4 @@
+plugins {
+ kotlin("multiplatform")
+ `maven-publish`
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/gradle.properties b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/gradle.properties
new file mode 100644
index 0000000..9ca8278
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/gradle.properties
@@ -0,0 +1 @@
+kotlin.mpp.enableUklibs=true
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/appleMain/kotlin/Apple.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/appleMain/kotlin/Apple.kt
new file mode 100644
index 0000000..7ee6903
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/appleMain/kotlin/Apple.kt
@@ -0,0 +1,2 @@
+class Apple {
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/commonMain/kotlin/Common.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/commonMain/kotlin/Common.kt
new file mode 100644
index 0000000..c86db65
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/commonMain/kotlin/Common.kt
@@ -0,0 +1,2 @@
+class Common {
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/linuxMain/kotlin/Linux.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/linuxMain/kotlin/Linux.kt
new file mode 100644
index 0000000..0ab4450
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/linuxMain/kotlin/Linux.kt
@@ -0,0 +1,2 @@
+class Linux {
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin/build.gradle.kts
index ff587bb..26b8d22 100644
--- a/libraries/tools/kotlin-gradle-plugin/build.gradle.kts
+++ b/libraries/tools/kotlin-gradle-plugin/build.gradle.kts
@@ -214,6 +214,7 @@
testImplementation(project(":kotlin-gradle-statistics"))
testImplementation(project(":kotlin-tooling-metadata"))
testImplementation(libs.lincheck)
+ testImplementation(commonDependency("org.jetbrains.kotlin:kotlin-reflect")) { isTransitive = false }
}
configurations.commonCompileClasspath.get().exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-core")
@@ -293,58 +294,58 @@
*/
pivotVersion = KotlinMetadataPivotVersion(1, 6, 0)
}
- asmDeprecation {
- val exclusions = listOf(
- "org.jetbrains.kotlin.gradle.**", // part of the plugin
- "org.jetbrains.kotlin.project.model.**", // part of the plugin
- "org.jetbrains.kotlin.statistics.**", // part of the plugin
- "org.jetbrains.kotlin.tooling.**", // part of the plugin
- "org.jetbrains.kotlin.org.**", // already shadowed dependencies
- "org.jetbrains.kotlin.com.**", // already shadowed dependencies
- "org.jetbrains.kotlin.it.unimi.**", // already shadowed dependencies
- "org.jetbrains.kotlin.internal.**", // already internal package
- )
- val deprecationMessage = """
- You're using a Kotlin compiler class bundled into KGP for its internal needs.
- This is discouraged and will not be supported in future releases.
- The class in this artifact is scheduled for removal in Kotlin 2.2. Please define dependency on it in an alternative way.
- See https://kotl.in/gradle/internal-compiler-symbols for more details
- """.trimIndent()
- deprecateClassesByPattern("org.jetbrains.kotlin.**", deprecationMessage, exclusions)
- }
+// asmDeprecation {
+// val exclusions = listOf(
+// "org.jetbrains.kotlin.gradle.**", // part of the plugin
+// "org.jetbrains.kotlin.project.model.**", // part of the plugin
+// "org.jetbrains.kotlin.statistics.**", // part of the plugin
+// "org.jetbrains.kotlin.tooling.**", // part of the plugin
+// "org.jetbrains.kotlin.org.**", // already shadowed dependencies
+// "org.jetbrains.kotlin.com.**", // already shadowed dependencies
+// "org.jetbrains.kotlin.it.unimi.**", // already shadowed dependencies
+// "org.jetbrains.kotlin.internal.**", // already internal package
+// )
+// val deprecationMessage = """
+// You're using a Kotlin compiler class bundled into KGP for its internal needs.
+// This is discouraged and will not be supported in future releases.
+// The class in this artifact is scheduled for removal in Kotlin 2.2. Please define dependency on it in an alternative way.
+// See https://kotl.in/gradle/internal-compiler-symbols for more details
+// """.trimIndent()
+// deprecateClassesByPattern("org.jetbrains.kotlin.**", deprecationMessage, exclusions)
+// }
}
- GradlePluginVariant.values().forEach { variant ->
- if (kotlinBuildProperties.isInJpsBuildIdeaSync) return@forEach
- val sourceSet = sourceSets.getByName(variant.sourceSetName)
- val taskSuffix = sourceSet.jarTaskName.capitalize()
- val shadowJarTaskName = "$EMBEDDABLE_COMPILER_TASK_NAME$taskSuffix"
- asmDeprecation {
- val dumpTask = registerDumpDeprecationsTask(shadowJarTaskName, taskSuffix)
- val dumpAllTask = getOrCreateTask<Task>("dumpDeprecations") {
- dependsOn(dumpTask)
- }
- val expectedFileDoesNotExistMessage = """
- The file with expected deprecations for the compiler modules bundled into KGP does not exist.
- Run ./gradlew ${project.path}:${dumpTask.name} first to create it.
- You may also use ./gradlew ${project.path}:${dumpAllTask.name} to dump deprecations of all fat jars.
- Context: https://youtrack.jetbrains.com/issue/KT-70251
- """.trimIndent()
- val checkFailureMessage = """
- Expected deprecations applied to the compiler modules bundled into KGP does not match with the actually applied ones.
- Run ./gradlew ${project.path}:${dumpTask.name} to see the difference.
- You may also use ./gradlew ${project.path}:${dumpAllTask.name} to dump deprecations of all fat jars.
- Use INFO level log for the exact deprecated classes set.
- Either commit the difference or adjust the package relocation rules in ${buildFile.absolutePath}
- Please be sure to leave a comment explaining any changes related to this failure clear enough.
- Context: https://youtrack.jetbrains.com/issue/KT-70251
- """.trimIndent()
- val checkTask =
- registerCheckDeprecationsTask(shadowJarTaskName, taskSuffix, expectedFileDoesNotExistMessage, checkFailureMessage)
- named("check") {
- dependsOn(checkTask)
- }
- }
- }
+// GradlePluginVariant.values().forEach {
+// if (kotlinBuildProperties.isInJpsBuildIdeaSync) return@forEach
+// val sourceSet = sourceSets.getByName(variant.sourceSetName)
+// val taskSuffix = sourceSet.jarTaskName.capitalize()
+// val shadowJarTaskName = "$EMBEDDABLE_COMPILER_TASK_NAME$taskSuffix"
+// asmDeprecation {
+// val dumpTask = registerDumpDeprecationsTask(shadowJarTaskName, taskSuffix)
+// val dumpAllTask = getOrCreateTask<Task>("dumpDeprecations") {
+// dependsOn(dumpTask)
+// }
+// val expectedFileDoesNotExistMessage = """
+// The file with expected deprecations for the compiler modules bundled into KGP does not exist.
+// Run ./gradlew ${project.path}:${dumpTask.name} first to create it.
+// You may also use ./gradlew ${project.path}:${dumpAllTask.name} to dump deprecations of all fat jars.
+// Context: https://youtrack.jetbrains.com/issue/KT-70251
+// """.trimIndent()
+// val checkFailureMessage = """
+// Expected deprecations applied to the compiler modules bundled into KGP does not match with the actually applied ones.
+// Run ./gradlew ${project.path}:${dumpTask.name} to see the difference.
+// You may also use ./gradlew ${project.path}:${dumpAllTask.name} to dump deprecations of all fat jars.
+// Use INFO level log for the exact deprecated classes set.
+// Either commit the difference or adjust the package relocation rules in ${buildFile.absolutePath}
+// Please be sure to leave a comment explaining any changes related to this failure clear enough.
+// Context: https://youtrack.jetbrains.com/issue/KT-70251
+// """.trimIndent()
+// val checkTask =
+// registerCheckDeprecationsTask(shadowJarTaskName, taskSuffix, expectedFileDoesNotExistMessage, checkFailureMessage)
+// named("check") {
+// dependsOn(checkTask)
+// }
+// }
+// }
}
tasks.named("validatePlugins") {
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinMetadataArtifact.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinMetadataArtifact.kt
index 09d480f2..4b456b7 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinMetadataArtifact.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinMetadataArtifact.kt
@@ -5,12 +5,19 @@
package org.jetbrains.kotlin.gradle.artifacts
+import org.gradle.api.Project
import org.gradle.api.artifacts.type.ArtifactTypeDefinition.JAR_TYPE
import org.gradle.api.attributes.Category
import org.gradle.api.attributes.Usage
+import org.gradle.api.file.FileCollection
+import org.jetbrains.kotlin.gradle.artifacts.uklibsPublication.UklibFragmentPlatformAttribute
+import org.jetbrains.kotlin.gradle.artifacts.uklibsPublication.uklibFragmentPlatformAttribute
+import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.categoryByName
import org.jetbrains.kotlin.gradle.plugin.mpp.*
+import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.plugin.usageByName
+import org.jetbrains.kotlin.gradle.targets.metadata.awaitMetadataCompilationsCreated
import org.jetbrains.kotlin.gradle.targets.metadata.isCompatibilityMetadataVariantEnabled
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
import org.jetbrains.kotlin.gradle.targets.metadata.locateOrRegisterGenerateProjectStructureMetadataTask
@@ -40,13 +47,12 @@
/* Include output of metadata compilations into metadata jar (including commonizer output if available */
val hostSpecificSourceSets = getHostSpecificSourceSets(target.project)
- target.compilations.all { compilation ->
- /* Filter legacy compilation */
- if (compilation is KotlinCommonCompilation && !compilation.isKlibCompilation) return@all
+ // FIXME: How are test compilations filtered out ????
+ target.publishedMetadataCompilations().filter {
/* Filter 'host specific' source sets (aka source sets that require a certain host to compile metadata) */
- if (compilation.defaultSourceSet in hostSpecificSourceSets) return@all
-
- metadataJarTask.configure { it.from(compilation.output.classesDirs) { spec -> spec.into(compilation.defaultSourceSet.name) } }
+ it.defaultSourceSet !in hostSpecificSourceSets
+ }.forEach { compilation ->
+ metadataJarTask.configure { it.from(compilation.metadataPublishedArtifacts) { spec -> spec.into(compilation.metadataFragmentIdentifier) } }
if (compilation is KotlinSharedNativeCompilation) {
target.project.includeCommonizedCInteropMetadata(metadataJarTask, compilation)
}
@@ -54,3 +60,18 @@
target.createPublishArtifact(metadataJarTask, JAR_TYPE, apiElements)
}
+
+internal suspend fun KotlinMetadataTarget.publishedMetadataCompilations(): List<KotlinCompilation<*>> {
+ return awaitMetadataCompilationsCreated().filter { compilation ->
+ /* Filter legacy compilation */
+ !(compilation is KotlinCommonCompilation && !compilation.isKlibCompilation)
+ }
+}
+
+internal val KotlinCompilation<*>.metadataPublishedArtifacts: FileCollection get() = output.classesDirs
+// FIXME: Use this everywhere we map between fragment name in PSM and the name of disk
+internal val KotlinCompilation<*>.metadataFragmentIdentifier: String get() = defaultSourceSet.name
+internal val KotlinCompilation<*>.metadataFragmentAttributes: Set<UklibFragmentPlatformAttribute> get() = defaultSourceSet.internal.compilations
+ .filterNot {
+ it is KotlinMetadataCompilation
+ }.map { it.uklibFragmentPlatformAttribute }.toSet()
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinNativeKlibArtifact.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinNativeKlibArtifact.kt
index 415f2eb..199dc82 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinNativeKlibArtifact.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinNativeKlibArtifact.kt
@@ -95,6 +95,7 @@
} else {
klibProducingTask.flatMap { it.klibFile }
}
+ // FIXME: Что такое DefaultArtifactPublicationSet?
with(compilation.project.configurations.getByName(apiElementsName)) {
outgoing.registerKlibArtifact(packedArtifactFile, compilation.compilationName, classifier)
attributes.setAttribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, NativeArtifactFormat.KLIB) // should we do it here?
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinUklibConsumptionSetupAction.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinUklibConsumptionSetupAction.kt
index 3972652..0b9541d 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinUklibConsumptionSetupAction.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinUklibConsumptionSetupAction.kt
@@ -5,202 +5,142 @@
package org.jetbrains.kotlin.gradle.artifacts
+import org.gradle.api.NamedDomainObjectCollection
+import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.artifacts.transform.InputArtifact
import org.gradle.api.artifacts.transform.TransformAction
import org.gradle.api.artifacts.transform.TransformOutputs
import org.gradle.api.artifacts.transform.TransformParameters
import org.gradle.api.attributes.*
-import org.gradle.api.attributes.java.TargetJvmEnvironment
import org.gradle.api.file.*
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
-import org.gradle.api.provider.SetProperty
import org.gradle.api.tasks.Input
-import org.jetbrains.kotlin.*
-import org.jetbrains.kotlin.gradle.artifacts.uklibsPublication.setupPublication
-import org.jetbrains.kotlin.gradle.dsl.awaitMetadataTarget
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Uklib
+import org.jetbrains.kotlin.gradle.artifacts.uklibsPublication.uklibFragmentPlatformAttribute
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterFinaliseCompilations
-import org.jetbrains.kotlin.gradle.plugin.KotlinProjectSetupAction
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
-import org.jetbrains.kotlin.gradle.plugin.attributes.KlibPackaging
-import org.jetbrains.kotlin.gradle.plugin.await
-import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
-import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnostic
-import org.jetbrains.kotlin.gradle.plugin.launch
import org.jetbrains.kotlin.gradle.plugin.mpp.*
-import org.jetbrains.kotlin.gradle.plugin.mpp.publishing.configureResourcesPublicationAttributes
import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
+import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import org.jetbrains.kotlin.gradle.utils.named
import org.jetbrains.kotlin.gradle.utils.setAttribute
import javax.inject.Inject
-private val artifactType: Attribute<String> get() = Attribute.of("artifactType", String::class.java)
-private val uklibArtifactType: String get() = "uklib"
-private val uklibUnzippedArtifactType: String get() = "uklib-unzipped"
-
internal val KotlinUklibConsumptionSetupAction = KotlinProjectSetupAction {
-
- if (project.kotlinPropertiesProvider.publishUklibVariant) {
- project.launch {
- setupPublication()
- }
- }
-
when (project.kotlinPropertiesProvider.uklibResolutionStrategy) {
- UklibResolutionStrategy.PreferUklibVariant,
- UklibResolutionStrategy.PreferPlatformSpecificVariant -> project.launch { setupConsumption() }
+ UklibResolutionStrategy.AllowResolvingUklibs -> project.launch { setupUklibConsumption() }
UklibResolutionStrategy.ResolveOnlyPlatformSpecificVariant -> { /* do nothing */ }
}
}
-val uklibStateAttribute = Attribute.of("uklibState", String::class.java)
-val uklibStateZipped = "zipped"
-val uklibStateUnzipped = "unzipped"
+internal val uklibStateAttribute = Attribute.of("uklibState", String::class.java)
+internal val uklibStateZipped = "zipped"
+internal val uklibStateUnzipped = "unzipped"
-val uklibPlatformAttribute = Attribute.of("uklibPlatform", String::class.java)
-val uklibPlatformUnknown = "unknown"
-val uklibNativeSliceAttribute = Attribute.of("uklibNativeSlice", String::class.java)
-val uklibNativeSliceUnknown = "unknown"
+internal val uklibDestinationAttribute = Attribute.of("uklibDestination", String::class.java)
+internal val uklibDestinationUnknown = "unknown"
-private suspend fun Project.setupConsumption() {
+/**
+ * Resolve Uklib artifacts using transforms:
+ * - Request a known [uklibDestinationAttribute] in all resolvable configurations that should be able to resolve uklibs
+ * - Register transform "zipped -> unzipped uklib"
+ * - Register transform "unzipped uklib -> [uklibDestinationAttribute]"
+ */
+private suspend fun Project.setupUklibConsumption() {
val sourceSets = multiplatformExtension.awaitSourceSets()
- val metadataTarget = multiplatformExtension.awaitMetadataTarget()
val targets = multiplatformExtension.awaitTargets()
AfterFinaliseCompilations.await()
- sourceSets.configureEach {
- with(it.internal.resolvableMetadataConfiguration) {
- attributes {
- when (project.kotlinPropertiesProvider.uklibResolutionStrategy) {
- UklibResolutionStrategy.PreferUklibVariant -> it.attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_UKLIB))
- UklibResolutionStrategy.PreferPlatformSpecificVariant -> {
- /* rely on the default + compatibility rule */
- }
- }
- it.attribute(uklibStateAttribute, uklibStateUnzipped)
- it.attribute(uklibPlatformAttribute, KotlinPlatformType.common.name)
- }
- }
- }
- // FIXME: Drop this transform and use the unzip transform instead
- dependencies.registerTransform(UnzippedUklibToMetadataCompilationTransform::class.java) {
- it.from
- .attribute(uklibStateAttribute, uklibStateUnzipped)
- .attribute(uklibPlatformAttribute, uklibPlatformUnknown)
- it.to
- .attribute(uklibStateAttribute, uklibStateUnzipped)
- .attribute(uklibPlatformAttribute, KotlinPlatformType.common.name)
- }
+ registerZippedUklibArtifact()
+ allowUklibsToUnzip()
+ allowMetadataConfigurationsToResolveUnzippedUklib(sourceSets)
+ allowPlatformCompilationsToResolvePlatformCompilationArtifactFromUklib(targets)
+}
+private fun Project.allowPlatformCompilationsToResolvePlatformCompilationArtifactFromUklib(
+ targets: NamedDomainObjectCollection<KotlinTarget>
+) {
targets.configureEach { target ->
- if (target is KotlinMetadataTarget) return@configureEach
- if (target is KotlinNativeTarget) {
- dependencies.registerTransform(UnzippedUklibToPlatformCompilationTransform::class.java) {
- it.from
- .attribute(uklibStateAttribute, uklibStateUnzipped)
- .attribute(uklibPlatformAttribute, uklibPlatformUnknown)
- .attribute(uklibNativeSliceAttribute, uklibNativeSliceUnknown)
- it.to
- .attribute(uklibStateAttribute, uklibStateUnzipped)
- .attribute(uklibPlatformAttribute, target.platformType.name)
- .attribute(uklibNativeSliceAttribute, target.targetName)
+ val destinationAttribute = when (target) {
+ is KotlinNativeTarget -> target.uklibFragmentPlatformAttribute
+ is KotlinJsIrTarget -> target.uklibFragmentPlatformAttribute
+ is KotlinJvmTarget -> target.uklibFragmentPlatformAttribute
+ else -> return@configureEach
+ }
- it.parameters.targetAttributes.set(setOf(target.targetName))
- it.parameters.fakeTransform.set(kotlinPropertiesProvider.fakeUkibTransforms)
- }
- target.compilations.configureEach {
- listOfNotNull(
- it.internal.configurations.compileDependencyConfiguration,
- it.internal.configurations.runtimeDependencyConfiguration,
- ).forEach { config ->
- with(config.attributes) {
- when (project.kotlinPropertiesProvider.uklibResolutionStrategy) {
- UklibResolutionStrategy.PreferUklibVariant -> attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_UKLIB))
- UklibResolutionStrategy.PreferPlatformSpecificVariant -> {
- /* rely on the default + compatibility rule */
- }
- }
- attribute(uklibStateAttribute, uklibStateUnzipped)
- attribute(uklibPlatformAttribute, target.platformType.name)
- attribute(uklibNativeSliceAttribute, target.targetName)
- }
- }
- }
- } else {
- dependencies.registerTransform(UnzippedUklibToPlatformCompilationTransform::class.java) {
- it.from
- .attribute(uklibStateAttribute, uklibStateUnzipped)
- .attribute(uklibPlatformAttribute, uklibPlatformUnknown)
- it.to
- .attribute(uklibStateAttribute, uklibStateUnzipped)
- .attribute(uklibPlatformAttribute, target.platformType.name)
+ dependencies.registerTransform(UnzippedUklibToPlatformCompilationTransform::class.java) {
+ it.from
+ .attribute(uklibStateAttribute, uklibStateUnzipped)
+ .attribute(uklibDestinationAttribute, uklibDestinationUnknown)
+ it.to
+ .attribute(uklibStateAttribute, uklibStateUnzipped)
+ .attribute(uklibDestinationAttribute, destinationAttribute.unwrap())
- it.parameters.targetAttributes.set(setOf(target.targetName))
- it.parameters.fakeTransform.set(kotlinPropertiesProvider.fakeUkibTransforms)
- }
- target.compilations.configureEach {
- listOfNotNull(
- it.internal.configurations.compileDependencyConfiguration,
- it.internal.configurations.runtimeDependencyConfiguration,
- ).forEach { config ->
- with(config.attributes) {
- when (project.kotlinPropertiesProvider.uklibResolutionStrategy) {
- UklibResolutionStrategy.PreferUklibVariant -> attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_UKLIB))
- UklibResolutionStrategy.PreferPlatformSpecificVariant -> {
- /* rely on the default + compatibility rule */
- }
- }
+ it.parameters.targetFragmentAttribute.set(destinationAttribute.unwrap())
+ it.parameters.fakeTransform.set(kotlinPropertiesProvider.fakeUkibTransforms)
+ }
- attribute(uklibStateAttribute, uklibStateUnzipped)
- attribute(uklibPlatformAttribute, target.platformType.name)
- }
+ // FIXME: Refactor this and encode what configurations should be allowed to transform per KotlinTarget somewhere around [uklibFragmentPlatformAttribute]
+ target.compilations.configureEach {
+ listOfNotNull(
+ it.internal.configurations.compileDependencyConfiguration,
+ it.internal.configurations.runtimeDependencyConfiguration,
+ ).forEach {
+ it.attributes {
+ it.attribute(uklibStateAttribute, uklibStateUnzipped)
+ it.attribute(uklibDestinationAttribute, destinationAttribute.unwrap())
}
}
}
}
+}
- with(dependencies.artifactTypes.create("uklib").attributes) {
+private fun Project.registerZippedUklibArtifact() {
+ with(dependencies.artifactTypes.create(Uklib.UKLIB_EXTENSION).attributes) {
attribute(uklibStateAttribute, uklibStateZipped)
- attribute(uklibPlatformAttribute, uklibPlatformUnknown)
- attribute(uklibNativeSliceAttribute, uklibNativeSliceUnknown)
+ attribute(uklibDestinationAttribute, uklibDestinationUnknown)
}
+}
- dependencies.registerTransform(UklibUnzipTransform::class.java) {
+private fun Project.allowUklibsToUnzip() {
+ dependencies.registerTransform(UnzipUklibTransform::class.java) {
it.from.attribute(uklibStateAttribute, uklibStateZipped)
it.to.attribute(uklibStateAttribute, uklibStateUnzipped)
it.parameters.performUnzip.set(!kotlinPropertiesProvider.fakeUkibTransforms)
}
-
- dependencies.attributesSchema.attribute(Usage.USAGE_ATTRIBUTE).compatibilityRules.add(
- MakeUklibCompatibleWithPlatformCompilations::class.java
- )
- dependencies.attributesSchema.attribute(Usage.USAGE_ATTRIBUTE).compatibilityRules.add(
- MakePlatformCompilationsCompatibleWithUklibCompilations::class.java
- )
- dependencies.attributesSchema.attribute(Usage.USAGE_ATTRIBUTE).disambiguationRules.add(
- MakeJavaRuntimePreferableForUklibCompilations::class.java
- )
-
- dependencies.attributesSchema.attribute(KotlinPlatformType.attribute).compatibilityRules.add(
- MakePlatformCompatibleWithUklibs::class.java
- )
- dependencies.attributesSchema.attribute(KotlinNativeTarget.konanTargetAttribute).compatibilityRules.add(
- MakeKNSliceCompatibleWithUklibs::class.java
- )
- dependencies.attributesSchema.attribute(TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE).compatibilityRules.add(
- MakeTargetJvmEnvironmentCompatibleWithUklibs::class.java
- )
-
}
-abstract class UklibUnzipTransform @Inject constructor(
+private fun Project.allowMetadataConfigurationsToResolveUnzippedUklib(
+ sourceSets: NamedDomainObjectContainer<KotlinSourceSet>,
+) {
+ sourceSets.configureEach {
+ with(it.internal.resolvableMetadataConfiguration) {
+ attributes {
+ it.attribute(uklibStateAttribute, uklibStateUnzipped)
+ it.attribute(uklibDestinationAttribute, KotlinPlatformType.common.name)
+ }
+ }
+ }
+ dependencies.registerTransform(UnzippedUklibToMetadataCompilationTransform::class.java) {
+ it.from
+ .attribute(uklibStateAttribute, uklibStateUnzipped)
+ .attribute(uklibDestinationAttribute, uklibDestinationUnknown)
+ it.to
+ .attribute(uklibStateAttribute, uklibStateUnzipped)
+ .attribute(uklibDestinationAttribute, KotlinPlatformType.common.name)
+ }
+}
+
+
+internal abstract class UnzipUklibTransform @Inject constructor(
private val fileOperations: FileSystemOperations,
private val archiveOperations: ArchiveOperations,
-) : TransformAction<UklibUnzipTransform.Parameters> {
+) : TransformAction<UnzipUklibTransform.Parameters> {
interface Parameters : TransformParameters {
@get:Input
val performUnzip: Property<Boolean>
@@ -210,11 +150,14 @@
abstract val inputArtifact: Provider<FileSystemLocation>
override fun transform(outputs: TransformOutputs) {
- // FIXME: 25.11.2024 - When resolving a jar with uklib packaging Gradle comes here with the jar
val input = inputArtifact.get().asFile
- if (input.extension == "uklib") {
+ /**
+ * FIXME: Test this !!!
+ *
+ * Due to kotlin-api/runtime Usages being compatible with java Usages, we might see a jar in this transform
+ */
+ if (input.extension == Uklib.UKLIB_EXTENSION) {
val outputDir = outputs.dir("unzipped_uklib_${input.name}")
- // FIXME: 13.11.2024 - Throw this away because this is not really testable with UT?
if (parameters.performUnzip.get()) {
fileOperations.copy {
it.from(archiveOperations.zipTree(inputArtifact.get().asFile))
@@ -225,9 +168,7 @@
}
}
-abstract class UnzippedUklibToMetadataCompilationTransform @Inject constructor() : TransformAction<UnzippedUklibToMetadataCompilationTransform.Parameters> {
- interface Parameters : TransformParameters {}
-
+internal abstract class UnzippedUklibToMetadataCompilationTransform : TransformAction<TransformParameters.None> {
@get:InputArtifact
abstract val inputArtifact: Provider<FileSystemLocation>
@@ -236,11 +177,10 @@
}
}
-abstract class UnzippedUklibToPlatformCompilationTransform @Inject constructor(
-) : TransformAction<UnzippedUklibToPlatformCompilationTransform.Parameters> {
+internal abstract class UnzippedUklibToPlatformCompilationTransform : TransformAction<UnzippedUklibToPlatformCompilationTransform.Parameters> {
interface Parameters : TransformParameters {
@get:Input
- val targetAttributes: SetProperty<String>
+ val targetFragmentAttribute: Property<String>
@get:Input
val fakeTransform: Property<Boolean>
@@ -256,115 +196,45 @@
}
val unzippedUklib = inputArtifact.get().asFile
-
- val targetAttributes = parameters.targetAttributes.get()
- val uklib = Uklib.deserializeFromDirectory(unzippedUklib)
- // FIXME: Build up a Set<Attribute> -> Fragment instead?
- val platformFragments = uklib.module.fragments.filter { it.attributes == targetAttributes }
+ val targetFragmentAttribute = parameters.targetFragmentAttribute.get()
+ // FIXME: Build up a Set<Attribute> -> Fragment map instead?
+ val platformFragments = Uklib.deserializeFromDirectory(unzippedUklib)
+ .module.fragments
+ .filter { it.attributes == setOf(targetFragmentAttribute) }
if (platformFragments.isEmpty()) {
- // The fragment is just not there. Skip this dependency
- return
+ /**
+ * FIXME: Uklib spec mentions that there may be an intermediate fragment without refiners. Was this a crutch for kotlin-test? Should we check this case silently ignore this case here?
+ */
+ error("Couldn't resolve platform compilation artifact from ${unzippedUklib} failed. Needed fragment with attribute '${targetFragmentAttribute}', but only the following fragments were available ${platformFragments}")
}
if (platformFragments.size > 1) {
- error("Somehow more than one platform fragment matches platform attributes: ${platformFragments}")
+ error("Matched multiple fragments from ${unzippedUklib}, but was expecting to find exactly one. Found fragments: ${platformFragments}")
}
- outputs.dir(uklib.fragmentToArtifact[platformFragments.single().identifier]!!)
+ outputs.dir(platformFragments.single().file())
}
}
internal fun HasAttributes.configureUklibConfigurationAttributes(project: Project) {
attributes.setAttribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attributes.setAttribute(Usage.USAGE_ATTRIBUTE, project.usageByName(KotlinUsages.KOTLIN_UKLIB))
-
- attributes.setAttribute(KotlinPlatformType.attribute, KotlinPlatformType.unknown)
- attributes.setAttribute(KotlinNativeTarget.konanTargetAttribute, "???")
- attributes.setAttribute(KlibPackaging.ATTRIBUTE, project.objects.named(KlibPackaging.PACKED))
- attributes.setAttribute(TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE, project.objects.named("???"))
}
-
-class MakeUklibCompatibleWithPlatformCompilations : AttributeCompatibilityRule<Usage> {
- override fun execute(t: CompatibilityCheckDetails<Usage>) {
- val allowedConsumers = setOf(
- KotlinUsages.KOTLIN_API,
- Usage.JAVA_API,
- Usage.JAVA_RUNTIME,
- )
-
- if (t.producerValue?.name == KotlinUsages.KOTLIN_UKLIB && t.consumerValue?.name in allowedConsumers) {
- t.compatible()
- }
- }
-}
-
-class MakePlatformCompilationsCompatibleWithUklibCompilations : AttributeCompatibilityRule<Usage> {
- override fun execute(t: CompatibilityCheckDetails<Usage>) {
- val allowedProducers = setOf(
- KotlinUsages.KOTLIN_API,
- Usage.JAVA_API,
- Usage.JAVA_RUNTIME,
- )
-
- if (t.producerValue?.name in allowedProducers && t.consumerValue?.name == KotlinUsages.KOTLIN_UKLIB) {
- t.compatible()
- }
- }
-}
-
-class MakeKNSliceCompatibleWithUklibs : AttributeCompatibilityRule<String> {
- override fun execute(t: CompatibilityCheckDetails<String>) {
- if (t.producerValue == "???") {
- t.compatible()
- }
- }
-}
-
-class MakeTargetJvmEnvironmentCompatibleWithUklibs : AttributeCompatibilityRule<TargetJvmEnvironment> {
- override fun execute(t: CompatibilityCheckDetails<TargetJvmEnvironment>) {
- if (t.producerValue?.name == "???") {
- t.compatible()
- }
- }
-}
-
-
-class MakePlatformCompatibleWithUklibs : AttributeCompatibilityRule<KotlinPlatformType> {
- override fun execute(t: CompatibilityCheckDetails<KotlinPlatformType>) {
- if (t.producerValue == KotlinPlatformType.unknown) {
- t.compatible()
- }
- }
-}
-
-class MakeJavaRuntimePreferableForUklibCompilations : AttributeDisambiguationRule<Usage> {
- override fun execute(p0: MultipleCandidatesDetails<Usage>) {
- if (p0.consumerValue?.name == KotlinUsages.KOTLIN_UKLIB) {
- p0.candidateValues.firstOrNull { it.name == Usage.JAVA_RUNTIME }?.let {
- p0.closestMatch(it)
- }
- }
- }
-}
-
-enum class UklibResolutionStrategy {
- PreferUklibVariant,
- PreferPlatformSpecificVariant,
+internal enum class UklibResolutionStrategy {
+ AllowResolvingUklibs,
ResolveOnlyPlatformSpecificVariant;
val propertyName: String
get() = when (this) {
- PreferUklibVariant -> "preferUklibVariant"
- PreferPlatformSpecificVariant -> "preferPlatformSpecificVariant"
+ AllowResolvingUklibs -> "allowResolvingUklibs"
ResolveOnlyPlatformSpecificVariant -> "resolveOnlyPlatformSpecificVariant"
}
companion object {
fun fromProperty(name: String): UklibResolutionStrategy? = when (name) {
- PreferUklibVariant.propertyName -> PreferUklibVariant
- PreferPlatformSpecificVariant.propertyName -> PreferPlatformSpecificVariant
+ AllowResolvingUklibs.propertyName -> AllowResolvingUklibs
ResolveOnlyPlatformSpecificVariant.propertyName -> ResolveOnlyPlatformSpecificVariant
else -> null
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/Resolve.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/Resolve.kt
deleted file mode 100644
index 48212ee..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/Resolve.kt
+++ /dev/null
@@ -1,214 +0,0 @@
-package org.jetbrains.kotlin
-
-import org.jetbrains.kotlin.tooling.core.withClosure
-import java.io.File
-
-/**
- * f1, f2, ... fN
- * ->
- * [
- * (f1, f1), (f1, f2), ... (f1, fn),
- * (f2, f1), (f2, f2), ... (f2, fn),
- * (fn, f1), (fn, f2), ... (fn, fn),
- * ]
- * ->
- * 1. Filter p[0].canSee(p[1])
- * 2. Sort visible fragments by canSee and then by name
- */
-
-// Compilation -> publishedFile: File
-inline fun <Compilation, Target, reified SourceSet> transformKGPModelToUklibModel(
- moduleIdentifier: String,
- publishedCompilations: List<Compilation>,
- publishedArtifact: Compilation.() -> File,
- defaultSourceSet: Compilation.() -> SourceSet,
- target: Compilation.() -> Target,
- dependsOn: SourceSet.() -> Set<SourceSet>,
- identifier: SourceSet.() -> String,
-// sourceSetArtifact: SourceSet.() -> Compilation,
-): Uklib<Target> {
- /**
- * 1. No parts of the graph are isolated
- * 2. There are no cycles (this is already done by KGP)
- * 3. Everything is rooted in a single node (already checked in KGP)
- * 4. There are no fragments with duplicated attributes
- */
- // Assume we did check everything
-
- val sourceSetToTargets = mutableMapOf<SourceSet, MutableSet<Target>>()
- val fragmentToArtifact = mutableMapOf<String, File>()
- val publishedSourceSets = publishedCompilations.map { it.defaultSourceSet() }.toSet()
- publishedCompilations.forEach { compilation ->
- val compilationTarget = compilation.target()
- compilation.defaultSourceSet().withClosure(dependsOn).filter { it in publishedSourceSets }.forEach { sourceSet ->
- sourceSetToTargets.getOrPut(
- sourceSet, { mutableSetOf() }
- ).add(compilationTarget)
- }
- fragmentToArtifact[compilation.defaultSourceSet().identifier()] = compilation.publishedArtifact()
- }
-
- return Uklib(
- module = Module(
- identifier = moduleIdentifier,
- fragments = sourceSetToTargets.map { (sourceSet, targets) ->
- Fragment(
- identifier = sourceSet.identifier(),
- attributes = targets,
- )
- }.toSet()
- ),
- fragmentToArtifact = fragmentToArtifact
- )
-}
-
-
-class ResolvedModuleClasspath<Target>(
- val fullFragmentClasspath: Map<Fragment<Target>, List<File>>,
- val exactlyMatchingFragmentClasspath: Map<Fragment<Target>, List<File>>,
-)
-
-
-fun <Target> resolveModuleFragmentClasspath(
- module: Uklib<Target>,
- dependencies: Set<Uklib<Target>>,
-): ResolvedModuleClasspath<Target> {
- val moduleFragments = module.module.fragments.toList()
- val fullFragmentClasspath = mutableMapOf<Fragment<Target>, MutableList<File>>()
- val exactFragmentClasspath = mutableMapOf<Fragment<Target>, MutableList<File>>()
- moduleFragments.forEach {
- fullFragmentClasspath[it] = mutableListOf()
- exactFragmentClasspath[it] = mutableListOf()
- }
-
- // FIXME: Do we ever want to resolve self fragments? Maybe we could refactor some KGP parts to better reflect this model, but not right now
-// resolveFragmentRefinersWithinModule(moduleFragments).forEach { (fragment, refiners) ->
-// fullFragmentClasspath.getOrPut(fragment, { mutableListOf() }).addAll(
-// refiners.map { module.fragmentToArtifact[it.identifier]!! }
-// )
-// }
-
- dependencies.forEach { dependency ->
- val dependencyFragments = dependency.module.fragments.toList()
- resolveFragmentDependencies(
- targetFragments = moduleFragments,
- dependencyFragments = dependencyFragments,
- ).forEach { (fragment, dependencies) ->
- fullFragmentClasspath[fragment]!!.addAll(
- dependencies.map {
- dependency.fragmentToArtifact[it.identifier]!!
- }
- )
- }
- resolvePlatformFragmentDependencies(
- targetPlatformFragments = moduleFragments,
- dependencyFragments = dependencyFragments,
- ).forEach { (fragment, dependencies) ->
- exactFragmentClasspath[fragment]!!.addAll(
- dependencies.map {
- dependency.fragmentToArtifact[it.identifier]!!
- }
- )
- }
- }
-
-
- return ResolvedModuleClasspath(
- fullFragmentClasspath = fullFragmentClasspath,
- exactlyMatchingFragmentClasspath = exactFragmentClasspath,
- )
-}
-
-/**
- * This function takes fragments of a module [moduleFragments] and outputs a map where the keys are [moduleFragments]
- * and the values are classpath-ordered refiners.
- */
-fun <Target> resolveFragmentRefinersWithinModule(
- moduleFragments: List<Fragment<Target>>,
-) = resolveFragmentDependencies(
- targetFragments = moduleFragments,
- dependencyFragments = moduleFragments,
- canSee = { attributes.isProperSubsetOf(it.attributes) }
-)
-
-/**
- * This function takes fragments [targetFragments] that depend on another module's fragments [dependencyFragments] and
- * outputs a map where the keys are [targetFragments] and the values are classpath-ordered [dependencyFragments] visible
- * from the target fragment
- */
-fun <Target> resolveFragmentDependencies(
- targetFragments: List<Fragment<Target>>,
- dependencyFragments: List<Fragment<Target>>,
-) = resolveFragmentDependencies(
- targetFragments = targetFragments,
- dependencyFragments = dependencyFragments,
- canSee = { attributes.isSubsetOf(it.attributes) }
-)
-
-/**
- * This function takes fragments [targetPlatformFragments] that depend on another module's fragments [dependencyFragments] and
- * outputs a map where the keys are [targetPlatformFragments] and the values are empty of single element lists of [dependencyFragments]
- * matching
- */
-fun <Target> resolvePlatformFragmentDependencies(
- targetPlatformFragments: List<Fragment<Target>>,
- dependencyFragments: List<Fragment<Target>>,
-) = resolveFragmentDependencies(
- targetFragments = targetPlatformFragments,
- dependencyFragments = dependencyFragments,
- canSee = { attributes == it.attributes }
-)
-
-fun <Target> resolveFragmentDependencies(
- targetFragments: List<Fragment<Target>>,
- dependencyFragments: List<Fragment<Target>>,
- canSee: Fragment<Target>.(Fragment<Target>) -> Boolean,
-): Map<Fragment<Target>, List<Fragment<Target>>> {
- val modulesFragmentClasspath = mutableMapOf<Fragment<Target>, List<Fragment<Target>>>()
- targetFragments.forEach { fragment ->
- val fragmentClasspath = dependencyFragments.filter {
- fragment.canSee(it)
- }.sortedWith(
- object : Comparator<Fragment<Target>> {
- override fun compare(left: Fragment<Target>, right: Fragment<Target>): Int {
- if (left.canSee(right)) {
- return -1
- } else if (right.canSee(left)) {
- return 1
- } else if (left == right) {
- return 0
- } else {
- /**
- * The target fragment can see left and right, but the fragments are incomparable. For example in:
- * ab; bc; b -> ab; b -> bc;
- * b can see ab and bc, but ab and bc are incomparable
- */
- return left.identifier.compareTo(right.identifier)
- }
- }
- }
- )
- modulesFragmentClasspath[fragment] = fragmentClasspath
- }
- return modulesFragmentClasspath
-}
-
-data class Module<Target>(
- // Do we even need this identifier
- val identifier: String,
- val fragments: Set<Fragment<Target>>,
-) {
-// override fun hashCode(): Int = identifier.hashCode()
-// override fun equals(other: Any?): Boolean = identifier.equals(other?.toString())
-}
-
-data class Fragment<Target>(
- val identifier: String,
- val attributes: Set<Target>,
-) {
-// override fun hashCode(): Int = attributes.hashCode()
-// override fun equals(other: Any?): Boolean = other is Fragment<*> && attributes.equals(other.attributes)
-}
-
-fun <E> Set<E>.isProperSubsetOf(another: Set<E>): Boolean = another.size > size && isSubsetOf(another)
-fun <E> Set<E>.isSubsetOf(another: Set<E>): Boolean = another.containsAll(this)
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/Serialization.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/Serialization.kt
deleted file mode 100644
index c65d9d8..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/Serialization.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.jetbrains.kotlin
-
-import com.google.gson.Gson
-import com.google.gson.GsonBuilder
-import java.io.File
-import java.nio.file.Path
-
-
-data class Uklib<Target>(
- val module: Module<Target>,
- val fragmentToArtifact: Map<String, File>,
-) {
- fun serializeUklibToArchive(
- outputZip: File,
- temporariesDirectory: File,
- serializeTarget: Target.() -> String = { this.toString() },
- ) {
- val gson = GsonBuilder().setPrettyPrinting().create()
- val manifest = gson.toJson(
- mapOf(
- "identifier" to module.identifier,
- // FIXME: How are we actually going to handle default target hierarchy cause bamboos?
- "fragments" to module.fragments.filter { fragmentToArtifact[it.identifier]!!.exists() }.map {
- mapOf(
- "identifier" to it.identifier,
- "targets" to it.attributes.map(serializeTarget),
- )
- }
- )
- )
- zipFragments(
- manifest = manifest,
- fragmentToArtifact = fragmentToArtifact.filter { it.value.exists() },
- outputZip = outputZip,
- temporariesDirectory = temporariesDirectory,
- )
- }
-
- companion object {
- fun deserializeFromArchive(
- archive: File,
- unarchiveDirectory: Path,
- ): Uklib<String> {
- unzip(
- zipFilePath = archive,
- outputFolderPath = unarchiveDirectory.toFile(),
- )
- return deserializeFromDirectory(
- unarchiveDirectory.toFile()
- )
- }
-
- fun deserializeFromDirectory(directory: File): Uklib<String> {
- val manifest = directory.resolve("umanifest")
- if (!manifest.exists()) error("manifest doesn't exist")
- val gson = Gson()
- val map = gson.fromJson(manifest.readText(), Map::class.java) as Map<String, Any>
- val identifier = map["identifier"] as String
- val fragmentTokens = map["fragments"] as List<Map<String, Any>>
-
- val fragments = fragmentTokens.map {
- Fragment(
- identifier = it["identifier"] as String,
- attributes = (it["targets"] as List<String>).toSet(),
- )
- }.toSet()
- return Uklib(
- module = Module(
- identifier = identifier,
- fragments = fragments,
- ),
- fragmentToArtifact = fragments.map {
- it.identifier to directory.resolve(it.identifier)
- }.toMap()
- )
- }
- }
-}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibFragmentResolution.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibFragmentResolution.kt
new file mode 100644
index 0000000..cf8e533
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibFragmentResolution.kt
@@ -0,0 +1,23 @@
+package org.jetbrains.kotlin.gradle.artifacts.uklibsModel
+
+import java.io.File
+
+// /**
+// * 1. No parts of the graph are isolated
+// * 2. There are no cycles (this is already done by KGP)
+// * 3. Everything is rooted in a single node (already checked in KGP)
+// * 4. There are no fragments with duplicated attributes
+// */
+
+data class Module(
+ val fragments: Set<Fragment>,
+)
+
+data class Fragment(
+ val identifier: String,
+ val attributes: Set<String>,
+ val file: () -> File,
+)
+
+fun <E> Set<E>.isProperSubsetOf(another: Set<E>): Boolean = another.size > size && isSubsetOf(another)
+fun <E> Set<E>.isSubsetOf(another: Set<E>): Boolean = another.containsAll(this)
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibSerialization.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibSerialization.kt
new file mode 100644
index 0000000..274a961
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibSerialization.kt
@@ -0,0 +1,93 @@
+package org.jetbrains.kotlin.gradle.artifacts.uklibsModel
+
+import com.google.gson.Gson
+import com.google.gson.GsonBuilder
+import org.jetbrains.kotlin.zipFragments
+import java.io.File
+
+
+internal data class Uklib(
+ val module: Module,
+ // FIXME: Use this version for a forward compatibility?
+ val manifestVersion: String,
+) {
+ fun serializeUklibToArchive(
+ outputZip: File,
+ temporariesDirectory: File,
+ ) {
+ val manifest = GsonBuilder().setPrettyPrinting().create().toJson(
+ mapOf(
+ FRAGMENTS to module.fragments.filter {
+ // FIXME: Where was this coming from ???
+ //fragmentIdentifierToArtifact[it.identifier]!!.exists()
+ true
+ }.sortedBy {
+ // Make sure we have some stable order of fragments
+ it.identifier
+ }.map {
+ mapOf(
+ FRAGMENT_IDENTIFIER to it.identifier,
+ ATTRIBUTES to it.attributes
+ // Make sure we have some stable order of attributes
+ .sorted(),
+ )
+ },
+ UMANIFEST_VERSION to manifestVersion,
+ )
+ )
+ zipFragments(
+ manifest = manifest,
+ fragmentToArtifact = module.fragments.map {
+ it.identifier to it.file()
+ }.toMap(),
+ outputZip = outputZip,
+ temporariesDirectory = temporariesDirectory,
+ )
+ }
+
+ companion object {
+ fun deserializeFromDirectory(directory: File): Uklib {
+ val umanifest = directory.resolve(UMANIFEST_FILE_NAME)
+ if (!umanifest.exists()) error("Can't deserialize Uklib from ${directory} because ${UMANIFEST_FILE_NAME} doesn't exist")
+ val json = Gson().fromJson(umanifest.readText(), Map::class.java) as Map<String, Any>
+
+ val fragments = (json[FRAGMENTS] as List<Map<String, Any>>).map { fragment ->
+ val fragmentIdentifier = fragment[FRAGMENT_IDENTIFIER] as String
+ Fragment(
+ identifier = fragmentIdentifier,
+ attributes = (fragment[ATTRIBUTES] as List<String>).toSet(),
+ file = {
+ directory.resolve(fragmentIdentifier)
+ }
+ )
+ }.toHashSet()
+ return Uklib(
+ module = Module(
+ fragments = fragments,
+ ),
+ manifestVersion = json[UMANIFEST_VERSION] as String,
+ )
+ }
+
+ // Use this in diagnostics
+ const val UKLIB_NAME = "uklib"
+
+ // This extension has to be stable because we need to filter transitive jars in the transform
+ const val UKLIB_EXTENSION = "uklib"
+
+ /**
+ * The packaging must be equal to the extension because when resolving POM only components, Gradle prefers the artifact with the
+ * <packaging> POM value over the .jar (but falls back to jar if the artifact doesn't exist)
+ */
+ const val UKLIB_PACKAGING = UKLIB_EXTENSION
+
+ const val UMANIFEST_FILE_NAME = "umanifest"
+
+ const val FRAGMENTS = "fragments"
+ const val FRAGMENT_IDENTIFIER = "identifier"
+ const val ATTRIBUTES = "targets"
+ const val UMANIFEST_VERSION = "manifestVersion"
+
+ const val CURRENT_UMANIFEST_VERSION = "0.0.1"
+ }
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibSerializationUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibSerializationUtils.kt
new file mode 100644
index 0000000..438e6b2
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibSerializationUtils.kt
@@ -0,0 +1,100 @@
+package org.jetbrains.kotlin
+
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Uklib
+import org.jetbrains.kotlin.incremental.deleteDirectoryContents
+import java.io.BufferedOutputStream
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileOutputStream
+import java.nio.file.Files
+import java.util.zip.ZipEntry
+import java.util.zip.ZipInputStream
+import java.util.zip.ZipOutputStream
+
+/**
+ * // FIXME: Test this!!!
+ *
+ * All of the rezipping happens at execution time in ArchiveUklibTask:
+ * - if the incoming fragment is a .klib or a .jar, just unzip it and zip into the .uklib zip
+ * - if the incoming fragment is a directory, probably it's an unpacked klib, so just copy it
+ */
+private val allowRepackingArchivesWithExtensions = setOf(
+ "klib",
+ "jar",
+)
+
+internal fun zipFragments(
+ manifest: String,
+ fragmentToArtifact: Map<String, File>,
+ outputZip: File,
+ temporariesDirectory: File,
+) {
+ ZipOutputStream(
+ BufferedOutputStream(
+ FileOutputStream(outputZip)
+ )
+ ).use { zipOutputStream ->
+ // Pack the manifest
+ zipOutputStream.putNextEntry(ZipEntry(Uklib.UMANIFEST_FILE_NAME))
+ manifest.byteInputStream().copyTo(zipOutputStream)
+
+ fragmentToArtifact.forEach { (identifier, file) ->
+ // Assume we are handling unpacked metadata and platform klibs
+ if (file.isDirectory) {
+ packDirectory(file, identifier, zipOutputStream)
+ } else if (file.extension in allowRepackingArchivesWithExtensions) {
+ val temp = temporariesDirectory.resolve(identifier)
+ if (temp.exists()) temp.deleteDirectoryContents()
+ temp.mkdirs()
+ unzip(
+ zipFilePath = file,
+ outputFolderPath = temp,
+ )
+ packDirectory(
+ directory = temp,
+ identifier = identifier,
+ zipOutputStream = zipOutputStream,
+ )
+ } else {
+ error("Trying to pack invalid file in uklib: ${file}")
+ }
+ }
+ zipOutputStream.closeEntry()
+ }
+}
+
+private fun packDirectory(
+ directory: File,
+ identifier: String,
+ zipOutputStream: ZipOutputStream
+) {
+ Files.walk(directory.toPath()).forEach { path ->
+ val zipEntry = ZipEntry(identifier + "/" + path.toFile().toRelativeString(directory))
+ if (!Files.isDirectory(path)) {
+ zipOutputStream.putNextEntry(zipEntry)
+ Files.newInputStream(path).use { inputStream ->
+ inputStream.copyTo(zipOutputStream)
+ }
+ zipOutputStream.closeEntry()
+ }
+ }
+}
+
+private fun unzip(zipFilePath: File, outputFolderPath: File) {
+ ZipInputStream(FileInputStream(zipFilePath)).use { zipInputStream ->
+ var zipEntry: ZipEntry? = zipInputStream.nextEntry
+ while (zipEntry != null) {
+ val newFile = File(outputFolderPath, zipEntry.name)
+ if (zipEntry.isDirectory) {
+ newFile.mkdirs()
+ } else {
+ newFile.parentFile?.mkdirs()
+ FileOutputStream(newFile).use { fileOutputStream ->
+ zipInputStream.copyTo(fileOutputStream)
+ }
+ }
+ zipEntry = zipInputStream.nextEntry
+ }
+ zipInputStream.closeEntry()
+ }
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/utils.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/utils.kt
deleted file mode 100644
index 7a84ac4..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/utils.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-package org.jetbrains.kotlin
-
-import org.jetbrains.kotlin.incremental.deleteDirectoryContents
-import java.io.BufferedOutputStream
-import java.io.File
-import java.io.FileInputStream
-import java.io.FileOutputStream
-import java.nio.file.Files
-import java.util.zip.ZipEntry
-import java.util.zip.ZipInputStream
-import java.util.zip.ZipOutputStream
-
-fun zipFragments(
- manifest: String,
- fragmentToArtifact: Map<String, File>,
- outputZip: File,
- temporariesDirectory: File,
-) {
- ZipOutputStream(BufferedOutputStream(FileOutputStream(outputZip))).use { zos ->
- fragmentToArtifact.forEach { (identifier, file) ->
- // Unpacked metadata classes
- if (file.isDirectory) {
- packDirectory(file, identifier, zos)
- } else if (file.extension == "klib") {
- val temp = temporariesDirectory.resolve(identifier)
- if (temp.exists()) temp.deleteDirectoryContents()
- temp.mkdirs()
- unzip(
- zipFilePath = file,
- outputFolderPath = temp,
- )
- packDirectory(
- directory = temp,
- identifier = identifier,
- zos = zos,
- )
- } else {
- error("Trying to pack invalid file in uklib: ${file}")
- }
- }
- zos.putNextEntry(ZipEntry("umanifest"))
- manifest.byteInputStream().copyTo(zos)
- zos.closeEntry()
- }
-}
-
-private fun packDirectory(
- directory: File,
- identifier: String,
- zos: ZipOutputStream
-) {
- Files.walk(directory.toPath()).forEach { path ->
- val zipEntry = ZipEntry(identifier + "/" + path.toFile().toRelativeString(directory))
- if (!Files.isDirectory(path)) {
- zos.putNextEntry(zipEntry)
- Files.newInputStream(path).use { inputStream ->
- inputStream.copyTo(zos)
- }
- zos.closeEntry()
- }
- }
-}
-
-fun unzip(zipFilePath: File, outputFolderPath: File) {
- val buffer = ByteArray(1024)
- ZipInputStream(FileInputStream(zipFilePath)).use { zis ->
- var zipEntry: ZipEntry? = zis.nextEntry
- while (zipEntry != null) {
- val newFile = File(outputFolderPath, zipEntry.name)
- if (zipEntry.isDirectory) {
- newFile.mkdirs()
- } else {
- newFile.parentFile?.mkdirs()
- FileOutputStream(newFile).use { fos ->
- zis.copyTo(fos)
- }
- }
- zipEntry = zis.nextEntry
- }
- zis.closeEntry()
- }
-}
-
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/UklibArchiveTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/ArchiveUklibTask.kt
similarity index 82%
rename from libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/UklibArchiveTask.kt
rename to libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/ArchiveUklibTask.kt
index 1c32e18..6f7e8e4 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/UklibArchiveTask.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/ArchiveUklibTask.kt
@@ -12,16 +12,16 @@
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
-import org.jetbrains.kotlin.Uklib
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Uklib
import org.jetbrains.kotlin.gradle.utils.getFile
-internal abstract class UklibArchiveTask : DefaultTask() {
+internal abstract class ArchiveUklibTask : DefaultTask() {
@get:Internal
- abstract val model: Property<Uklib<String>>
+ abstract val model: Property<Uklib>
@get:OutputFile
val outputZip: RegularFileProperty = project.objects.fileProperty().convention(
- project.layout.buildDirectory.file("output.uklib")
+ project.layout.buildDirectory.file("package.${Uklib.UKLIB_EXTENSION}")
)
@get:Internal
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/SetupPublication.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/SetupPublication.kt
deleted file mode 100644
index c4a2ffe..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/SetupPublication.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
- */
-
-package org.jetbrains.kotlin.gradle.artifacts.uklibsPublication
-
-import org.gradle.api.Project
-import org.gradle.api.attributes.Usage
-import org.jetbrains.kotlin.gradle.dsl.awaitMetadataTarget
-import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
-import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
-import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
-import org.jetbrains.kotlin.gradle.plugin.await
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
-import org.jetbrains.kotlin.gradle.tasks.dependsOn
-
-internal suspend fun Project.setupPublication() {
- val sourceSets = multiplatformExtension.awaitSourceSets()
- val metadataTarget = multiplatformExtension.awaitMetadataTarget()
- val targets = multiplatformExtension.awaitTargets()
- KotlinPluginLifecycle.Stage.AfterFinaliseCompilations.await()
-
- val packUklib = tasks.register("packUklib", UklibArchiveTask::class.java)
-
- val kgpModel = uklibFromKGPModel(
- targets = targets.toList(),
- onPublishCompilation = {
- packUklib.dependsOn(it.compileTaskProvider)
- }
- )
-
- packUklib.configure {
- it.model.set(kgpModel)
- }
- artifacts.add(metadataTarget.uklibElementsConfigurationName, packUklib)
-
- if (kotlinPropertiesProvider.disablePlatformSpecificComponentsReferences) {
- // FIXME: 20.11.2024 - ???
- configurations.configureEach {
- if (!it.isCanBeConsumed) return@configureEach
- if (it.attributes.getAttribute(Usage.USAGE_ATTRIBUTE)?.name != KotlinUsages.KOTLIN_UKLIB) {
- it.isCanBeConsumed = false
- }
- }
- }
-}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/SetupUklibPublication.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/SetupUklibPublication.kt
new file mode 100644
index 0000000..d09f7ec
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/SetupUklibPublication.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.gradle.artifacts.uklibsPublication
+
+import org.gradle.api.Project
+import org.gradle.api.tasks.TaskProvider
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Uklib
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Module
+import org.jetbrains.kotlin.gradle.dsl.awaitMetadataTarget
+import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
+import org.jetbrains.kotlin.gradle.tasks.locateTask
+
+internal suspend fun Project.archiveUklibTask(): TaskProvider<ArchiveUklibTask> {
+ val taskName = "archiveUklib"
+ tasks.locateTask<ArchiveUklibTask>(taskName)?.let { return it }
+
+ val archiveUklib = tasks.register(taskName, ArchiveUklibTask::class.java)
+
+ val metadataTarget = multiplatformExtension.awaitMetadataTarget()
+ val allTargets = multiplatformExtension.awaitTargets().toMutableList()
+
+ val kgpFragments = kgpFragments(
+ metadataTarget = metadataTarget,
+ allTargets = allTargets,
+ )
+
+ kgpFragments.forEach { fragment ->
+ archiveUklib.configure {
+ // outputFile might be a directory or a file
+ it.inputs.files(fragment.outputFile)
+ // some outputFiles are derived from a project.provider, use explicit task dependency
+ it.dependsOn(fragment.providingTask)
+ }
+ }
+
+ archiveUklib.configure {
+ it.model.set(
+ Uklib(
+ module = Module(
+ fragments = kgpFragments.map {
+ it.fragment
+ }.toHashSet(),
+ ),
+ manifestVersion = Uklib.CURRENT_UMANIFEST_VERSION,
+ )
+ )
+ }
+
+ return archiveUklib
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/UklibFromKGPModel.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/UklibFromKGPModel.kt
index 78da1fa..fd31faa 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/UklibFromKGPModel.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/UklibFromKGPModel.kt
@@ -5,95 +5,193 @@
package org.jetbrains.kotlin.gradle.artifacts.uklibsPublication
-import org.jetbrains.kotlin.Uklib
-import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
-import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinCommonCompilation
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
+import org.gradle.api.provider.Provider
+import org.gradle.api.tasks.TaskProvider
+import org.gradle.jvm.tasks.Jar
+import org.jetbrains.kotlin.gradle.artifacts.metadataFragmentAttributes
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Fragment
+import org.jetbrains.kotlin.gradle.artifacts.metadataFragmentIdentifier
+import org.jetbrains.kotlin.gradle.artifacts.metadataPublishedArtifacts
+import org.jetbrains.kotlin.gradle.artifacts.publishedMetadataCompilations
+import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
-import org.jetbrains.kotlin.transformKGPModelToUklibModel
+import org.jetbrains.kotlin.gradle.plugin.*
+import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
+import org.jetbrains.kotlin.gradle.plugin.await
+import org.jetbrains.kotlin.gradle.plugin.mpp.external.DecoratedExternalKotlinTarget
+import org.jetbrains.kotlin.gradle.targets.js.KotlinWasmTargetType
import java.io.File
-internal fun uklibFromKGPModel(
- targets: List<KotlinTarget>,
- onPublishCompilation: (KotlinCompilation<*>) -> Unit = {}
-): Uklib<String> {
- val compilationToArtifact = mutableMapOf<KotlinCompilation<*>, Iterable<File>>()
- targets.forEach { target ->
+internal data class KGPFragment(
+ val fragment: Fragment,
+ val providingTask: TaskProvider<*>,
+ val outputFile: Provider<File>,
+)
+
+internal suspend fun kgpFragments(
+ metadataTarget: KotlinMetadataTarget,
+ allTargets: List<KotlinTarget>,
+): List<KGPFragment> {
+ // Guarantee that we can safely access any compilations
+ KotlinPluginLifecycle.Stage.AfterFinaliseCompilations.await()
+
+ val fragments = mutableListOf<KGPFragment>()
+
+ metadataTarget.publishedMetadataCompilations().forEach { metadataCompilation ->
+ val artifact = metadataCompilation.project.provider {
+ metadataCompilation.metadataPublishedArtifacts.singleFile
+ }
+ fragments.add(
+ KGPFragment(
+ fragment = Fragment(
+ identifier = metadataCompilation.metadataFragmentIdentifier,
+ attributes = metadataCompilation.metadataFragmentAttributes.map { it.unwrap() }.toSet(),
+ file = {
+ artifact.get()
+ }
+ ),
+ providingTask = metadataCompilation.compileTaskProvider,
+ outputFile = artifact,
+ )
+ )
+ }
+
+ allTargets.filterNot {
+ it == metadataTarget
+ }.forEach { target ->
+ /**
+ * FIXME: Tie this implementation to the publication implementations that are hardcoded in KotlinTarget to make the dependency
+ * between the artifact that is published in Uklib and in the old publication model visible
+ */
when (target) {
is KotlinJsIrTarget -> {
- error("...")
-// val mainComp = target.compilations.getByName(MAIN_COMPILATION_NAME)
-// compilationToArtifact[mainComp] = mainComp.out
- }
- is KotlinJvmTarget -> {
- val mainComp = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
- // FIXME: How do we handle that there are multiple classesDir?
- /**
- * What should we do with multiple classes output:
- *
- * 1. What is going to happen if Foo collides across Kotlin and Java compilations. Is one picked over the other or is there a
- * class redeclaration error?
- * 2. Publication always has a single jar
- *
- * TODO: Discuss this case in text
- */
- compilationToArtifact[mainComp] = mainComp.output.classesDirs
- onPublishCompilation(mainComp)
+ val mainCompilation = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
+ val file = mainCompilation.compileTaskProvider.flatMap { it.klibOutput }
+ fragments.add(
+ KGPFragment(
+ fragment = Fragment(
+ identifier = mainCompilation.fragmentIdentifier,
+ attributes = setOf(mainCompilation.uklibFragmentPlatformAttribute.unwrap()),
+ file = {
+ file.get()
+ }
+ ),
+ providingTask = mainCompilation.compileTaskProvider,
+ outputFile = file,
+ )
+ )
}
is KotlinNativeTarget -> {
- val mainComp = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
- compilationToArtifact[mainComp] = listOf(
- // FIXME: Make this lazy
- // FIXME: We have to unzip this
- // FIXME: 13.11 - Just use unpacked compilation directly
- mainComp.compileTaskProvider.flatMap {
- it.outputFile
- }.get()
+ val mainCompilation = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
+ val file = mainCompilation.compileTaskProvider.flatMap { it.klibOutput }
+ fragments.add(
+ KGPFragment(
+ fragment = Fragment(
+ identifier = mainCompilation.fragmentIdentifier,
+ attributes = setOf(mainCompilation.uklibFragmentPlatformAttribute.unwrap()),
+ file = {
+ file.get()
+ }
+ ),
+ providingTask = mainCompilation.compileTaskProvider,
+ outputFile = file,
+ )
)
- onPublishCompilation(mainComp)
}
- // FIXME: Metadata target forms a natural bamboo with default target hierarchy
- /**
- * What to do with bamboo and default target hierarchy: this is actually a problem because this works in KGP, but with Uklibs
- * this is not going to work
- *
- *
- * 1. Can we refactor metadata compilations to compile all same-target compilations: no because expect/actuals must not be in the same compilation
- * But maybe we could relax this inside the compiler
- *
- * 2. Source set target context feature? It will allow declaring e.g. commonMain that is constrained to ios and jvm, but providing jvm
- * will not be required.
- *
- * 3. Prohibit bamboo source set configuration in. This will work for cases where there are no expect/actuals across metadata compilations
- *
- * Typical use case:
- *
- * TODO: Write communication about this in the channel
- */
- is KotlinMetadataTarget -> {
- target.compilations
- // Probably this is not needed
- .filterNot { it is KotlinCommonCompilation && !it.isKlibCompilation }
- .forEach { compilation ->
- // FIXME: Aren't test compilations going to be here?
- compilationToArtifact[compilation] = compilation.output.classesDirs
- onPublishCompilation(compilation)
- }
+ is KotlinJvmTarget -> {
+ val mainCompilation = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
+ @Suppress("UNCHECKED_CAST")
+ val jarTask = (target.project.tasks.named(target.artifactsTaskName) as TaskProvider<Jar>)
+ val jarArtifact = jarTask.flatMap {
+ it.archiveFile.map { it.asFile }
+ }
+ fragments.add(
+ KGPFragment(
+ fragment = Fragment(
+ identifier = mainCompilation.fragmentIdentifier,
+ attributes = setOf(mainCompilation.uklibFragmentPlatformAttribute.unwrap()),
+ file = {
+ jarArtifact.get()
+ }
+ ),
+ providingTask = jarTask,
+ outputFile = jarArtifact,
+ )
+ )
+ }
+ else -> {
+ when (target.uklibFragmentPlatformAttribute) {
+ is UklibFragmentPlatformAttribute.OnlyConsumeInMetadataCompilationsAndIgnoreAtPublication -> { /* Do nothing for AGP */ }
+ is UklibFragmentPlatformAttribute.PublishAndConsumeInAllCompilations -> { /* FIXME: rewrite the logic above */ }
+ is UklibFragmentPlatformAttribute.FailOnPublicationAndIgnoreForConsumption -> target.uklibFragmentPlatformAttribute.unwrap()
+ }
}
}
}
- return transformKGPModelToUklibModel(
- "stub",
- publishedCompilations = compilationToArtifact.keys.toList(),
- publishedArtifact = { compilationToArtifact[this]!!.single() },
- defaultSourceSet = { this.defaultSourceSet },
- target = { this.target.targetName },
- dependsOn = { this.dependsOn },
- identifier = { this.name }
- )
-}
\ No newline at end of file
+ return fragments
+}
+
+internal enum class UklibJsTargetIdentifier {
+ js_ir,
+ wasm_js,
+ wasm_wasi;
+
+ fun deserialize(value: String): UklibJsTargetIdentifier {
+ return enumValueOf<UklibJsTargetIdentifier>(value)
+ }
+}
+
+internal sealed class UklibFragmentPlatformAttribute {
+ // Jvm, native, js
+ data class PublishAndConsumeInAllCompilations(val attribute: String) : UklibFragmentPlatformAttribute()
+ // Android
+ data class OnlyConsumeInMetadataCompilationsAndIgnoreAtPublication(val attribute: String) : UklibFragmentPlatformAttribute()
+ // External target
+ data class FailOnPublicationAndIgnoreForConsumption(val error: String) : UklibFragmentPlatformAttribute()
+
+ // FIXME: Separate unwrap to consume for publication vs compilation
+ fun unwrap(): String = when (this) {
+ is PublishAndConsumeInAllCompilations -> attribute
+ is OnlyConsumeInMetadataCompilationsAndIgnoreAtPublication -> attribute
+ is FailOnPublicationAndIgnoreForConsumption -> error(error)
+ }
+}
+
+internal val KotlinCompilation<*>.uklibFragmentPlatformAttribute: UklibFragmentPlatformAttribute get() = this.target.uklibFragmentPlatformAttribute
+internal val KotlinTarget.uklibFragmentPlatformAttribute: UklibFragmentPlatformAttribute
+ get() {
+ // FIXME: Actually maybe request jvm transform in Android?
+ if (this is KotlinAndroidTarget) {
+ return UklibFragmentPlatformAttribute.OnlyConsumeInMetadataCompilationsAndIgnoreAtPublication(targetName)
+ }
+
+ when (this) {
+ is KotlinNativeTarget -> konanTarget.name
+ is KotlinJsIrTarget -> when (platformType) {
+ KotlinPlatformType.js -> UklibJsTargetIdentifier.js_ir.name
+ KotlinPlatformType.wasm -> when (wasmTargetType ?: error("${KotlinJsIrTarget::class} missing wasm type in wasm platform ")) {
+ KotlinWasmTargetType.JS -> UklibJsTargetIdentifier.wasm_js.name
+ KotlinWasmTargetType.WASI -> UklibJsTargetIdentifier.wasm_wasi.name
+ }
+ else -> error("${KotlinJsIrTarget::class} unexpected platform type ${platformType}")
+ }
+ // FIXME: Is this correct?
+ is KotlinJvmTarget -> targetName
+ else -> null
+ }?.let {
+ return UklibFragmentPlatformAttribute.PublishAndConsumeInAllCompilations(it)
+ }
+
+ val error = when (this) {
+ is KotlinMetadataTarget -> "Metadata target does't have a platform attribute"
+ // FIXME: Test this !!!
+ is DecoratedExternalKotlinTarget -> "FIXME: This is explicitly unsupported"
+ else -> "???"
+ }
+ return UklibFragmentPlatformAttribute.FailOnPublicationAndIgnoreForConsumption(error)
+ }
+
+internal val KotlinCompilation<*>.fragmentIdentifier: String get() = defaultSourceSet.name
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/AbstractKotlinNativeBinaryContainer.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/AbstractKotlinNativeBinaryContainer.kt
index d19ecba..65301db 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/AbstractKotlinNativeBinaryContainer.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/AbstractKotlinNativeBinaryContainer.kt
@@ -5,6 +5,7 @@
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toUpperCaseAsciiOnly
+import java.util.concurrent.atomic.AtomicReference
// DO NOT EDIT MANUALLY! Generated by org.jetbrains.kotlin.generators.gradle.dsl.MppNativeBinaryDSLCodegenKt
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 96b9512..0140d41 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
@@ -184,7 +184,7 @@
KotlinPlatformType.js -> if (isVersionWithGradleMetadata) KOTLIN_STDLIB_MODULE_NAME else KOTLIN_STDLIB_JS_MODULE_NAME
KotlinPlatformType.wasm -> KOTLIN_STDLIB_MODULE_NAME
- KotlinPlatformType.native, KotlinPlatformType.unknown -> null
+ KotlinPlatformType.native -> null
KotlinPlatformType.common -> // there's no platform compilation that the source set is default for
if (isVersionWithGradleMetadata) KOTLIN_STDLIB_MODULE_NAME else KOTLIN_STDLIB_COMMON_MODULE_NAME
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt
index fc31597..8e83fb3 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt
@@ -40,7 +40,7 @@
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_OPTIMISTIC_NUMBER_COMMONIZATION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_PLATFORM_INTEGER_COMMONIZATION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_RESOURCES_PUBLICATION
-import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_PUBLISH_UKLIB_VARIANT
+import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_PUBLISH_UKLIB
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_FILTER_RESOURCES_BY_EXTENSION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_BY_DEFAULT
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_SUPPORT
@@ -195,10 +195,10 @@
val uklibResolutionStrategy: UklibResolutionStrategy
get() = this.get(KOTLIN_MPP_UKLIB_RESOLUTION_STRATEGY)?.let {
UklibResolutionStrategy.fromProperty(it)
- } ?: UklibResolutionStrategy.PreferUklibVariant
+ } ?: UklibResolutionStrategy.AllowResolvingUklibs
- val publishUklibVariant: Boolean
- get() = booleanProperty(KOTLIN_MPP_PUBLISH_UKLIB_VARIANT) ?: false
+ val publishUklib: Boolean
+ get() = booleanProperty(KOTLIN_MPP_PUBLISH_UKLIB) ?: false
val fakeUkibTransforms: Boolean
get() = booleanProperty(KOTLIN_MPP_FAKE_UKLIB_TRANSFORMS) ?: false
@@ -639,7 +639,7 @@
val KOTLIN_JS_STDLIB_DOM_API_INCLUDED = property("kotlin.js.stdlib.dom.api.included")
val KOTLIN_JS_YARN = property("kotlin.js.yarn")
- val KOTLIN_MPP_PUBLISH_UKLIB_VARIANT = property("kotlin.mpp.publishUklibVariant")
+ val KOTLIN_MPP_PUBLISH_UKLIB = property("kotlin.mpp.publishUklib")
val KOTLIN_MPP_FAKE_UKLIB_TRANSFORMS = property("kotlin.mpp.fakeUklibTransforms")
val KOTLIN_MPP_DISABLE_PLATFORM_SPECIFIC_COMPONENTS_REFERENCES = property("kotlin.mpp.disablePlatformSpecificComponentsReferences")
val KOTLIN_MPP_UKLIB_RESOLUTION_STRATEGY = property("kotlin.mpp.uklibResolutionStrategy")
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/IncorrectCompileOnlyDependenciesChecker.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/IncorrectCompileOnlyDependenciesChecker.kt
index bc47212..06eab08 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/IncorrectCompileOnlyDependenciesChecker.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/IncorrectCompileOnlyDependenciesChecker.kt
@@ -105,7 +105,7 @@
KotlinPlatformType.js,
-> false
- KotlinPlatformType.native, KotlinPlatformType.unknown -> {
+ KotlinPlatformType.native -> {
@Suppress("DEPRECATION")
PropertiesProvider(project).ignoreIncorrectNativeDependencies == true
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt
index f382249..458380f 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt
@@ -11,6 +11,8 @@
import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport.SourceSetConstraint
import org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers.*
import org.jetbrains.kotlin.gradle.plugin.ide.dependencyTransformers.IdePlatformStdlibCommonDependencyFilter
+import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinCommonCompilation
+import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.targets.native.internal.commonizerTarget
internal fun IdeMultiplatformImport(extension: KotlinProjectExtension): IdeMultiplatformImport {
@@ -65,6 +67,7 @@
priority = IdeMultiplatformImport.Priority.normal
)
+ // Этот мы используем для резолва метадаты
registerDependencyResolver(
resolver = IdeTransformedMetadataDependencyResolver,
constraint = !SourceSetConstraint.isSingleKotlinTarget and !SourceSetConstraint.isJvmAndAndroid,
@@ -72,6 +75,7 @@
priority = IdeMultiplatformImport.Priority.normal
)
+ // Не понимаю зачем это нужно если есть верхний матчер
registerDependencyResolver(
resolver = IdeOriginalMetadataDependencyResolver,
constraint = !SourceSetConstraint.isLeaf,
@@ -81,6 +85,7 @@
registerDependencyResolver(
resolver = IdeBinaryDependencyResolver(),
+ // FIXME: Why is this single platform and not target?
constraint = SourceSetConstraint.isSinglePlatformType,
phase = IdeMultiplatformImport.DependencyResolutionPhase.BinaryDependencyResolution,
priority = IdeMultiplatformImport.Priority.normal
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt
index 359961a..7a2e1e3 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt
@@ -14,6 +14,9 @@
import org.gradle.internal.component.local.model.OpaqueComponentArtifactIdentifier
import org.gradle.internal.resolve.ModuleVersionResolveException
import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
+import org.jetbrains.kotlin.gradle.artifacts.uklibDestinationAttribute
+import org.jetbrains.kotlin.gradle.artifacts.uklibStateAttribute
+import org.jetbrains.kotlin.gradle.artifacts.uklibStateUnzipped
import org.jetbrains.kotlin.gradle.idea.tcs.*
import org.jetbrains.kotlin.gradle.idea.tcs.extras.artifactsClasspath
import org.jetbrains.kotlin.gradle.idea.tcs.extras.isOpaqueFileDependency
@@ -23,7 +26,6 @@
import org.jetbrains.kotlin.gradle.plugin.ide.*
import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver.Companion.gradleArtifact
import org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers.IdeBinaryDependencyResolver.ArtifactResolutionStrategy
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.internal
import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
@@ -166,7 +168,7 @@
is ModuleComponentIdentifier -> {
// FIXME: Где-то тут разламывается AS интеграция из-за того что совпадает id?
if (artifact.variant.attributes.getAttribute(uklibStateAttribute) == uklibStateUnzipped) {
- val platform = artifact.variant.attributes.getAttribute(uklibPlatformAttribute)
+ val platform = artifact.variant.attributes.getAttribute(uklibDestinationAttribute)
IdeaKotlinResolvedBinaryDependency(
coordinates = IdeaKotlinBinaryCoordinates(
group = componentId.group,
@@ -251,10 +253,11 @@
Prevent case where this resolver was configured to resolve dependencies for a metadata compilation:
Refuse resolution. Write your own code if you really want to do this!
*/
- if (compilation is KotlinMetadataCompilation<*>) {
- logger.warn("Unexpected ${KotlinMetadataCompilation::class.java}(${compilation.name}) for $sourceSet")
- return null
- }
+ // FIXME: Why?
+// if (compilation is KotlinMetadataCompilation<*>) {
+// logger.warn("Unexpected ${KotlinMetadataCompilation::class.java}(${compilation.name}) for $sourceSet")
+// return null
+// }
return createArtifactViewFromConfiguration(sourceSet, compilation.internal.configurations.compileDependencyConfiguration)
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/AbstractKotlinTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/AbstractKotlinTarget.kt
index 1719ea8..e04ad15 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/AbstractKotlinTarget.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/AbstractKotlinTarget.kt
@@ -92,7 +92,7 @@
)
)
- val result = createKotlinVariant(componentName, mainCompilation, usageContexts)
+ val result = createKotlinVariant(componentName, usageContexts)
setOf(result)
}
@@ -107,19 +107,18 @@
protected open fun createKotlinVariant(
componentName: String,
- compilation: KotlinCompilation<*>,
usageContexts: Set<DefaultKotlinUsageContext>
): KotlinVariant {
val kotlinExtension = project.kotlinExtension
val result =
if (kotlinExtension !is KotlinMultiplatformExtension || targetName == KotlinMetadataTarget.METADATA_TARGET_NAME)
- KotlinVariantWithCoordinates(compilation, usageContexts)
+ KotlinVariantWithCoordinates(this, usageContexts)
else {
val metadataTarget =
kotlinExtension.targets.getByName(KotlinMetadataTarget.METADATA_TARGET_NAME) as AbstractKotlinTarget
- KotlinVariantWithMetadataVariant(compilation, usageContexts, metadataTarget)
+ KotlinVariantWithMetadataVariant(this, usageContexts, metadataTarget)
}
result.componentName = componentName
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt
index 22df14d..37afd0f 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt
@@ -17,6 +17,10 @@
import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.gradle.artifacts.uklibStateAttribute
import org.jetbrains.kotlin.gradle.artifacts.uklibStateUnzipped
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Fragment
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Uklib
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.isSubsetOf
+import org.jetbrains.kotlin.gradle.artifacts.uklibsPublication.uklibFragmentPlatformAttribute
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.*
@@ -47,6 +51,9 @@
return "$verb, dependency = $dependency"
}
+ /**
+ * KeepOriginalDependency нужен для кейса если в GMT попали настоящие jar'ники?
+ */
class KeepOriginalDependency(
dependency: ResolvedComponentResult,
) : MetadataDependencyResolution(dependency)
@@ -116,8 +123,7 @@
val objects: ObjectFactory,
val kotlinKmpProjectIsolationEnabled: Boolean,
val sourceSetMetadataLocationsOfProjectDependencies: KotlinProjectSharedDataProvider<SourceSetMetadataLocations>,
- // FIXME: ???
- val sourceSetTargetMembership: Set<String>,
+ val uklibFragmentAttributes: Set<String>,
) {
constructor(project: Project, kotlinSourceSet: KotlinSourceSet) : this(
build = project.currentBuild,
@@ -133,11 +139,10 @@
kotlinKmpProjectIsolationEnabled = project.kotlinPropertiesProvider.kotlinKmpProjectIsolationEnabled,
sourceSetMetadataLocationsOfProjectDependencies = project.kotlinSecondaryVariantsDataSharing
.consumeCommonSourceSetMetadataLocations(kotlinSourceSet.internal.resolvableMetadataConfiguration),
- sourceSetTargetMembership = kotlinSourceSet.internal.compilations
+ uklibFragmentAttributes = kotlinSourceSet.internal.compilations
.map { it.target }
.filter { it !is KotlinMetadataTarget }
- // FIXME: See uklibFromKGPModel
- .map { it.targetName }
+ .map { it.uklibFragmentPlatformAttribute.unwrap() }
.toSet()
)
}
@@ -161,6 +166,7 @@
private fun doTransform(): Iterable<MetadataDependencyResolution> {
val result = mutableListOf<MetadataDependencyResolution>()
+ // Это очередь из порезолвленных компонентнов?
val resolvedDependencyQueue: Queue<ResolvedDependencyResult> = ArrayDeque<ResolvedDependencyResult>().apply {
addAll(
params.resolvedMetadataConfiguration
@@ -234,13 +240,25 @@
* * based on the project structure metadata, determine which of the module's dependencies are requested by the
* source sets in *S*, then consider only these transitive dependencies, ignore the others;
*/
+ // По идее эта логика исполняется на зависимость, на каждый потребляющий SS
private fun processDependency(
dependency: ResolvedDependencyResult,
+ // Я не понимаю откуда приходят эти SS
+ /**
+ * 24.11.2024 - Наверное для iosMain они приходят из commonMain. Это точно так, они приходят из parent тасок которые делают GMT
+ */
sourceSetsVisibleInParents: Set<String>,
): MetadataDependencyResolution {
val module = dependency.selected
val moduleId = module.id
+ /**
+ * FIXME: 01.12-2024 - Add diagnostics:
+ *
+ * 1. Look at the graph of
+ */
+
+ // Это .jar ник с метадатными klib'ами
val artifact = params
.resolvedMetadataConfiguration
.getArtifacts(dependency)
@@ -266,44 +284,43 @@
moduleId,
sourceSetsVisibleInParents,
- sourceSetName = params.sourceSetName,
- targetMembership = params.sourceSetTargetMembership,
+ //sourceSetName = params.sourceSetName,
+ uklibFragmentAttributes = params.uklibFragmentAttributes,
)
} else {
return MetadataDependencyResolution.KeepOriginalDependency(module)
}
}
+ // FIXME: How do we ensure classpath ordering for PSM dependencies ???
private fun processUklibDependency(
compositeMetadataArtifact: ResolvedArtifactResult,
dependency: ResolvedDependencyResult,
module: ResolvedComponentResult,
moduleId: ComponentIdentifier,
- // FIXME: ???
- sourceSetsVisibleInParents: Set<String>,
- sourceSetName: String,
- targetMembership: Set<String>,
+ sourceSetsVisibleInParents: Set<String>,
+ uklibFragmentAttributes: Set<String>,
): MetadataDependencyResolution {
+ // Validate that
+
val uklibDependency = Uklib.deserializeFromDirectory(
compositeMetadataArtifact.file,
)
- val fragment = Fragment(sourceSetName, targetMembership)
- val canSee: Fragment<String>.(Fragment<String>) -> Boolean = { attributes.isSubsetOf(it.attributes) }
-
+ val fragmentCanSee: Fragment.(Fragment) -> Boolean = { attributes.isSubsetOf(it.attributes) }
val visibleFragments = uklibDependency.module.fragments.filter {
- fragment.canSee(it)
- // FIXME: ??
+ uklibFragmentAttributes.isSubsetOf(it.attributes)
+ // FIXME: Is this the correct place to filter out compilations transformed by the parent ?? See allVisibleSourceSetNames and visibleSourceSetNamesExcludingDependsOn
&& it.identifier !in sourceSetsVisibleInParents
}.sortedWith(
- object : Comparator<Fragment<String>> {
- override fun compare(left: Fragment<String>, right: Fragment<String>): Int {
- if (left.canSee(right)) {
+ object : Comparator<Fragment> {
+ override fun compare(left: Fragment, right: Fragment): Int {
+ if (left.fragmentCanSee(right)) {
return -1
- } else if (right.canSee(left)) {
+ } else if (right.fragmentCanSee(left)) {
return 1
- } else if (left == right) {
+ } else if (left.attributes == right.attributes) {
return 0
} else {
return left.identifier.compareTo(right.identifier)
@@ -318,12 +335,12 @@
dependency = dependency.selected,
projectStructureMetadata = null,
// FIXME: Don't filter this
- allVisibleSourceSetNames = visibleFragments.map { it.identifier }.toSet(),
+ allVisibleSourceSetNames = visibleFragments.map { it.identifier }.toHashSet(),
// FIXME: Only filter this, but for some reason this doesn't work???
- visibleSourceSetNamesExcludingDependsOn = visibleFragments.map { it.identifier }.toSet(),
+ visibleSourceSetNamesExcludingDependsOn = visibleFragments.map { it.identifier }.toHashSet(),
// 26.11.2024 - This is likely only used to walk further dependencies, so we want all of them
- visibleTransitiveDependencies = dependency.selected.dependencies.filterIsInstance<ResolvedDependencyResult>().toSet(),
+ visibleTransitiveDependencies = dependency.selected.dependencies.filterIsInstance<ResolvedDependencyResult>().toHashSet(),
metadataProvider = ArtifactMetadataProvider(
object : CompositeMetadataArtifact {
@@ -359,7 +376,7 @@
get() = ""
override fun copyTo(file: File): Boolean {
- return uklibDependency.fragmentToArtifact[fragment.identifier]!!.copyRecursively(
+ return fragment.file().copyRecursively(
file,
overwrite = true,
)
@@ -431,11 +448,18 @@
isResolvedToProject
)
+ // Тут будут те SS которые видит потребитель? Но где тогда происходит маппинг между SS?
+ /**
+ * 24.11.2024 - Все это происходит в рамках resolve'а classpath текущего SS
+ */
val allVisibleSourceSets = sourceSetVisibility.visibleSourceSetNames
// Keep only the transitive dependencies requested by the visible source sets:
// Visit the transitive dependencies visible by parents, too (i.e. allVisibleSourceSets), as this source set might get a more
// concrete view on them:
+ /**
+ * Набираем то, какие зависимости были указаны в рамках SS
+ */
val requestedTransitiveDependencies: Set<ModuleDependencyIdentifier> =
mutableSetOf<ModuleDependencyIdentifier>().apply {
projectStructureMetadata.sourceSetModuleDependencies.forEach { (sourceSetName, moduleDependencies) ->
@@ -449,9 +473,15 @@
.filterIsInstance<ResolvedDependencyResult>()
.filterTo(mutableSetOf()) { it.toModuleDependencyIdentifier() in requestedTransitiveDependencies }
+ /**
+ * Кажется мы проверяем, что SS в котором мы сейчас не платформенный и что он не порезолвился в проектную зависимость
+ *
+ * Не понимаю зачем это нужно, особенно как работает часть про !isResolvedToProject
+ */
if (params.sourceSetName in params.platformCompilationSourceSets && !isResolvedToProject)
return MetadataDependencyResolution.Exclude.PublishedPlatformSourceSetDependency(module, transitiveDependenciesToVisit)
+ // Наверное тут будут только новые видимые SS которые еще не были видны в parent SS
val visibleSourceSetsExcludingDependsOn = allVisibleSourceSets.filterTo(mutableSetOf()) { it !in sourceSetsVisibleInParents }
val metadataProvider = when (mppDependencyMetadataExtractor) {
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataTarget.kt
index c549d2f..55c18ea 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataTarget.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataTarget.kt
@@ -6,13 +6,16 @@
package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project
+import org.gradle.api.artifacts.ModuleVersionIdentifier
+import org.gradle.api.artifacts.PublishArtifact
+import org.gradle.api.component.ComponentWithCoordinates
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.HasConfigurableKotlinCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptionsDefault
-import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
-import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
-import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent
+import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
+import org.jetbrains.kotlin.gradle.plugin.*
+import org.jetbrains.kotlin.gradle.plugin.launch
import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
import org.jetbrains.kotlin.gradle.utils.newInstance
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt
index 6a0d735..70e32cd 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt
@@ -86,7 +86,7 @@
// overrideConfigurationArtifacts = project.setProperty { listOf(allMetadataArtifact) }
)
- if (project.kotlinPropertiesProvider.publishUklibVariant) {
+ if (project.kotlinPropertiesProvider.publishUklib) {
this += DefaultKotlinUsageContext(
compilation = metadataTarget.compilations.getByName(MAIN_COMPILATION_NAME),
mavenScope = KotlinUsageContext.MavenScope.COMPILE,
@@ -202,10 +202,15 @@
override fun getDependencyConstraints(): MutableSet<out DependencyConstraint> =
configuration.incoming.dependencyConstraints
- override fun getArtifacts(): Set<PublishArtifact> =
- overrideConfigurationArtifacts?.get()?.toSet() ?:
+ override fun getArtifacts(): Set<PublishArtifact> {
+ // Don't publish anything except the uklib
+ // FIXME: 11.11.2024 - I used this to disable the publication of all other artifacts
+ // FIXME: 19.11.2024 - Use this under a feature toggle?
+ // if (configuration.name != "metadataUklibElements") return emptySet()
+ return overrideConfigurationArtifacts?.get()?.toSet() ?:
// TODO Gradle Java plugin does that in a different way; check whether we can improve this
configuration.artifacts
+ }
override fun getAttributes(): AttributeContainer {
val configurationAttributes = overrideConfigurationAttributes ?: configuration.attributes
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt
index 9aa5e8d..9bb4906 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt
@@ -59,7 +59,13 @@
private const val JAVA_RUNTIME_CLASSES = "java-runtime-classes"
private const val JAVA_RUNTIME_RESOURCES = "java-runtime-resources"
+ // FIXME: Rename this?
val values = setOf(KOTLIN_API, KOTLIN_RUNTIME)
+ val compatibleKotlinConsumerUsages = mapOf(
+ setOf(KOTLIN_API) to setOf(JAVA_API, "java-api-jars"),
+ // This should really only list KOTLIN_RUNTIME
+ setOf(KOTLIN_API, KOTLIN_RUNTIME) to setOf(JAVA_RUNTIME, "java-runtime-jars"),
+ )
private val jvmPlatformTypes: Set<KotlinPlatformType> = setOf(jvm, androidJvm)
@@ -113,6 +119,7 @@
when {
consumerValue?.name == KOTLIN_API && producerValue?.name.let { it == JAVA_API || it == "java-api-jars" } ->
compatible()
+ // FIXME: This can't really match KOTLIN_API because it matches the case above???
consumerValue?.name in values && producerValue?.name.let { it == JAVA_RUNTIME || it == "java-runtime-jars" } ->
compatible()
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MetadataDependencyTransformationTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MetadataDependencyTransformationTask.kt
index e39d08c..ef39d98 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MetadataDependencyTransformationTask.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MetadataDependencyTransformationTask.kt
@@ -139,6 +139,7 @@
@TaskAction
fun transformMetadata() {
+ // Не понимаю, это parent всмысле как commonMain для iosMain
val parentLibrariesRecords: List<List<TransformedMetadataLibraryRecord>> = parentLibrariesIndexFiles
.get()
.map { librariesIndexFile -> librariesIndexFile.records() }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependenciesProjectStructureMetadataExtractorFactoryDeprecated.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependenciesProjectStructureMetadataExtractorFactoryDeprecated.kt
index 7597d55..b0f9a2c 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependenciesProjectStructureMetadataExtractorFactoryDeprecated.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependenciesProjectStructureMetadataExtractorFactoryDeprecated.kt
@@ -41,8 +41,11 @@
): MppDependencyProjectStructureMetadataExtractor {
val moduleId = metadataArtifact.variant.owner
+
return if (moduleId is ProjectComponentIdentifier) {
+ // Чекаем участвует ли эта зависимость в билде? Зачем
if (moduleId in currentBuild) {
+ // Это легаси логика которая ходит в рутовый проект и ищет там (in-memory?) PSM
val projectStructureMetadataProvider = currentBuildProjectStructureMetadataProviders[moduleId.projectPath]
?: error("Project structure metadata not found for project '${moduleId.projectPath}'")
@@ -51,6 +54,7 @@
projectStructureMetadataProvider = projectStructureMetadataProvider::value
)
} else {
+ // Это что-то про included build
/*
We switched to using 'buildPath' instead of 'buildName' in 1.9.20,
(See: https://youtrack.jetbrains.com/issue/KT-58157/)
@@ -70,6 +74,7 @@
)
}
} else {
+ // Просто достаем PSM из jar'ника
JarMppDependencyProjectStructureMetadataExtractor(metadataArtifact.file)
}
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt
index f3b53c0..054e05d 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt
@@ -81,21 +81,41 @@
* the Gradle API for dependency variants behaves differently for project dependencies and published ones.
*/
fun getVisibleSourceSets(
+ // e.g. commonMain
visibleFromSourceSet: KotlinSourceSetName,
+ // Это порезолвленная зависимость (вероятно ее компонент в котором лежит PSM)
resolvedRootMppDependency: ResolvedDependencyResult,
+ // Это видимо PSM этой зависимости
dependencyProjectStructureMetadata: KotlinProjectStructureMetadata,
+ // Это просто значит, что это проектная зависимость
resolvedToOtherProject: Boolean,
): SourceSetVisibilityResult {
val resolvedRootMppDependencyId = resolvedRootMppDependency.selected.id
val platformCompilationsByResolvedVariantName = mutableMapOf<String, PlatformCompilationData>()
+ /** Откуда берутся platformCompilations?
+ * platformCompilations это платформенные компиляции текущего модуля который делает GMT резолв
+ *
+ * 1. Берем платформенные компиляции
+ * 2. Только те которые участвуют в компиляции этого SS
+ * 3. Смотрим какие variant'ы порезолвили эти конфигурации и восстанавливаем
+ */
val visiblePlatformVariantNames: List<Set<String>> = platformCompilations
+ /**
+ * Visibility алгоритм работает на конкретном SS. Тут мы отфильтировываем платформенные компиляции до тех который включают в себя этот SS
+ */
.filter { visibleFromSourceSet in it.allSourceSets }
.mapNotNull { platformCompilationData ->
val resolvedPlatformDependencies = platformCompilationData
+ /**
+ * resolvedDependenciesConfiguration это конфигурация которую платформенная компиляция будет резолвить для получения платформенных артефактов
+ */
.resolvedDependenciesConfiguration
.allResolvedDependencies
+ /**
+ * Мне кажется тут Антон рассказывал про проблемы с shouldResolveConsistently
+ */
.filter { it.selected.id isEqualsIgnoringVersion resolvedRootMppDependencyId }
/*
Returning null if we can't find the given dependency in a certain platform compilations dependencies.
@@ -111,7 +131,14 @@
*/
.ifEmpty { return@mapNotNull null }
+ /**
+ * Смотрим на зависимости которые порезолвила плафтморенная compileDependencyConfiguration. А именно на variant'ы которые
+ * она порезолвила
+ */
resolvedPlatformDependencies.map { resolvedPlatformDependency ->
+ /**
+ * Дропаем "-published" маркер названия варианта и восстанавливаем из него resolved variant
+ */
val resolvedVariant = kotlinVariantNameFromPublishedVariantName(
resolvedPlatformDependency.resolvedVariant.displayName
)
@@ -128,6 +155,7 @@
return SourceSetVisibilityResult(emptySet(), emptyMap())
}
+
val visibleSourceSetNames = visiblePlatformVariantNames
.mapNotNull { platformVariants ->
platformVariants
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinCompilation.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinCompilation.kt
index 66168bf..b77fe0e 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinCompilation.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinCompilation.kt
@@ -38,7 +38,7 @@
KotlinPlatformType.jvm -> KotlinJvmCompilerOptionsFactory
KotlinPlatformType.androidJvm -> KotlinJvmCompilerOptionsFactory
KotlinPlatformType.js -> KotlinJsCompilerOptionsFactory
- KotlinPlatformType.native, KotlinPlatformType.unknown -> KotlinNativeCompilerOptionsFactory
+ KotlinPlatformType.native -> KotlinNativeCompilerOptionsFactory
KotlinPlatformType.wasm -> KotlinMultiplatformCommonCompilerOptionsFactory
},
compilationSourceSetsContainerFactory = { _, _ -> KotlinCompilationSourceSetsContainer(descriptor.defaultSourceSet) },
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinTarget.kt
index f9eea0e..b91887e 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinTarget.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinTarget.kt
@@ -77,7 +77,7 @@
KotlinPlatformType.wasm,
KotlinPlatformType.js -> project.objects.newInstance<KotlinJsCompilerOptionsDefault>()
KotlinPlatformType.common -> project.objects.newInstance<KotlinCommonCompilerOptionsDefault>()
- KotlinPlatformType.native, KotlinPlatformType.unknown -> project.objects.newInstance<KotlinNativeCompilerOptionsDefault>()
+ KotlinPlatformType.native -> project.objects.newInstance<KotlinNativeCompilerOptionsDefault>()
}
val target = ExternalKotlinTargetImpl(
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt
index ab9c94c..50c9281 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt
@@ -50,19 +50,16 @@
}
open class KotlinVariant(
- val producingCompilation: KotlinCompilation<*>,
+ override val target: KotlinTarget,
private val usages: Set<DefaultKotlinUsageContext>
) : InternalKotlinTargetComponent(), KotlinTargetComponentWithPublication {
var componentName: String? = null
var artifactTargetName: String = target.targetName
- final override val target: KotlinTarget
- get() = producingCompilation.target
-
override fun getUsages(): Set<KotlinUsageContext> = usages.publishableUsages()
- override fun getName(): String = componentName ?: producingCompilation.target.targetName
+ override fun getName(): String = componentName ?: target.targetName
override var publishable: Boolean = true
override val publishableOnCurrentHost: Boolean
@@ -90,16 +87,16 @@
}
open class KotlinVariantWithCoordinates(
- producingCompilation: KotlinCompilation<*>,
+ target: KotlinTarget,
usages: Set<DefaultKotlinUsageContext>,
-) : KotlinVariant(producingCompilation, usages),
+) : KotlinVariant(target, usages),
KotlinTargetComponentWithCoordinatesAndPublication /* Gradle 4.7+ API, don't use with older versions */
class KotlinVariantWithMetadataVariant(
- producingCompilation: KotlinCompilation<*>,
+ target: KotlinTarget,
usages: Set<DefaultKotlinUsageContext>,
internal val metadataTarget: AbstractKotlinTarget,
-) : KotlinVariantWithCoordinates(producingCompilation, usages), ComponentWithVariants {
+) : KotlinVariantWithCoordinates(target, usages), ComponentWithVariants {
override fun getVariants() = metadataTarget.components
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/PomDependenciesRewriter.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/PomDependenciesRewriter.kt
index c07be88..876a662 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/PomDependenciesRewriter.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/PomDependenciesRewriter.kt
@@ -30,6 +30,7 @@
}
}
+// FIXME: 28.11.2024 - Наверное смысл PomDependenciesRewriter'а в том чтобы переписывать зависимости на платформенные слайсы
internal abstract class PomDependenciesRewriter {
open val taskDependencies: Any? get() = null
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/Publishing.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/Publishing.kt
index e35ab96..0c0e630 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/Publishing.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/Publishing.kt
@@ -12,6 +12,9 @@
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Uklib
+import org.jetbrains.kotlin.gradle.artifacts.uklibsPublication.archiveUklibTask
+import org.jetbrains.kotlin.gradle.dsl.awaitMetadataTarget
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
@@ -34,6 +37,7 @@
project.extensions.configure(PublishingExtension::class.java) { publishing ->
createRootPublication(project, publishing).also(kotlinMultiplatformRootPublicationImpl::complete)
createTargetPublications(project, publishing)
+ createUklibSpecificMavenPublications(project, publishing)
}
} else {
kotlinMultiplatformRootPublicationImpl.complete(null)
@@ -55,6 +59,9 @@
(this as MavenPublicationInternal).publishWithOriginalFileName()
addKotlinToolingMetadataArtifactIfNeeded(project)
+ if (project.kotlinPropertiesProvider.publishUklib) {
+ addUklibArtifactAndChangePackaging(project)
+ }
}
}
@@ -67,6 +74,16 @@
}
}
+private fun MavenPublication.addUklibArtifactAndChangePackaging(project: Project) {
+ // FIXME: This will break coroutines !!!
+ pom.packaging = Uklib.UKLIB_PACKAGING
+ project.launch {
+ artifact(project.archiveUklibTask()) { artifact ->
+ artifact.extension = Uklib.UKLIB_EXTENSION
+ }
+ }
+}
+
private fun createTargetPublications(project: Project, publishing: PublishingExtension) {
val kotlin = project.multiplatformExtension
// Enforce the order of creating the publications, since the metadata publication is used in the other publications:
@@ -84,6 +101,22 @@
}
}
+private fun createUklibSpecificMavenPublications(project: Project, publishing: PublishingExtension) {
+ val publications = publishing.publications
+ project.launch {
+ val metadataTarget = project.multiplatformExtension.awaitMetadataTarget()
+ val componentPublication = publications.create("uklib", MavenPublication::class.java).apply {
+ artifactId = "${artifactId}-uklib"
+
+ // FIXME: jvm + uklib
+// artifact(
+//
+// )
+ }
+ metadataTarget.onPublicationCreated(componentPublication)
+ }
+}
+
private fun InternalKotlinTarget.createTargetSpecificMavenPublications(publications: PublicationContainer) {
kotlinComponents
.filter { kotlinComponent -> kotlinComponent.publishableOnCurrentHost }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt
index da42660..df4a03c 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt
@@ -137,6 +137,8 @@
}
KotlinTargetArtifact.extensionPoint.apply {
+ // FIXME: This isn't mpp only
+ // FIXME: Disabling this breaks KotlinTargetSoftwareComponentImpl
register(project, KotlinMetadataArtifact)
register(project, KotlinLegacyCompatibilityMetadataArtifact)
register(project, KotlinLegacyMetadataArtifact)
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/CreateTargetConfigurationsSideEffect.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/CreateTargetConfigurationsSideEffect.kt
index a23dd77..02408f2 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/CreateTargetConfigurationsSideEffect.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/CreateTargetConfigurationsSideEffect.kt
@@ -133,7 +133,12 @@
}
if (target is KotlinMetadataTarget) {
- if (target.project.kotlinPropertiesProvider.publishUklibVariant) {
+ if (target.project.kotlinPropertiesProvider.publishUklib) {
+ /**
+ * FIXME: 29.11.2024 - Do we actually want/need a consumable configuration?
+ *
+ * How will the POM publish with a project dependency and a multi-project publication?
+ */
configurations.maybeCreateConsumable(target.internal.uklibElementsConfigurationName).apply {
description = "Resource files of main compilation of ${target.name}."
isVisible = false
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidTarget.kt
index f15c43a..5c5e93a 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidTarget.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidTarget.kt
@@ -192,7 +192,6 @@
createKotlinVariant(
lowerCamelCaseName(compilation.target.name, *flavorGroupNameParts.toTypedArray()),
- compilation,
usageContexts,
).apply {
publishable = isVariantPublished(androidVariant)
@@ -281,6 +280,7 @@
compilation,
mavenScope,
dependencyConfigurationName,
+ // !!!
overrideConfigurationArtifacts = project.setProperty { listOf(artifact) },
overrideConfigurationAttributes = configuration.attributes.filterOutAndroidVariantAttributes()
)
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt
index a4badad..b58226b 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt
@@ -95,17 +95,16 @@
)
)
- val result = createKotlinVariant(componentName, mainCompilation, usageContexts)
+ val result = createKotlinVariant(componentName, usageContexts)
setOf(result)
}
override fun createKotlinVariant(
componentName: String,
- compilation: KotlinCompilation<*>,
usageContexts: Set<DefaultKotlinUsageContext>,
): KotlinVariant {
- return super.createKotlinVariant(componentName, compilation, usageContexts).apply {
+ return super.createKotlinVariant(componentName, usageContexts).apply {
artifactTargetName = wasmDecamelizedDefaultNameOrNull() ?: componentName
}
}
@@ -120,6 +119,7 @@
compilation = compilations.getByName(MAIN_COMPILATION_NAME),
mavenScope = KotlinUsageContext.MavenScope.COMPILE,
dependencyConfigurationName = commonFakeApiElementsConfigurationName,
+ // !!!
overrideConfigurationArtifacts = project.setProperty { emptyList() }
)
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt
index 900b6c0..0c1e278 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt
@@ -11,6 +11,8 @@
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
+import org.jetbrains.kotlin.gradle.artifacts.uklibStateAttribute
+import org.jetbrains.kotlin.gradle.artifacts.uklibStateUnzipped
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.dsl.metadataTarget
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
@@ -263,6 +265,7 @@
}
private val ResolvedArtifactResult.isMpp: Boolean get() = variant.attributes.containsMultiplatformAttributes
+ || variant.attributes.getAttribute(uklibStateAttribute) == uklibStateUnzipped
}
internal fun Project.locateOrRegisterGenerateProjectStructureMetadataTask(): TaskProvider<GenerateProjectStructureMetadata> =
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTarget.kt
index 059487d..fddb4f3 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTarget.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTarget.kt
@@ -67,7 +67,7 @@
mainCompilation,
KotlinUsageContext.MavenScope.COMPILE,
hostSpecificMetadataElementsConfigurationName,
- includeIntoProjectStructureMetadata = false
+ includeIntoProjectStructureMetadata = false,
)
)
}
@@ -87,7 +87,7 @@
)
)
- val result = createKotlinVariant(targetName, mainCompilation, mutableUsageContexts)
+ val result = createKotlinVariant(targetName, mutableUsageContexts)
setOf(result)
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/KotlinPlatformTypeUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/KotlinPlatformTypeUtils.kt
index 57dea70..113cd18 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/KotlinPlatformTypeUtils.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/KotlinPlatformTypeUtils.kt
@@ -14,6 +14,6 @@
KotlinPlatformType.jvm -> "Kotlin/JVM"
KotlinPlatformType.js -> "Kotlin/JS"
KotlinPlatformType.androidJvm -> "Kotlin/Android"
- KotlinPlatformType.native, KotlinPlatformType.unknown -> "Kotlin/Native"
+ KotlinPlatformType.native -> "Kotlin/Native"
KotlinPlatformType.wasm -> "Kotlin/Wasm"
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/regressionTests/KT71398KotlinNativeBundleConfigurationOnUnsupportedPlatform.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/regressionTests/KT71398KotlinNativeBundleConfigurationOnFailOnPublicationAndIgnoreForConsumptionPlatform.kt
similarity index 93%
rename from libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/regressionTests/KT71398KotlinNativeBundleConfigurationOnUnsupportedPlatform.kt
rename to libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/regressionTests/KT71398KotlinNativeBundleConfigurationOnFailOnPublicationAndIgnoreForConsumptionPlatform.kt
index fbfe006..0f511d7 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/regressionTests/KT71398KotlinNativeBundleConfigurationOnUnsupportedPlatform.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/regressionTests/KT71398KotlinNativeBundleConfigurationOnFailOnPublicationAndIgnoreForConsumptionPlatform.kt
@@ -14,7 +14,7 @@
import kotlin.test.Test
import kotlin.test.assertNull
-class KT71398KotlinNativeBundleConfigurationOnUnsupportedPlatform {
+class KT71398KotlinNativeBundleConfigurationOnFailOnPublicationAndIgnoreForConsumptionPlatform {
@Test
fun `KT-71398 - project with multiplatform plugin should not add kotlinNativeBundleConfiguration`() {
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/IdeKotilnCompilerArgumentsResolverTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/IdeKotilnCompilerArgumentsResolverTest.kt
index b2500bd..b03ec8b 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/IdeKotilnCompilerArgumentsResolverTest.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/IdeKotilnCompilerArgumentsResolverTest.kt
@@ -62,7 +62,7 @@
else parseCommandLineArguments<K2MetadataCompilerArguments>(argumentsList)
KotlinPlatformType.jvm, KotlinPlatformType.androidJvm -> parseCommandLineArguments<K2JVMCompilerArguments>(argumentsList)
KotlinPlatformType.js, KotlinPlatformType.wasm -> parseCommandLineArguments<K2JSCompilerArguments>(argumentsList)
- KotlinPlatformType.native, KotlinPlatformType.unknown -> parseCommandLineArguments<K2NativeCompilerArguments>(argumentsList)
+ KotlinPlatformType.native -> parseCommandLineArguments<K2NativeCompilerArguments>(argumentsList)
}
val parsedArgumentsList = parsedArguments.toArgumentStrings(shortArgumentKeys = true, compactArgumentValues = false)
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/UklibResolutionTests.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/UklibResolutionTests.kt
new file mode 100644
index 0000000..b49741d
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/UklibResolutionTests.kt
@@ -0,0 +1,761 @@
+/*
+ * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.gradle.unitTests
+
+import org.gradle.api.Project
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.attributes.Attribute
+import org.gradle.kotlin.dsl.maven
+import org.jetbrains.kotlin.gradle.artifacts.UklibResolutionStrategy
+import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
+import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
+import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration
+import org.jetbrains.kotlin.gradle.plugin.sources.internal
+import org.jetbrains.kotlin.gradle.util.*
+import org.jetbrains.kotlin.gradle.utils.projectPathOrNull
+import org.jetbrains.kotlin.utils.keysToMap
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.reflect.full.*
+
+class UklibResolutionTests {
+
+ @Test
+ fun `uklib resolution - from direct pom dependency with uklib packaging`() {
+ val consumer = consumer(UklibResolutionStrategy.AllowResolvingUklibs) {
+ jvm()
+ iosArm64()
+ iosX64()
+ js()
+ wasmJs()
+ wasmWasi()
+
+ sourceSets.commonMain.dependencies {
+ implementation("foo.bar:pure-maven-uklib:1.0")
+ }
+ }
+
+ val metadataCompilationVariants = consumer.multiplatformExtension.sourceSets.getByName("commonMain")
+ .internal.resolvableMetadataConfiguration
+ .resolveProjectDependencyComponentsWithArtifacts()
+ val iosArm64CompilationVariants = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
+ .configurations.compileDependencyConfiguration.resolveProjectDependencyComponentsWithArtifacts()
+ val jvmRuntimeVariants = consumer.multiplatformExtension.jvm().compilations.getByName("main")
+ .configurations.runtimeDependencyConfiguration!!.resolveProjectDependencyComponentsWithArtifacts()
+ val jsRuntimeVariants = consumer.multiplatformExtension.js().compilations.getByName("main")
+ .configurations.runtimeDependencyConfiguration!!.resolveProjectDependencyComponentsWithArtifacts()
+ val wasmJsVariants = consumer.multiplatformExtension.wasmJs().compilations.getByName("main")
+ .configurations.runtimeDependencyConfiguration!!.resolveProjectDependencyComponentsWithArtifacts()
+ val wasmWasiVariants = consumer.multiplatformExtension.wasmWasi().compilations.getByName("main")
+ .configurations.runtimeDependencyConfiguration!!.resolveProjectDependencyComponentsWithArtifacts()
+
+ assertEquals(
+ mapOf(
+ ":" to ResolvedComponentWithArtifacts(
+ configuration="commonMainResolvableDependenciesMetadata",
+ artifacts=mutableListOf()
+ ),
+ "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+ configuration="compile",
+ artifacts=mutableListOf(jvmPomApiAttributes + uklibTransformationMetadataAttributes)
+ ),
+ ),
+ metadataCompilationVariants
+ )
+
+ assertEquals(
+ mapOf(
+ ":" to ResolvedComponentWithArtifacts(
+ configuration="iosArm64CompileKlibraries",
+ artifacts=mutableListOf()
+ ),
+ "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+ configuration="compile",
+ artifacts=mutableListOf(jvmPomApiAttributes + uklibTransformationIosArm64Attributes)
+ ),
+ ),
+ iosArm64CompilationVariants
+ )
+
+ assertEquals(
+ mapOf(
+ ":" to ResolvedComponentWithArtifacts(
+ configuration="jvmRuntimeClasspath",
+ artifacts=mutableListOf()
+ ),
+ "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+ configuration="runtime",
+ artifacts=mutableListOf(jvmPomRuntimeAttributes + uklibTransformationJvmAttributes)
+ ),
+ ),
+ jvmRuntimeVariants
+ )
+
+ assertEquals(
+ mapOf(
+ ":" to ResolvedComponentWithArtifacts(
+ configuration="jsRuntimeClasspath",
+ artifacts=mutableListOf()
+ ),
+ "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+ configuration="runtime",
+ artifacts=mutableListOf(jvmPomRuntimeAttributes + uklibTransformationJsAttributes)
+ ),
+ ),
+ jsRuntimeVariants
+ )
+
+ assertEquals(
+ mapOf(
+ ":" to ResolvedComponentWithArtifacts(
+ configuration="wasmJsRuntimeClasspath",
+ artifacts=mutableListOf()
+ ),
+ "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+ configuration="runtime",
+ artifacts=mutableListOf(jvmPomRuntimeAttributes + uklibTransformationWasmJsAttributes)
+ ),
+ ),
+ wasmJsVariants
+ )
+
+ assertEquals(
+ mapOf(
+ ":" to ResolvedComponentWithArtifacts(
+ configuration="wasmWasiRuntimeClasspath",
+ artifacts=mutableListOf()
+ ),
+ "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+ configuration="runtime",
+ artifacts=mutableListOf(jvmPomRuntimeAttributes + uklibTransformationWasmWasiAttributes)
+ ),
+ ),
+ wasmWasiVariants
+ )
+ }
+
+ @Test
+ fun `uklib resolution - from direct pom dependency with uklib packaging points to untrasformed uklib - when uklibs are not allowed to resolve`() {
+ val consumer = consumer(UklibResolutionStrategy.ResolveOnlyPlatformSpecificVariant) {
+ jvm()
+ iosArm64()
+ iosX64()
+
+ sourceSets.commonMain.dependencies {
+ implementation("foo.bar:pure-maven-uklib:1.0")
+ }
+ }
+
+ /**
+ * FIXME: This is unfortunate and in opposition to how KMP dependencies resolve right now because:
+ *
+ * KMP dependencies will fail to resolve if they have a missing platform/native type attribute
+ *
+ * but this is similar to how pure java dependencies (e.g. com.google.guava:guava:+) will resolve just fine
+ */
+
+ val metadataCompilationVariants = consumer.multiplatformExtension.sourceSets.getByName("commonMain")
+ .internal.resolvableMetadataConfiguration
+ .resolveProjectDependencyComponentsWithArtifacts()
+ val iosArm64CompilationVariants = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
+ .configurations.compileDependencyConfiguration.resolveProjectDependencyComponentsWithArtifacts()
+ val jvmRuntimeVariants = consumer.multiplatformExtension.jvm().compilations.getByName("main")
+ .configurations.runtimeDependencyConfiguration!!.resolveProjectDependencyComponentsWithArtifacts()
+
+ assertEquals(
+ mapOf(
+ ":" to ResolvedComponentWithArtifacts(
+ configuration="commonMainResolvableDependenciesMetadata",
+ artifacts=mutableListOf()
+ ),
+ "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+ configuration="compile",
+ artifacts=mutableListOf(jvmPomApiAttributes + uklibArtifact)
+ ),
+ ),
+ metadataCompilationVariants
+ )
+
+ assertEquals(
+ mapOf(
+ ":" to ResolvedComponentWithArtifacts(
+ configuration="iosArm64CompileKlibraries",
+ artifacts=mutableListOf()
+ ),
+ "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+ configuration="compile",
+ artifacts=mutableListOf(jvmPomApiAttributes + uklibArtifact)
+ ),
+ ),
+ iosArm64CompilationVariants
+ )
+
+ assertEquals(
+ mapOf(
+ ":" to ResolvedComponentWithArtifacts(
+ configuration="jvmRuntimeClasspath",
+ artifacts=mutableListOf()
+ ),
+ "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+ configuration="runtime",
+ artifacts=mutableListOf(jvmPomRuntimeAttributes + uklibArtifact)
+ ),
+ ),
+ jvmRuntimeVariants
+ )
+ }
+
+ // consumer <- pure jvm <- uklib <- PSM-only
+ @Test
+ fun `uklib resolution - from transitive uklib dependency`() {
+ val consumer = consumer(UklibResolutionStrategy.AllowResolvingUklibs) {
+ jvm()
+ iosArm64()
+ iosX64()
+
+ sourceSets.commonMain.dependencies {
+ implementation("foo.bar:pure-maven-jvm-with-trasitive-uklib-dependency:1.0")
+ }
+ }
+
+ val metadataCompilationVariants = consumer.multiplatformExtension.sourceSets.getByName("commonMain")
+ .internal.resolvableMetadataConfiguration
+ .resolveProjectDependencyComponentsWithArtifacts()
+
+ val iosArm64CompilationVariants = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
+ .configurations.compileDependencyConfiguration.resolveProjectDependencyComponentsWithArtifacts()
+
+ val jvmRuntimeVariants = consumer.multiplatformExtension.jvm().compilations.getByName("main")
+ .configurations.runtimeDependencyConfiguration!!.resolveProjectDependencyComponentsWithArtifacts()
+
+ assertEquals(
+ mapOf(
+ ":" to ResolvedComponentWithArtifacts(
+ configuration="commonMainResolvableDependenciesMetadata",
+ artifacts=mutableListOf()
+ ),
+ "foo.bar:pure-maven-jvm-with-trasitive-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
+ configuration="compile",
+ artifacts=mutableListOf(jvmPomApiAttributes + jarArtifact)
+ ),
+ "foo.bar:pure-maven-uklib-with-transitive-non-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
+ configuration="compile",
+ artifacts=mutableListOf(jvmPomApiAttributes + uklibTransformationMetadataAttributes)
+ ),
+ "foo.bar:uklib-maven-gradle-packaging:1.0" to ResolvedComponentWithArtifacts(
+ configuration="metadataApiElements",
+ artifacts=mutableListOf(metadataVariantAttributes + releaseStatus)
+ ),
+ ).pp(),
+ metadataCompilationVariants.pp()
+ )
+
+ assertEquals(
+ mapOf(
+ ":" to ResolvedComponentWithArtifacts(
+ configuration="jvmRuntimeClasspath",
+ artifacts=mutableListOf()
+ ),
+ "foo.bar:pure-maven-jvm-with-trasitive-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
+ configuration="runtime",
+ artifacts=mutableListOf(jvmPomRuntimeAttributes + jarArtifact)
+ ),
+ "foo.bar:pure-maven-uklib-with-transitive-non-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
+ configuration="runtime",
+ artifacts=mutableListOf(jvmPomRuntimeAttributes + uklibTransformationJvmAttributes)
+ ),
+ "foo.bar:uklib-maven-gradle-packaging:1.0" to ResolvedComponentWithArtifacts(
+ configuration="jvmRuntimeElements-published",
+ artifacts=mutableListOf()
+ ),
+ "foo.bar:uklib-maven-gradle-packaging-jvm:1.0" to ResolvedComponentWithArtifacts(
+ configuration="jvmRuntimeElements-published",
+ artifacts=mutableListOf(platformJvmVariantAttributes + releaseStatus)
+ ),
+ ),
+ jvmRuntimeVariants
+ )
+
+ assertEquals(
+ mapOf(
+ ":" to ResolvedComponentWithArtifacts(
+ configuration="iosArm64CompileKlibraries",
+ artifacts=mutableListOf()
+ ),
+ "foo.bar:pure-maven-jvm-with-trasitive-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
+ configuration="compile",
+ artifacts=mutableListOf(jvmPomApiAttributes + jarArtifact)
+ ),
+ "foo.bar:pure-maven-uklib-with-transitive-non-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
+ configuration="compile",
+ artifacts=mutableListOf(jvmPomApiAttributes + uklibTransformationIosArm64Attributes)
+ ),
+ "foo.bar:uklib-maven-gradle-packaging:1.0" to ResolvedComponentWithArtifacts(
+ configuration="iosArm64ApiElements-published",
+ artifacts=mutableListOf()
+ ),
+ "foo.bar:uklib-maven-gradle-packaging-iosarm64:1.0" to ResolvedComponentWithArtifacts(
+ configuration="iosArm64ApiElements-published",
+ // klib + cinterop klib
+ artifacts=mutableListOf(
+ platformIosArm64Attributes + releaseStatus,
+ platformIosArm64Attributes + releaseStatus,
+ )
+ ),
+ ),
+ iosArm64CompilationVariants
+ )
+ }
+
+// @Test
+ fun `resolve uklib - in Swift Export and ObjC binaries export configurations`() {
+ error("TODO")
+ }
+
+// @Test
+ fun `resolve uklib - in resolvable JS configurations with klibs`() {
+ error("TODO")
+ }
+
+ // ---
+ private fun consumer(
+ strategy: UklibResolutionStrategy,
+ configure: KotlinMultiplatformExtension.() -> Unit,
+ ): Project {
+ return buildProjectWithMPP(
+ preApplyCode = {
+ publishUklibVariant()
+ fakeUklibTransforms()
+ setUklibResolutionStrategy(strategy)
+ // Test stdlib in a separate test
+ enableDefaultStdlibDependency(false)
+ enableDefaultJsDomApiDependency(false)
+ }
+ ) {
+ kotlin {
+ configure()
+ }
+
+ repositories.maven(javaClass.getResource("/dependenciesResolution/UklibTests/repo")!!)
+ }.evaluate()
+ }
+
+ // @Test
+ fun `prefer klib variant`() {
+ val consumer = mixedCompilationsGraphConsumer(
+ uklibResolutionStrategy = UklibResolutionStrategy.AllowResolvingUklibs,
+ )
+
+ val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
+ .configurations.compileDependencyConfiguration
+ val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
+
+ val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
+ .configurations.runtimeDependencyConfiguration!!
+ val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
+
+ assertEquals(
+ mapOf(
+ ":E_consumes_D" to ResolvedComponentWithArtifacts(
+ configuration="jvmRuntimeClasspath",
+ artifacts=mutableListOf()
+ ),
+ ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
+ configuration="jvmRuntimeElements",
+ artifacts=mutableListOf(platformJvmVariantAttributes)
+ ),
+ ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
+ configuration="metadataUklibElements",
+ artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes)
+ ),
+ ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
+ configuration="jvmRuntimeElements",
+ artifacts=mutableListOf(platformJvmVariantAttributes)
+ ),
+ ":A_produces_uklib" to ResolvedComponentWithArtifacts(
+ configuration="jvmRuntimeElements",
+ artifacts=mutableListOf(platformJvmVariantAttributes),
+ )
+ ),
+ jvmResolvedVariants
+ )
+
+ assertEquals(
+ mapOf(
+ ":E_consumes_D" to ResolvedComponentWithArtifacts(
+ configuration="iosArm64CompileKlibraries",
+ artifacts=mutableListOf()
+ ),
+ ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
+ configuration="iosArm64ApiElements",
+ artifacts=mutableListOf(platformIosArm64Attributes + nonPacked)
+ ),
+ ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
+ configuration="metadataUklibElements",
+ artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes)
+ ),
+ ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
+ configuration="iosArm64ApiElements",
+ artifacts=mutableListOf(platformIosArm64Attributes + nonPacked)
+ ),
+ ":A_produces_uklib" to ResolvedComponentWithArtifacts(
+ configuration="iosArm64ApiElements",
+ artifacts=mutableListOf(platformIosArm64Attributes + nonPacked),
+ )
+ ),
+ iosArm64ResolvedVariants
+ )
+ }
+
+ // @Test
+ fun `prefer uklib variant`() {
+ val consumer = mixedCompilationsGraphConsumer(
+ uklibResolutionStrategy = UklibResolutionStrategy.AllowResolvingUklibs,
+ )
+
+ val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
+ .configurations.compileDependencyConfiguration
+ val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
+
+ val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
+ .configurations.runtimeDependencyConfiguration!!
+ // FIXME: java-api variant doesn't resolve A
+ val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
+
+ assertEquals(
+ mapOf(
+ ":E_consumes_D" to ResolvedComponentWithArtifacts(
+ configuration="jvmRuntimeClasspath",
+ artifacts=mutableListOf()
+ ),
+ ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
+ configuration="metadataUklibElements",
+ artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes)
+ ),
+ ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
+ configuration="metadataUklibElements",
+ artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes)
+ ),
+ ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
+ configuration="jvmRuntimeElements",
+ artifacts=mutableListOf(platformJvmVariantAttributes)
+ ),
+ ":A_produces_uklib" to ResolvedComponentWithArtifacts(
+ configuration="metadataUklibElements",
+ artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes),
+ )
+ ),
+ jvmResolvedVariants
+ )
+
+ assertEquals(
+ mapOf(
+ ":E_consumes_D" to ResolvedComponentWithArtifacts(
+ configuration="iosArm64CompileKlibraries",
+ artifacts=mutableListOf()
+ ),
+ ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
+ configuration="metadataUklibElements",
+ artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes)
+ ),
+ ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
+ configuration="metadataUklibElements",
+ artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes)
+ ),
+ ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
+ configuration="iosArm64ApiElements",
+ artifacts=mutableListOf(platformIosArm64Attributes + nonPacked)
+ ),
+ ":A_produces_uklib" to ResolvedComponentWithArtifacts(
+ configuration="metadataUklibElements",
+ artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes),
+ )
+ ),
+ iosArm64ResolvedVariants
+ )
+ }
+
+ private fun mixedCompilationsGraphConsumer(
+ uklibResolutionStrategy: UklibResolutionStrategy,
+ ): Project {
+ val root = buildProject()
+ return root.child(
+ "E_consumes_D",
+ uklibResolutionStrategy = uklibResolutionStrategy,
+ consume= root.child(
+ "D_produces_uklib_consumes_C",
+ consume = root.child(
+ "C_produces_only_uklib_consumes_B",
+ disablePlatformComponentReferences = true,
+ consume = root.child(
+ "B_produces_only_platform_variant_consumes_A",
+ publishUklibVariant = false,
+ consume = root.child(
+ "A_produces_uklib",
+ consume = null
+ )
+ )
+ )
+ )
+ )
+ }
+
+ private val uklibTransformationIosArm64Attributes = mapOf(
+ "artifactType" to "uklib",
+ "uklibDestination" to "ios_arm64",
+ "uklibState" to "unzipped",
+ )
+
+ private val uklibTransformationJvmAttributes = mapOf(
+ "artifactType" to "uklib",
+ "uklibDestination" to "jvm",
+ "uklibState" to "unzipped",
+ )
+
+ private val uklibTransformationMetadataAttributes = mapOf(
+ "artifactType" to "uklib",
+ "uklibDestination" to "common",
+ "uklibState" to "unzipped",
+ )
+
+ private val uklibTransformationJsAttributes = mapOf(
+ "artifactType" to "uklib",
+ "uklibDestination" to "js_ir",
+ "uklibState" to "unzipped",
+ )
+
+ private val uklibTransformationWasmJsAttributes = mapOf(
+ "artifactType" to "uklib",
+ "uklibDestination" to "wasm_js",
+ "uklibState" to "unzipped",
+ )
+
+ private val uklibTransformationWasmWasiAttributes = mapOf(
+ "artifactType" to "uklib",
+ "uklibDestination" to "wasm_wasi",
+ "uklibState" to "unzipped",
+ )
+
+ private val uklibVariantAttributes = mapOf(
+ "org.gradle.category" to "library",
+ "org.gradle.jvm.environment" to "???",
+ "org.gradle.usage" to "kotlin-uklib",
+ "org.jetbrains.kotlin.klib.packaging" to "packed",
+ "org.jetbrains.kotlin.native.target" to "???",
+ "org.jetbrains.kotlin.platform.type" to "unknown",
+ )
+
+ private val jvmPomRuntimeAttributes = mapOf(
+ "org.gradle.category" to "library",
+ "org.gradle.libraryelements" to "jar",
+ "org.gradle.status" to "release",
+ "org.gradle.usage" to "java-runtime",
+ )
+
+ private val jvmPomApiAttributes = mapOf(
+ "org.gradle.category" to "library",
+ "org.gradle.libraryelements" to "jar",
+ "org.gradle.status" to "release",
+ "org.gradle.usage" to "java-api",
+ )
+
+ private val platformJvmVariantAttributes = mapOf(
+ "artifactType" to "jar",
+ "org.gradle.category" to "library",
+ "org.gradle.jvm.environment" to "standard-jvm",
+ "org.gradle.libraryelements" to "jar",
+ "org.gradle.usage" to "java-runtime",
+ "org.jetbrains.kotlin.platform.type" to "jvm",
+ )
+
+ private val metadataVariantAttributes = mapOf(
+ "artifactType" to "jar",
+ "org.gradle.category" to "library",
+ "org.gradle.jvm.environment" to "non-jvm",
+ "org.gradle.libraryelements" to "jar",
+ "org.gradle.usage" to "kotlin-metadata",
+ "org.jetbrains.kotlin.platform.type" to "common",
+ )
+
+ private val releaseStatus = mapOf(
+ "org.gradle.status" to "release",
+ )
+
+ // We only emit packing in secondary variants which are not published?
+ private val nonPacked = mapOf(
+ "org.jetbrains.kotlin.klib.packaging" to "non-packed",
+ )
+
+ private val jarArtifact = mapOf(
+ "artifactType" to "jar",
+ )
+
+ private val uklibArtifact = mapOf(
+ "artifactType" to "uklib",
+ )
+
+ private val platformIosArm64Attributes = mapOf(
+ "artifactType" to "org.jetbrains.kotlin.klib",
+ "org.gradle.category" to "library",
+ "org.gradle.jvm.environment" to "non-jvm",
+ "org.gradle.usage" to "kotlin-api",
+ "org.jetbrains.kotlin.cinteropCommonizerArtifactType" to "klib",
+ "org.jetbrains.kotlin.native.target" to "ios_arm64",
+ "org.jetbrains.kotlin.platform.type" to "native",
+ )
+
+ data class ResolvedComponentWithArtifacts(
+ val configuration: String,
+ val artifacts: MutableList<Map<String, String>> = mutableListOf(),
+ )
+
+ private fun Configuration.resolveProjectDependencyComponentsWithArtifacts(): Map<String, ResolvedComponentWithArtifacts> {
+ val artifacts = resolveProjectDependencyVariantsFromArtifacts()
+ val components = resolveProjectDependencyComponents()
+ val componentToArtifacts = LinkedHashMap<String, ResolvedComponentWithArtifacts>()
+ components.forEach { component ->
+ if (componentToArtifacts[component.path] == null) {
+ componentToArtifacts[component.path] = ResolvedComponentWithArtifacts(component.configuration)
+ } else {
+ error("${component} resolved multiple times?")
+ }
+ }
+ artifacts.forEach { artifact ->
+ componentToArtifacts[artifact.path]?.let {
+ it.artifacts.add(artifact.attributes)
+ } ?: error("Missing resolved component for artifact: ${artifact}")
+ }
+ return componentToArtifacts
+ }
+
+ data class ResolvedVariant(
+ val path: String,
+ val attributes: Map<String, String>,
+ )
+
+ private fun Configuration.resolveProjectDependencyVariantsFromArtifacts(): List<ResolvedVariant> {
+ return incoming.artifacts.artifacts
+ .map { artifact ->
+ val uklibAttributes: List<Attribute<*>> = artifact.variant.attributes.keySet()
+ .sortedBy { it.name }
+ ResolvedVariant(
+ artifact.variant.owner.projectPathOrNull ?: artifact.variant.owner.displayName,
+ uklibAttributes.keysToMap {
+ artifact.variant.attributes.getAttribute(it as Attribute<*>).toString()
+ }.mapKeys { it.key.name }
+ )
+ }
+ }
+
+ data class ResolvedComponent(
+ val path: String,
+ val configuration: String,
+ )
+
+ private fun Configuration.resolveProjectDependencyComponents(): List<ResolvedComponent> {
+ return incoming.resolutionResult.allComponents
+ .map { component ->
+ ResolvedComponent(
+ component.id.projectPathOrNull ?: component.id.displayName,
+ // Expect a single variant to always be selected?
+ component.variants.single().displayName
+ )
+ }
+ }
+
+ private fun Project.child(
+ name: String,
+ consume: Project?,
+ publishUklibVariant: Boolean = true,
+ disablePlatformComponentReferences: Boolean = false,
+ uklibResolutionStrategy: UklibResolutionStrategy = UklibResolutionStrategy.ResolveOnlyPlatformSpecificVariant,
+ ): Project {
+ val parent = this
+ return buildProjectWithMPP(
+ preApplyCode = {
+ if (publishUklibVariant) {
+ publishUklibVariant()
+ }
+ fakeUklibTransforms()
+ setUklibResolutionStrategy(uklibResolutionStrategy)
+ disablePlatformSpecificComponentReferences(disablePlatformComponentReferences)
+ // Test stdlib in a separate test
+ enableDefaultStdlibDependency(false)
+ enableDefaultJsDomApiDependency(false)
+ },
+ projectBuilder = {
+ withParent(parent)
+ withName(name)
+ }
+ ) {
+ kotlin {
+ iosArm64()
+ iosX64()
+ jvm()
+
+ if (consume != null) {
+ sourceSets.commonMain.dependencies {
+ implementation(project(consume.project.path))
+ }
+ }
+ }
+ }.evaluate()
+ }
+}
+
+class PP(
+ val value: Any,
+ val indentation: Int,
+) {
+ override fun toString(): String {
+ val twoSpaces = " ".repeat(2)
+ val indentationSpace = " ".repeat(indentation)
+ val nextIndentationDepth = indentation + 2
+ val elements: Array<String> = when (value) {
+ is Map<*, *> -> arrayOf(
+ "{",
+ *value.map { it }.sortedBy { it.key.toString() }.map { "${twoSpaces}${it.key}=${it.value?.pp(nextIndentationDepth)}," }.toTypedArray(),
+ "}",
+ )
+ is List<*> -> arrayOf(
+ "[",
+ *value.map { "${twoSpaces}${it?.pp(nextIndentationDepth)}," }.toTypedArray(),
+ "]",
+ )
+ else -> {
+ val packageName = value::class.java.packageName
+ if (packageName.startsWith("kotlin.") || packageName.startsWith("java.")) {
+ arrayOf(value.toString())
+ } else {
+ val kClass = value::class
+ arrayOf(
+ "${kClass.simpleName}(",
+ *kClass.memberProperties.map { prop ->
+ "${twoSpaces}${prop.name}=${prop.getter.call(value)?.pp(nextIndentationDepth)},"
+ }.toTypedArray(),
+ ")",
+ )
+ }
+ }
+ }
+
+ if (elements.size == 1) return elements[0]
+
+ return (listOf(elements[0]) + elements.toList().subList(1, elements.size).map { "${indentationSpace}${it}" }).joinToString("\n")
+ }
+
+ override fun hashCode(): Int {
+ return value.hashCode()
+ }
+
+ override fun equals(other: Any?): Boolean {
+ var otherUnwrapped = other
+ if (other is PP) otherUnwrapped = other.value
+ return value.equals(otherUnwrapped)
+ }
+}
+
+private fun Any.pp(indentation: Int = 0): PP = PP(this, indentation)
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/UklibTests.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/UklibTests.kt
deleted file mode 100644
index 8aa653a..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/UklibTests.kt
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
- */
-
-package org.jetbrains.kotlin.gradle.unitTests
-
-import org.gradle.api.Project
-import org.gradle.api.artifacts.Configuration
-import org.gradle.api.attributes.Attribute
-import org.gradle.api.attributes.Usage
-import org.gradle.kotlin.dsl.maven
-import org.gradle.kotlin.dsl.named
-import org.jetbrains.kotlin.gradle.artifacts.UklibResolutionStrategy
-import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
-import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
-import org.jetbrains.kotlin.gradle.util.*
-import org.jetbrains.kotlin.gradle.utils.projectPathOrNull
-import org.jetbrains.kotlin.utils.keysToMap
-import kotlin.test.Test
-import kotlin.test.assertEquals
-
-class UklibTests {
-
- @Test
- fun `resolve uklib - from pom with uklib packaging`() {
- val consumer = consumer(UklibResolutionStrategy.PreferPlatformSpecificVariant) {
- sourceSets.commonMain.dependencies {
- // FIXME: Everything works kind of nicely, but either the consumer has to publish a separate component for pure Maven jar consumption, or Maven has to know about uklibs
- implementation("foo.bar:regular-maven-jar-packaging-with-uklib-uklib-dependency:1.0")
- }
- }
-
- val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
- .configurations.compileDependencyConfiguration
- val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
- val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
- .configurations.runtimeDependencyConfiguration!!
- val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
- assertEquals(
- mapOf(
- ":" to ResolvedComponentWithArtifacts(
- configuration="jvmRuntimeClasspath",
- artifacts=mutableListOf()
- ),
- "foo.bar:regular-maven-jar-packaging-with-uklib-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
- configuration="runtime",
- artifacts=mutableListOf(jvmPomRuntimeAttributes + jarArtifact)
- ),
- "foo.bar:uklib-maven-uklib-packaging:1.0" to ResolvedComponentWithArtifacts(
- configuration="runtime",
- artifacts=mutableListOf(jvmPomRuntimeAttributes + uklibTransformationJvmAttributes)
- ),
- "foo.bar:uklib-maven-gradle-packaging:1.0" to ResolvedComponentWithArtifacts(
- configuration="jvmRuntimeElements-published",
- artifacts=mutableListOf()
- ),
- "foo.bar:uklib-maven-gradle-packaging-jvm:1.0" to ResolvedComponentWithArtifacts(
- configuration="jvmRuntimeElements-published",
- artifacts=mutableListOf(platformJvmVariantAttributes + releaseStatus)
- ),
- ),
- jvmResolvedVariants
- )
-
- assertEquals(
- mapOf(
- ":" to ResolvedComponentWithArtifacts(
- configuration="iosArm64CompileKlibraries",
- artifacts=mutableListOf()
- ),
- "foo.bar:regular-maven-jar-packaging-with-uklib-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
- configuration="compile",
- artifacts=mutableListOf(jvmPomApiAttributes + jarArtifact)
- ),
- "foo.bar:uklib-maven-uklib-packaging:1.0" to ResolvedComponentWithArtifacts(
- configuration="compile",
- artifacts=mutableListOf(jvmPomApiAttributes + uklibTransformationIosArm64Attributes)
- ),
- "foo.bar:uklib-maven-gradle-packaging:1.0" to ResolvedComponentWithArtifacts(
- configuration="iosArm64ApiElements-published",
- artifacts=mutableListOf()
- ),
- "foo.bar:uklib-maven-gradle-packaging-iosarm64:1.0" to ResolvedComponentWithArtifacts(
- configuration="iosArm64ApiElements-published",
- // klib + cinterop klib
- artifacts=mutableListOf(
- platformIosArm64Attributes + releaseStatus,
- platformIosArm64Attributes + releaseStatus,
- )
- ),
- ),
- iosArm64ResolvedVariants
- )
- }
-
- @Test
- fun `resolve uklib - from pom with jar packaging - with explicit extension`() {
- val consumer = consumer(UklibResolutionStrategy.PreferPlatformSpecificVariant) {
- sourceSets.commonMain.dependencies {
- /**
- * FIXME: If this dependency is brought transitively, it's unclear how the regular-maven-jar-packaging POM should specify the dependency on a uklib, such that both KGP and Maven consumers can depend on it easily
- *
- * This could work with variant reselection, but then we have to use artifactViews
- */
- // implementation("foo.bar:regular-maven-jar-packaging:1.0")
- implementation("foo.bar:uklib-maven-jar-packaging:1.0@uklib") {
- // FIXME: Why does explicit extension specification unset transitiveness?
- assert(!isTransitive)
- isTransitive = true
- }
- }
- }
-
- val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
- .configurations.compileDependencyConfiguration
- val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
- val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
- .configurations.runtimeDependencyConfiguration!!
- val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
- assertEquals(
- mapOf(
- ":" to ResolvedComponentWithArtifacts(
- configuration="jvmRuntimeClasspath",
- artifacts=mutableListOf()
- ),
- "foo.bar:uklib-maven-jar-packaging:1.0" to ResolvedComponentWithArtifacts(
- configuration="runtime",
- artifacts=mutableListOf(uklibTransformationJvmAttributes + releaseStatus)
- ),
- "foo.bar:uklib-maven-gradle-packaging:1.0" to ResolvedComponentWithArtifacts(
- configuration="jvmRuntimeElements-published",
- artifacts=mutableListOf()
- ),
- "foo.bar:uklib-maven-gradle-packaging-jvm:1.0" to ResolvedComponentWithArtifacts(
- configuration="jvmRuntimeElements-published",
- artifacts=mutableListOf(platformJvmVariantAttributes + releaseStatus)
- ),
- ),
- jvmResolvedVariants
- )
-
- assertEquals(
- mapOf(
- ":" to ResolvedComponentWithArtifacts(
- configuration="iosArm64CompileKlibraries",
- artifacts=mutableListOf()
- ),
- "foo.bar:uklib-maven-jar-packaging:1.0" to ResolvedComponentWithArtifacts(
- configuration="compile",
- artifacts=mutableListOf(uklibTransformationIosArm64Attributes + releaseStatus)
- ),
- "foo.bar:uklib-maven-gradle-packaging:1.0" to ResolvedComponentWithArtifacts(
- configuration="iosArm64ApiElements-published",
- artifacts=mutableListOf()
- ),
- "foo.bar:uklib-maven-gradle-packaging-iosarm64:1.0" to ResolvedComponentWithArtifacts(
- configuration="iosArm64ApiElements-published",
- artifacts=mutableListOf(
- platformIosArm64Attributes + releaseStatus,
- platformIosArm64Attributes + releaseStatus,
- )
- ),
- ),
- iosArm64ResolvedVariants
- )
- }
-
-
- // FIXME: Maybe this is usable?
-// consumer.configurations.configureEach {
-// if (it.isCanBeResolved) {
-// it.resolutionStrategy.eachDependency {
-// it.artifactSelection {
-//
-// }
-// }
-// it.resolutionStrategy.componentSelection.all {
-// it.
-// }
-// }
-// }
- @Test
- fun `resolve uklib - from pom with jar packaging - with explicit extension - and component rule`() {
- val consumer = consumer(UklibResolutionStrategy.PreferUklibVariant) {
- sourceSets.commonMain.dependencies {
- // implementation("foo.bar:uklib-maven-jar-packaging:1.0")
- // consume "foo.bar:uklib-maven-jar-packaging:1.0" transitively
- // FIXME: With a naive component metadata rule regular jars fail to resolve
- implementation("foo.bar:regular-maven-jar-packaging-with-uklib-jar-dependency:1.0")
- }
-
- project.dependencies.components.all { component ->
- component.maybeAddVariant(
- "uklib",
- // FIXME: runtime?
- "compile",
- ) {
- // How do you know that the file will be there?
- it.withFiles {
- // When there are multiple artifacts, Gradle doesn't set artifactType
- it.removeAllFiles()
- it.addFile("${component.id.name}-${component.id.version}.uklib")
- }
- it.attributes.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(KotlinUsages.KOTLIN_UKLIB))
- }
- }
- }
-
- val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
- .configurations.compileDependencyConfiguration
- val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
- val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
- .configurations.runtimeDependencyConfiguration!!
- val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
- // ???
- }
-
- // @Test
- // FIXME: This is probably pretty useless because with the classifier artifactType has to be jar and its unclear how to force a transform
- fun `resolve uklib - from pom with jar packaging - with explicit classifier`() {
- val consumer = consumer(UklibResolutionStrategy.PreferPlatformSpecificVariant) {
- sourceSets.commonMain.dependencies {
- implementation("foo.bar:uklib-maven-jar-packaging-classifier:1.0:uklib")
- }
- }
-
- val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
- .configurations.compileDependencyConfiguration
- val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
- val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
- .configurations.runtimeDependencyConfiguration!!
- val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
- // ???
- }
-
- private fun consumer(
- strategy: UklibResolutionStrategy,
- configure: KotlinMultiplatformExtension.() -> Unit,
- ): Project {
- return buildProjectWithMPP(
- preApplyCode = {
- publishUklibVariant()
- fakeUklibTransforms()
- setUklibResolutionStrategy(strategy)
- // Test stdlib in a separate test
- enableDefaultStdlibDependency(false)
- }
- ) {
- kotlin {
- iosArm64()
- iosX64()
- jvm()
-
- configure()
- }
-
- repositories.maven(javaClass.getResource("/dependenciesResolution/UklibTests/repo")!!)
- }.evaluate()
- }
-
- @Test
- fun `prefer klib variant`() {
- val consumer = mixedCompilationsGraphConsumer(
- uklibResolutionStrategy = UklibResolutionStrategy.PreferPlatformSpecificVariant,
- )
-
- val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
- .configurations.compileDependencyConfiguration
- val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
- val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
- .configurations.runtimeDependencyConfiguration!!
- val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
- assertEquals(
- mapOf(
- ":E_consumes_D" to ResolvedComponentWithArtifacts(
- configuration="jvmRuntimeClasspath",
- artifacts=mutableListOf()
- ),
- ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
- configuration="jvmRuntimeElements",
- artifacts=mutableListOf(platformJvmVariantAttributes)
- ),
- ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
- configuration="metadataUklibElements",
- artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes)
- ),
- ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
- configuration="jvmRuntimeElements",
- artifacts=mutableListOf(platformJvmVariantAttributes)
- ),
- ":A_produces_uklib" to ResolvedComponentWithArtifacts(
- configuration="jvmRuntimeElements",
- artifacts=mutableListOf(platformJvmVariantAttributes),
- )
- ),
- jvmResolvedVariants
- )
-
- assertEquals(
- mapOf(
- ":E_consumes_D" to ResolvedComponentWithArtifacts(
- configuration="iosArm64CompileKlibraries",
- artifacts=mutableListOf()
- ),
- ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
- configuration="iosArm64ApiElements",
- artifacts=mutableListOf(platformIosArm64Attributes + nonPacked)
- ),
- ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
- configuration="metadataUklibElements",
- artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes)
- ),
- ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
- configuration="iosArm64ApiElements",
- artifacts=mutableListOf(platformIosArm64Attributes + nonPacked)
- ),
- ":A_produces_uklib" to ResolvedComponentWithArtifacts(
- configuration="iosArm64ApiElements",
- artifacts=mutableListOf(platformIosArm64Attributes + nonPacked),
- )
- ),
- iosArm64ResolvedVariants
- )
- }
-
- @Test
- fun `prefer uklib variant`() {
- val consumer = mixedCompilationsGraphConsumer(
- uklibResolutionStrategy = UklibResolutionStrategy.PreferUklibVariant,
- )
-
- val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
- .configurations.compileDependencyConfiguration
- val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
- val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
- .configurations.runtimeDependencyConfiguration!!
- // FIXME: java-api variant doesn't resolve A
- val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
- assertEquals(
- mapOf(
- ":E_consumes_D" to ResolvedComponentWithArtifacts(
- configuration="jvmRuntimeClasspath",
- artifacts=mutableListOf()
- ),
- ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
- configuration="metadataUklibElements",
- artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes)
- ),
- ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
- configuration="metadataUklibElements",
- artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes)
- ),
- ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
- configuration="jvmRuntimeElements",
- artifacts=mutableListOf(platformJvmVariantAttributes)
- ),
- ":A_produces_uklib" to ResolvedComponentWithArtifacts(
- configuration="metadataUklibElements",
- artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes),
- )
- ),
- jvmResolvedVariants
- )
-
- assertEquals(
- mapOf(
- ":E_consumes_D" to ResolvedComponentWithArtifacts(
- configuration="iosArm64CompileKlibraries",
- artifacts=mutableListOf()
- ),
- ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
- configuration="metadataUklibElements",
- artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes)
- ),
- ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
- configuration="metadataUklibElements",
- artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes)
- ),
- ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
- configuration="iosArm64ApiElements",
- artifacts=mutableListOf(platformIosArm64Attributes + nonPacked)
- ),
- ":A_produces_uklib" to ResolvedComponentWithArtifacts(
- configuration="metadataUklibElements",
- artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes),
- )
- ),
- iosArm64ResolvedVariants
- )
- }
-
- private fun mixedCompilationsGraphConsumer(
- uklibResolutionStrategy: UklibResolutionStrategy,
- ): Project {
- val root = buildProject()
- return root.child(
- "E_consumes_D",
- uklibResolutionStrategy = uklibResolutionStrategy,
- consume= root.child(
- "D_produces_uklib_consumes_C",
- consume = root.child(
- "C_produces_only_uklib_consumes_B",
- disablePlatformComponentReferences = true,
- consume = root.child(
- "B_produces_only_platform_variant_consumes_A",
- publishUklibVariant = false,
- consume = root.child(
- "A_produces_uklib",
- consume = null
- )
- )
- )
- )
- )
- }
-
- private val uklibTransformationIosArm64Attributes = mapOf(
- "artifactType" to "uklib",
- "uklibNativeSlice" to "iosArm64",
- "uklibPlatform" to "native",
- "uklibState" to "unzipped",
- )
-
- private val uklibTransformationJvmAttributes = mapOf(
- "artifactType" to "uklib",
- "uklibNativeSlice" to "unknown",
- "uklibPlatform" to "jvm",
- "uklibState" to "unzipped",
- )
-
- private val uklibVariantAttributes = mapOf(
- "org.gradle.category" to "library",
- "org.gradle.jvm.environment" to "???",
- "org.gradle.usage" to "kotlin-uklib",
- "org.jetbrains.kotlin.klib.packaging" to "packed",
- "org.jetbrains.kotlin.native.target" to "???",
- "org.jetbrains.kotlin.platform.type" to "unknown",
- )
-
- private val jvmPomRuntimeAttributes = mapOf(
- "org.gradle.category" to "library",
- "org.gradle.libraryelements" to "jar",
- "org.gradle.status" to "release",
- "org.gradle.usage" to "java-runtime",
- )
-
- private val jvmPomApiAttributes = mapOf(
- "org.gradle.category" to "library",
- "org.gradle.libraryelements" to "jar",
- "org.gradle.status" to "release",
- "org.gradle.usage" to "java-api",
- )
-
- private val platformJvmVariantAttributes = mapOf(
- "artifactType" to "jar",
- "org.gradle.category" to "library",
- "org.gradle.jvm.environment" to "standard-jvm",
- "org.gradle.libraryelements" to "jar",
- "org.gradle.usage" to "java-runtime",
- "org.jetbrains.kotlin.platform.type" to "jvm",
- )
-
- private val releaseStatus = mapOf(
- "org.gradle.status" to "release",
- )
-
- // We only emit packing in secondary variants which are not published?
- private val nonPacked = mapOf(
- "org.jetbrains.kotlin.klib.packaging" to "non-packed",
- )
-
- private val jarArtifact = mapOf(
- "artifactType" to "jar",
- )
-
- private val platformIosArm64Attributes = mapOf(
- "artifactType" to "org.jetbrains.kotlin.klib",
- "org.gradle.category" to "library",
- "org.gradle.jvm.environment" to "non-jvm",
- "org.gradle.usage" to "kotlin-api",
- "org.jetbrains.kotlin.cinteropCommonizerArtifactType" to "klib",
- "org.jetbrains.kotlin.native.target" to "ios_arm64",
- "org.jetbrains.kotlin.platform.type" to "native",
- )
-
- data class ResolvedComponentWithArtifacts(
- val configuration: String,
- val artifacts: MutableList<Map<String, String>> = mutableListOf(),
- )
-
- private fun Configuration.resolveProjectDependencyComponentsWithArtifacts(): Map<String, ResolvedComponentWithArtifacts> {
- val artifacts = resolveProjectDependencyVariantsFromArtifacts()
- val components = resolveProjectDependencyComponents()
- val componentToArtifacts = LinkedHashMap<String, ResolvedComponentWithArtifacts>()
- components.forEach { component ->
- if (componentToArtifacts[component.path] == null) {
- componentToArtifacts[component.path] = ResolvedComponentWithArtifacts(component.configuration)
- } else {
- error("${component} resolved multiple times?")
- }
- }
- artifacts.forEach { artifact ->
- componentToArtifacts[artifact.path]?.let {
- it.artifacts.add(artifact.attributes)
- } ?: error("Missing resolved component for artifact: ${artifact}")
- }
- return componentToArtifacts
- }
-
- data class ResolvedVariant(
- val path: String,
- val attributes: Map<String, String>,
- )
-
- private fun Configuration.resolveProjectDependencyVariantsFromArtifacts(): List<ResolvedVariant> {
- return incoming.artifacts.artifacts
- .map { artifact ->
- val uklibAttributes: List<Attribute<*>> = artifact.variant.attributes.keySet()
- .sortedBy { it.name }
- ResolvedVariant(
- artifact.variant.owner.projectPathOrNull ?: artifact.variant.owner.displayName,
- uklibAttributes.keysToMap {
- artifact.variant.attributes.getAttribute(it as Attribute<*>).toString()
- }.mapKeys { it.key.name }
- )
- }
- }
-
- data class ResolvedComponent(
- val path: String,
- val configuration: String,
- )
-
- private fun Configuration.resolveProjectDependencyComponents(): List<ResolvedComponent> {
- return incoming.resolutionResult.allComponents
- .map { component ->
- ResolvedComponent(
- component.id.projectPathOrNull ?: component.id.displayName,
- // Expect a single variant to always be selected?
- component.variants.single().displayName
- )
- }
- }
-
- private fun Project.child(
- name: String,
- consume: Project?,
- publishUklibVariant: Boolean = true,
- disablePlatformComponentReferences: Boolean = false,
- uklibResolutionStrategy: UklibResolutionStrategy = UklibResolutionStrategy.ResolveOnlyPlatformSpecificVariant,
- ): Project {
- val parent = this
- return buildProjectWithMPP(
- preApplyCode = {
- if (publishUklibVariant) {
- publishUklibVariant()
- }
- fakeUklibTransforms()
- setUklibResolutionStrategy(uklibResolutionStrategy)
- disablePlatformSpecificComponentReferences(disablePlatformComponentReferences)
- // Test stdlib in a separate test
- enableDefaultStdlibDependency(false)
- },
- projectBuilder = {
- withParent(parent)
- withName(name)
- }
- ) {
- kotlin {
- iosArm64()
- iosX64()
- jvm()
-
- if (consume != null) {
- sourceSets.commonMain.dependencies {
- implementation(project(consume.project.path))
- }
- }
- }
- }.evaluate()
- }
-
-}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/buildProject.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/buildProject.kt
index 762da67..3e3b9ac 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/buildProject.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/buildProject.kt
@@ -135,10 +135,10 @@
}
fun Project.publishUklibVariant(enabled: Boolean = true) {
- propertiesExtension.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_PUBLISH_UKLIB_VARIANT, enabled.toString())
+ propertiesExtension.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_PUBLISH_UKLIB, enabled.toString())
}
-fun Project.setUklibResolutionStrategy(strategy: UklibResolutionStrategy) {
+internal fun Project.setUklibResolutionStrategy(strategy: UklibResolutionStrategy) {
propertiesExtension.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_UKLIB_RESOLUTION_STRATEGY, strategy.propertyName)
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-uklib-dependency/1.0/regular-maven-jar-packaging-with-uklib-uklib-dependency-1.0.jar b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-jvm-with-trasitive-uklib-dependency/1.0/pure-maven-jvm-with-trasitive-uklib-dependency-1.0.jar
similarity index 100%
rename from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-uklib-dependency/1.0/regular-maven-jar-packaging-with-uklib-uklib-dependency-1.0.jar
rename to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-jvm-with-trasitive-uklib-dependency/1.0/pure-maven-jvm-with-trasitive-uklib-dependency-1.0.jar
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-jvm-with-trasitive-uklib-dependency/1.0/pure-maven-jvm-with-trasitive-uklib-dependency-1.0.pom
similarity index 74%
copy from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom
copy to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-jvm-with-trasitive-uklib-dependency/1.0/pure-maven-jvm-with-trasitive-uklib-dependency-1.0.pom
index 176d810..6e0ac2b 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-jvm-with-trasitive-uklib-dependency/1.0/pure-maven-jvm-with-trasitive-uklib-dependency-1.0.pom
@@ -3,13 +3,12 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>foo.bar</groupId>
- <artifactId>uklib-maven-uklib-packaging</artifactId>
+ <artifactId>pure-maven-jvm-with-trasitive-uklib-dependency</artifactId>
<version>1.0</version>
- <packaging>uklib</packaging>
<dependencies>
<dependency>
<groupId>foo.bar</groupId>
- <artifactId>uklib-maven-gradle-packaging</artifactId>
+ <artifactId>pure-maven-uklib-with-transitive-non-uklib-dependency</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib-with-transitive-non-uklib-dependency/1.0/pure-maven-uklib-with-transitive-non-uklib-dependency-1.0.jar
similarity index 100%
copy from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib
copy to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib-with-transitive-non-uklib-dependency/1.0/pure-maven-uklib-with-transitive-non-uklib-dependency-1.0.jar
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib-with-transitive-non-uklib-dependency/1.0/pure-maven-uklib-with-transitive-non-uklib-dependency-1.0.pom
similarity index 86%
rename from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom
rename to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib-with-transitive-non-uklib-dependency/1.0/pure-maven-uklib-with-transitive-non-uklib-dependency-1.0.pom
index 176d810..0b56a7f 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib-with-transitive-non-uklib-dependency/1.0/pure-maven-uklib-with-transitive-non-uklib-dependency-1.0.pom
@@ -3,7 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>foo.bar</groupId>
- <artifactId>uklib-maven-uklib-packaging</artifactId>
+ <artifactId>pure-maven-uklib-with-transitive-non-uklib-dependency</artifactId>
<version>1.0</version>
<packaging>uklib</packaging>
<dependencies>
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib-with-transitive-non-uklib-dependency/1.0/pure-maven-uklib-with-transitive-non-uklib-dependency-1.0.uklib
similarity index 100%
copy from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib
copy to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib-with-transitive-non-uklib-dependency/1.0/pure-maven-uklib-with-transitive-non-uklib-dependency-1.0.uklib
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib/1.0/pure-maven-uklib-1.0.jar
similarity index 100%
copy from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib
copy to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib/1.0/pure-maven-uklib-1.0.jar
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib/1.0/pure-maven-uklib-1.0.pom
similarity index 60%
copy from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom
copy to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib/1.0/pure-maven-uklib-1.0.pom
index 176d810..062ba26 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib/1.0/pure-maven-uklib-1.0.pom
@@ -3,14 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>foo.bar</groupId>
- <artifactId>uklib-maven-uklib-packaging</artifactId>
+ <artifactId>pure-maven-uklib</artifactId>
<version>1.0</version>
<packaging>uklib</packaging>
- <dependencies>
- <dependency>
- <groupId>foo.bar</groupId>
- <artifactId>uklib-maven-gradle-packaging</artifactId>
- <version>1.0</version>
- </dependency>
- </dependencies>
</project>
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib/1.0/pure-maven-uklib-1.0.uklib
similarity index 100%
rename from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib
rename to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib/1.0/pure-maven-uklib-1.0.uklib
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-jar-dependency/1.0/regular-maven-jar-packaging-with-uklib-jar-dependency-1.0.jar b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-jar-dependency/1.0/regular-maven-jar-packaging-with-uklib-jar-dependency-1.0.jar
deleted file mode 100644
index 8b13789..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-jar-dependency/1.0/regular-maven-jar-packaging-with-uklib-jar-dependency-1.0.jar
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-jar-dependency/1.0/regular-maven-jar-packaging-with-uklib-jar-dependency-1.0.pom b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-jar-dependency/1.0/regular-maven-jar-packaging-with-uklib-jar-dependency-1.0.pom
deleted file mode 100644
index 8402982..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-jar-dependency/1.0/regular-maven-jar-packaging-with-uklib-jar-dependency-1.0.pom
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <modelVersion>4.0.0</modelVersion>
- <groupId>foo.bar</groupId>
- <artifactId>regular-maven-jar-packaging-with-uklib-jar-dependency</artifactId>
- <version>1.0</version>
-<!-- This is the implicit default-->
-<!-- <packaging>jar</packaging>-->
- <dependencies>
- <dependency>
- <groupId>foo.bar</groupId>
- <artifactId>uklib-maven-jar-packaging</artifactId>
- <version>1.0</version>
- </dependency>
- </dependencies>
-</project>
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-uklib-dependency/1.0/regular-maven-jar-packaging-with-uklib-uklib-dependency-1.0.pom b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-uklib-dependency/1.0/regular-maven-jar-packaging-with-uklib-uklib-dependency-1.0.pom
deleted file mode 100644
index d4bcedf..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-uklib-dependency/1.0/regular-maven-jar-packaging-with-uklib-uklib-dependency-1.0.pom
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <modelVersion>4.0.0</modelVersion>
- <groupId>foo.bar</groupId>
- <artifactId>regular-maven-jar-packaging-with-uklib-uklib-dependency</artifactId>
- <version>1.0</version>
-<!-- This is the implicit default-->
-<!-- <packaging>jar</packaging>-->
- <dependencies>
- <dependency>
- <groupId>foo.bar</groupId>
- <artifactId>uklib-maven-uklib-packaging</artifactId>
- <version>1.0</version>
- </dependency>
- </dependencies>
-</project>
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0-uklib.jar b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0-uklib.jar
deleted file mode 100644
index 8b13789..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0-uklib.jar
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0.jar b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0.jar
deleted file mode 100644
index 8b13789..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0.jar
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0.pom b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0.pom
deleted file mode 100644
index 625e1ab..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0.pom
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <modelVersion>4.0.0</modelVersion>
- <groupId>foo.bar</groupId>
- <artifactId>uklib-maven-jar-packaging-classifier</artifactId>
- <version>1.0</version>
-<!-- This is the implicit default-->
-<!-- <packaging>jar</packaging>-->
- <dependencies>
- <dependency>
- <groupId>foo.bar</groupId>
- <artifactId>uklib-maven-gradle-packaging</artifactId>
- <version>1.0</version>
- </dependency>
- </dependencies>
-</project>
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.jar b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.jar
deleted file mode 100644
index 8b13789..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.jar
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.pom b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.pom
deleted file mode 100644
index 57a198b..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.pom
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <modelVersion>4.0.0</modelVersion>
- <groupId>foo.bar</groupId>
- <artifactId>uklib-maven-jar-packaging</artifactId>
- <version>1.0</version>
-<!-- This is the implicit default-->
-<!-- <packaging>jar</packaging>-->
- <dependencies>
- <dependency>
- <groupId>foo.bar</groupId>
- <artifactId>uklib-maven-gradle-packaging</artifactId>
- <version>1.0</version>
- </dependency>
- </dependencies>
-</project>
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.jar b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.jar
deleted file mode 100644
index 8b13789..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.jar
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.uklib b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.uklib
deleted file mode 100644
index e69de29..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.uklib
+++ /dev/null