diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/DependencyGraphResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/DependencyGraphResolver.kt index 3055044dedb..8fa6ce903f4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/DependencyGraphResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/DependencyGraphResolver.kt @@ -111,3 +111,15 @@ class GradleDependencyGraph( override val requestingModule: KotlinGradleModule, override val root: GradleDependencyGraphNode ) : DependencyGraphResolution.DependencyGraph(requestingModule, root) + +val GradleDependencyGraph.allGraphNodes: Iterable + get() = mutableSetOf().apply { + fun visit(node: GradleDependencyGraphNode) { + if (add(node)) + node.dependenciesByFragment.values.flatten().forEach(::visit) + } + visit(root) + } + +val GradleDependencyGraph.allDependencyModules: Iterable + get() = allGraphNodes.map { it.module }.filter { it != root.module } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinCompilationData.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinCompilationData.kt index 42e1805a8e0..8de54b13061 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinCompilationData.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinCompilationData.kt @@ -5,15 +5,18 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 -import org.gradle.api.Project +import org.gradle.api.artifacts.component.ProjectComponentIdentifier import org.gradle.api.file.FileCollection import org.gradle.api.file.SourceDirectorySet import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions import org.jetbrains.kotlin.gradle.dsl.pm20Extension import org.jetbrains.kotlin.gradle.plugin.* +import org.jetbrains.kotlin.gradle.plugin.mpp.GradleModuleVariantResolver import org.jetbrains.kotlin.gradle.plugin.mpp.isMain import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.disambiguateName +import org.jetbrains.kotlin.gradle.utils.filesProvider import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName +import org.jetbrains.kotlin.project.model.VariantResolution import org.jetbrains.kotlin.project.model.refinesClosure interface KotlinVariantCompilationDataInternal : KotlinVariantCompilationData { @@ -27,11 +30,27 @@ interface KotlinVariantCompilationDataInternal : Kotlin get() = owner.refinesClosure.filterIsInstance().associate { it.disambiguateName("") to it.kotlinSourceRoots } override val friendPaths: Iterable - // TODO for now, all output classes of the module are considered friends, even those not on the classpath get() { - // FIXME support compiling against the artifact task outputs - // TODO note for Android: see the friend artifacts code in KotlinAndroidCompilation - return owner.containingModule.project.kpmModules.flatMap { it.variants.map { it.compilationOutputs.classesDirs } } + // TODO note for Android: see the friend artifacts code in KotlinAndroidCompilation; should we port it here? + return listOf( + project.filesProvider { + val friendVariants = resolveFriendVariants() + val friendModuleClassifiers = friendVariants.map { it.containingModule.moduleClassifier }.toSet() + val artifactView = owner.compileDependenciesConfiguration + .incoming.artifactView { view -> + view.componentFilter { id -> + // FIXME rewrite using the proper module resolution after those changes are merged + val asProject = id as? ProjectComponentIdentifier + asProject?.build?.isCurrentBuild == true && + asProject.projectPath == owner.project.path + } + }.artifacts + artifactView.filter { + // FIXME rewrite using the proper module resolution after those changes are merged + moduleClassifiersFromCapabilities(it.variant.capabilities).any { it in friendModuleClassifiers } + }.map { it.file } + } + ) } override val moduleName: String @@ -41,6 +60,29 @@ interface KotlinVariantCompilationDataInternal : Kotlin override val ownModuleName: String get() = owner.ownModuleName() + + private fun resolveFriendVariants(): Iterable { + val moduleResolver = GradleModuleDependencyResolver.getForCurrentBuild(project) + val variantResolver = GradleModuleVariantResolver.getForCurrentBuild(project) + val dependencyGraphResolver = GradleKotlinDependencyGraphResolver(moduleResolver) + + val friendModules = + ((dependencyGraphResolver.resolveDependencyGraph(owner.containingModule) as? GradleDependencyGraph) + ?: error("Failed to resolve dependencies of ${owner.containingModule}")) + .allDependencyModules + .filterIsInstance() + .filter { + // the module comes from the same Gradle project // todo: extend to other friends once supported + it.project == owner.containingModule.project && + // also, important to check that the owner variant really requests this module: + variantResolver.getChosenVariant(owner, it) is VariantResolution.VariantMatch + } + + val friendVariants = friendModules.map { + (variantResolver.getChosenVariant(owner, it) as VariantResolution.VariantMatch).chosenVariant + } + return friendVariants.filterIsInstance() + } } fun KotlinCompilationData<*>.isMainCompilationData(): Boolean = when (this) {