[MPP] Initial support for cinterop import with KGP resolvers
KT-54975
This commit is contained in:
committed by
Space Team
parent
20e80401b2
commit
7e2a7579e8
+24
@@ -5,11 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.ide
|
||||
|
||||
import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
|
||||
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.targets.native.internal.getCommonizerTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.ide.dependencyTransformers.UnusedSourcesAndDocumentationFilter
|
||||
|
||||
internal fun IdeMultiplatformImport(extension: KotlinProjectExtension): IdeMultiplatformImport {
|
||||
return IdeMultiplatformImportImpl(extension).apply {
|
||||
@@ -84,6 +87,27 @@ internal fun IdeMultiplatformImport(extension: KotlinProjectExtension): IdeMulti
|
||||
level = IdeMultiplatformImport.DependencyResolutionLevel.Default
|
||||
)
|
||||
|
||||
registerDependencyResolver(
|
||||
resolver = IdePlatformCinteropDependencyResolver,
|
||||
constraint = { sourceSet -> SourceSetConstraint.isLeaf(sourceSet) && SourceSetConstraint.isNative(sourceSet) },
|
||||
phase = IdeMultiplatformImport.DependencyResolutionPhase.BinaryDependencyResolution,
|
||||
level = IdeMultiplatformImport.DependencyResolutionLevel.Default,
|
||||
)
|
||||
|
||||
registerDependencyResolver(
|
||||
resolver = IdeCommonizedCinteropDependencyResolver,
|
||||
constraint = { sourceSet -> SourceSetConstraint.isNative(sourceSet) && getCommonizerTarget(sourceSet) is SharedCommonizerTarget },
|
||||
phase = IdeMultiplatformImport.DependencyResolutionPhase.BinaryDependencyResolution,
|
||||
level = IdeMultiplatformImport.DependencyResolutionLevel.Default,
|
||||
)
|
||||
|
||||
registerDependencyResolver(
|
||||
resolver = IdeCInteropMetadataDependencyClasspathResolver,
|
||||
constraint = { SourceSetConstraint.isNative(it) && !SourceSetConstraint.isLeaf(it) },
|
||||
phase = IdeMultiplatformImport.DependencyResolutionPhase.BinaryDependencyResolution,
|
||||
level = IdeMultiplatformImport.DependencyResolutionLevel.Default,
|
||||
)
|
||||
|
||||
/*
|
||||
Register resolution of dependencies for jvm+android dependencies:
|
||||
This resolver will resolve dependencies visible to the source set from a 'jvm' perspective.
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.targets.native.internal.createCInteropMetadataDependencyClasspathForIde
|
||||
|
||||
object IdeCInteropMetadataDependencyClasspathResolver : IdeDependencyResolver {
|
||||
override fun resolve(sourceSet: KotlinSourceSet): Set<IdeaKotlinDependency> {
|
||||
if (sourceSet !is DefaultKotlinSourceSet) return emptySet()
|
||||
|
||||
val project = sourceSet.project
|
||||
// TODO (kirpichenkov): sensitive to task being registered for the source set
|
||||
val cinteropFiles = project.createCInteropMetadataDependencyClasspathForIde(sourceSet)
|
||||
return resolveCinteropDependencies(project, cinteropFiles)
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.targets.native.internal.cinteropCommonizerDependencies
|
||||
|
||||
object IdeCommonizedCinteropDependencyResolver : IdeDependencyResolver {
|
||||
override fun resolve(sourceSet: KotlinSourceSet): Set<IdeaKotlinDependency> {
|
||||
if (sourceSet !is DefaultKotlinSourceSet) return emptySet()
|
||||
|
||||
val project = sourceSet.project
|
||||
val cinteropFiles = project.cinteropCommonizerDependencies(sourceSet)
|
||||
return resolveCinteropDependencies(project, cinteropFiles)
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.internal
|
||||
import org.jetbrains.kotlin.gradle.targets.native.internal.getAllCInteropOutputFiles
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
object IdePlatformCinteropDependencyResolver : IdeDependencyResolver {
|
||||
override fun resolve(sourceSet: KotlinSourceSet): Set<IdeaKotlinDependency> {
|
||||
if (sourceSet !is DefaultKotlinSourceSet) return emptySet()
|
||||
val project = sourceSet.project
|
||||
|
||||
val nativeCompilation = sourceSet.internal.compilations.singleOrNull().safeAs<KotlinNativeCompilation>() ?: return emptySet()
|
||||
val cinteropFiles = project.getAllCInteropOutputFiles(nativeCompilation)
|
||||
|
||||
return resolveCinteropDependencies(project, cinteropFiles)
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.artifacts.component.ProjectComponentIdentifier
|
||||
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver
|
||||
|
||||
object IdeProjectToProjectCInteropDependencyResolver : IdeDependencyResolver {
|
||||
private val platformDependencyResolver = IdePlatformDependencyResolver(
|
||||
resolvedArtifactHandler = handler@{ artifact, context ->
|
||||
val identifier = artifact.id.componentIdentifier as? ProjectComponentIdentifier
|
||||
?: return@handler null
|
||||
|
||||
val projectArtifact = context.allArtifacts.filter { otherArtifact ->
|
||||
val otherIdentifier = otherArtifact.id.componentIdentifier
|
||||
otherIdentifier is ProjectComponentIdentifier && otherIdentifier.projectName == identifier.projectName
|
||||
}
|
||||
|
||||
null
|
||||
}
|
||||
)
|
||||
|
||||
override fun resolve(sourceSet: KotlinSourceSet): Set<IdeaKotlinDependency> {
|
||||
return platformDependencyResolver.resolve(sourceSet)
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.gradle.api.file.FileCollection
|
||||
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.idea.tcs.extras.klibExtra
|
||||
import org.jetbrains.kotlin.gradle.plugin.ide.KlibExtra
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION
|
||||
import org.jetbrains.kotlin.library.ToolingSingleFileKlibResolveStrategy
|
||||
import org.jetbrains.kotlin.library.commonizerTarget
|
||||
import org.jetbrains.kotlin.library.resolveSingleFileKlib
|
||||
|
||||
fun resolveCinteropDependencies(project: Project, cinteropFiles: FileCollection): Set<IdeaKotlinDependency> {
|
||||
return cinteropFiles.files
|
||||
.filter { it.isDirectory || it.extension == KLIB_FILE_EXTENSION }
|
||||
.mapNotNullTo(mutableSetOf()) { libraryFile ->
|
||||
createCinteropLibraryDependency(project, libraryFile)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCinteropLibraryDependency(project: Project, libraryFile: java.io.File): IdeaKotlinResolvedBinaryDependency? {
|
||||
val library = try {
|
||||
resolveSingleFileKlib(
|
||||
libraryFile = File(libraryFile.absolutePath),
|
||||
strategy = ToolingSingleFileKlibResolveStrategy
|
||||
)
|
||||
} catch (error: Throwable) {
|
||||
project.logger.error("Failed to resolve library ${libraryFile.path}", error)
|
||||
return null
|
||||
}
|
||||
|
||||
return IdeaKotlinResolvedBinaryDependency(
|
||||
binaryType = IdeaKotlinDependency.CLASSPATH_BINARY_TYPE,
|
||||
binaryFile = libraryFile,
|
||||
coordinates = IdeaKotlinBinaryCoordinates(
|
||||
group = project.group.toString(),
|
||||
module = library.moduleDisplayName,
|
||||
version = null,
|
||||
sourceSetName = library.commonizerTarget
|
||||
),
|
||||
).apply {
|
||||
klibExtra = KlibExtra(library)
|
||||
}
|
||||
}
|
||||
+9
@@ -9,8 +9,17 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.metadataDependencyResolutionsOrEmpty
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope.*
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import org.jetbrains.kotlin.library.packageFqName
|
||||
import org.jetbrains.kotlin.library.shortName
|
||||
import org.jetbrains.kotlin.library.uniqueName
|
||||
|
||||
internal inline fun <reified T : MetadataDependencyResolution> KotlinSourceSet.resolveMetadata(): List<T> {
|
||||
if (this !is DefaultKotlinSourceSet) return emptyList()
|
||||
return compileDependenciesTransformation.metadataDependencyResolutionsOrEmpty.filterIsInstance<T>()
|
||||
}
|
||||
|
||||
internal val KotlinLibrary.moduleDisplayName: String
|
||||
get() = packageFqName ?: shortName ?: uniqueName
|
||||
|
||||
+8
-3
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.gradle.targets.native.internal
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation
|
||||
@@ -42,16 +43,20 @@ private fun Project.setupCInteropCommonizerDependenciesForCompilation(compilatio
|
||||
* The copying task prevent red code within the IDE after cleaning the build output.
|
||||
*/
|
||||
private fun Project.setupCInteropCommonizerDependenciesForIde(sourceSet: DefaultKotlinSourceSet) {
|
||||
val cinteropCommonizerTask = project.copyCommonizeCInteropForIdeTask ?: return
|
||||
addIntransitiveMetadataDependencyIfPossible(sourceSet, cinteropCommonizerDependencies(sourceSet))
|
||||
}
|
||||
|
||||
addIntransitiveMetadataDependencyIfPossible(sourceSet, filesProvider files@{
|
||||
internal fun Project.cinteropCommonizerDependencies(sourceSet: DefaultKotlinSourceSet): FileCollection {
|
||||
val cinteropCommonizerTask = project.copyCommonizeCInteropForIdeTask ?: return project.files()
|
||||
|
||||
return filesProvider {
|
||||
val directlyDependent = CInteropCommonizerDependent.from(sourceSet)
|
||||
val associateDependent = CInteropCommonizerDependent.fromAssociateCompilations(sourceSet)
|
||||
|
||||
listOfNotNull(directlyDependent, associateDependent).map { cinteropCommonizerDependent ->
|
||||
cinteropCommonizerTask.get().commonizedOutputLibraries(cinteropCommonizerDependent)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.setupCInteropTransformCompositeMetadataDependenciesForIde(sourceSet: DefaultKotlinSourceSet) {
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ private fun Project.getPropagatedCInteropDependenciesOrEmpty(compilation: Kotlin
|
||||
getAllCInteropOutputFiles(platformCompilation)
|
||||
}
|
||||
|
||||
private fun Project.getAllCInteropOutputFiles(compilation: KotlinNativeCompilation): FileCollection {
|
||||
internal fun Project.getAllCInteropOutputFiles(compilation: KotlinNativeCompilation): FileCollection {
|
||||
val cinteropTasks = compilation.cinterops.map { interop -> interop.interopProcessingTaskName }
|
||||
.mapNotNull { taskName -> tasks.findByName(taskName) as? CInteropProcess }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user