[Gradle] Implement setupCInteropPropagatedDependencies
This commit will forward/propagate cinterops to intermediate source sets with only one native dependent (and their metadata compilation) ^KT-47523 Verification Pending
This commit is contained in:
committed by
Space
parent
fee670e1a5
commit
882d72b1f7
+3
-5
@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.compilerRunner.konanVersion
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.*
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.DisabledNativeTargetsReporter
|
import org.jetbrains.kotlin.gradle.targets.native.DisabledNativeTargetsReporter
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.internal.NativeDistributionTypeProvider
|
import org.jetbrains.kotlin.gradle.targets.native.internal.*
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.internal.PlatformLibrariesGenerator
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.internal.setupCInteropCommonizerDependencies
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.internal.setupKotlinNativePlatformDependencies
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
|
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
|
||||||
import org.jetbrains.kotlin.gradle.utils.SingleActionPerProject
|
import org.jetbrains.kotlin.gradle.utils.SingleActionPerProject
|
||||||
import org.jetbrains.kotlin.konan.CompilerVersion
|
import org.jetbrains.kotlin.konan.CompilerVersion
|
||||||
@@ -92,8 +89,9 @@ abstract class AbstractKotlinNativeTargetPreset<T : KotlinNativeTarget>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleActionPerProject.run(project, "setupCInteropCommonizerDependencies") {
|
SingleActionPerProject.run(project, "setupCInteropDependencies") {
|
||||||
project.setupCInteropCommonizerDependencies()
|
project.setupCInteropCommonizerDependencies()
|
||||||
|
project.setupCInteropPropagatedDependencies()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!konanTarget.enabledOnCurrentHost) {
|
if (!konanTarget.enabledOnCurrentHost) {
|
||||||
|
|||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.targets.native.internal
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dependencies here are using a special configuration called 'intransitiveMetadataConfiguration'.
|
||||||
|
* This special configuration can tell the IDE that this dependencies shall *not* be transitively be visible
|
||||||
|
* to dependsOn edges. This is necessary for the way the commonizer handles it's "expect refinement" approach.
|
||||||
|
* In this mode, every source set will receive exactly one commonized library to analyze its source code with.
|
||||||
|
*/
|
||||||
|
internal fun Project.addIntransitiveMetadataDependencyIfPossible(sourceSet: DefaultKotlinSourceSet, dependency: FileCollection) {
|
||||||
|
val dependencyConfigurationName =
|
||||||
|
if (project.isIntransitiveMetadataConfigurationEnabled) sourceSet.intransitiveMetadataConfigurationName
|
||||||
|
else sourceSet.implementationMetadataConfigurationName
|
||||||
|
project.dependencies.add(dependencyConfigurationName, dependency)
|
||||||
|
}
|
||||||
+4
-21
@@ -6,9 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.gradle.targets.native.internal
|
package org.jetbrains.kotlin.gradle.targets.native.internal
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.file.FileCollection
|
|
||||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
|
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
|
||||||
import org.jetbrains.kotlin.gradle.utils.filesProvider
|
import org.jetbrains.kotlin.gradle.utils.filesProvider
|
||||||
@@ -17,13 +15,11 @@ import java.io.File
|
|||||||
internal fun Project.setupCInteropCommonizerDependencies() {
|
internal fun Project.setupCInteropCommonizerDependencies() {
|
||||||
val kotlin = this.multiplatformExtensionOrNull ?: return
|
val kotlin = this.multiplatformExtensionOrNull ?: return
|
||||||
|
|
||||||
kotlin.targets.withType(KotlinMetadataTarget::class.java).all { target ->
|
kotlin.forAllSharedNativeCompilations { compilation ->
|
||||||
target.compilations.withType(KotlinSharedNativeCompilation::class.java).all { compilation ->
|
setupCInteropCommonizerDependenciesForCompilation(compilation)
|
||||||
setupCInteropCommonizerDependenciesForCompilation(compilation)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin.sourceSets.withType(DefaultKotlinSourceSet::class.java).all { sourceSet ->
|
kotlin.forAllDefaultKotlinSourceSets { sourceSet ->
|
||||||
setupCInteropCommonizerDependenciesForIde(sourceSet)
|
setupCInteropCommonizerDependenciesForIde(sourceSet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,7 +41,7 @@ private fun Project.setupCInteropCommonizerDependenciesForCompilation(compilatio
|
|||||||
private fun Project.setupCInteropCommonizerDependenciesForIde(sourceSet: DefaultKotlinSourceSet) {
|
private fun Project.setupCInteropCommonizerDependenciesForIde(sourceSet: DefaultKotlinSourceSet) {
|
||||||
val cinteropCommonizerTask = project.copyCommonizeCInteropForIdeTask ?: return
|
val cinteropCommonizerTask = project.copyCommonizeCInteropForIdeTask ?: return
|
||||||
|
|
||||||
addDependency(sourceSet, filesProvider files@{
|
addIntransitiveMetadataDependencyIfPossible(sourceSet, filesProvider files@{
|
||||||
val directlyDependent = CInteropCommonizerDependent.from(project, sourceSet)
|
val directlyDependent = CInteropCommonizerDependent.from(project, sourceSet)
|
||||||
val associateDependent = CInteropCommonizerDependent.fromAssociateCompilations(project, sourceSet)
|
val associateDependent = CInteropCommonizerDependent.fromAssociateCompilations(project, sourceSet)
|
||||||
|
|
||||||
@@ -54,16 +50,3 @@ private fun Project.setupCInteropCommonizerDependenciesForIde(sourceSet: Default
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Dependencies here are using a special configuration called 'intransitiveMetadataConfiguration'.
|
|
||||||
* This special configuration can tell the IDE that this dependencies shall *not* be transitively be visible
|
|
||||||
* to dependsOn edges. This is necessary for the way the commonizer handles it's "expect refinement" approach.
|
|
||||||
* In this mode, every source set will receive exactly one commonized library to analyze its source code with.
|
|
||||||
*/
|
|
||||||
private fun Project.addDependency(sourceSet: DefaultKotlinSourceSet, dependency: FileCollection) {
|
|
||||||
val dependencyConfigurationName =
|
|
||||||
if (project.isIntransitiveMetadataConfigurationEnabled) sourceSet.intransitiveMetadataConfigurationName
|
|
||||||
else sourceSet.implementationMetadataConfigurationName
|
|
||||||
project.dependencies.add(dependencyConfigurationName, dependency)
|
|
||||||
}
|
|
||||||
|
|||||||
+1
-25
@@ -7,15 +7,11 @@ package org.jetbrains.kotlin.gradle.targets.native.internal
|
|||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
|
import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
|
||||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationSourceSetUtil.compilationsBySourceSets
|
import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationSourceSetUtil.compilationsBySourceSets
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithTransitiveClosure
|
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithTransitiveClosure
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.kotlinSourceSetsIncludingDefault
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropIdentifier.Scope
|
import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropIdentifier.Scope
|
||||||
import org.jetbrains.kotlin.gradle.utils.UnsafeApi
|
import org.jetbrains.kotlin.gradle.utils.UnsafeApi
|
||||||
|
|
||||||
@@ -80,7 +76,7 @@ internal fun CInteropCommonizerDependent.Factory.from(
|
|||||||
internal fun CInteropCommonizerDependent.Factory.from(compilation: KotlinSharedNativeCompilation): CInteropCommonizerDependent? {
|
internal fun CInteropCommonizerDependent.Factory.from(compilation: KotlinSharedNativeCompilation): CInteropCommonizerDependent? {
|
||||||
return from(
|
return from(
|
||||||
compilation.project.getCommonizerTarget(compilation) as? SharedCommonizerTarget ?: return null,
|
compilation.project.getCommonizerTarget(compilation) as? SharedCommonizerTarget ?: return null,
|
||||||
compilation.findDependingNativeCompilations()
|
compilation.getImplicitlyDependingNativeCompilations()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,23 +100,3 @@ internal fun CInteropCommonizerDependent.Factory.fromAssociateCompilations(
|
|||||||
.toSet()
|
.toSet()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinSharedNativeCompilation.findDependingNativeCompilations(): Set<KotlinNativeCompilation> {
|
|
||||||
val multiplatformExtension = project.multiplatformExtensionOrNull ?: return emptySet()
|
|
||||||
val allParticipatingSourceSetsOfCompilation = allParticipatingSourceSets()
|
|
||||||
|
|
||||||
return multiplatformExtension.targets
|
|
||||||
.flatMap { target -> target.compilations }
|
|
||||||
.filterIsInstance<KotlinNativeCompilation>()
|
|
||||||
.filter { nativeCompilation -> nativeCompilation.allParticipatingSourceSets().containsAll(allParticipatingSourceSetsOfCompilation) }
|
|
||||||
.toSet()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Some implementations of [KotlinCompilation] do not contain the default source set in
|
|
||||||
* [KotlinCompilation.kotlinSourceSets] or [KotlinCompilation.allKotlinSourceSets]
|
|
||||||
* see KT-45412
|
|
||||||
*/
|
|
||||||
private fun KotlinCompilation<*>.allParticipatingSourceSets(): Set<KotlinSourceSet> {
|
|
||||||
return kotlinSourceSetsIncludingDefault + kotlinSourceSetsIncludingDefault.resolveAllDependsOnSourceSets()
|
|
||||||
}
|
|
||||||
|
|||||||
+87
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.targets.native.internal
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationSourceSetUtil
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.CInteropProcess
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.filesProvider
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will propagate "original"/"platform" cinterops to intermediate source sets
|
||||||
|
* and 'shared native' compilations if necessary.
|
||||||
|
*
|
||||||
|
* cinterops will be forwarded when a source set/ compilation has just a single platform
|
||||||
|
* dependee
|
||||||
|
*
|
||||||
|
* e.g.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* kotlin {
|
||||||
|
* sourceSets {
|
||||||
|
* val nativeMain by sourceSets.creating
|
||||||
|
* val linuxX64Main by sourceSets.getting
|
||||||
|
* linuxX64Main.dependsOn(nativeMain)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* In this example 'nativeMain' has only a single native
|
||||||
|
* target and a single native source set depending on it.
|
||||||
|
* All cinterops defined on linuxX64's main compilation shall be propagated
|
||||||
|
* to the 'nativeMain' source set (and its 'shared native' compilation) if it exists.
|
||||||
|
*/
|
||||||
|
internal fun Project.setupCInteropPropagatedDependencies() {
|
||||||
|
val kotlin = this.multiplatformExtensionOrNull ?: return
|
||||||
|
|
||||||
|
kotlin.forAllSharedNativeCompilations { compilation ->
|
||||||
|
compilation.compileDependencyFiles += getPropagatedCInteropDependenciesOrEmpty(compilation)
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin.forAllDefaultKotlinSourceSets { sourceSet ->
|
||||||
|
addIntransitiveMetadataDependencyIfPossible(
|
||||||
|
sourceSet, getPropagatedCInteropDependenciesOrEmpty(sourceSet)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Project.getPropagatedCInteropDependenciesOrEmpty(sourceSet: DefaultKotlinSourceSet): FileCollection {
|
||||||
|
return filesProvider files@{
|
||||||
|
/*
|
||||||
|
compatibility metadata variant will still register
|
||||||
|
a 'KotlinMetadataCompilation for 'commonMain' which is irrelevant here
|
||||||
|
*/
|
||||||
|
val compilations = CompilationSourceSetUtil.compilationsBySourceSets(this)[sourceSet].orEmpty()
|
||||||
|
.filter { compilation -> compilation !is KotlinMetadataCompilation }
|
||||||
|
|
||||||
|
/* Participating in multiple compilations? -> can't propagate -> should be commonized */
|
||||||
|
val compilation = compilations.singleOrNull() as? KotlinNativeCompilation ?: return@files emptySet<File>()
|
||||||
|
|
||||||
|
/* Source Set is directly included in compilation -> No need to add dependency again (will be handled already) */
|
||||||
|
if (sourceSet in compilation.kotlinSourceSets) return@files emptySet<File>()
|
||||||
|
getAllCInteropOutputFiles(compilation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Project.getPropagatedCInteropDependenciesOrEmpty(compilation: KotlinSharedNativeCompilation) = filesProvider files@{
|
||||||
|
val compilations = compilation.getImplicitlyDependingNativeCompilations()
|
||||||
|
val platformCompilation = compilations.singleOrNull() ?: return@files emptySet<File>()
|
||||||
|
getAllCInteropOutputFiles(platformCompilation)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Project.getAllCInteropOutputFiles(compilation: KotlinNativeCompilation): List<File> {
|
||||||
|
return compilation.cinterops
|
||||||
|
.map { interop -> interop.interopProcessingTaskName }
|
||||||
|
.mapNotNull { taskName -> tasks.findByName(taskName) as? CInteropProcess }
|
||||||
|
.map { it.outputFile }
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.targets.native.internal
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.kotlinSourceSetsIncludingDefault
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets
|
||||||
|
|
||||||
|
internal fun KotlinSharedNativeCompilation.getImplicitlyDependingNativeCompilations(): Set<KotlinNativeCompilation> {
|
||||||
|
val multiplatformExtension = project.multiplatformExtensionOrNull ?: return emptySet()
|
||||||
|
val allParticipatingSourceSetsOfCompilation = allParticipatingSourceSets()
|
||||||
|
|
||||||
|
return multiplatformExtension.targets
|
||||||
|
.flatMap { target -> target.compilations }
|
||||||
|
.filterIsInstance<KotlinNativeCompilation>()
|
||||||
|
.filter { nativeCompilation -> nativeCompilation.allParticipatingSourceSets().containsAll(allParticipatingSourceSetsOfCompilation) }
|
||||||
|
.toSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some implementations of [KotlinCompilation] do not contain the default source set in
|
||||||
|
* [KotlinCompilation.kotlinSourceSets] or [KotlinCompilation.allKotlinSourceSets]
|
||||||
|
* see KT-45412
|
||||||
|
*/
|
||||||
|
private fun KotlinCompilation<*>.allParticipatingSourceSets(): Set<KotlinSourceSet> {
|
||||||
|
return kotlinSourceSetsIncludingDefault + kotlinSourceSetsIncludingDefault.resolveAllDependsOnSourceSets()
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.targets.native.internal
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
|
||||||
|
|
||||||
|
internal inline fun KotlinMultiplatformExtension.forAllSharedNativeCompilations(
|
||||||
|
crossinline action: (compilation: KotlinSharedNativeCompilation) -> Unit
|
||||||
|
) {
|
||||||
|
targets.withType(KotlinMetadataTarget::class.java).all { target ->
|
||||||
|
target.compilations.withType(KotlinSharedNativeCompilation::class.java).all { compilation ->
|
||||||
|
action(compilation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline fun KotlinMultiplatformExtension.forAllDefaultKotlinSourceSets(
|
||||||
|
crossinline action: (sourceSet: DefaultKotlinSourceSet) -> Unit
|
||||||
|
) {
|
||||||
|
sourceSets.withType(DefaultKotlinSourceSet::class.java).all { sourceSet ->
|
||||||
|
action(sourceSet)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user