Add caching to dependency resolvers in PM20 + some refactoring
This commit is contained in:
+27
-4
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.getVisibleSourceSetsFromAssociateCompilations
|
import org.jetbrains.kotlin.gradle.plugin.sources.getVisibleSourceSetsFromAssociateCompilations
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.getOrPutRootProjectProperty
|
||||||
import org.jetbrains.kotlin.project.model.*
|
import org.jetbrains.kotlin.project.model.*
|
||||||
|
|
||||||
class ProjectStructureMetadataModuleBuilder {
|
class ProjectStructureMetadataModuleBuilder {
|
||||||
@@ -260,22 +261,35 @@ internal fun Dependency.toModuleDependency(
|
|||||||
private fun BasicKotlinModule.fragmentByName(name: String) =
|
private fun BasicKotlinModule.fragmentByName(name: String) =
|
||||||
fragments.single { it.fragmentName == name }
|
fragments.single { it.fragmentName == name }
|
||||||
|
|
||||||
class GradleModuleVariantResolver(val project: Project) : ModuleVariantResolver {
|
class CachingModuleVariantResolver(private val actualResolver: ModuleVariantResolver) : ModuleVariantResolver {
|
||||||
private val resolvedVariantProvider = ResolvedMppVariantsProvider.get(project)
|
private val resultCacheByRequestingVariant: MutableMap<KotlinModuleVariant, MutableMap<KotlinModule, VariantResolution>> = mutableMapOf()
|
||||||
|
|
||||||
|
override fun getChosenVariant(requestingVariant: KotlinModuleVariant, dependencyModule: KotlinModule): VariantResolution {
|
||||||
|
val resultCache = resultCacheByRequestingVariant.getOrPut(requestingVariant) { mutableMapOf() }
|
||||||
|
return resultCache.getOrPut(dependencyModule) { actualResolver.getChosenVariant(requestingVariant, dependencyModule) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GradleModuleVariantResolver : ModuleVariantResolver {
|
||||||
override fun getChosenVariant(requestingVariant: KotlinModuleVariant, dependencyModule: KotlinModule): VariantResolution {
|
override fun getChosenVariant(requestingVariant: KotlinModuleVariant, dependencyModule: KotlinModule): VariantResolution {
|
||||||
// TODO maybe improve this behavior? Currently it contradicts dependency resolution in that it may return a chosen variant for an
|
// TODO maybe improve this behavior? Currently it contradicts dependency resolution in that it may return a chosen variant for an
|
||||||
// unrequested dependency. This workaround is needed for synthetic modules which were not produced from module metadata, so maybe
|
// unrequested dependency. This workaround is needed for synthetic modules which were not produced from module metadata, so maybe
|
||||||
// those modules should be marked somehow
|
// those modules should be marked somehow
|
||||||
if (dependencyModule is ExternalSyntheticKotlinModule) {
|
if (dependencyModule is ExternalPlainKotlinModule) {
|
||||||
return VariantResolution.fromMatchingVariants(
|
return VariantResolution.fromMatchingVariants(
|
||||||
requestingVariant,
|
requestingVariant,
|
||||||
dependencyModule,
|
dependencyModule,
|
||||||
listOf(dependencyModule.variants.single())
|
listOf(dependencyModule.singleVariant)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (requestingVariant !is KotlinGradleVariant) {
|
||||||
|
return VariantResolution.Unknown(requestingVariant, dependencyModule)
|
||||||
|
}
|
||||||
|
|
||||||
val module = requestingVariant.containingModule
|
val module = requestingVariant.containingModule
|
||||||
|
val project = module.project
|
||||||
|
val resolvedVariantProvider = ResolvedMppVariantsProvider.get(project)
|
||||||
|
|
||||||
// This implementation can only resolve variants for the current project's KotlinModule
|
// This implementation can only resolve variants for the current project's KotlinModule
|
||||||
require(module.representsProject(project))
|
require(module.representsProject(project))
|
||||||
@@ -324,4 +338,13 @@ class GradleModuleVariantResolver(val project: Project) : ModuleVariantResolver
|
|||||||
}
|
}
|
||||||
else -> error("could not find the compile dependencies configuration for variant $requestingVariant")
|
else -> error("could not find the compile dependencies configuration for variant $requestingVariant")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getForCurrentBuild(project: Project): ModuleVariantResolver {
|
||||||
|
val extraPropertyName = "org.jetbrains.kotlin.dependencyResolution.variantResolver.${project.getKotlinPluginVersion()}"
|
||||||
|
return project.getOrPutRootProjectProperty(extraPropertyName) {
|
||||||
|
CachingModuleVariantResolver(GradleModuleVariantResolver())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
@@ -433,6 +433,7 @@ internal open class JarArtifactMppDependencyMetadataExtractor(
|
|||||||
val primaryArtifact: File
|
val primaryArtifact: File
|
||||||
) : MppDependencyMetadataExtractor(project, dependency) {
|
) : MppDependencyMetadataExtractor(project, dependency) {
|
||||||
|
|
||||||
|
// TODO: add proper API to make an artifact extractor with just the composite artifact "evolve" into one with host-specific artifacts
|
||||||
val metadataArtifactBySourceSet: MutableMap<String, File> = mutableMapOf()
|
val metadataArtifactBySourceSet: MutableMap<String, File> = mutableMapOf()
|
||||||
|
|
||||||
private fun parseJsonProjectStructureMetadata(input: InputStream) =
|
private fun parseJsonProjectStructureMetadata(input: InputStream) =
|
||||||
|
|||||||
+4
-6
@@ -17,19 +17,17 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.toModuleIdentifiers
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.toModuleIdentifiers
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.toSingleModuleIdentifier
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.toSingleModuleIdentifier
|
||||||
import org.jetbrains.kotlin.gradle.plugin.usageByName
|
import org.jetbrains.kotlin.gradle.plugin.usageByName
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.getOrPut
|
||||||
import org.jetbrains.kotlin.project.model.KotlinModuleIdentifier
|
import org.jetbrains.kotlin.project.model.KotlinModuleIdentifier
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal class ResolvedMppVariantsProvider private constructor(private val project: Project) {
|
internal class ResolvedMppVariantsProvider private constructor(private val project: Project) {
|
||||||
companion object {
|
companion object {
|
||||||
|
fun get(project: Project): ResolvedMppVariantsProvider {
|
||||||
fun get(project: Project): ResolvedMppVariantsProvider = with(project.extensions.extraProperties) {
|
|
||||||
val propertyName = "kotlin.mpp.internal.resolvedModuleVariantsProvider"
|
val propertyName = "kotlin.mpp.internal.resolvedModuleVariantsProvider"
|
||||||
if (!has(propertyName)) {
|
return project.extensions.extraProperties.getOrPut(propertyName) {
|
||||||
set(propertyName, ResolvedMppVariantsProvider(project))
|
ResolvedMppVariantsProvider(project)
|
||||||
}
|
}
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
get(propertyName) as ResolvedMppVariantsProvider
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -44,8 +44,6 @@ class GradleKotlinDependencyGraphResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveAsGraph(requestingModule: KotlinGradleModule): GradleDependencyGraph {
|
private fun resolveAsGraph(requestingModule: KotlinGradleModule): GradleDependencyGraph {
|
||||||
val excludeLegacyMetadataModulesFromResult = mutableSetOf<ResolvedComponentResult>()
|
|
||||||
|
|
||||||
val nodeByModuleId = mutableMapOf<KotlinModuleIdentifier, GradleDependencyGraphNode>()
|
val nodeByModuleId = mutableMapOf<KotlinModuleIdentifier, GradleDependencyGraphNode>()
|
||||||
|
|
||||||
fun getKotlinModuleFromComponentResult(component: ResolvedComponentResult): KotlinModule =
|
fun getKotlinModuleFromComponentResult(component: ResolvedComponentResult): KotlinModule =
|
||||||
@@ -100,6 +98,8 @@ class GradleKotlinDependencyGraphResolver(
|
|||||||
class GradleDependencyGraphNode(
|
class GradleDependencyGraphNode(
|
||||||
override val module: KotlinModule,
|
override val module: KotlinModule,
|
||||||
val selectedComponent: ResolvedComponentResult,
|
val selectedComponent: ResolvedComponentResult,
|
||||||
|
/** If the Kotlin module description was provided by a different component, such as with legacy publishing layout using *-metadata
|
||||||
|
* modules, then this property points to the other component. */
|
||||||
val metadataSourceComponent: ResolvedComponentResult?,
|
val metadataSourceComponent: ResolvedComponentResult?,
|
||||||
override val dependenciesByFragment: Map<KotlinModuleFragment, Iterable<GradleDependencyGraphNode>>
|
override val dependenciesByFragment: Map<KotlinModuleFragment, Iterable<GradleDependencyGraphNode>>
|
||||||
) : DependencyGraphNode(module, dependenciesByFragment)
|
) : DependencyGraphNode(module, dependenciesByFragment)
|
||||||
|
|||||||
+76
-16
@@ -11,31 +11,69 @@ import org.gradle.api.artifacts.component.*
|
|||||||
import org.gradle.api.artifacts.result.ResolvedComponentResult
|
import org.gradle.api.artifacts.result.ResolvedComponentResult
|
||||||
import org.gradle.api.artifacts.result.ResolvedDependencyResult
|
import org.gradle.api.artifacts.result.ResolvedDependencyResult
|
||||||
import org.gradle.api.capabilities.Capability
|
import org.gradle.api.capabilities.Capability
|
||||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.getProjectStructureMetadata
|
import org.jetbrains.kotlin.gradle.plugin.mpp.getProjectStructureMetadata
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
import org.jetbrains.kotlin.gradle.utils.getOrPut
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.getOrPutRootProjectProperty
|
||||||
import org.jetbrains.kotlin.project.model.*
|
import org.jetbrains.kotlin.project.model.*
|
||||||
import java.util.ArrayDeque
|
import java.util.*
|
||||||
|
|
||||||
|
class CachingModuleDependencyResolver(private val actualResolver: ModuleDependencyResolver) : ModuleDependencyResolver {
|
||||||
|
private val cacheByRequestingModule = WeakHashMap<KotlinModule, MutableMap<KotlinModuleDependency, KotlinModule?>>()
|
||||||
|
|
||||||
|
private fun cacheForRequestingModule(requestingModule: KotlinModule) =
|
||||||
|
cacheByRequestingModule.getOrPut(requestingModule) { mutableMapOf() }
|
||||||
|
|
||||||
|
override fun resolveDependency(requestingModule: KotlinModule, moduleDependency: KotlinModuleDependency): KotlinModule? =
|
||||||
|
cacheForRequestingModule(requestingModule).getOrPut(moduleDependency) {
|
||||||
|
actualResolver.resolveDependency(requestingModule, moduleDependency)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class GradleComponentResultCachingResolver {
|
||||||
|
private val cachedResultsByRequestingModule = mutableMapOf<KotlinGradleModule, Map<KotlinModuleIdentifier, ResolvedComponentResult>>()
|
||||||
|
|
||||||
|
protected open fun configurationToResolve(requestingModule: KotlinGradleModule): Configuration =
|
||||||
|
configurationToResolveMetadataDependencies(requestingModule.project, requestingModule)
|
||||||
|
|
||||||
|
protected open fun resolveDependencies(module: KotlinGradleModule): Map<KotlinModuleIdentifier, ResolvedComponentResult> {
|
||||||
|
val allComponents = configurationToResolve(module).incoming.resolutionResult.allComponents
|
||||||
|
// FIXME handle multi-component results
|
||||||
|
return allComponents.flatMap { component -> component.toModuleIdentifiers().map { it to component } }.toMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getResultsForModule(module: KotlinGradleModule): Map<KotlinModuleIdentifier, ResolvedComponentResult> =
|
||||||
|
cachedResultsByRequestingModule.getOrPut(module) { resolveDependencies(module) }
|
||||||
|
|
||||||
|
fun resolveModuleDependencyAsComponentResult(
|
||||||
|
requestingModule: KotlinGradleModule,
|
||||||
|
moduleDependency: KotlinModuleDependency
|
||||||
|
): ResolvedComponentResult? =
|
||||||
|
getResultsForModule(requestingModule)[moduleDependency.moduleIdentifier]
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getForCurrentBuild(project: Project): GradleComponentResultCachingResolver {
|
||||||
|
val extraPropertyName = "org.jetbrains.kotlin.dependencyResolution.gradleComponentResolver.${project.getKotlinPluginVersion()}"
|
||||||
|
return project.getOrPutRootProjectProperty(extraPropertyName) {
|
||||||
|
GradleComponentResultCachingResolver()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class GradleModuleDependencyResolver(
|
class GradleModuleDependencyResolver(
|
||||||
|
private val gradleComponentResultResolver: GradleComponentResultCachingResolver,
|
||||||
private val projectStructureMetadataModuleBuilder: ProjectStructureMetadataModuleBuilder,
|
private val projectStructureMetadataModuleBuilder: ProjectStructureMetadataModuleBuilder,
|
||||||
private val projectModuleBuilder: GradleProjectModuleBuilder
|
private val projectModuleBuilder: GradleProjectModuleBuilder
|
||||||
) : ModuleDependencyResolver {
|
) : ModuleDependencyResolver {
|
||||||
|
|
||||||
private fun configurationToResolve(requestingModule: KotlinGradleModule): Configuration =
|
|
||||||
configurationToResolveMetadataDependencies(requestingModule.project, requestingModule)
|
|
||||||
|
|
||||||
override fun resolveDependency(requestingModule: KotlinModule, moduleDependency: KotlinModuleDependency): KotlinModule? {
|
override fun resolveDependency(requestingModule: KotlinModule, moduleDependency: KotlinModuleDependency): KotlinModule? {
|
||||||
require(requestingModule is KotlinGradleModule)
|
require(requestingModule is KotlinGradleModule)
|
||||||
val project = requestingModule.project
|
val project = requestingModule.project
|
||||||
|
|
||||||
val allComponents = configurationToResolve(requestingModule).incoming.resolutionResult.allComponents
|
val component = gradleComponentResultResolver.resolveModuleDependencyAsComponentResult(requestingModule, moduleDependency)
|
||||||
// TODO: optimize O(n) search, store the resolved components with dependency keys?
|
|
||||||
val component = allComponents.find { it.id.matchesModuleDependency(moduleDependency) }
|
|
||||||
val id = component?.id
|
val id = component?.id
|
||||||
|
|
||||||
//FIXME multiple?
|
//FIXME multiple?
|
||||||
@@ -49,7 +87,8 @@ class GradleModuleDependencyResolver(
|
|||||||
val metadata = getProjectStructureMetadata(
|
val metadata = getProjectStructureMetadata(
|
||||||
project,
|
project,
|
||||||
component,
|
component,
|
||||||
configurationToResolve(requestingModule),
|
// TODO: consistent choice of configurations across multiple resolvers?
|
||||||
|
configurationToResolveMetadataDependencies(requestingModule.project, requestingModule),
|
||||||
moduleDependency.moduleIdentifier
|
moduleDependency.moduleIdentifier
|
||||||
) ?: return null
|
) ?: return null
|
||||||
val result = projectStructureMetadataModuleBuilder.getModule(component, metadata)
|
val result = projectStructureMetadataModuleBuilder.getModule(component, metadata)
|
||||||
@@ -58,13 +97,30 @@ class GradleModuleDependencyResolver(
|
|||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getForCurrentBuild(project: Project): ModuleDependencyResolver {
|
||||||
|
val extraPropertyName = "org.jetbrains.kotlin.dependencyResolution.moduleResolver.${project.getKotlinPluginVersion()}"
|
||||||
|
return project.getOrPutRootProjectProperty(extraPropertyName) {
|
||||||
|
val componentResultResolver = GradleComponentResultCachingResolver.getForCurrentBuild(project)
|
||||||
|
val metadataModuleBuilder = ProjectStructureMetadataModuleBuilder()
|
||||||
|
val projectModuleBuilder = GradleProjectModuleBuilder(true)
|
||||||
|
CachingModuleDependencyResolver(
|
||||||
|
GradleModuleDependencyResolver(componentResultResolver, metadataModuleBuilder, projectModuleBuilder)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// refactor extract to a separate class/interface
|
// refactor extract to a separate class/interface
|
||||||
// TODO think about multi-variant stub modules for non-Kotlin modules which got more than one chosen variant
|
// TODO think about multi-variant stub modules for non-Kotlin modules which got more than one chosen variant
|
||||||
internal fun buildSyntheticModule(resolvedComponentResult: ResolvedComponentResult, singleVariantName: String): ExternalSyntheticKotlinModule {
|
internal fun buildSyntheticPlainModule(
|
||||||
|
resolvedComponentResult: ResolvedComponentResult,
|
||||||
|
singleVariantName: String
|
||||||
|
): ExternalPlainKotlinModule {
|
||||||
val moduleDependency = resolvedComponentResult.toModuleDependency()
|
val moduleDependency = resolvedComponentResult.toModuleDependency()
|
||||||
return ExternalSyntheticKotlinModule(BasicKotlinModule(moduleDependency.moduleIdentifier).apply {
|
return ExternalPlainKotlinModule(BasicKotlinModule(moduleDependency.moduleIdentifier).apply {
|
||||||
BasicKotlinModuleVariant(this@apply, singleVariantName, DefaultLanguageSettingsBuilder()).apply {
|
BasicKotlinModuleVariant(this@apply, singleVariantName, DefaultLanguageSettingsBuilder()).apply {
|
||||||
fragments.add(this)
|
fragments.add(this)
|
||||||
this.declaredModuleDependencies.addAll(
|
this.declaredModuleDependencies.addAll(
|
||||||
@@ -76,8 +132,12 @@ internal fun buildSyntheticModule(resolvedComponentResult: ResolvedComponentResu
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ExternalSyntheticKotlinModule(private val moduleData: BasicKotlinModule) : KotlinModule by moduleData {
|
internal class ExternalPlainKotlinModule(private val moduleData: BasicKotlinModule) : KotlinModule by moduleData {
|
||||||
override fun toString(): String = "synthetic $moduleData"
|
override fun toString(): String = "external plain $moduleData"
|
||||||
|
|
||||||
|
val singleVariant: KotlinModuleVariant
|
||||||
|
get() = moduleData.variants.singleOrNull()
|
||||||
|
?: error("synthetic $moduleData was expected to have a single variant, got: ${moduleData.variants}")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ExternalImportedKotlinModule(
|
internal class ExternalImportedKotlinModule(
|
||||||
|
|||||||
+22
-21
@@ -31,10 +31,8 @@ internal class FragmentGranularMetadataResolver(
|
|||||||
refinesParentResolvers.value.flatMap { it.resolutions }.groupBy { it.dependency.toSingleModuleIdentifier() }
|
refinesParentResolvers.value.flatMap { it.resolutions }.groupBy { it.dependency.toSingleModuleIdentifier() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val metadataModuleBuilder = ProjectStructureMetadataModuleBuilder()
|
private val moduleResolver = GradleModuleDependencyResolver.getForCurrentBuild(project)
|
||||||
private val projectModuleBuilder = GradleProjectModuleBuilder(true)
|
private val variantResolver = GradleModuleVariantResolver.getForCurrentBuild(project)
|
||||||
private val moduleResolver = GradleModuleDependencyResolver(metadataModuleBuilder, projectModuleBuilder)
|
|
||||||
private val variantResolver = GradleModuleVariantResolver(project)
|
|
||||||
private val fragmentResolver = DefaultModuleFragmentsResolver(variantResolver)
|
private val fragmentResolver = DefaultModuleFragmentsResolver(variantResolver)
|
||||||
private val dependencyGraphResolver = GradleKotlinDependencyGraphResolver(moduleResolver)
|
private val dependencyGraphResolver = GradleKotlinDependencyGraphResolver(moduleResolver)
|
||||||
|
|
||||||
@@ -78,22 +76,12 @@ internal class FragmentGranularMetadataResolver(
|
|||||||
val resolvedComponentResult = dependencyNode.selectedComponent
|
val resolvedComponentResult = dependencyNode.selectedComponent
|
||||||
val isResolvedAsProject = resolvedComponentResult.toProjectOrNull(project)
|
val isResolvedAsProject = resolvedComponentResult.toProjectOrNull(project)
|
||||||
val result = when (dependencyModule) {
|
val result = when (dependencyModule) {
|
||||||
is ExternalSyntheticKotlinModule -> {
|
is ExternalPlainKotlinModule -> {
|
||||||
MetadataDependencyResolution.KeepOriginalDependency(resolvedComponentResult, isResolvedAsProject)
|
MetadataDependencyResolution.KeepOriginalDependency(resolvedComponentResult, isResolvedAsProject)
|
||||||
}
|
}
|
||||||
else -> run {
|
else -> run {
|
||||||
val projectStructureMetadata = (dependencyModule as? ExternalImportedKotlinModule)?.projectStructureMetadata
|
|
||||||
?: checkNotNull(getProjectStructureMetadata(project, resolvedComponentResult, configurationToResolve))
|
|
||||||
|
|
||||||
val metadataSourceComponent = dependencyNode.run { metadataSourceComponent ?: selectedComponent }
|
val metadataSourceComponent = dependencyNode.run { metadataSourceComponent ?: selectedComponent }
|
||||||
|
|
||||||
val parentResolutionsForDependency =
|
|
||||||
parentResultsByModuleIdentifier[metadataSourceComponent.toSingleModuleIdentifier()].orEmpty()
|
|
||||||
val fragmentsVisibleByParents =
|
|
||||||
parentResolutionsForDependency.filterIsInstance<ChooseVisibleSourceSetsImpl>()
|
|
||||||
.flatMapTo(mutableSetOf()) { it.allVisibleSourceSetNames }
|
|
||||||
val visibleFragmentNames = visibleFragments.map { it.fragmentName }.toSet()
|
|
||||||
|
|
||||||
val metadataExtractor = getMetadataExtractor(project, resolvedComponentResult, configurationToResolve, true)
|
val metadataExtractor = getMetadataExtractor(project, resolvedComponentResult, configurationToResolve, true)
|
||||||
|
|
||||||
if (dependencyModule is ExternalImportedKotlinModule &&
|
if (dependencyModule is ExternalImportedKotlinModule &&
|
||||||
@@ -103,12 +91,20 @@ internal class FragmentGranularMetadataResolver(
|
|||||||
resolveHostSpecificMetadataArtifacts(dependencyModule, chosenFragments, metadataExtractor)
|
resolveHostSpecificMetadataArtifacts(dependencyModule, chosenFragments, metadataExtractor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val projectStructureMetadata = (dependencyModule as? ExternalImportedKotlinModule)?.projectStructureMetadata
|
||||||
|
?: checkNotNull(metadataExtractor?.getProjectStructureMetadata())
|
||||||
|
|
||||||
|
val visibleFragmentNames = visibleFragments.map { it.fragmentName }.toSet()
|
||||||
|
val visibleFragmentNamesExcludingVisibleByParents =
|
||||||
|
visibleFragmentNames
|
||||||
|
.minus(fragmentsNamesVisibleByParents(metadataSourceComponent.toSingleModuleIdentifier()))
|
||||||
|
|
||||||
ChooseVisibleSourceSetsImpl(
|
ChooseVisibleSourceSetsImpl(
|
||||||
metadataSourceComponent,
|
metadataSourceComponent,
|
||||||
isResolvedAsProject,
|
isResolvedAsProject,
|
||||||
projectStructureMetadata,
|
projectStructureMetadata,
|
||||||
visibleFragmentNames,
|
visibleFragmentNames,
|
||||||
visibleFragmentNames.minus(fragmentsVisibleByParents),
|
visibleFragmentNamesExcludingVisibleByParents,
|
||||||
visibleTransitiveDependencies.map { resolvedDependenciesByModuleId.getValue(it.module.moduleIdentifier) }.toSet(),
|
visibleTransitiveDependencies.map { resolvedDependenciesByModuleId.getValue(it.module.moduleIdentifier) }.toSet(),
|
||||||
checkNotNull(metadataExtractor)
|
checkNotNull(metadataExtractor)
|
||||||
)
|
)
|
||||||
@@ -126,6 +122,12 @@ internal class FragmentGranularMetadataResolver(
|
|||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun fragmentsNamesVisibleByParents(kotlinModuleIdentifier: KotlinModuleIdentifier): MutableSet<String> {
|
||||||
|
val parentResolutionsForDependency = parentResultsByModuleIdentifier[kotlinModuleIdentifier].orEmpty()
|
||||||
|
return parentResolutionsForDependency.filterIsInstance<ChooseVisibleSourceSetsImpl>()
|
||||||
|
.flatMapTo(mutableSetOf()) { it.allVisibleSourceSetNames }
|
||||||
|
}
|
||||||
|
|
||||||
private fun resolveHostSpecificMetadataArtifacts(
|
private fun resolveHostSpecificMetadataArtifacts(
|
||||||
dependencyModule: ExternalImportedKotlinModule,
|
dependencyModule: ExternalImportedKotlinModule,
|
||||||
chosenFragments: FragmentResolution.ChosenFragments,
|
chosenFragments: FragmentResolution.ChosenFragments,
|
||||||
@@ -135,19 +137,18 @@ internal class FragmentGranularMetadataResolver(
|
|||||||
val variantResolutions = chosenFragments.variantResolutions
|
val variantResolutions = chosenFragments.variantResolutions
|
||||||
val hostSpecificFragments = dependencyModule.hostSpecificFragments
|
val hostSpecificFragments = dependencyModule.hostSpecificFragments
|
||||||
val hostSpecificFragmentToArtifact = visibleFragments.intersect(hostSpecificFragments).mapNotNull { hostSpecificFragment ->
|
val hostSpecificFragmentToArtifact = visibleFragments.intersect(hostSpecificFragments).mapNotNull { hostSpecificFragment ->
|
||||||
val relevantResolution = variantResolutions
|
val relevantVariantResolution = variantResolutions
|
||||||
.filterIsInstance<VariantResolution.VariantMatch>()
|
.filterIsInstance<VariantResolution.VariantMatch>()
|
||||||
// find some of our variants that resolved a dependency's variant containing the fragment
|
// find some of our variants that resolved a dependency's variant containing the fragment
|
||||||
.find { hostSpecificFragment in it.chosenVariant.refinesClosure }
|
.find { hostSpecificFragment in it.chosenVariant.refinesClosure }
|
||||||
// resolve the dependencies of that variant getting the host-specific metadata artifact
|
// resolve the dependencies of that variant getting the host-specific metadata artifact
|
||||||
relevantResolution?.let { resolution ->
|
relevantVariantResolution?.let { resolution ->
|
||||||
val variantResolvingPlatformArtifact =
|
val configurationResolvingPlatformVariant =
|
||||||
(resolution.requestingVariant as KotlinGradleVariant).compileDependencyConfiguration
|
(resolution.requestingVariant as KotlinGradleVariant).compileDependencyConfiguration
|
||||||
val configuration = variantResolvingPlatformArtifact
|
|
||||||
val hostSpecificArtifact = ResolvedMppVariantsProvider.get(project)
|
val hostSpecificArtifact = ResolvedMppVariantsProvider.get(project)
|
||||||
.getHostSpecificMetadataArtifactByRootModule(
|
.getHostSpecificMetadataArtifactByRootModule(
|
||||||
dependencyModule.moduleIdentifier,
|
dependencyModule.moduleIdentifier,
|
||||||
configuration
|
configurationResolvingPlatformVariant
|
||||||
)
|
)
|
||||||
hostSpecificArtifact?.let { hostSpecificFragment.fragmentName to it }
|
hostSpecificArtifact?.let { hostSpecificFragment.fragmentName to it }
|
||||||
}
|
}
|
||||||
|
|||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.plugins.ExtraPropertiesExtension
|
||||||
|
|
||||||
|
internal inline fun <reified T : Any> ExtraPropertiesExtension.getOrPut(key: String, provideValue: () -> T): T {
|
||||||
|
return synchronized(this) {
|
||||||
|
if (!has(key)) {
|
||||||
|
set(key, provideValue())
|
||||||
|
}
|
||||||
|
get(key) as T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline fun <reified T : Any> Project.getOrPutRootProjectProperty(key: String, provideValue: () -> T) =
|
||||||
|
rootProject.extensions.extraProperties.getOrPut(key, provideValue)
|
||||||
@@ -13,7 +13,6 @@ interface ModuleDependencyResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface KotlinDependencyGraphResolver {
|
interface KotlinDependencyGraphResolver {
|
||||||
// TODO add explicit dependency consistency scopes if we decide to keep non-production code in the same variant
|
|
||||||
fun resolveDependencyGraph(requestingModule: KotlinModule): DependencyGraphResolution
|
fun resolveDependencyGraph(requestingModule: KotlinModule): DependencyGraphResolution
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user