diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt index a566b33fa78..cef860e6c9d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt @@ -10,6 +10,7 @@ import org.gradle.api.internal.plugins.DslObject import org.gradle.api.logging.Logger import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.plugin.* +import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterFinaliseDsl import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider import org.jetbrains.kotlin.gradle.plugin.mpp.* import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.KotlinTargetHierarchyDslImpl @@ -25,6 +26,11 @@ abstract class KotlinMultiplatformExtension(project: Project) : final override val targets: NamedDomainObjectCollection = project.container(KotlinTarget::class.java) + internal suspend fun awaitTargets(): NamedDomainObjectCollection { + await(AfterFinaliseDsl) + return targets + } + override val compilerTypeFromProperties: KotlinJsCompilerType? = project.kotlinPropertiesProvider.jsCompiler private val presetExtension = project.objects.newInstance( diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt index 9ca52e1d4bb..e1f3307878b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt @@ -155,6 +155,11 @@ open class KotlinProjectExtension @Inject constructor(project: Project) : Kotlin internal set(value) { DslObject(this).extensions.add("sourceSets", value) } + + internal suspend fun awaitSourceSets(): NamedDomainObjectContainer { + await(KotlinPluginLifecycle.Stage.AfterFinaliseDsl) + return sourceSets + } } abstract class KotlinSingleTargetExtension(project: Project) : KotlinProjectExtension(project) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport.kt index db8bc9b5193..c2b914b94d9 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport.kt @@ -174,7 +174,7 @@ interface IdeMultiplatformImport { companion object { val unconstrained = SourceSetConstraint { true } - val isNative = SourceSetConstraint { isNativeSourceSet(it) } + val isNative = SourceSetConstraint { it.isNativeSourceSet.getOrThrow() } val isSharedNative = isNative and SourceSetConstraint { sourceSet -> sourceSet.internal.compilations.filterIsInstance() 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 14819da03d4..433afe12471 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 @@ -203,7 +203,7 @@ internal fun Project.buildAdhocComponentsFromKotlinVariants(kotlinVariants: Set< return kotlinVariants.map { kotlinVariant -> val adhocVariant = softwareComponentFactory.adhoc(kotlinVariant.name) - project.whenEvaluated { + project.launchInStage(KotlinPluginLifecycle.Stage.AfterFinaliseCompilations) { (kotlinVariant as SoftwareComponentInternal).usages.filterIsInstance().forEach { kotlinUsageContext -> val publishedConfigurationName = publishedConfigurationName(kotlinUsageContext.name) val configuration = project.configurations.findByName(publishedConfigurationName) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt index 1af130e7dfa..77782d590ec 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt @@ -267,14 +267,14 @@ internal fun applyUserDefinedAttributes(target: AbstractKotlinTarget) { internal fun sourcesJarTask(compilation: KotlinCompilation<*>, componentName: String, artifactNameAppendix: String): TaskProvider = sourcesJarTask( compilation.target.project, - lazy { compilation.allKotlinSourceSets.associate { it.name to it.kotlin } }, + compilation.target.project.future { compilation.allKotlinSourceSets.associate { it.name to it.kotlin } }, componentName, artifactNameAppendix ) private fun sourcesJarTask( project: Project, - sourceSets: Lazy>>, + sourceSets: Future>>, taskNamePrefix: String, artifactNameAppendix: String ): TaskProvider = @@ -284,7 +284,7 @@ internal fun sourcesJarTaskNamed( taskName: String, componentName: String, project: Project, - sourceSets: Lazy>>, + sourceSets: Future>>, artifactNameAppendix: String, componentTypeName: String = "target", ): TaskProvider { @@ -301,9 +301,9 @@ internal fun sourcesJarTaskNamed( sourcesJar.description = "Assembles a jar archive containing the sources of $componentTypeName '$componentName'." } - project.whenEvaluated { - result.configure { - sourceSets.value.forEach { (sourceSetName, sourceSetFiles) -> + result.configure { + project.launch { + sourceSets.await().forEach { (sourceSetName, sourceSetFiles) -> it.from(sourceSetFiles) { copySpec -> copySpec.into(sourceSetName) // Duplicates are coming from `SourceSets` that `sourceSet` depends on. diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt index 1f30dee9aaf..658829bb44f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.gradle.targets.metadata.getPublishedPlatformCompilat import org.jetbrains.kotlin.gradle.targets.metadata.isNativeSourceSet import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropCommonizerCompositeMetadataJarBundling.cinteropMetadataDirectoryPath import org.jetbrains.kotlin.gradle.utils.compositeBuildRootProject +import org.jetbrains.kotlin.gradle.utils.future import org.jetbrains.kotlin.gradle.utils.getOrPut import org.w3c.dom.Document import org.w3c.dom.Element @@ -166,7 +167,8 @@ private fun buildKotlinProjectStructureMetadata(extension: KotlinMultiplatformEx .getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME) .compilations.associateBy { it.defaultSourceSet } - val publishedVariantsNamesWithCompilation = getPublishedPlatformCompilations(project).mapKeys { it.key.name } + val publishedVariantsNamesWithCompilation = project.future { getPublishedPlatformCompilations(project).mapKeys { it.key.name } } + .getOrThrow() return KotlinProjectStructureMetadata( sourceSetNamesByVariantName = publishedVariantsNamesWithCompilation.mapValues { (_, compilation) -> @@ -181,7 +183,7 @@ private fun buildKotlinProjectStructureMetadata(extension: KotlinMultiplatformEx * published as API dependencies of the metadata module to get into the resolution result, see * [KotlinMetadataTargetConfigurator.exportDependenciesForPublishing]. */ - val isNativeSharedSourceSet = isNativeSourceSet(sourceSet) + val isNativeSharedSourceSet = sourceSet.isNativeSourceSet.getOrThrow() val scopes = listOfNotNull( KotlinDependencyScope.API_SCOPE, KotlinDependencyScope.IMPLEMENTATION_SCOPE.takeIf { isNativeSharedSourceSet } @@ -198,9 +200,9 @@ private fun buildKotlinProjectStructureMetadata(extension: KotlinMultiplatformEx sourceSet.name to sourceSetExportedDependencies.map { ModuleIds.fromDependency(it) }.toSet() }, sourceSetCInteropMetadataDirectory = sourceSetsWithMetadataCompilations.keys - .filter { isNativeSourceSet(it) } + .filter { it.isNativeSourceSet.getOrThrow() } .associate { sourceSet -> sourceSet.name to cinteropMetadataDirectoryPath(sourceSet.name) }, - hostSpecificSourceSets = getHostSpecificSourceSets(project) + hostSpecificSourceSets = project.future { getHostSpecificSourceSets(project) }.getOrThrow() .filter { it in sourceSetsWithMetadataCompilations }.map { it.name } .toSet(), sourceSetBinaryLayout = sourceSetsWithMetadataCompilations.keys.associate { sourceSet -> @@ -239,7 +241,7 @@ internal fun buildProjectStructureMetadata(module: GradleKpmModule): KotlinProje sourceSetBinaryLayout = module.fragments.associate { it.name to SourceSetMetadataLayout.KLIB }, sourceSetModuleDependencies = fragmentDependencies, sourceSetCInteropMetadataDirectory = emptyMap(), // Not supported yet - hostSpecificSourceSets = getHostSpecificFragments(module).mapTo(mutableSetOf()) { it.name }, + hostSpecificSourceSets = module.project.future { getHostSpecificFragments(module).mapTo(mutableSetOf()) { it.name } }.getOrThrow(), isPublishedAsRoot = true, sourceSetNames = module.fragments.map { it.name }.toSet() ) 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 3c6826a538e..ed3b031fe6e 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 @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.gradle.targets.metadata.* import org.jetbrains.kotlin.gradle.targets.metadata.COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME import org.jetbrains.kotlin.gradle.targets.metadata.isCompatibilityMetadataVariantEnabled import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled +import org.jetbrains.kotlin.gradle.utils.future import org.jetbrains.kotlin.gradle.utils.setProperty import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly @@ -100,7 +101,7 @@ abstract class KotlinSoftwareComponent( return _usages.publishableUsages() } - private fun allPublishableCommonSourceSets() = getCommonSourceSetsForMetadataCompilation(project) + + private suspend fun allPublishableCommonSourceSets() = getCommonSourceSetsForMetadataCompilation(project) + getHostSpecificMainSharedSourceSets(project) /** @@ -108,12 +109,12 @@ abstract class KotlinSoftwareComponent( * user build scripts want to have access to sourcesJar task to configure it */ private val sourcesJarTask: TaskProvider = sourcesJarTaskNamed( - "sourcesJar", - name, - project, - lazy { allPublishableCommonSourceSets().associate { it.name to it.kotlin } }, - name.toLowerCaseAsciiOnly() - ) + "sourcesJar", + name, + project, + project.future { allPublishableCommonSourceSets().associate { it.name to it.kotlin } }, + name.toLowerCaseAsciiOnly() + ) private fun addSourcesJarArtifactToConfiguration(configurationName: String): PublishArtifact { return project.artifacts.add(configurationName, sourcesJarTask) { sourcesJarArtifact -> diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmMetadataCompilationData.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmMetadataCompilationData.kt index c14a2f56b04..89f36e676cb 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmMetadataCompilationData.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmMetadataCompilationData.kt @@ -17,10 +17,9 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.disambiguateName import org.jetbrains.kotlin.gradle.targets.metadata.ResolvedMetadataFilesProvider import org.jetbrains.kotlin.gradle.targets.native.NativeCompilerOptions -import org.jetbrains.kotlin.gradle.utils.getValue +import org.jetbrains.kotlin.gradle.utils.* import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import org.jetbrains.kotlin.gradle.utils.newProperty -import org.jetbrains.kotlin.gradle.utils.setValue import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.KonanTarget @@ -140,7 +139,7 @@ internal fun GradleKpmFragment.isNativeShared(): Boolean = } internal fun GradleKpmFragment.isNativeHostSpecific(): Boolean = - this in getHostSpecificFragments(containingModule) + this.project.future { this@isNativeHostSpecific in getHostSpecificFragments(containingModule) }.lenient.getOrNull() ?: false internal open class GradleKpmNativeFragmentMetadataCompilationDataImpl( project: Project, diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmSourceArchiveTaskConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmSourceArchiveTaskConfigurator.kt index fd133e0e739..a26a404fef2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmSourceArchiveTaskConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmSourceArchiveTaskConfigurator.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 import org.gradle.api.tasks.TaskProvider import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.unambiguousNameInProject import org.jetbrains.kotlin.gradle.plugin.mpp.sourcesJarTaskNamed +import org.jetbrains.kotlin.gradle.utils.future interface GradleKpmSourceArchiveTaskConfigurator { fun registerSourceArchiveTask(variant: T): TaskProvider<*>? @@ -19,7 +20,7 @@ object GradleKpmDefaultKotlinSourceArchiveTaskConfigurator : GradleKpmSourceArch taskName = variant.sourceArchiveTaskName, componentName = variant.name, project = variant.project, - sourceSets = lazy { + sourceSets = variant.project.future { GradleKpmFragmentSourcesProvider().getSourcesFromRefinesClosureAsMap(variant) .entries.associate { it.key.unambiguousNameInProject to it.value.get() } }, diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/setupFragmentsMetadataForKpmModules.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/setupFragmentsMetadataForKpmModules.kt index 2a89dec9c43..80a5f92c12e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/setupFragmentsMetadataForKpmModules.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/setupFragmentsMetadataForKpmModules.kt @@ -20,7 +20,8 @@ import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigur import org.jetbrains.kotlin.gradle.targets.metadata.createGenerateProjectStructureMetadataTask import org.jetbrains.kotlin.gradle.targets.metadata.filesWithUnpackedArchives import org.jetbrains.kotlin.gradle.tasks.* -import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation +import org.jetbrains.kotlin.gradle.tasks.withType +import org.jetbrains.kotlin.gradle.utils.* import org.jetbrains.kotlin.gradle.utils.dashSeparatedName import org.jetbrains.kotlin.gradle.utils.filesProvider import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName @@ -72,7 +73,9 @@ private fun configureMetadataExposure(module: GradleKpmModule) { module.disambiguateName("allSourcesJar"), module.name, project, - lazy { GradleKpmFragmentSourcesProvider().getAllFragmentSourcesAsMap(module).entries.associate { it.key.fragmentName to it.value.get() } }, + project.future { + GradleKpmFragmentSourcesProvider().getAllFragmentSourcesAsMap(module).entries.associate { it.key.fragmentName to it.value.get() } + }, sourcesArtifactAppendix, "module", ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/InternalKotlinSourceSet.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/InternalKotlinSourceSet.kt index 8537d052de8..e8bfa6448bc 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/InternalKotlinSourceSet.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/InternalKotlinSourceSet.kt @@ -6,7 +6,10 @@ package org.jetbrains.kotlin.gradle.plugin.sources import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation +import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.await +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataCompilation import org.jetbrains.kotlin.gradle.utils.MutableObservableSet import org.jetbrains.kotlin.gradle.utils.ObservableSet @@ -21,3 +24,8 @@ internal interface InternalKotlinSourceSet : KotlinSourceSet { val withDependsOnClosure: ObservableSet val compilations: MutableObservableSet> } + +internal suspend fun InternalKotlinSourceSet.awaitPlatformCompilations(): Set> { + await(KotlinPluginLifecycle.Stage.FinaliseRefinesEdges) + return compilations.filter { it !is KotlinMetadataCompilation }.toSet() +} 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 773f0cefdf5..8301389058e 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 @@ -33,11 +33,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider import org.jetbrains.kotlin.gradle.tasks.registerTask import org.jetbrains.kotlin.gradle.utils.* -import org.jetbrains.kotlin.gradle.utils.filesProvider -import org.jetbrains.kotlin.gradle.utils.getResolvedArtifactsCompat -import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics -import org.jetbrains.kotlin.tooling.core.UnsafeApi import org.jetbrains.kotlin.tooling.core.extrasLazyProperty internal const val COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME = "commonMainMetadataElements" @@ -184,36 +180,38 @@ class KotlinMetadataTargetConfigurator : private fun createMetadataCompilationsForCommonSourceSets( target: KotlinMetadataTarget, allMetadataJar: TaskProvider - ) = target.project.launchInRequiredStage(KotlinPluginLifecycle.Stage.FinaliseCompilations) { - // Do this after all targets are configured by the user build script + ) = target.project.launchInStage(KotlinPluginLifecycle.Stage.BeforeFinaliseCompilations) { + withRestrictedStages(KotlinPluginLifecycle.Stage.upTo(KotlinPluginLifecycle.Stage.FinaliseCompilations)) { + // Do this after all targets are configured by the user build script - val publishedCommonSourceSets: Set = getCommonSourceSetsForMetadataCompilation(project) - val hostSpecificSourceSets: Set = getHostSpecificSourceSets(project).toSet() + val publishedCommonSourceSets: Set = getCommonSourceSetsForMetadataCompilation(project) + val hostSpecificSourceSets: Set = getHostSpecificSourceSets(project).toSet() - val sourceSetsWithMetadataCompilations: Map> = publishedCommonSourceSets - .associateWith { sourceSet -> - createMetadataCompilation(target, sourceSet, allMetadataJar, sourceSet in hostSpecificSourceSets) - } - .onEach { (sourceSet, compilation) -> - if (!isMetadataCompilationSupported(sourceSet)) { - compilation.compileKotlinTaskProvider.configure { it.enabled = false } + val sourceSetsWithMetadataCompilations: Map> = publishedCommonSourceSets + .associateWith { sourceSet -> + createMetadataCompilation(target, sourceSet, allMetadataJar, sourceSet in hostSpecificSourceSets) } + .onEach { (sourceSet, compilation) -> + if (!isMetadataCompilationSupported(sourceSet)) { + compilation.compileKotlinTaskProvider.configure { it.enabled = false } + } + } + + if (project.isCompatibilityMetadataVariantEnabled) { + val mainCompilation = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME) + configureMetadataDependenciesForCompilation(mainCompilation) } - if (project.isCompatibilityMetadataVariantEnabled) { - val mainCompilation = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME) - configureMetadataDependenciesForCompilation(mainCompilation) - } + sourceSetsWithMetadataCompilations.values.forEach { compilation -> + exportDependenciesForPublishing(compilation) + } - sourceSetsWithMetadataCompilations.values.forEach { compilation -> - exportDependenciesForPublishing(compilation) + target.metadataCompilationsCreated.complete() } - - target.metadataCompilationsCreated.complete() } - private fun isMetadataCompilationSupported(sourceSet: KotlinSourceSet): Boolean { - val platforms = sourceSet.internal.compilations + private suspend fun isMetadataCompilationSupported(sourceSet: KotlinSourceSet): Boolean { + val platforms = sourceSet.internal.awaitPlatformCompilations() .filter { it.target !is KotlinMetadataTarget } .map { it.target.platformType }.distinct() @@ -296,7 +294,7 @@ class KotlinMetadataTargetConfigurator : val platformCompilations = sourceSet.internal.compilations .filter { it.target.name != KotlinMultiplatformPlugin.METADATA_TARGET_NAME } - val isNativeSourceSet = isNativeSourceSet(sourceSet) + val isNativeSourceSet = sourceSet.isNativeSourceSet.await() val compilationFactory: KotlinCompilationFactory> = when { isNativeSourceSet -> KotlinSharedNativeCompilationFactory( @@ -423,9 +421,10 @@ internal interface ResolvedMetadataFilesProvider { val metadataFilesByResolution: Map } -internal fun isNativeSourceSet(sourceSet: KotlinSourceSet): Boolean { - val compilations = sourceSet.internal.compilations.filterNot { it.platformType == KotlinPlatformType.common } - return compilations.isNotEmpty() && compilations.all { it.platformType == KotlinPlatformType.native } + +internal val KotlinSourceSet.isNativeSourceSet: Future by futureExtension("isNativeSourceSet") { + val compilations = internal.awaitPlatformCompilations() + compilations.isNotEmpty() && compilations.all { it.platformType == KotlinPlatformType.native } } internal fun isSinglePlatformTypeSourceSet(sourceSet: KotlinSourceSet): Boolean { @@ -449,12 +448,12 @@ internal fun dependsOnClosureWithInterCompilationDependencies(sourceSet: KotlinS * support metadata compilation (see [KotlinMetadataTargetConfigurator.isMetadataCompilationSupported]. * Those compilations will be created but the corresponding tasks will be disabled. */ -internal fun getCommonSourceSetsForMetadataCompilation(project: Project): Set { +internal suspend fun getCommonSourceSetsForMetadataCompilation(project: Project): Set { if (!project.shouldCompileIntermediateSourceSetsToMetadata) - return setOf(project.multiplatformExtension.sourceSets.getByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)) + return setOf(project.multiplatformExtension.awaitSourceSets().getByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)) val compilationsBySourceSet: Map>> = - project.kotlinExtension.sourceSets.associateWith { it.internal.compilations } + project.kotlinExtension.awaitSourceSets().associateWith { it.internal.awaitPlatformCompilations() } val sourceSetsUsedInMultipleTargets = compilationsBySourceSet.filterValues { compilations -> compilations.map { it.target.platformType }.distinct().run { @@ -472,10 +471,10 @@ internal fun getCommonSourceSetsForMetadataCompilation(project: Project): Set> { +internal suspend fun getPublishedPlatformCompilations(project: Project): Map> { val result = mutableMapOf>() - project.multiplatformExtension.targets.withType(AbstractKotlinTarget::class.java).forEach { target -> + project.multiplatformExtension.awaitTargets().withType(AbstractKotlinTarget::class.java).forEach { target -> if (target.platformType == KotlinPlatformType.common) return@forEach 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 285fcb783fe..71eb6efae5d 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 @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinNativeBinaryContainer import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.* +import org.jetbrains.kotlin.gradle.plugin.sources.awaitPlatformCompilations import org.jetbrains.kotlin.gradle.plugin.sources.internal import org.jetbrains.kotlin.gradle.targets.metadata.* import org.jetbrains.kotlin.gradle.targets.native.KotlinNativeBinaryTestRun @@ -165,13 +166,13 @@ private val targetsEnabledOnAllHosts by lazy { hostManager.enabledByHost.values. internal fun isHostSpecificKonanTargetsSet(konanTargets: Iterable): Boolean = konanTargets.none { target -> target in targetsEnabledOnAllHosts } -private fun getHostSpecificElements( +private suspend fun getHostSpecificElements( fragments: Iterable, - isNativeShared: (T) -> Boolean, - getKonanTargets: (T) -> Set + isNativeShared: suspend (T) -> Boolean, + getKonanTargets: suspend (T) -> Set ): Set = fragments.filterTo(mutableSetOf()) { isNativeShared(it) && isHostSpecificKonanTargetsSet(getKonanTargets(it)) } -internal fun getHostSpecificFragments( +internal suspend fun getHostSpecificFragments( module: GradleKpmModule ): Set = getHostSpecificElements( module.fragments, @@ -182,12 +183,12 @@ internal fun getHostSpecificFragments( } ) -internal fun getHostSpecificSourceSets(project: Project): Set { +internal suspend fun getHostSpecificSourceSets(project: Project): Set { return getHostSpecificElements( - project.kotlinExtension.sourceSets, - isNativeShared = { sourceSet -> isNativeSourceSet(sourceSet) }, + project.kotlinExtension.awaitSourceSets(), + isNativeShared = { sourceSet -> sourceSet.isNativeSourceSet.await() }, getKonanTargets = { sourceSet -> - sourceSet.internal.compilations + sourceSet.internal.awaitPlatformCompilations() .filterIsInstance() .mapTo(mutableSetOf()) { it.konanTarget } } @@ -197,7 +198,7 @@ internal fun getHostSpecificSourceSets(project: Project): Set { /** * Returns all host-specific source sets that will be compiled to two or more targets */ -internal fun getHostSpecificMainSharedSourceSets(project: Project): Set { +internal suspend fun getHostSpecificMainSharedSourceSets(project: Project): Set { fun KotlinSourceSet.testOnly(): Boolean = internal.compilations.all { it.isTest() } fun KotlinSourceSet.isCompiledToSingleTarget(): Boolean { diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/sources/InternalKotlinSourceSetTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/sources/InternalKotlinSourceSetTest.kt index f05fbf5e106..f6dcb8c03cc 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/sources/InternalKotlinSourceSetTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/sources/InternalKotlinSourceSetTest.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.gradle.plugin.sources.internal import org.jetbrains.kotlin.gradle.util.assertAllImplementationsAlsoImplement import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP import org.jetbrains.kotlin.gradle.util.kotlin +import org.jetbrains.kotlin.gradle.utils.future import kotlin.test.Test import kotlin.test.assertEquals @@ -177,7 +178,7 @@ class InternalKotlinSourceSetTest { project.evaluate() val expected = listOf("iosMain", "ios2Main").sorted() - val actual = getHostSpecificMainSharedSourceSets(project).map { it.name }.sorted() + val actual = project.future { getHostSpecificMainSharedSourceSets(project).map { it.name }.sorted() }.getOrThrow() assertEquals(expected, actual) }