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 ab8cf0b2f04..ebb3fd6e3dc 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 @@ -8,10 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin.ide import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinExtrasSerializer import org.jetbrains.kotlin.gradle.kpm.idea.kotlinDebugKey -import org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers.IdeDependsOnDependencyResolver -import org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers.IdeJvmAndAndroidPlatformBinaryDependencyResolver -import org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers.IdePlatformBinaryDependencyResolver -import org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers.IdeTransformedMetadataDependencyResolver +import org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers.* fun IdeMultiplatformImport(extension: KotlinMultiplatformExtension): IdeMultiplatformImport { return IdeMultiplatformImportImpl(extension).apply { @@ -48,6 +45,13 @@ fun IdeMultiplatformImport(extension: KotlinMultiplatformExtension): IdeMultipla level = IdeMultiplatformImport.DependencyResolutionLevel.Default ) + registerDependencyResolver( + resolver = IdeNativePlatformDependencyResolver, + constraint = IdeMultiplatformImport.SourceSetConstraint.isNative, + phase = IdeMultiplatformImport.DependencyResolutionPhase.BinaryDependencyResolution, + level = IdeMultiplatformImport.DependencyResolutionLevel.Default + ) + registerExtrasSerializationExtension { register(kotlinDebugKey, IdeaKotlinExtrasSerializer.javaIoSerializable()) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeNativePlatformDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeNativePlatformDependencyResolver.kt new file mode 100644 index 00000000000..e9ce0a55288 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeNativePlatformDependencyResolver.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2022 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.plugin.ide.dependencyResolvers + +import org.gradle.api.Project +import org.jetbrains.kotlin.commonizer.KonanDistribution +import org.jetbrains.kotlin.commonizer.LeafCommonizerTarget +import org.jetbrains.kotlin.commonizer.platformLibsDir +import org.jetbrains.kotlin.compilerRunner.konanHome +import org.jetbrains.kotlin.compilerRunner.konanVersion +import org.jetbrains.kotlin.gradle.idea.kpm.IdeaKpmDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryCoordinates +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver +import org.jetbrains.kotlin.gradle.plugin.sources.project +import org.jetbrains.kotlin.gradle.targets.native.internal.getCommonizerTarget +import org.jetbrains.kotlin.library.* +import org.jetbrains.kotlin.tooling.core.mutableExtrasOf +import java.io.File + +object IdeNativePlatformDependencyResolver : IdeDependencyResolver { + override fun resolve(sourceSet: KotlinSourceSet): Set { + val commonizerTarget = sourceSet.project.getCommonizerTarget(sourceSet) as? LeafCommonizerTarget ?: return emptySet() + val konanTarget = commonizerTarget.konanTargetOrNull ?: return emptySet() + + return sourceSet.project.konanDistribution.platformLibsDir.resolve(konanTarget.name) + .listFiles().orEmpty() + .filter { it.isDirectory || it.extension == KLIB_FILE_EXTENSION } + .mapNotNull { libraryFile -> sourceSet.project.resolveKlib(libraryFile) } + .toSet() + } + + private val Project.konanDistribution: KonanDistribution + get() = KonanDistribution(project.file(konanHome)) + + private fun Project.resolveKlib(file: File): IdeaKotlinResolvedBinaryDependency? { + try { + val kotlinLibrary = resolveSingleFileKlib( + org.jetbrains.kotlin.konan.file.File(file.absolutePath), + strategy = ToolingSingleFileKlibResolveStrategy + ) + + return IdeaKotlinResolvedBinaryDependency( + binaryType = IdeaKpmDependency.CLASSPATH_BINARY_TYPE, + binaryFile = file, + extras = mutableExtrasOf(), + coordinates = IdeaKotlinBinaryCoordinates( + group = "org.jetbrains.kotlin.native", + module = kotlinLibrary.packageFqName ?: kotlinLibrary.shortName ?: kotlinLibrary.uniqueName, + version = project.konanVersion.toString() + ), + ) + } catch (t: Throwable) { + logger.error("Failed resolving library ${file.path}", t) + return null + } + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeNativePlatformDependencyResolverTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeNativePlatformDependencyResolverTest.kt new file mode 100644 index 00000000000..7f7d2fcdb2c --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeNativePlatformDependencyResolverTest.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2022 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. + */ + +@file:Suppress("FunctionName") + +package org.jetbrains.kotlin.gradle.ide + +import org.jetbrains.kotlin.compilerRunner.konanVersion +import org.jetbrains.kotlin.gradle.buildProjectWithMPP +import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension +import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.assertMatches +import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.binaryCoordinates +import org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers.IdeNativePlatformDependencyResolver +import org.jetbrains.kotlin.konan.target.HostManager +import org.junit.Assume +import kotlin.test.Test + +class IdeNativePlatformDependencyResolverTest { + + @Test + fun `test - posix on linux`() { + val project = buildProjectWithMPP() + val kotlin = project.multiplatformExtension + kotlin.linuxX64() + + val commonMain = kotlin.sourceSets.getByName("commonMain") + val commonTest = kotlin.sourceSets.getByName("commonTest") + val linuxX64Main = kotlin.sourceSets.getByName("linuxX64Main") + val linuxX64Test = kotlin.sourceSets.getByName("linuxX64Test") + + val dependencies = listOf( + binaryCoordinates("org.jetbrains.kotlin.native:platform.posix:${project.konanVersion}"), + binaryCoordinates(Regex("""org\.jetbrains\.kotlin\.native:.*:${project.konanVersion}""")) + ) + + IdeNativePlatformDependencyResolver.resolve(commonMain).assertMatches(dependencies) + IdeNativePlatformDependencyResolver.resolve(commonTest).assertMatches(dependencies) + IdeNativePlatformDependencyResolver.resolve(linuxX64Main).assertMatches(dependencies) + IdeNativePlatformDependencyResolver.resolve(linuxX64Test).assertMatches(dependencies) + } + + @Test + fun `test - CoreFoundation on macos`() { + Assume.assumeTrue("Macos host required for this test", HostManager.hostIsMac) + val project = buildProjectWithMPP() + val kotlin = project.multiplatformExtension + kotlin.macosArm64() + + val commonMain = kotlin.sourceSets.getByName("commonMain") + val commonTest = kotlin.sourceSets.getByName("commonTest") + val macosArm64Main = kotlin.sourceSets.getByName("macosArm64Main") + val macosArm64Test = kotlin.sourceSets.getByName("macosArm64Test") + + val dependencies = listOf( + binaryCoordinates("org.jetbrains.kotlin.native:platform.CoreFoundation:${project.konanVersion}"), + binaryCoordinates(Regex("""org\.jetbrains\.kotlin\.native:.*:${project.konanVersion}""")) + ) + + IdeNativePlatformDependencyResolver.resolve(commonMain).assertMatches(dependencies) + IdeNativePlatformDependencyResolver.resolve(commonTest).assertMatches(dependencies) + IdeNativePlatformDependencyResolver.resolve(macosArm64Main).assertMatches(dependencies) + IdeNativePlatformDependencyResolver.resolve(macosArm64Test).assertMatches(dependencies) + } +}