Support published MPP consumption with PM2.0 projects
This commit is contained in:
+3
@@ -35,6 +35,9 @@ internal fun Project.createKotlinExtension(extensionClass: KClass<out KotlinTopL
|
|||||||
internal val Project.topLevelExtension: KotlinTopLevelExtension
|
internal val Project.topLevelExtension: KotlinTopLevelExtension
|
||||||
get() = extensions.getByName(KOTLIN_PROJECT_EXTENSION_NAME) as KotlinTopLevelExtension
|
get() = extensions.getByName(KOTLIN_PROJECT_EXTENSION_NAME) as KotlinTopLevelExtension
|
||||||
|
|
||||||
|
internal val Project.topLevelExtensionOrNull: KotlinTopLevelExtension?
|
||||||
|
get() = extensions.findByName(KOTLIN_PROJECT_EXTENSION_NAME) as KotlinTopLevelExtension?
|
||||||
|
|
||||||
internal val Project.kotlinExtensionOrNull: KotlinProjectExtension?
|
internal val Project.kotlinExtensionOrNull: KotlinProjectExtension?
|
||||||
get() = extensions.findByName(KOTLIN_PROJECT_EXTENSION_NAME) as? KotlinProjectExtension
|
get() = extensions.findByName(KOTLIN_PROJECT_EXTENSION_NAME) as? KotlinProjectExtension
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
|||||||
import org.jetbrains.kotlin.gradle.model.builder.KotlinModelBuilder
|
import org.jetbrains.kotlin.gradle.model.builder.KotlinModelBuilder
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.isMain
|
||||||
import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubplugin
|
import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubplugin
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.ir.*
|
import org.jetbrains.kotlin.gradle.targets.js.ir.*
|
||||||
@@ -283,14 +284,14 @@ internal class Kotlin2JsSourceSetProcessor(
|
|||||||
val baseName = if (kotlinCompilation.isMain()) {
|
val baseName = if (kotlinCompilation.isMain()) {
|
||||||
project.name
|
project.name
|
||||||
} else {
|
} else {
|
||||||
"${project.name}_${kotlinCompilation.name}"
|
"${project.name}_${kotlinCompilation.compilationPurpose}"
|
||||||
}
|
}
|
||||||
kotlinTaskInstance.kotlinOptions.freeCompilerArgs += "$MODULE_NAME=${project.klibModuleName(baseName)}"
|
kotlinTaskInstance.kotlinOptions.freeCompilerArgs += "$MODULE_NAME=${project.klibModuleName(baseName)}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
|
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
|
||||||
if (kotlinCompilation is KotlinCompilation<*>) {
|
if (kotlinCompilation is KotlinCompilation<*>) { // FIXME support compiler plugins with PM20
|
||||||
subpluginEnvironment.addSubpluginOptions(project, kotlinCompilation)
|
subpluginEnvironment.addSubpluginOptions(project, kotlinCompilation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-3
@@ -86,9 +86,6 @@ abstract class KotlinBasePluginWrapper : Plugin<Project> {
|
|||||||
kotlinGradleBuildServices.detectKotlinPluginLoadedInMultipleProjects(project, kotlinPluginVersion)
|
kotlinGradleBuildServices.detectKotlinPluginLoadedInMultipleProjects(project, kotlinPluginVersion)
|
||||||
|
|
||||||
project.createKotlinExtension(projectExtensionClass).apply {
|
project.createKotlinExtension(projectExtensionClass).apply {
|
||||||
if (this is KotlinPm20ProjectExtension)
|
|
||||||
this.project = project // refactor this code to remove the specific plugin class?
|
|
||||||
|
|
||||||
coreLibrariesVersion = kotlinPluginVersion
|
coreLibrariesVersion = kotlinPluginVersion
|
||||||
|
|
||||||
fun kotlinSourceSetContainer(factory: NamedDomainObjectFactory<KotlinSourceSet>) =
|
fun kotlinSourceSetContainer(factory: NamedDomainObjectFactory<KotlinSourceSet>) =
|
||||||
|
|||||||
+3
-7
@@ -11,10 +11,6 @@ import org.gradle.api.tasks.Nested
|
|||||||
import org.gradle.api.tasks.OutputFile
|
import org.gradle.api.tasks.OutputFile
|
||||||
import org.gradle.api.tasks.TaskAction
|
import org.gradle.api.tasks.TaskAction
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.xml.transform.OutputKeys
|
|
||||||
import javax.xml.transform.TransformerFactory
|
|
||||||
import javax.xml.transform.dom.DOMSource
|
|
||||||
import javax.xml.transform.stream.StreamResult
|
|
||||||
|
|
||||||
open class GenerateProjectStructureMetadata : DefaultTask() {
|
open class GenerateProjectStructureMetadata : DefaultTask() {
|
||||||
@get:Internal
|
@get:Internal
|
||||||
@@ -25,14 +21,14 @@ open class GenerateProjectStructureMetadata : DefaultTask() {
|
|||||||
get() = lazyKotlinProjectStructureMetadata.value
|
get() = lazyKotlinProjectStructureMetadata.value
|
||||||
|
|
||||||
@get:OutputFile
|
@get:OutputFile
|
||||||
val resultXmlFile: File
|
val resultFile: File
|
||||||
get() = project.buildDir.resolve("kotlinProjectStructureMetadata/$MULTIPLATFORM_PROJECT_METADATA_JSON_FILE_NAME")
|
get() = project.buildDir.resolve("kotlinProjectStructureMetadata/$MULTIPLATFORM_PROJECT_METADATA_JSON_FILE_NAME")
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun generateMetadataXml() {
|
fun generateMetadataXml() {
|
||||||
resultXmlFile.parentFile.mkdirs()
|
resultFile.parentFile.mkdirs()
|
||||||
val resultString = kotlinProjectStructureMetadata.toJson()
|
val resultString = kotlinProjectStructureMetadata.toJson()
|
||||||
resultXmlFile.writeText(resultString)
|
resultFile.writeText(resultString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+83
-59
@@ -7,13 +7,15 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
|
|||||||
|
|
||||||
import org.gradle.api.Named
|
import org.gradle.api.Named
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.artifacts.Configuration
|
||||||
import org.gradle.api.artifacts.Dependency
|
import org.gradle.api.artifacts.Dependency
|
||||||
import org.gradle.api.artifacts.ModuleDependency
|
import org.gradle.api.artifacts.ModuleDependency
|
||||||
import org.gradle.api.artifacts.ProjectDependency
|
import org.gradle.api.artifacts.ProjectDependency
|
||||||
|
import org.gradle.api.artifacts.result.ResolvedComponentResult
|
||||||
|
import org.gradle.api.artifacts.result.ResolvedDependencyResult
|
||||||
import org.gradle.api.attributes.Attribute
|
import org.gradle.api.attributes.Attribute
|
||||||
import org.gradle.api.attributes.AttributeContainer
|
import org.gradle.api.attributes.AttributeContainer
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
import org.jetbrains.kotlin.gradle.dsl.*
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
|
|
||||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
@@ -28,45 +30,56 @@ class ProjectStructureMetadataModuleBuilder {
|
|||||||
private val modulesCache = mutableMapOf<KotlinModuleIdentifier, KotlinModule>()
|
private val modulesCache = mutableMapOf<KotlinModuleIdentifier, KotlinModule>()
|
||||||
|
|
||||||
private fun buildModuleFromProjectStructureMetadata(
|
private fun buildModuleFromProjectStructureMetadata(
|
||||||
moduleIdentifier: KotlinModuleIdentifier,
|
component: ResolvedComponentResult,
|
||||||
metadata: KotlinProjectStructureMetadata
|
metadata: KotlinProjectStructureMetadata
|
||||||
): KotlinModule =
|
): KotlinModule {
|
||||||
BasicKotlinModule(moduleIdentifier).apply {
|
return ExternalImportedKotlinModule(
|
||||||
metadata.sourceSetNamesByVariantName.keys.forEach { variantName ->
|
BasicKotlinModule(component.toModuleIdentifier()).apply {
|
||||||
fragments.add(BasicKotlinModuleVariant(this@apply, variantName))
|
metadata.sourceSetNamesByVariantName.keys.forEach { variantName ->
|
||||||
}
|
fragments.add(BasicKotlinModuleVariant(this@apply, variantName))
|
||||||
fun fragment(sourceSetName: String): BasicKotlinModuleFragment {
|
|
||||||
if (fragments.none { it.fragmentName == sourceSetName })
|
|
||||||
fragments.add(BasicKotlinModuleFragment(this@apply, sourceSetName))
|
|
||||||
return fragmentByName(sourceSetName)
|
|
||||||
}
|
|
||||||
metadata.sourceSetNamesByVariantName.forEach { (variantName, sourceSets) ->
|
|
||||||
val variant = fragmentByName(variantName)
|
|
||||||
sourceSets.forEach { sourceSetName ->
|
|
||||||
variant.directRefinesDependencies.add(fragment(sourceSetName))
|
|
||||||
}
|
}
|
||||||
}
|
fun fragment(sourceSetName: String): BasicKotlinModuleFragment {
|
||||||
metadata.sourceSetModuleDependencies.forEach { (sourceSetName, dependencies) ->
|
if (fragments.none { it.fragmentName == sourceSetName })
|
||||||
val fragment = fragment(sourceSetName)
|
fragments.add(BasicKotlinModuleFragment(this@apply, sourceSetName))
|
||||||
dependencies.forEach { dependency ->
|
return fragmentByName(sourceSetName)
|
||||||
fragment.declaredModuleDependencies.add(
|
}
|
||||||
KotlinModuleDependency(MavenModuleIdentifier(dependency.groupId.orEmpty(), dependency.moduleId, null /* TODO */))
|
metadata.sourceSetNamesByVariantName.forEach { (variantName, sourceSets) ->
|
||||||
)
|
val variant = fragmentByName(variantName)
|
||||||
|
sourceSets.forEach { sourceSetName ->
|
||||||
|
variant.directRefinesDependencies.add(fragment(sourceSetName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metadata.sourceSetModuleDependencies.forEach { (sourceSetName, dependencies) ->
|
||||||
|
val fragment = fragment(sourceSetName)
|
||||||
|
dependencies.forEach { dependency ->
|
||||||
|
fragment.declaredModuleDependencies.add(
|
||||||
|
KotlinModuleDependency(
|
||||||
|
MavenModuleIdentifier(
|
||||||
|
dependency.groupId.orEmpty(),
|
||||||
|
dependency.moduleId,
|
||||||
|
null /* TODO */
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
metadata.sourceSetsDependsOnRelation.forEach { (depending, dependencies) ->
|
metadata.sourceSetsDependsOnRelation.forEach { (depending, dependencies) ->
|
||||||
val dependingFragment = fragment(depending)
|
val dependingFragment = fragment(depending)
|
||||||
dependencies.forEach { dependency ->
|
dependencies.forEach { dependency ->
|
||||||
dependingFragment.directRefinesDependencies.add(fragment(dependency))
|
dependingFragment.directRefinesDependencies.add(fragment(dependency))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
metadata
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun getModule(moduleIdentifier: KotlinModuleIdentifier, projectStructureMetadata: KotlinProjectStructureMetadata): KotlinModule {
|
fun getModule(component: ResolvedComponentResult, projectStructureMetadata: KotlinProjectStructureMetadata): KotlinModule {
|
||||||
return modulesCache.getOrPut(moduleIdentifier) {
|
val moduleId = component.toModuleIdentifier()
|
||||||
|
return modulesCache.getOrPut(moduleId) {
|
||||||
buildModuleFromProjectStructureMetadata(
|
buildModuleFromProjectStructureMetadata(
|
||||||
moduleIdentifier,
|
component,
|
||||||
projectStructureMetadata
|
projectStructureMetadata
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -107,7 +120,12 @@ private fun detectModules(targets: Iterable<KotlinTarget>, sourceSets: Iterable<
|
|||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class GradleProjectModuleBuilder(private val addInferredSourceSetVisibilityAsExplicit: Boolean) {
|
class GradleProjectModuleBuilder(private val addInferredSourceSetVisibilityAsExplicit: Boolean) {
|
||||||
|
private fun getModulesFromPm20Project(project: Project) = project.pm20Extension.modules.toList()
|
||||||
|
|
||||||
fun buildModulesFromProject(project: Project): List<KotlinModule> {
|
fun buildModulesFromProject(project: Project): List<KotlinModule> {
|
||||||
|
if (project.topLevelExtension is KotlinPm20ProjectExtension)
|
||||||
|
return getModulesFromPm20Project(project)
|
||||||
|
|
||||||
val extension = project.multiplatformExtensionOrNull
|
val extension = project.multiplatformExtensionOrNull
|
||||||
?: project.kotlinExtension
|
?: project.kotlinExtension
|
||||||
?: return emptyList()
|
?: return emptyList()
|
||||||
@@ -217,15 +235,6 @@ class GradleProjectModuleBuilder(private val addInferredSourceSetVisibilityAsExp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun <T : Any> attributeString(container: AttributeContainer, attributeKey: Attribute<T>): String {
|
|
||||||
val value = container.getAttribute(attributeKey)
|
|
||||||
return when (value) {
|
|
||||||
is Named -> value.name
|
|
||||||
else -> value.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun Dependency.toModuleDependency(
|
internal fun Dependency.toModuleDependency(
|
||||||
project: Project
|
project: Project
|
||||||
): KotlinModuleDependency {
|
): KotlinModuleDependency {
|
||||||
@@ -266,21 +275,7 @@ class GradleModuleVariantResolver(val project: Project) : ModuleVariantResolver
|
|||||||
// 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))
|
||||||
|
|
||||||
val targets =
|
val compileClasspath = getCompileDependenciesConfigurationForVariant(project, requestingVariant)
|
||||||
project.multiplatformExtensionOrNull?.targets ?: listOf((project.kotlinExtension as KotlinSingleTargetExtension).target)
|
|
||||||
|
|
||||||
val compilation =
|
|
||||||
targets.filterIsInstance<AbstractKotlinTarget>()
|
|
||||||
.flatMap { it.kotlinComponents.filterIsInstance<KotlinVariant>() }
|
|
||||||
.flatMap { it.usages }
|
|
||||||
.firstOrNull { it.name == requestingVariant.fragmentName }
|
|
||||||
?.compilation
|
|
||||||
?: targets.asSequence().flatMap { it.compilations.asSequence() }.single {
|
|
||||||
it.defaultSourceSetName == requestingVariant.fragmentName
|
|
||||||
} // TODO: generalize the mapping PM2.0 <-> MPP
|
|
||||||
?: return VariantResolution.Unknown(requestingVariant, dependencyModule)
|
|
||||||
|
|
||||||
val compileClasspath = project.configurations.getByName(compilation.compileDependencyConfigurationName)
|
|
||||||
|
|
||||||
// TODO optimize O(n) search, store the mapping
|
// TODO optimize O(n) search, store the mapping
|
||||||
val component = compileClasspath.incoming.resolutionResult.allComponents.find { it.id.matchesModule(dependencyModule) }
|
val component = compileClasspath.incoming.resolutionResult.allComponents.find { it.id.matchesModule(dependencyModule) }
|
||||||
@@ -288,7 +283,9 @@ class GradleModuleVariantResolver(val project: Project) : ModuleVariantResolver
|
|||||||
|
|
||||||
val dependencyModuleId = ModuleIds.fromComponent(project, component)
|
val dependencyModuleId = ModuleIds.fromComponent(project, component)
|
||||||
// FIXME check composite builds, it's likely that resolvedVariantProvider fails on them?
|
// FIXME check composite builds, it's likely that resolvedVariantProvider fails on them?
|
||||||
val variantName = resolvedVariantProvider.getResolvedVariantName(dependencyModuleId, compileClasspath)
|
val variantName =
|
||||||
|
resolvedVariantProvider.getResolvedVariantName(dependencyModuleId, compileClasspath)
|
||||||
|
?.let(::kotlinVariantNameFromPublishedVariantName)
|
||||||
|
|
||||||
val resultVariant = dependencyModule.variants.singleOrNull { it.fragmentName == variantName }
|
val resultVariant = dependencyModule.variants.singleOrNull { it.fragmentName == variantName }
|
||||||
|
|
||||||
@@ -297,4 +294,31 @@ class GradleModuleVariantResolver(val project: Project) : ModuleVariantResolver
|
|||||||
else
|
else
|
||||||
VariantResolution.VariantMatch(requestingVariant, dependencyModule, resultVariant)
|
VariantResolution.VariantMatch(requestingVariant, dependencyModule, resultVariant)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getCompileDependenciesConfigurationForVariant(project: Project, requestingVariant: KotlinModuleVariant): Configuration =
|
||||||
|
when (project.topLevelExtension) {
|
||||||
|
is KotlinMultiplatformExtension, is KotlinSingleTargetExtension -> {
|
||||||
|
val targets =
|
||||||
|
project.multiplatformExtensionOrNull?.targets ?: listOf((project.kotlinExtension as KotlinSingleTargetExtension).target)
|
||||||
|
|
||||||
|
val compilation =
|
||||||
|
targets.filterIsInstance<AbstractKotlinTarget>()
|
||||||
|
.flatMap { it.kotlinComponents.filterIsInstance<KotlinVariant>() }
|
||||||
|
.flatMap { it.usages }
|
||||||
|
.firstOrNull { it.name == requestingVariant.fragmentName }
|
||||||
|
?.compilation
|
||||||
|
|
||||||
|
?: targets.asSequence().flatMap { it.compilations.asSequence() }.single {
|
||||||
|
it.defaultSourceSetName == requestingVariant.fragmentName
|
||||||
|
} // TODO: generalize the mapping PM2.0 <-> MPP
|
||||||
|
|
||||||
|
?: error("could not find a compilation that produces the variant $requestingVariant in $project")
|
||||||
|
|
||||||
|
project.configurations.getByName(compilation.compileDependencyConfigurationName)
|
||||||
|
}
|
||||||
|
is KotlinPm20ProjectExtension -> {
|
||||||
|
project.configurations.getByName((requestingVariant as KotlinGradleVariant).compileDependencyConfigurationName)
|
||||||
|
}
|
||||||
|
else -> error("could not find the compile dependencies configuration for variant $requestingVariant")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+69
-34
@@ -13,8 +13,12 @@ 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.attributes.Attribute
|
import org.gradle.api.attributes.Attribute
|
||||||
import org.gradle.api.file.FileCollection
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.topLevelExtension
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.toModuleIdentifier
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
|
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
|
||||||
import org.jetbrains.kotlin.gradle.targets.metadata.ALL_COMPILE_METADATA_CONFIGURATION_NAME
|
import org.jetbrains.kotlin.gradle.targets.metadata.ALL_COMPILE_METADATA_CONFIGURATION_NAME
|
||||||
@@ -207,7 +211,7 @@ internal class GranularMetadataTransformation(
|
|||||||
resolveViaAvailableAt = false // we will process the available-at module as a dependency later in the queue
|
resolveViaAvailableAt = false // we will process the available-at module as a dependency later in the queue
|
||||||
)
|
)
|
||||||
|
|
||||||
val resolvedToProject: Project? = (mppDependencyMetadataExtractor as? ProjectMppDependencyMetadataExtractor)?.dependencyProject
|
val resolvedToProject: Project? = module.toProjectOrNull(project)
|
||||||
|
|
||||||
val projectStructureMetadata = mppDependencyMetadataExtractor?.getProjectStructureMetadata()
|
val projectStructureMetadata = mppDependencyMetadataExtractor?.getProjectStructureMetadata()
|
||||||
?: return MetadataDependencyResolution.KeepOriginalDependency(module, resolvedToProject)
|
?: return MetadataDependencyResolution.KeepOriginalDependency(module, resolvedToProject)
|
||||||
@@ -254,25 +258,33 @@ internal class GranularMetadataTransformation(
|
|||||||
transitiveDependenciesToVisit, mppDependencyMetadataExtractor
|
transitiveDependenciesToVisit, mppDependencyMetadataExtractor
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class ChooseVisibleSourceSetsImpl(
|
internal class ChooseVisibleSourceSetsImpl(
|
||||||
dependency: ResolvedComponentResult,
|
dependency: ResolvedComponentResult,
|
||||||
projectDependency: Project?,
|
projectDependency: Project?,
|
||||||
projectStructureMetadata: KotlinProjectStructureMetadata,
|
projectStructureMetadata: KotlinProjectStructureMetadata,
|
||||||
allVisibleSourceSetNames: Set<String>,
|
allVisibleSourceSetNames: Set<String>,
|
||||||
visibleSourceSetNamesExcludingDependsOn: Set<String>,
|
visibleSourceSetNamesExcludingDependsOn: Set<String>,
|
||||||
visibleTransitiveDependencies: Set<ResolvedDependencyResult>,
|
visibleTransitiveDependencies: Set<ResolvedDependencyResult>,
|
||||||
private val metadataExtractor: MppDependencyMetadataExtractor
|
private val metadataExtractor: MppDependencyMetadataExtractor
|
||||||
) : MetadataDependencyResolution.ChooseVisibleSourceSets(
|
) : MetadataDependencyResolution.ChooseVisibleSourceSets(
|
||||||
dependency,
|
dependency,
|
||||||
projectDependency,
|
projectDependency,
|
||||||
projectStructureMetadata,
|
projectStructureMetadata,
|
||||||
allVisibleSourceSetNames,
|
allVisibleSourceSetNames,
|
||||||
visibleSourceSetNamesExcludingDependsOn,
|
visibleSourceSetNamesExcludingDependsOn,
|
||||||
visibleTransitiveDependencies
|
visibleTransitiveDependencies
|
||||||
) {
|
) {
|
||||||
override fun getExtractableMetadataFiles(baseDir: File): ExtractableMetadataFiles =
|
override fun getExtractableMetadataFiles(baseDir: File): ExtractableMetadataFiles =
|
||||||
metadataExtractor.getExtractableMetadataFiles(visibleSourceSetNamesExcludingDependsOn, baseDir)
|
metadataExtractor.getExtractableMetadataFiles(visibleSourceSetNamesExcludingDependsOn, baseDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun ResolvedComponentResult.toProjectOrNull(currentProject: Project): Project? {
|
||||||
|
val identifier = id
|
||||||
|
return when {
|
||||||
|
identifier is ProjectComponentIdentifier && identifier.build.isCurrentBuild -> currentProject.project(identifier.projectPath)
|
||||||
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,7 +357,7 @@ internal fun requestedDependencies(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private abstract class MppDependencyMetadataExtractor(val project: Project, val dependency: ResolvedComponentResult) {
|
internal abstract class MppDependencyMetadataExtractor(val project: Project, val dependency: ResolvedComponentResult) {
|
||||||
abstract fun getProjectStructureMetadata(): KotlinProjectStructureMetadata?
|
abstract fun getProjectStructureMetadata(): KotlinProjectStructureMetadata?
|
||||||
|
|
||||||
abstract fun getExtractableMetadataFiles(
|
abstract fun getExtractableMetadataFiles(
|
||||||
@@ -366,9 +378,19 @@ private class ProjectMppDependencyMetadataExtractor(
|
|||||||
visibleSourceSetNames: Set<String>,
|
visibleSourceSetNames: Set<String>,
|
||||||
baseDir: File
|
baseDir: File
|
||||||
): ExtractableMetadataFiles {
|
): ExtractableMetadataFiles {
|
||||||
val result = dependencyProject.multiplatformExtension.targets.getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME).compilations
|
val result = when (val projectExtension = dependencyProject.topLevelExtension) {
|
||||||
.filter { it.name in visibleSourceSetNames }
|
is KotlinMultiplatformExtension -> projectExtension.targets.getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME).compilations
|
||||||
.associate { it.defaultSourceSet.name to it.output.classesDirs }
|
.filter { it.name in visibleSourceSetNames }.associate { it.defaultSourceSet.name to it.output.classesDirs }
|
||||||
|
is KotlinPm20ProjectExtension -> {
|
||||||
|
val moduleId = dependency.toModuleIdentifier()
|
||||||
|
val module = projectExtension.modules.single { it.moduleIdentifier == moduleId }
|
||||||
|
val metadataCompilationRegistry = projectExtension.metadataCompilationRegistryByModuleId.getValue(moduleId)
|
||||||
|
visibleSourceSetNames.associateWith {
|
||||||
|
metadataCompilationRegistry.byFragment(module.fragments.getByName(it)).output.classesDirs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> error("unexpected top-level Kotlin extension $projectExtension")
|
||||||
|
}
|
||||||
|
|
||||||
return object : ExtractableMetadataFiles() {
|
return object : ExtractableMetadataFiles() {
|
||||||
override fun getMetadataFilesPerSourceSet(doProcessFiles: Boolean): Map<String, FileCollection> = result
|
override fun getMetadataFilesPerSourceSet(doProcessFiles: Boolean): Map<String, FileCollection> = result
|
||||||
@@ -502,32 +524,45 @@ private open class JarArtifactMppDependencyMetadataExtractor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getMetadataExtractor(
|
internal fun getMetadataExtractor(
|
||||||
project: Project,
|
project: Project,
|
||||||
module: ResolvedComponentResult,
|
resolvedComponentResult: ResolvedComponentResult,
|
||||||
configuration: Configuration,
|
configuration: Configuration,
|
||||||
resolveViaAvailableAt: Boolean
|
resolveViaAvailableAt: Boolean
|
||||||
): MppDependencyMetadataExtractor? {
|
): MppDependencyMetadataExtractor? {
|
||||||
val resolvedMppVariantsProvider = ResolvedMppVariantsProvider.get(project)
|
val resolvedMppVariantsProvider = ResolvedMppVariantsProvider.get(project)
|
||||||
val moduleIdentifier = ModuleIds.fromComponent(project, module)
|
val moduleIdentifier = ModuleIds.fromComponent(project, resolvedComponentResult)
|
||||||
|
// TODO check how this code works with multi-capability resolutions
|
||||||
|
|
||||||
|
var resolvedViaAvailableAt = false
|
||||||
|
|
||||||
val metadataArtifact = resolvedMppVariantsProvider.getResolvedArtifactByPlatformModule(
|
val metadataArtifact = resolvedMppVariantsProvider.getResolvedArtifactByPlatformModule(
|
||||||
moduleIdentifier,
|
moduleIdentifier,
|
||||||
configuration
|
configuration
|
||||||
) ?: if (resolveViaAvailableAt) resolvedMppVariantsProvider.getHostSpecificMetadataArtifactByRootModule(
|
) ?: if (resolveViaAvailableAt) {
|
||||||
moduleIdentifier,
|
resolvedMppVariantsProvider.getHostSpecificMetadataArtifactByRootModule(
|
||||||
configuration
|
moduleIdentifier,
|
||||||
) else null
|
configuration
|
||||||
|
)?.also {
|
||||||
|
resolvedViaAvailableAt = true
|
||||||
|
}
|
||||||
|
} else null
|
||||||
|
|
||||||
val moduleId = module.id
|
val actualComponent = if (resolvedViaAvailableAt) {
|
||||||
|
resolvedComponentResult.dependencies.filterIsInstance<ResolvedDependencyResult>().singleOrNull()?.selected
|
||||||
|
?: resolvedComponentResult
|
||||||
|
} else resolvedComponentResult
|
||||||
|
|
||||||
|
val moduleId = actualComponent.id
|
||||||
return when {
|
return when {
|
||||||
moduleId is ProjectComponentIdentifier -> when {
|
moduleId is ProjectComponentIdentifier -> when {
|
||||||
moduleId.build.isCurrentBuild ->
|
moduleId.build.isCurrentBuild ->
|
||||||
ProjectMppDependencyMetadataExtractor(project, module, project.project(moduleId.projectPath))
|
ProjectMppDependencyMetadataExtractor(project, actualComponent, project.project(moduleId.projectPath))
|
||||||
metadataArtifact != null ->
|
metadataArtifact != null ->
|
||||||
IncludedBuildMetadataExtractor(project, module, metadataArtifact)
|
IncludedBuildMetadataExtractor(project, actualComponent, metadataArtifact)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
metadataArtifact != null -> JarArtifactMppDependencyMetadataExtractor(project, module, metadataArtifact)
|
metadataArtifact != null -> JarArtifactMppDependencyMetadataExtractor(project, actualComponent, metadataArtifact)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+77
-4
@@ -10,10 +10,16 @@ import com.google.gson.JsonObject
|
|||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.tasks.Input
|
import org.gradle.api.tasks.Input
|
||||||
import org.gradle.api.tasks.Internal
|
import org.gradle.api.tasks.Internal
|
||||||
import org.gradle.api.tasks.Nested
|
import org.gradle.api.tasks.Nested
|
||||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.topLevelExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.topLevelExtensionOrNull
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinGradleModule
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.refinesClosure
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.withAllDependsOnSourceSets
|
import org.jetbrains.kotlin.gradle.plugin.sources.withAllDependsOnSourceSets
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
|
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
|
||||||
@@ -27,10 +33,40 @@ import org.w3c.dom.NodeList
|
|||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
import javax.xml.parsers.DocumentBuilderFactory
|
import javax.xml.parsers.DocumentBuilderFactory
|
||||||
|
|
||||||
data class ModuleDependencyIdentifier(
|
// FIXME support module classifiers for PM2.0 or drop this class in favor of KotlinModuleIdentifier
|
||||||
val groupId: String?,
|
open class ModuleDependencyIdentifier(
|
||||||
val moduleId: String
|
open val groupId: String?,
|
||||||
)
|
open val moduleId: String
|
||||||
|
) {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (other !is ModuleDependencyIdentifier) return false
|
||||||
|
|
||||||
|
if (groupId != other.groupId) return false
|
||||||
|
if (moduleId != other.moduleId) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = groupId?.hashCode() ?: 0
|
||||||
|
result = 31 * result + moduleId.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun component1(): String? = groupId
|
||||||
|
operator fun component2(): String = moduleId
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangingModuleDependencyIdentifier(
|
||||||
|
val groupIdProvider: () -> String?,
|
||||||
|
val moduleIdProvider: () -> String
|
||||||
|
) : ModuleDependencyIdentifier(groupIdProvider(), moduleIdProvider()) {
|
||||||
|
override val groupId: String?
|
||||||
|
get() = groupIdProvider()
|
||||||
|
override val moduleId: String
|
||||||
|
get() = moduleIdProvider()
|
||||||
|
}
|
||||||
|
|
||||||
sealed class SourceSetMetadataLayout(
|
sealed class SourceSetMetadataLayout(
|
||||||
@get:Input
|
@get:Input
|
||||||
@@ -96,6 +132,12 @@ data class KotlinProjectStructureMetadata(
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun buildKotlinProjectStructureMetadata(project: Project): KotlinProjectStructureMetadata? {
|
internal fun buildKotlinProjectStructureMetadata(project: Project): KotlinProjectStructureMetadata? {
|
||||||
|
val topLevelExtensionOrNull = project.topLevelExtensionOrNull
|
||||||
|
if (topLevelExtensionOrNull is KotlinPm20ProjectExtension) {
|
||||||
|
// FIXME: get module by ID, don't just take the main module
|
||||||
|
return buildProjectStructureMetadata(topLevelExtensionOrNull.main)
|
||||||
|
}
|
||||||
|
|
||||||
val sourceSetsWithMetadataCompilations =
|
val sourceSetsWithMetadataCompilations =
|
||||||
project.multiplatformExtensionOrNull?.targets?.getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME)?.compilations?.associate {
|
project.multiplatformExtensionOrNull?.targets?.getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME)?.compilations?.associate {
|
||||||
it.defaultSourceSet to it
|
it.defaultSourceSet to it
|
||||||
@@ -142,6 +184,37 @@ internal fun buildKotlinProjectStructureMetadata(project: Project): KotlinProjec
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun buildProjectStructureMetadata(module: KotlinGradleModule): KotlinProjectStructureMetadata {
|
||||||
|
val kotlinVariantToGradleVariantNames = module.variants.associate { it.name to it.gradleVariantNames }
|
||||||
|
|
||||||
|
fun <T> expandVariantKeys(map: Map<String, T>) =
|
||||||
|
map.entries.flatMap { (key, value) ->
|
||||||
|
kotlinVariantToGradleVariantNames[key].orEmpty().plus(key).map { it to value }
|
||||||
|
}.toMap()
|
||||||
|
|
||||||
|
val kotlinFragmentsPerKotlinVariant =
|
||||||
|
module.variants.associate { variant -> variant.name to variant.refinesClosure.map { it.name }.toSet() }
|
||||||
|
val fragmentRefinesRelation =
|
||||||
|
module.fragments.associate { it.name to it.directRefinesDependencies.map { it.name }.toSet() }
|
||||||
|
|
||||||
|
// FIXME: support native implementation-as-api-dependencies
|
||||||
|
val fragmentDependencies =
|
||||||
|
module.fragments.associate { fragment ->
|
||||||
|
fragment.name to fragment.declaredModuleDependencies.map {
|
||||||
|
ModuleIds.lossyFromModuleIdentifier(module.project, it.moduleIdentifier)
|
||||||
|
}.toSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
return KotlinProjectStructureMetadata(
|
||||||
|
expandVariantKeys(kotlinFragmentsPerKotlinVariant),
|
||||||
|
fragmentRefinesRelation,
|
||||||
|
module.fragments.associate { it.name to SourceSetMetadataLayout.KLIB },
|
||||||
|
fragmentDependencies,
|
||||||
|
emptySet(),
|
||||||
|
isPublishedAsRoot = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
internal fun <Serializer> KotlinProjectStructureMetadata.serialize(
|
internal fun <Serializer> KotlinProjectStructureMetadata.serialize(
|
||||||
serializer: Serializer,
|
serializer: Serializer,
|
||||||
node: Serializer.(name: String, Serializer.() -> Unit) -> Unit,
|
node: Serializer.(name: String, Serializer.() -> Unit) -> Unit,
|
||||||
|
|||||||
+6
-2
@@ -84,9 +84,13 @@ abstract class KotlinSoftwareComponent(
|
|||||||
return _usages
|
return _usages
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val sourcesArtifacts: Set<PublishArtifact> by lazy {
|
val sourcesArtifacts: Set<PublishArtifact> by lazy {
|
||||||
val sourcesJarTask = sourcesJarTask(project, lazy { project.kotlinExtension.sourceSets.toSet() }, null, name.toLowerCase())
|
val sourcesJarTask = sourcesJarTask(
|
||||||
|
project,
|
||||||
|
lazy { project.kotlinExtension.sourceSets.associate { it.name to it.kotlin } },
|
||||||
|
null,
|
||||||
|
name.toLowerCase()
|
||||||
|
)
|
||||||
val sourcesJarArtifact = project.artifacts.add(Dependency.ARCHIVES_CONFIGURATION, sourcesJarTask) { sourcesJarArtifact ->
|
val sourcesJarArtifact = project.artifacts.add(Dependency.ARCHIVES_CONFIGURATION, sourcesJarTask) { sourcesJarArtifact ->
|
||||||
sourcesJarArtifact.classifier = "sources"
|
sourcesJarArtifact.classifier = "sources"
|
||||||
}
|
}
|
||||||
|
|||||||
+63
@@ -10,8 +10,18 @@ import org.gradle.api.artifacts.Dependency
|
|||||||
import org.gradle.api.artifacts.ProjectDependency
|
import org.gradle.api.artifacts.ProjectDependency
|
||||||
import org.gradle.api.artifacts.component.*
|
import org.gradle.api.artifacts.component.*
|
||||||
import org.gradle.api.artifacts.result.ResolvedComponentResult
|
import org.gradle.api.artifacts.result.ResolvedComponentResult
|
||||||
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.topLevelExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.currentBuildId
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||||
|
import org.jetbrains.kotlin.project.model.KotlinModuleIdentifier
|
||||||
|
import org.jetbrains.kotlin.project.model.LocalModuleIdentifier
|
||||||
|
import org.jetbrains.kotlin.project.model.MavenModuleIdentifier
|
||||||
|
import java.lang.IllegalArgumentException
|
||||||
|
|
||||||
internal object ModuleIds {
|
internal object ModuleIds {
|
||||||
fun fromDependency(dependency: Dependency) = when (dependency) {
|
fun fromDependency(dependency: Dependency) = when (dependency) {
|
||||||
@@ -60,4 +70,57 @@ internal object ModuleIds {
|
|||||||
|
|
||||||
private fun idOfRootModuleByProjectPath(thisProject: Project, projectPath: String): ModuleDependencyIdentifier =
|
private fun idOfRootModuleByProjectPath(thisProject: Project, projectPath: String): ModuleDependencyIdentifier =
|
||||||
idOfRootModule(thisProject.project(projectPath))
|
idOfRootModule(thisProject.project(projectPath))
|
||||||
|
|
||||||
|
// FIXME use capabilities to point to auxiliary modules
|
||||||
|
fun lossyFromModuleIdentifier(thisProject: Project, moduleIdentifier: KotlinModuleIdentifier): ModuleDependencyIdentifier {
|
||||||
|
when (moduleIdentifier) {
|
||||||
|
is LocalModuleIdentifier -> {
|
||||||
|
check(moduleIdentifier.buildId == thisProject.currentBuildId().name)
|
||||||
|
val dependencyProject = thisProject.project(moduleIdentifier.projectId)
|
||||||
|
val getRootPublication: () -> MavenPublication? = when (val topLevelExtension = dependencyProject.topLevelExtension) {
|
||||||
|
is KotlinMultiplatformExtension -> {
|
||||||
|
{ topLevelExtension.rootSoftwareComponent.publicationDelegate }
|
||||||
|
}
|
||||||
|
is KotlinPm20ProjectExtension -> {
|
||||||
|
{ topLevelExtension.rootPublication }
|
||||||
|
}
|
||||||
|
else -> error("unexpected top-level extension $topLevelExtension")
|
||||||
|
}
|
||||||
|
val coordinatesProvider = MultiplatformRootPublicationCoordinatesProvider(dependencyProject, getRootPublication)
|
||||||
|
return ChangingModuleDependencyIdentifier({ coordinatesProvider.group }, { coordinatesProvider.name })
|
||||||
|
}
|
||||||
|
is MavenModuleIdentifier -> {
|
||||||
|
return ModuleDependencyIdentifier(moduleIdentifier.group, moduleIdentifier.name)
|
||||||
|
}
|
||||||
|
else -> error("unexpected module identifier $moduleIdentifier")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PublishedModuleCoordinatesProvider {
|
||||||
|
val group: String
|
||||||
|
val name: String
|
||||||
|
val version: String
|
||||||
|
val capabilities: Iterable<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
class MultiplatformRootPublicationCoordinatesProvider(
|
||||||
|
project: Project,
|
||||||
|
val getPublication: () -> MavenPublication?
|
||||||
|
) : PublishedModuleCoordinatesProvider {
|
||||||
|
|
||||||
|
override val group: String by project.provider {
|
||||||
|
getPublication()?.groupId ?: project.group.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val name: String by project.provider {
|
||||||
|
getPublication()?.artifactId ?: project.group.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val version: String by project.provider {
|
||||||
|
getPublication()?.artifactId ?: project.version.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val capabilities: Iterable<String>
|
||||||
|
get() = emptyList()
|
||||||
}
|
}
|
||||||
+1
-1
@@ -123,7 +123,7 @@ internal class SourceSetVisibilityProvider(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun kotlinVariantNameFromPublishedVariantName(resolvedToVariantName: String): String =
|
internal fun kotlinVariantNameFromPublishedVariantName(resolvedToVariantName: String): String =
|
||||||
originalVariantNameFromPublished(resolvedToVariantName) ?: resolvedToVariantName
|
originalVariantNameFromPublished(resolvedToVariantName) ?: resolvedToVariantName
|
||||||
|
|
||||||
private fun Project.resolvableConfigurationFromCompilationByScope(
|
private fun Project.resolvableConfigurationFromCompilationByScope(
|
||||||
|
|||||||
+12
-2
@@ -11,10 +11,12 @@ import org.gradle.api.tasks.*
|
|||||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
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.pm20.TransformKotlinGranularMetadataForFragment
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope.*
|
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.withAllDependsOnSourceSets
|
import org.jetbrains.kotlin.gradle.plugin.sources.withAllDependsOnSourceSets
|
||||||
import org.jetbrains.kotlin.gradle.targets.metadata.ALL_COMPILE_METADATA_CONFIGURATION_NAME
|
import org.jetbrains.kotlin.gradle.targets.metadata.ALL_COMPILE_METADATA_CONFIGURATION_NAME
|
||||||
import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator
|
import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.metadata.ResolvedMetadataFilesProvider
|
||||||
import org.jetbrains.kotlin.gradle.targets.metadata.dependsOnClosureWithInterCompilationDependencies
|
import org.jetbrains.kotlin.gradle.targets.metadata.dependsOnClosureWithInterCompilationDependencies
|
||||||
import org.jetbrains.kotlin.gradle.utils.getValue
|
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -100,9 +102,9 @@ open class TransformKotlinGranularMetadata
|
|||||||
.associateWith { it.getExtractableMetadataFiles(outputsDir) }
|
.associateWith { it.getExtractableMetadataFiles(outputsDir) }
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
internal val filesByResolution: Map<out MetadataDependencyResolution, FileCollection>
|
internal val filesByResolution: Map<MetadataDependencyResolution, FileCollection>
|
||||||
get() = extractableFilesByResolution.mapValues { (_, value) ->
|
get() = extractableFilesByResolution.mapValues { (_, value) ->
|
||||||
project.files(value.getMetadataFilesPerSourceSet(false).values)
|
project.files(value.getMetadataFilesPerSourceSet(false).values).builtBy(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val extractableFiles by project.provider { extractableFilesByResolution.values }
|
private val extractableFiles by project.provider { extractableFilesByResolution.values }
|
||||||
@@ -117,3 +119,11 @@ open class TransformKotlinGranularMetadata
|
|||||||
extractableFiles.forEach { it.getMetadataFilesPerSourceSet(doProcessFiles = true) }
|
extractableFiles.forEach { it.getMetadataFilesPerSourceSet(doProcessFiles = true) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class SourceSetResolvedMetadataProvider(
|
||||||
|
taskProvider: TaskProvider<out TransformKotlinGranularMetadata>
|
||||||
|
) : ResolvedMetadataFilesProvider {
|
||||||
|
override val buildDependencies: Iterable<TaskProvider<*>> = listOf(taskProvider)
|
||||||
|
override val metadataResolutions: Iterable<MetadataDependencyResolution> by taskProvider.map { it.metadataDependencyResolutions }
|
||||||
|
override val metadataFilesByResolution: Map<MetadataDependencyResolution, FileCollection> by taskProvider.map { it.filesByResolution }
|
||||||
|
}
|
||||||
|
|||||||
+6
@@ -236,6 +236,12 @@ abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
|
|||||||
} else files()
|
} else files()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val friendPaths: Iterable<FileCollection>
|
||||||
|
get() = mutableListOf<FileCollection>().also { allCollections ->
|
||||||
|
associateWithTransitiveClosure.forEach { allCollections.add(it.output.classesDirs) }
|
||||||
|
allCollections.add(friendArtifacts)
|
||||||
|
}
|
||||||
|
|
||||||
override val moduleName: String
|
override val moduleName: String
|
||||||
get() = KotlinCompilationsModuleGroups.getModuleLeaderCompilation(this).takeIf { it != this }?.ownModuleName() ?: ownModuleName
|
get() = KotlinCompilationsModuleGroups.getModuleLeaderCompilation(this).takeIf { it != this }?.ownModuleName() ?: ownModuleName
|
||||||
|
|
||||||
|
|||||||
+28
-11
@@ -10,22 +10,33 @@ import org.gradle.api.artifacts.Configuration
|
|||||||
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.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.topLevelExtension
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration
|
import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
||||||
import org.jetbrains.kotlin.project.model.*
|
import org.jetbrains.kotlin.project.model.*
|
||||||
|
|
||||||
class GradleKotlinDependencyGraphResolver(
|
internal fun resolvableMetadataConfiguration(
|
||||||
private val project: Project,
|
module: KotlinGradleModule
|
||||||
private val moduleResolver: ModuleDependencyResolver,
|
) = module.project.configurations.getByName(module.resolvableMetadataConfigurationName)
|
||||||
private val fragmentsResolver: ModuleFragmentsResolver
|
|
||||||
) : KotlinDependencyGraphResolver {
|
|
||||||
|
|
||||||
private val configurationToResolve: Configuration
|
internal fun configurationToResolveMetadataDependencies(project: Project, requestingModule: KotlinModule): Configuration =
|
||||||
get() = resolvableMetadataConfiguration(
|
when (project.topLevelExtension) {
|
||||||
|
is KotlinPm20ProjectExtension -> resolvableMetadataConfiguration(requestingModule as KotlinGradleModule)
|
||||||
|
else -> resolvableMetadataConfiguration(
|
||||||
project,
|
project,
|
||||||
project.kotlinExtension.sourceSets, // take dependencies from all source sets; TODO introduce consistency scopes?
|
project.kotlinExtension.sourceSets, // take dependencies from all source sets; TODO introduce consistency scopes?
|
||||||
KotlinDependencyScope.compileScopes
|
KotlinDependencyScope.compileScopes
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class GradleKotlinDependencyGraphResolver(
|
||||||
|
private val project: Project,
|
||||||
|
private val moduleResolver: ModuleDependencyResolver
|
||||||
|
) : KotlinDependencyGraphResolver {
|
||||||
|
|
||||||
|
private fun configurationToResolve(requestingModule: KotlinModule): Configuration =
|
||||||
|
configurationToResolveMetadataDependencies(project, requestingModule)
|
||||||
|
|
||||||
override fun resolveDependencyGraph(requestingModule: KotlinModule): DependencyGraphResolution {
|
override fun resolveDependencyGraph(requestingModule: KotlinModule): DependencyGraphResolution {
|
||||||
if (!requestingModule.representsProject(project))
|
if (!requestingModule.representsProject(project))
|
||||||
@@ -40,11 +51,17 @@ class GradleKotlinDependencyGraphResolver(
|
|||||||
return nodeByModuleId.getOrPut(id) {
|
return nodeByModuleId.getOrPut(id) {
|
||||||
val module = if (isRoot)
|
val module = if (isRoot)
|
||||||
requestingModule
|
requestingModule
|
||||||
else moduleResolver.resolveDependency(component.toModuleDependency())
|
else moduleResolver.resolveDependency(requestingModule, component.toModuleDependency())
|
||||||
.takeIf { component !in excludeLegacyMetadataModulesFromResult }
|
.takeIf { component !in excludeLegacyMetadataModulesFromResult }
|
||||||
?: buildStubModule(component, component.variants.singleOrNull()?.displayName ?: "default")
|
?: buildSyntheticModule(component, component.variants.singleOrNull()?.displayName ?: "default")
|
||||||
|
|
||||||
val resolvedComponentDependencies = component.dependencies
|
val componentContainingTransitiveDependencies =
|
||||||
|
(module as? ExternalImportedKotlinModule)
|
||||||
|
?.takeIf { it.hasLegacyMetadataModule }
|
||||||
|
?.let { (component.dependencies.singleOrNull() as? ResolvedDependencyResult)?.selected }
|
||||||
|
?: component
|
||||||
|
|
||||||
|
val resolvedComponentDependencies = componentContainingTransitiveDependencies.dependencies
|
||||||
.filterIsInstance<ResolvedDependencyResult>()
|
.filterIsInstance<ResolvedDependencyResult>()
|
||||||
.flatMap { dependency -> dependency.requested.toModuleIdentifiers().map { id -> id to dependency.selected } }
|
.flatMap { dependency -> dependency.requested.toModuleIdentifiers().map { id -> id to dependency.selected } }
|
||||||
.toMap()
|
.toMap()
|
||||||
@@ -61,7 +78,7 @@ class GradleKotlinDependencyGraphResolver(
|
|||||||
|
|
||||||
return DependencyGraphResolution.DependencyGraph(
|
return DependencyGraphResolution.DependencyGraph(
|
||||||
requestingModule,
|
requestingModule,
|
||||||
nodeFromComponent(configurationToResolve.incoming.resolutionResult.root, isRoot = true)
|
nodeFromComponent(configurationToResolve(requestingModule).incoming.resolutionResult.root, isRoot = true)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+27
-20
@@ -13,8 +13,7 @@ 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.dsl.kotlinExtension
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.ProjectStructureMetadataModuleBuilder
|
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.GradleProjectModuleBuilder
|
|
||||||
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.mpp.resolvableMetadataConfiguration
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
||||||
@@ -27,15 +26,11 @@ class GradleModuleDependencyResolver(
|
|||||||
private val projectModuleBuilder: GradleProjectModuleBuilder
|
private val projectModuleBuilder: GradleProjectModuleBuilder
|
||||||
) : ModuleDependencyResolver {
|
) : ModuleDependencyResolver {
|
||||||
|
|
||||||
private val configurationToResolve: Configuration
|
private fun configurationToResolve(requestingModule: KotlinModule): Configuration =
|
||||||
get() = resolvableMetadataConfiguration(
|
configurationToResolveMetadataDependencies(project, requestingModule)
|
||||||
project,
|
|
||||||
project.kotlinExtension.sourceSets, // take dependencies from all source sets; TODO introduce consistency scopes?
|
|
||||||
listOf(KotlinDependencyScope.API_SCOPE, KotlinDependencyScope.IMPLEMENTATION_SCOPE, KotlinDependencyScope.COMPILE_ONLY_SCOPE)
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun resolveDependency(moduleDependency: KotlinModuleDependency): KotlinModule? {
|
override fun resolveDependency(requestingModule: KotlinModule, moduleDependency: KotlinModuleDependency): KotlinModule? {
|
||||||
val allComponents = configurationToResolve.incoming.resolutionResult.allComponents
|
val allComponents = configurationToResolve(requestingModule).incoming.resolutionResult.allComponents
|
||||||
// TODO: optimize O(n) search, store the resolved components with dependency keys?
|
// TODO: optimize O(n) search, store the resolved components with dependency keys?
|
||||||
val component = allComponents.find { it.id.matchesModuleDependency(moduleDependency) }
|
val component = allComponents.find { it.id.matchesModuleDependency(moduleDependency) }
|
||||||
val id = component?.id
|
val id = component?.id
|
||||||
@@ -48,8 +43,9 @@ class GradleModuleDependencyResolver(
|
|||||||
projectModuleBuilder.buildModulesFromProject(project.project(id.projectPath))
|
projectModuleBuilder.buildModulesFromProject(project.project(id.projectPath))
|
||||||
.find { it.moduleIdentifier.moduleClassifier == classifier }
|
.find { it.moduleIdentifier.moduleClassifier == classifier }
|
||||||
id is ModuleComponentIdentifier -> {
|
id is ModuleComponentIdentifier -> {
|
||||||
val metadata = getProjectStructureMetadata(project, component, configurationToResolve) ?: return null
|
val metadata = getProjectStructureMetadata(project, component, configurationToResolve(requestingModule)) ?: return null
|
||||||
projectStructureMetadataModuleBuilder.getModule(id.toModuleIdentifier(classifier), metadata)
|
val result = projectStructureMetadataModuleBuilder.getModule(component, metadata)
|
||||||
|
result
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
@@ -110,9 +106,9 @@ class FragmentDependenciesDiscovery(
|
|||||||
val component = resolvedComponentQueue.removeFirst()
|
val component = resolvedComponentQueue.removeFirst()
|
||||||
visited.add(component)
|
visited.add(component)
|
||||||
|
|
||||||
val module = moduleResolver.resolveDependency(component.toModuleDependency())
|
val module = moduleResolver.resolveDependency(fragment.containingModule, component.toModuleDependency())
|
||||||
.takeIf { component !in excludeLegacyMetadataModulesFromResult }
|
.takeIf { component !in excludeLegacyMetadataModulesFromResult }
|
||||||
?: buildStubModule(component, component.variants.singleOrNull()?.displayName ?: "default")
|
?: buildSyntheticModule(component, component.variants.singleOrNull()?.displayName ?: "default")
|
||||||
|
|
||||||
val transitiveDepsToVisit = when (val fragmentsResolution = fragmentsResolver.getChosenFragments(fragment, module)) {
|
val transitiveDepsToVisit = when (val fragmentsResolution = fragmentsResolver.getChosenFragments(fragment, module)) {
|
||||||
is FragmentResolution.ChosenFragments ->
|
is FragmentResolution.ChosenFragments ->
|
||||||
@@ -126,9 +122,7 @@ class FragmentDependenciesDiscovery(
|
|||||||
|
|
||||||
// With legacy publication scheme, the root MPP module may have a single 'dependency' (available-at) to the metadata module
|
// With legacy publication scheme, the root MPP module may have a single 'dependency' (available-at) to the metadata module
|
||||||
val isMetadataModulePublishedSeparately =
|
val isMetadataModulePublishedSeparately =
|
||||||
getProjectStructureMetadata(project, component, configurationToResolve)
|
(module is ExternalImportedKotlinModule) && module.hasLegacyMetadataModule
|
||||||
?.let { !it.isPublishedAsRoot }
|
|
||||||
?: false
|
|
||||||
val singleDependencyComponentOrNull = (component.dependencies.singleOrNull() as? ResolvedDependencyResult)?.selected
|
val singleDependencyComponentOrNull = (component.dependencies.singleOrNull() as? ResolvedDependencyResult)?.selected
|
||||||
if (isMetadataModulePublishedSeparately && singleDependencyComponentOrNull != null) {
|
if (isMetadataModulePublishedSeparately && singleDependencyComponentOrNull != null) {
|
||||||
newTransitiveDeps.add(singleDependencyComponentOrNull)
|
newTransitiveDeps.add(singleDependencyComponentOrNull)
|
||||||
@@ -144,9 +138,9 @@ class FragmentDependenciesDiscovery(
|
|||||||
|
|
||||||
// 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 buildStubModule(resolvedComponentResult: ResolvedComponentResult, singleVariantName: String): KotlinModule {
|
internal fun buildSyntheticModule(resolvedComponentResult: ResolvedComponentResult, singleVariantName: String): ExternalSyntheticKotlinModule {
|
||||||
val moduleDependency = resolvedComponentResult.toModuleDependency()
|
val moduleDependency = resolvedComponentResult.toModuleDependency()
|
||||||
return BasicKotlinModule(moduleDependency.moduleIdentifier).apply {
|
return ExternalSyntheticKotlinModule(BasicKotlinModule(moduleDependency.moduleIdentifier).apply {
|
||||||
BasicKotlinModuleVariant(this@apply, singleVariantName).apply {
|
BasicKotlinModuleVariant(this@apply, singleVariantName).apply {
|
||||||
fragments.add(this)
|
fragments.add(this)
|
||||||
this.declaredModuleDependencies.addAll(
|
this.declaredModuleDependencies.addAll(
|
||||||
@@ -155,7 +149,20 @@ internal fun buildStubModule(resolvedComponentResult: ResolvedComponentResult, s
|
|||||||
.map { it.selected.toModuleDependency() }
|
.map { it.selected.toModuleDependency() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ExternalSyntheticKotlinModule(private val moduleData: BasicKotlinModule) : KotlinModule by moduleData {
|
||||||
|
override fun toString(): String = "synthetic $moduleData"
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ExternalImportedKotlinModule(
|
||||||
|
private val moduleData: BasicKotlinModule,
|
||||||
|
val projectStructureMetadata: KotlinProjectStructureMetadata
|
||||||
|
) : KotlinModule by moduleData {
|
||||||
|
val hasLegacyMetadataModule = !projectStructureMetadata.isPublishedAsRoot
|
||||||
|
|
||||||
|
override fun toString(): String = "imported $moduleData"
|
||||||
}
|
}
|
||||||
|
|
||||||
class VariantDependencyDiscovery(
|
class VariantDependencyDiscovery(
|
||||||
|
|||||||
+131
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* 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.plugin.mpp.pm20
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.artifacts.result.ResolvedDependencyResult
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.ChooseVisibleSourceSetsImpl
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.getMetadataExtractor
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.getProjectStructureMetadata
|
||||||
|
import org.jetbrains.kotlin.project.model.*
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.flattenTo
|
||||||
|
import java.util.ArrayDeque
|
||||||
|
|
||||||
|
internal class FragmentGranularMetadataResolver(
|
||||||
|
val requestingFragment: KotlinGradleFragment,
|
||||||
|
val refinesParentResolvers: Lazy<Iterable<FragmentGranularMetadataResolver>>
|
||||||
|
) {
|
||||||
|
val resolutions: Iterable<MetadataDependencyResolution> by lazy {
|
||||||
|
doResolveMetadataDependencies()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val project: Project
|
||||||
|
get() = requestingFragment.containingModule.project
|
||||||
|
|
||||||
|
private val parentResultsByModuleIdentifier: Map<KotlinModuleIdentifier, List<MetadataDependencyResolution>> by lazy {
|
||||||
|
refinesParentResolvers.value.flatMap { it.resolutions }.groupBy { it.dependency.toModuleIdentifier() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private val metadataModuleBuilder = ProjectStructureMetadataModuleBuilder()
|
||||||
|
private val projectModuleBuilder = GradleProjectModuleBuilder(true)
|
||||||
|
private val moduleResolver = GradleModuleDependencyResolver(project, metadataModuleBuilder, projectModuleBuilder)
|
||||||
|
private val variantResolver = GradleModuleVariantResolver(project)
|
||||||
|
private val fragmentResolver = DefaultModuleFragmentsResolver(variantResolver)
|
||||||
|
private val dependencyGraphResolver = GradleKotlinDependencyGraphResolver(project, moduleResolver)
|
||||||
|
|
||||||
|
private fun doResolveMetadataDependencies(): Iterable<MetadataDependencyResolution> {
|
||||||
|
val configurationToResolve = configurationToResolveMetadataDependencies(project, requestingFragment.containingModule)
|
||||||
|
val resolvedComponentsByModuleId =
|
||||||
|
configurationToResolve.incoming.resolutionResult.allComponents.associateBy { it.toModuleIdentifier() }
|
||||||
|
val resolvedDependenciesByModuleId =
|
||||||
|
configurationToResolve.incoming.resolutionResult.allDependencies.filterIsInstance<ResolvedDependencyResult>()
|
||||||
|
.flatMap { dependency -> dependency.requested.toModuleIdentifiers().map { id -> id to dependency } }.toMap()
|
||||||
|
|
||||||
|
val dependencyGraph = dependencyGraphResolver.resolveDependencyGraph(requestingFragment.containingModule)
|
||||||
|
|
||||||
|
if (dependencyGraph is DependencyGraphResolution.Unknown)
|
||||||
|
error("unexpected failure in dependency graph resolution for $requestingFragment in $project")
|
||||||
|
|
||||||
|
dependencyGraph as DependencyGraphResolution.DependencyGraph
|
||||||
|
val fragmentsToInclude = requestingFragment.refinesClosure
|
||||||
|
val requestedDependencies = dependencyGraph.root.dependenciesByFragment.filterKeys { it in fragmentsToInclude }.values.flatten()
|
||||||
|
|
||||||
|
val visited = mutableSetOf<DependencyGraphNode>()
|
||||||
|
val fragmentResolutionQueue = ArrayDeque<DependencyGraphNode>().apply {
|
||||||
|
addAll(requestedDependencies)
|
||||||
|
}
|
||||||
|
|
||||||
|
val results = mutableSetOf<MetadataDependencyResolution>()
|
||||||
|
|
||||||
|
while (fragmentResolutionQueue.isNotEmpty()) {
|
||||||
|
val dependencyNode = fragmentResolutionQueue.removeFirst()
|
||||||
|
visited.add(dependencyNode)
|
||||||
|
|
||||||
|
val dependencyModule = dependencyNode.module
|
||||||
|
|
||||||
|
val fragmentVisibility = fragmentResolver.getChosenFragments(requestingFragment, dependencyModule)
|
||||||
|
val visibleFragments = (fragmentVisibility as? FragmentResolution.ChosenFragments)?.visibleFragments?.toList().orEmpty()
|
||||||
|
val variantResolutions =
|
||||||
|
(fragmentVisibility as? FragmentResolution.ChosenFragments)?.variantResolutions?.associateBy { it.requestingVariant }
|
||||||
|
|
||||||
|
val visibleTransitiveDependencies =
|
||||||
|
dependencyNode.dependenciesByFragment.filterKeys { it in visibleFragments }.values.flattenTo(mutableSetOf())
|
||||||
|
|
||||||
|
//FIXME host-specific fragments
|
||||||
|
|
||||||
|
fragmentResolutionQueue.addAll(visibleTransitiveDependencies.filter { it !in visited })
|
||||||
|
|
||||||
|
val resolvedComponentResult = resolvedComponentsByModuleId.getValue(dependencyModule.moduleIdentifier)
|
||||||
|
val isResolvedAsProject = resolvedComponentResult.toProjectOrNull(project)
|
||||||
|
val result = when (dependencyModule) {
|
||||||
|
is ExternalSyntheticKotlinModule -> {
|
||||||
|
MetadataDependencyResolution.KeepOriginalDependency(resolvedComponentResult, isResolvedAsProject)
|
||||||
|
}
|
||||||
|
else -> run {
|
||||||
|
val projectStructureMetadata = (dependencyModule as? ExternalImportedKotlinModule)?.projectStructureMetadata
|
||||||
|
?: checkNotNull(getProjectStructureMetadata(project, resolvedComponentResult, configurationToResolve))
|
||||||
|
|
||||||
|
// FIXME host-specific metadata!!!
|
||||||
|
|
||||||
|
val metadataSourceComponent = when {
|
||||||
|
dependencyModule is ExternalImportedKotlinModule && dependencyModule.hasLegacyMetadataModule ->
|
||||||
|
resolvedComponentResult.dependencies.filterIsInstance<ResolvedDependencyResult>().singleOrNull()?.selected
|
||||||
|
?: resolvedComponentResult
|
||||||
|
else -> resolvedComponentResult
|
||||||
|
}
|
||||||
|
|
||||||
|
val parentResolutionsForDependency =
|
||||||
|
parentResultsByModuleIdentifier[metadataSourceComponent.toModuleIdentifier()].orEmpty()
|
||||||
|
val fragmentsVisibleByParents =
|
||||||
|
parentResolutionsForDependency.filterIsInstance<ChooseVisibleSourceSetsImpl>()
|
||||||
|
.flatMapTo(mutableSetOf()) { it.allVisibleSourceSetNames }
|
||||||
|
val visibleFragmentNames = visibleFragments.map { it.fragmentName }.toSet()
|
||||||
|
|
||||||
|
ChooseVisibleSourceSetsImpl(
|
||||||
|
metadataSourceComponent,
|
||||||
|
isResolvedAsProject,
|
||||||
|
projectStructureMetadata,
|
||||||
|
visibleFragmentNames,
|
||||||
|
visibleFragmentNames.minus(fragmentsVisibleByParents),
|
||||||
|
visibleTransitiveDependencies.map { resolvedDependenciesByModuleId.getValue(it.module.moduleIdentifier) }.toSet(),
|
||||||
|
checkNotNull(getMetadataExtractor(project, resolvedComponentResult, configurationToResolve, true))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results.add(result)
|
||||||
|
fragmentResolutionQueue.addAll(visibleTransitiveDependencies.filterNot(visited::contains))
|
||||||
|
}
|
||||||
|
|
||||||
|
val resultSourceComponents = results.mapTo(mutableSetOf()) { it.dependency }
|
||||||
|
resolvedComponentsByModuleId.values.minus(resultSourceComponents).forEach {
|
||||||
|
results.add(MetadataDependencyResolution.ExcludeAsUnrequested(it, it.toProjectOrNull(project)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
-14
@@ -5,16 +5,35 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
|
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
|
||||||
|
|
||||||
import org.gradle.api.NamedDomainObjectContainer
|
import org.gradle.api.*
|
||||||
import org.gradle.api.NamedDomainObjectProvider
|
import org.gradle.api.attributes.Usage
|
||||||
import org.gradle.api.Plugin
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.plugins.JavaBasePlugin
|
import org.gradle.api.plugins.JavaBasePlugin
|
||||||
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
|
import org.gradle.api.tasks.TaskProvider
|
||||||
|
import org.gradle.jvm.tasks.Jar
|
||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformCommonOptions
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension
|
import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension
|
||||||
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
|
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
|
||||||
import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies
|
import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCommonSourceSetProcessor
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.MULTIPLATFORM_PROJECT_METADATA_JSON_FILE_NAME
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.addSourcesToKotlinCompileTask
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.buildKotlinProjectStructureMetadata
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.usageByName
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.metadata.createGenerateProjectStructureMetadataTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.withType
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||||
import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility
|
import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
import org.jetbrains.kotlin.project.model.KotlinModuleFragment
|
||||||
|
import org.jetbrains.kotlin.project.model.KotlinModuleIdentifier
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
abstract class KotlinPm20GradlePlugin : Plugin<Project> {
|
abstract class KotlinPm20GradlePlugin : Plugin<Project> {
|
||||||
override fun apply(project: Project) {
|
override fun apply(project: Project) {
|
||||||
@@ -43,21 +62,17 @@ abstract class KotlinPm20GradlePlugin : Plugin<Project> {
|
|||||||
modules.create(KotlinGradleModule.TEST_MODULE_NAME)
|
modules.create(KotlinGradleModule.TEST_MODULE_NAME)
|
||||||
main { makePublic() }
|
main { makePublic() }
|
||||||
}
|
}
|
||||||
|
setupMetadataCompilationAndDependencyResolution(project)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupMetadataCompilation() {
|
private fun setupMetadataCompilationAndDependencyResolution(project: Project) {
|
||||||
// TODO dependency transformations in tasks
|
project.pm20Extension.modules.all { module ->
|
||||||
// TODO classpath configurations
|
configureMetadataResolutionAndBuild(module)
|
||||||
// TODO compilation data -> tasks
|
}
|
||||||
// TODO project structure metadata -> metadata artifact
|
|
||||||
// TODO task outputs -> metadata artifact
|
|
||||||
// TODO export the metadata artifact in consumable configurations
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open class KotlinPm20ProjectExtension : KotlinTopLevelExtension() {
|
open class KotlinPm20ProjectExtension(project: Project) : KotlinTopLevelExtension(project) {
|
||||||
internal lateinit var project: Project
|
|
||||||
|
|
||||||
val modules: NamedDomainObjectContainer<KotlinGradleModule> by lazy {
|
val modules: NamedDomainObjectContainer<KotlinGradleModule> by lazy {
|
||||||
project.objects.domainObjectContainer(
|
project.objects.domainObjectContainer(
|
||||||
KotlinGradleModule::class.java,
|
KotlinGradleModule::class.java,
|
||||||
@@ -79,6 +94,11 @@ open class KotlinPm20ProjectExtension : KotlinTopLevelExtension() {
|
|||||||
|
|
||||||
fun main(configure: KotlinGradleModule.() -> Unit = { }) = main.apply(configure)
|
fun main(configure: KotlinGradleModule.() -> Unit = { }) = main.apply(configure)
|
||||||
fun test(configure: KotlinGradleModule.() -> Unit = { }) = test.apply(configure)
|
fun test(configure: KotlinGradleModule.() -> Unit = { }) = test.apply(configure)
|
||||||
|
|
||||||
|
internal val metadataCompilationRegistryByModuleId: MutableMap<KotlinModuleIdentifier, MetadataCompilationRegistry> =
|
||||||
|
mutableMapOf()
|
||||||
|
|
||||||
|
internal var rootPublication: MavenPublication? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
val KotlinGradleModule.jvm: KotlinJvmVariant
|
val KotlinGradleModule.jvm: KotlinJvmVariant
|
||||||
|
|||||||
+9
@@ -9,9 +9,11 @@ import org.gradle.api.Project
|
|||||||
import org.gradle.api.file.FileCollection
|
import org.gradle.api.file.FileCollection
|
||||||
import org.gradle.api.file.SourceDirectorySet
|
import org.gradle.api.file.SourceDirectorySet
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationOutput
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationOutput
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
|
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
|
||||||
|
|
||||||
interface KotlinCompilationData<T : KotlinCommonOptions> {
|
interface KotlinCompilationData<T : KotlinCommonOptions> {
|
||||||
val project: Project
|
val project: Project
|
||||||
@@ -34,4 +36,11 @@ interface KotlinCompilationData<T : KotlinCommonOptions> {
|
|||||||
val ownModuleName: String
|
val ownModuleName: String
|
||||||
|
|
||||||
val kotlinOptions: T
|
val kotlinOptions: T
|
||||||
|
|
||||||
|
val friendPaths: Iterable<FileCollection>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KotlinCompilationData<*>.isMain(): Boolean = when (this) {
|
||||||
|
is KotlinCompilation<*> -> isMain()
|
||||||
|
else -> compilationPurpose == KotlinGradleModule.MAIN_MODULE_NAME
|
||||||
}
|
}
|
||||||
+115
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* 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.plugin.mpp.pm20
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.file.SourceDirectorySet
|
||||||
|
import org.gradle.api.plugins.BasePluginConvention
|
||||||
|
import org.gradle.api.tasks.TaskProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformCommonOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformCommonOptionsImpl
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationOutput
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinCompilationOutput
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.filterModuleName
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.metadata.ResolvedMetadataFilesProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.metadata.createTransformedMetadataClasspath
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
|
||||||
|
internal class KotlinFragmentMetadataCompilationData(
|
||||||
|
override val project: Project,
|
||||||
|
val fragment: KotlinGradleFragment,
|
||||||
|
private val module: KotlinGradleModule,
|
||||||
|
private val compileAllTask: TaskProvider<DefaultTask>,
|
||||||
|
val metadataCompilationRegistry: MetadataCompilationRegistry,
|
||||||
|
private val resolvedMetadataFiles: Lazy<Iterable<ResolvedMetadataFilesProvider>>
|
||||||
|
) : KotlinCompilationData<KotlinMultiplatformCommonOptions> {
|
||||||
|
|
||||||
|
override val owner
|
||||||
|
get() = project.pm20Extension
|
||||||
|
|
||||||
|
override val compilationPurpose: String
|
||||||
|
get() = fragment.fragmentName
|
||||||
|
|
||||||
|
override val compilationClassifier: String
|
||||||
|
get() = lowerCamelCaseName(module.name, "metadata")
|
||||||
|
|
||||||
|
override val kotlinSourceDirectoriesByFragmentName: Map<String, SourceDirectorySet>
|
||||||
|
get() = mapOf(fragment.fragmentName to fragment.kotlinSourceRoots)
|
||||||
|
|
||||||
|
override val compileKotlinTaskName: String
|
||||||
|
get() = lowerCamelCaseName("compile", fragment.disambiguateName(""), "KotlinMetadata")
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = compileAllTask.name
|
||||||
|
|
||||||
|
override val compileDependencyFiles: FileCollection by project.provider {
|
||||||
|
createTransformedMetadataClasspath(
|
||||||
|
project,
|
||||||
|
resolvableMetadataConfiguration(fragment.containingModule),
|
||||||
|
lazy { fragment.refinesClosure.minus(fragment).map { metadataCompilationRegistry.byFragment(it).output.classesDirs } },
|
||||||
|
resolvedMetadataFiles
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val output: KotlinCompilationOutput = DefaultKotlinCompilationOutput(
|
||||||
|
project,
|
||||||
|
project.provider { project.buildDir.resolve("processedResources/${fragment.disambiguateName("metadata")}") }
|
||||||
|
)
|
||||||
|
|
||||||
|
override val languageSettings: LanguageSettingsBuilder = DefaultLanguageSettingsBuilder() // FIXME apply settings
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.common
|
||||||
|
|
||||||
|
override val moduleName: String
|
||||||
|
get() { // FIXME deduplicate with ownModuleName
|
||||||
|
val baseName = project.convention.findPlugin(BasePluginConvention::class.java)?.archivesBaseName
|
||||||
|
?: project.name
|
||||||
|
val suffix = if (module.moduleClassifier == null) "" else "_${module.moduleClassifier}"
|
||||||
|
return filterModuleName("$baseName$suffix")
|
||||||
|
}
|
||||||
|
|
||||||
|
override val ownModuleName: String
|
||||||
|
get() = moduleName
|
||||||
|
|
||||||
|
override val kotlinOptions: KotlinMultiplatformCommonOptions = // FIXME expose for configuration
|
||||||
|
KotlinMultiplatformCommonOptionsImpl()
|
||||||
|
|
||||||
|
override val friendPaths: Iterable<FileCollection>
|
||||||
|
get() = metadataCompilationRegistry.run {
|
||||||
|
fragment.refinesClosure.minus(fragment)
|
||||||
|
.map {
|
||||||
|
metadataCompilationRegistry.byFragment(it).output.classesDirs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MetadataCompilationRegistry {
|
||||||
|
private val compilationDataPerFragment = mutableMapOf<KotlinGradleFragment, KotlinFragmentMetadataCompilationData>()
|
||||||
|
|
||||||
|
fun register(fragment: KotlinGradleFragment, compilationData: KotlinFragmentMetadataCompilationData) {
|
||||||
|
compilationDataPerFragment[fragment]?.let { error("compilation data for fragment $fragment already registered") }
|
||||||
|
compilationDataPerFragment[fragment] = compilationData
|
||||||
|
withAllCallbacks.forEach { it.invoke(compilationData) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun byFragment(fragment: KotlinGradleFragment): KotlinFragmentMetadataCompilationData =
|
||||||
|
compilationDataPerFragment.getValue(fragment)
|
||||||
|
|
||||||
|
private val withAllCallbacks = mutableListOf<(KotlinFragmentMetadataCompilationData) -> Unit>()
|
||||||
|
|
||||||
|
fun withAll(action: (KotlinFragmentMetadataCompilationData) -> Unit) {
|
||||||
|
compilationDataPerFragment.forEach { action(it.value) }
|
||||||
|
withAllCallbacks += action
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-1
@@ -16,11 +16,13 @@ import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
|
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
|
||||||
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
|
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinDependencyHandler
|
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinDependencyHandler
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.toModuleDependency
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
||||||
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
import org.jetbrains.kotlin.project.model.KotlinModuleDependency
|
import org.jetbrains.kotlin.project.model.KotlinModuleDependency
|
||||||
import org.jetbrains.kotlin.project.model.KotlinModuleFragment
|
import org.jetbrains.kotlin.project.model.KotlinModuleFragment
|
||||||
|
import org.jetbrains.kotlin.project.model.refinesClosure
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
open class KotlinGradleFragment @Inject constructor(
|
open class KotlinGradleFragment @Inject constructor(
|
||||||
@@ -31,6 +33,8 @@ open class KotlinGradleFragment @Inject constructor(
|
|||||||
override fun getName(): String = fragmentName
|
override fun getName(): String = fragmentName
|
||||||
|
|
||||||
// TODO pull up to KotlinModuleFragment
|
// TODO pull up to KotlinModuleFragment
|
||||||
|
// FIXME apply to compilation
|
||||||
|
// FIXME check for consistency
|
||||||
val languageSettings: LanguageSettingsBuilder = DefaultLanguageSettingsBuilder()
|
val languageSettings: LanguageSettingsBuilder = DefaultLanguageSettingsBuilder()
|
||||||
|
|
||||||
protected val project: Project
|
protected val project: Project
|
||||||
@@ -80,7 +84,7 @@ open class KotlinGradleFragment @Inject constructor(
|
|||||||
get() = _directRefinesDependencies.map { it.get() }
|
get() = _directRefinesDependencies.map { it.get() }
|
||||||
|
|
||||||
override val declaredModuleDependencies: Iterable<KotlinModuleDependency>
|
override val declaredModuleDependencies: Iterable<KotlinModuleDependency>
|
||||||
get() = TODO("Not yet implemented")
|
get() = project.configurations.getByName(apiConfigurationName).allDependencies.map { it.toModuleDependency(project) } // FIXME impl
|
||||||
|
|
||||||
override val kotlinSourceRoots: SourceDirectorySet by lazy {
|
override val kotlinSourceRoots: SourceDirectorySet by lazy {
|
||||||
project.objects.sourceDirectorySet(
|
project.objects.sourceDirectorySet(
|
||||||
@@ -104,7 +108,12 @@ open class KotlinGradleFragment @Inject constructor(
|
|||||||
companion object {
|
companion object {
|
||||||
const val COMMON_FRAGMENT_NAME = "common"
|
const val COMMON_FRAGMENT_NAME = "common"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = "fragment $fragmentName in $containingModule"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun KotlinModuleFragment.disambiguateName(simpleName: String) =
|
internal fun KotlinModuleFragment.disambiguateName(simpleName: String) =
|
||||||
lowerCamelCaseName(fragmentName, containingModule.moduleIdentifier.moduleClassifier ?: KotlinGradleModule.MAIN_MODULE_NAME, simpleName)
|
lowerCamelCaseName(fragmentName, containingModule.moduleIdentifier.moduleClassifier ?: KotlinGradleModule.MAIN_MODULE_NAME, simpleName)
|
||||||
|
|
||||||
|
val KotlinGradleFragment.refinesClosure: Set<KotlinGradleFragment>
|
||||||
|
get() = (this as KotlinModuleFragment).refinesClosure.map { it as KotlinGradleFragment }.toSet()
|
||||||
|
|||||||
+10
-3
@@ -12,9 +12,8 @@ import org.gradle.api.NamedDomainObjectSet
|
|||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
|
import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
|
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
|
||||||
import org.jetbrains.kotlin.project.model.KotlinModule
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
import org.jetbrains.kotlin.project.model.KotlinModuleIdentifier
|
import org.jetbrains.kotlin.project.model.*
|
||||||
import org.jetbrains.kotlin.project.model.LocalModuleIdentifier
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
open class KotlinGradleModule(
|
open class KotlinGradleModule(
|
||||||
@@ -87,7 +86,15 @@ open class KotlinGradleModule(
|
|||||||
|
|
||||||
override val runtimeOnlyConfigurationName: String
|
override val runtimeOnlyConfigurationName: String
|
||||||
get() = common.runtimeOnlyConfigurationName
|
get() = common.runtimeOnlyConfigurationName
|
||||||
|
|
||||||
|
override fun toString(): String = "$moduleIdentifier (Gradle)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val KotlinGradleModule.resolvableMetadataConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(name, "DependenciesMetadata")
|
||||||
|
|
||||||
internal val KotlinGradleModule.isMain
|
internal val KotlinGradleModule.isMain
|
||||||
get() = moduleIdentifier.moduleClassifier == null
|
get() = moduleIdentifier.moduleClassifier == null
|
||||||
|
|
||||||
|
fun KotlinGradleModule.variantsContainingFragment(fragment: KotlinModuleFragment): Iterable<KotlinGradleVariant> =
|
||||||
|
variants.filter { fragment in it.refinesClosure }
|
||||||
+1
-1
@@ -20,7 +20,7 @@ open class KotlinGradleModuleFactory(private val project: Project) : NamedDomain
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected open fun registerDefaultCommonFragment(module: KotlinGradleModule) {
|
protected open fun registerDefaultCommonFragment(module: KotlinGradleModule) {
|
||||||
module.fragments.create(KotlinGradleFragment.COMMON_FRAGMENT_NAME, KotlinGradleFragment::class.java)
|
module.fragments.register(KotlinGradleFragment.COMMON_FRAGMENT_NAME, KotlinGradleFragment::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun addDefaultRefinementDependencyOnCommon(module: KotlinGradleModule) {
|
protected open fun addDefaultRefinementDependencyOnCommon(module: KotlinGradleModule) {
|
||||||
|
|||||||
+7
@@ -58,6 +58,13 @@ class KotlinJvmVariantCompilationData(val variant: KotlinJvmVariant) : KotlinCom
|
|||||||
override val platformType: KotlinPlatformType
|
override val platformType: KotlinPlatformType
|
||||||
get() = variant.platformType
|
get() = variant.platformType
|
||||||
|
|
||||||
|
override val friendPaths: Iterable<FileCollection>
|
||||||
|
// TODO for now, all output classes of the module are considered friends, even those not on the classpath
|
||||||
|
get() {
|
||||||
|
// FIXME support compiling against the JARs
|
||||||
|
return variant.containingModule.project.pm20Extension.modules.flatMap { it.variants.map { it.compilationOutputs.classesDirs } }
|
||||||
|
}
|
||||||
|
|
||||||
override val moduleName: String
|
override val moduleName: String
|
||||||
get() = // TODO accurate module names that don't rely on all variants having a main counterpart
|
get() = // TODO accurate module names that don't rely on all variants having a main counterpart
|
||||||
variant.containingModule.project.pm20Extension.modules
|
variant.containingModule.project.pm20Extension.modules
|
||||||
|
|||||||
+97
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* 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.plugin.mpp.pm20
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.model.ObjectFactory
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.ExtractableMetadataFiles
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.metadata.ResolvedMetadataFilesProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||||
|
import java.io.File
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal open class TransformKotlinGranularMetadataForFragment
|
||||||
|
@Inject constructor(
|
||||||
|
@get:Internal
|
||||||
|
@field:Transient
|
||||||
|
val fragment: KotlinGradleFragment,
|
||||||
|
//FIXME annotations
|
||||||
|
private val transformation: FragmentGranularMetadataResolver
|
||||||
|
) : DefaultTask() {
|
||||||
|
|
||||||
|
@get:OutputDirectory
|
||||||
|
val outputsDir: File by project.provider {
|
||||||
|
project.buildDir.resolve("kotlinFragmentDependencyMetadata").resolve(fragment.disambiguateName(""))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused") // Gradle input
|
||||||
|
@get:InputFiles
|
||||||
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||||
|
internal val allSourceSetsMetadataConfiguration: FileCollection by lazy {
|
||||||
|
project.files(resolvableMetadataConfiguration(fragment.containingModule))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused") // Gradle input
|
||||||
|
@get:Input
|
||||||
|
internal val inputFragmentsAndVariants: Map<String, Iterable<String>> by project.provider {
|
||||||
|
val participatingFragments = fragment.refinesClosure
|
||||||
|
participatingFragments.associateWith { it.containingModule.variantsContainingFragment(it) }
|
||||||
|
.entries.associate { (fragment, variants) ->
|
||||||
|
fragment.name to variants.map { it.fragmentName }.sorted()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused") // Gradle input
|
||||||
|
@get:Input
|
||||||
|
internal val inputVariantDependencies: Map<String, Set<List<String?>>> by project.provider {
|
||||||
|
val participatingFragments = fragment.refinesClosure
|
||||||
|
val participatingCompilations = participatingFragments.flatMap { it.containingModule.variantsContainingFragment(it) }
|
||||||
|
participatingCompilations.associate { variant ->
|
||||||
|
variant.fragmentName to project.configurations.getByName(variant.compileDependencyConfigurationName)
|
||||||
|
.allDependencies.map { listOf(it.group, it.name, it.version) }.toSet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
@delegate:Transient // exclude from Gradle instant execution state
|
||||||
|
internal val metadataDependencyResolutions: Iterable<MetadataDependencyResolution> by project.provider {
|
||||||
|
transformation.resolutions
|
||||||
|
}
|
||||||
|
|
||||||
|
private val extractableFilesByResolution: Map<out MetadataDependencyResolution, ExtractableMetadataFiles>
|
||||||
|
get() = metadataDependencyResolutions
|
||||||
|
.filterIsInstance<MetadataDependencyResolution.ChooseVisibleSourceSets>()
|
||||||
|
.associateWith { it.getExtractableMetadataFiles(outputsDir) }
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
internal val filesByResolution: Map<MetadataDependencyResolution, FileCollection>
|
||||||
|
get() = extractableFilesByResolution.mapValues { (_, value) ->
|
||||||
|
project.files(value.getMetadataFilesPerSourceSet(false).values).builtBy(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val extractableFiles by project.provider { extractableFilesByResolution.values }
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun transformMetadata() {
|
||||||
|
if (outputsDir.isDirectory) {
|
||||||
|
outputsDir.deleteRecursively()
|
||||||
|
}
|
||||||
|
outputsDir.mkdirs()
|
||||||
|
|
||||||
|
extractableFiles.forEach { it.getMetadataFilesPerSourceSet(doProcessFiles = true) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class FragmentResolvedMetadataProvider(
|
||||||
|
taskProvider: TaskProvider<out TransformKotlinGranularMetadataForFragment>
|
||||||
|
) : ResolvedMetadataFilesProvider {
|
||||||
|
override val buildDependencies: Iterable<TaskProvider<*>> = listOf(taskProvider)
|
||||||
|
override val metadataResolutions: Iterable<MetadataDependencyResolution> by taskProvider.map { it.metadataDependencyResolutions }
|
||||||
|
override val metadataFilesByResolution: Map<MetadataDependencyResolution, FileCollection> by taskProvider.map { it.filesByResolution }
|
||||||
|
}
|
||||||
+13
-2
@@ -12,7 +12,7 @@ import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationOutput
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationOutput
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinCompilationOutput
|
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinCompilationOutput
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.fromPlatform
|
import org.jetbrains.kotlin.gradle.plugin.mpp.publishedConfigurationName
|
||||||
import org.jetbrains.kotlin.gradle.tasks.withType
|
import org.jetbrains.kotlin.gradle.tasks.withType
|
||||||
import org.jetbrains.kotlin.project.model.KotlinAttributeKey
|
import org.jetbrains.kotlin.project.model.KotlinAttributeKey
|
||||||
import org.jetbrains.kotlin.project.model.KotlinModuleVariant
|
import org.jetbrains.kotlin.project.model.KotlinModuleVariant
|
||||||
@@ -26,7 +26,7 @@ abstract class KotlinGradleVariant(
|
|||||||
abstract val platformType: KotlinPlatformType
|
abstract val platformType: KotlinPlatformType
|
||||||
|
|
||||||
override val variantAttributes: Map<KotlinAttributeKey, String>
|
override val variantAttributes: Map<KotlinAttributeKey, String>
|
||||||
get() = mapOf(KotlinPlatformTypeAttribute to KotlinPlatformTypeAttribute.fromPlatform(platformType)) // TODO user attributes
|
get() = mapOf(KotlinPlatformTypeAttribute to kotlinPlatformTypeAttributeFromPlatform(platformType)) // TODO user attributes
|
||||||
|
|
||||||
// TODO generalize with KotlinCompilation?
|
// TODO generalize with KotlinCompilation?
|
||||||
val compileDependencyConfigurationName: String
|
val compileDependencyConfigurationName: String
|
||||||
@@ -48,8 +48,15 @@ abstract class KotlinGradleVariant(
|
|||||||
// TODO generalize exposing outputs: what if a variant has more than one such configurations or none?
|
// TODO generalize exposing outputs: what if a variant has more than one such configurations or none?
|
||||||
val apiElementsConfigurationName: String
|
val apiElementsConfigurationName: String
|
||||||
get() = disambiguateName("apiElements")
|
get() = disambiguateName("apiElements")
|
||||||
|
|
||||||
|
open val gradleVariantNames: Set<String>
|
||||||
|
get() = listOf(apiElementsConfigurationName, publishedConfigurationName(apiElementsConfigurationName)).toSet()
|
||||||
|
|
||||||
|
override fun toString(): String = "variant $fragmentName in $containingModule"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun kotlinPlatformTypeAttributeFromPlatform(platformType: KotlinPlatformType) = platformType.name
|
||||||
|
|
||||||
// TODO: rewrite with the artifacts API
|
// TODO: rewrite with the artifacts API
|
||||||
internal val KotlinGradleVariant.defaultSourceArtifactTaskName: String
|
internal val KotlinGradleVariant.defaultSourceArtifactTaskName: String
|
||||||
get() = disambiguateName("sourcesJar")
|
get() = disambiguateName("sourcesJar")
|
||||||
@@ -71,4 +78,8 @@ abstract class KotlinGradleVariantWithRuntimeDependencies(
|
|||||||
// TODO generalize exposing outputs: what if a variant has more than one such configurations or none?
|
// TODO generalize exposing outputs: what if a variant has more than one such configurations or none?
|
||||||
val runtimeElementsConfigurationName: String
|
val runtimeElementsConfigurationName: String
|
||||||
get() = disambiguateName("runtimeElements")
|
get() = disambiguateName("runtimeElements")
|
||||||
|
|
||||||
|
override val gradleVariantNames: Set<String>
|
||||||
|
get() = super.gradleVariantNames +
|
||||||
|
listOf(runtimeElementsConfigurationName, publishedConfigurationName(runtimeElementsConfigurationName))
|
||||||
}
|
}
|
||||||
+198
@@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* 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.plugin.mpp.pm20
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.attributes.Usage
|
||||||
|
import org.gradle.api.tasks.TaskProvider
|
||||||
|
import org.gradle.jvm.tasks.Jar
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformCommonOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCommonSourceSetProcessor
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.MULTIPLATFORM_PROJECT_METADATA_JSON_FILE_NAME
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.addSourcesToKotlinCompileTask
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.buildKotlinProjectStructureMetadata
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.disambiguateName
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.usageByName
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.metadata.createGenerateProjectStructureMetadataTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.withType
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
import org.jetbrains.kotlin.project.model.KotlinModuleFragment
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
|
internal fun configureMetadataResolutionAndBuild(module: KotlinGradleModule) {
|
||||||
|
val project = module.project
|
||||||
|
createResolvableMetadataConfigurationForModule(module)
|
||||||
|
|
||||||
|
val metadataCompilationRegistry = MetadataCompilationRegistry()
|
||||||
|
project.pm20Extension.metadataCompilationRegistryByModuleId[module.moduleIdentifier] =
|
||||||
|
metadataCompilationRegistry
|
||||||
|
|
||||||
|
configureMetadataCompilationsAndCreateRegistry(module, metadataCompilationRegistry)
|
||||||
|
|
||||||
|
configureMetadataJarTask(module, metadataCompilationRegistry)
|
||||||
|
generateAndExportProjectStructureMetadata(module)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateAndExportProjectStructureMetadata(
|
||||||
|
module: KotlinGradleModule
|
||||||
|
) {
|
||||||
|
val project = module.project
|
||||||
|
val projectStructureMetadata = project.createGenerateProjectStructureMetadataTask(module.moduleClassifier)
|
||||||
|
project.tasks.withType<Jar>().named(metadataJarName(module)).configure { jar ->
|
||||||
|
jar.from(projectStructureMetadata.map { it.resultFile }) { spec ->
|
||||||
|
spec.into("META-INF")
|
||||||
|
.rename { MULTIPLATFORM_PROJECT_METADATA_JSON_FILE_NAME }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GlobalProjectStructureMetadataStorage.registerProjectStructureMetadata(project) {
|
||||||
|
checkNotNull(buildKotlinProjectStructureMetadata(project))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createResolvableMetadataConfigurationForModule(module: KotlinGradleModule) {
|
||||||
|
val project = module.project
|
||||||
|
project.configurations.create(module.resolvableMetadataConfigurationName).apply {
|
||||||
|
isCanBeConsumed = false
|
||||||
|
isCanBeResolved = true
|
||||||
|
attributes.attribute(Usage.USAGE_ATTRIBUTE, project.usageByName(KotlinUsages.KOTLIN_METADATA))
|
||||||
|
module.fragments.all { fragment ->
|
||||||
|
project.addExtendsFromRelation(name, fragment.apiConfigurationName)
|
||||||
|
project.addExtendsFromRelation(name, fragment.implementationConfigurationName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun configureMetadataCompilationsAndCreateRegistry(
|
||||||
|
module: KotlinGradleModule,
|
||||||
|
metadataCompilationRegistry: MetadataCompilationRegistry
|
||||||
|
) {
|
||||||
|
val project = module.project
|
||||||
|
val metadataResolutionByFragment = mutableMapOf<KotlinGradleFragment, FragmentGranularMetadataResolver>()
|
||||||
|
module.fragments.all { fragment ->
|
||||||
|
val transformation = FragmentGranularMetadataResolver(fragment, lazy {
|
||||||
|
fragment.refinesClosure.minus(fragment).map {
|
||||||
|
metadataResolutionByFragment.getValue(it)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
metadataResolutionByFragment[fragment] = transformation
|
||||||
|
createExtractMetadataTask(project, fragment, transformation)
|
||||||
|
}
|
||||||
|
val compileAllTask = project.registerTask<DefaultTask>(lowerCamelCaseName(module.moduleClassifier, "metadataClasses"))
|
||||||
|
module.fragments.all { fragment ->
|
||||||
|
createMetadataCompilation(fragment, compileAllTask, metadataCompilationRegistry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun configureMetadataJarTask(
|
||||||
|
module: KotlinGradleModule,
|
||||||
|
registry: MetadataCompilationRegistry
|
||||||
|
) {
|
||||||
|
val project = module.project
|
||||||
|
val allMetadataJar = project.registerTask<Jar>(metadataJarName(module)) { task ->
|
||||||
|
task.archiveAppendix.set("metadata")
|
||||||
|
task.from()
|
||||||
|
}
|
||||||
|
registry.withAll { compilationData ->
|
||||||
|
allMetadataJar.configure { jar ->
|
||||||
|
jar.from(compilationData.output.allOutputs) { spec ->
|
||||||
|
spec.into(compilationData.fragment.fragmentName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun metadataJarName(module: KotlinGradleModule) =
|
||||||
|
lowerCamelCaseName(module.moduleClassifier, "metadataJar")
|
||||||
|
|
||||||
|
private fun createMetadataCompilation(
|
||||||
|
fragment: KotlinGradleFragment,
|
||||||
|
compileAllTask: TaskProvider<DefaultTask>,
|
||||||
|
metadataCompilationRegistry: MetadataCompilationRegistry
|
||||||
|
): KotlinCompilationData<out KotlinMultiplatformCommonOptions> {
|
||||||
|
val module = fragment.containingModule
|
||||||
|
val project = module.project
|
||||||
|
|
||||||
|
val metadataCompilationData =
|
||||||
|
KotlinFragmentMetadataCompilationData(
|
||||||
|
project,
|
||||||
|
fragment,
|
||||||
|
module,
|
||||||
|
compileAllTask,
|
||||||
|
metadataCompilationRegistry,
|
||||||
|
lazy {
|
||||||
|
fragment.refinesClosure.map {
|
||||||
|
FragmentResolvedMetadataProvider(
|
||||||
|
project.tasks.withType<TransformKotlinGranularMetadataForFragment>()
|
||||||
|
.named(transformFragmentMetadataTaskName(it))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
metadataCompilationRegistry.register(fragment, metadataCompilationData)
|
||||||
|
|
||||||
|
addSourcesToKotlinCompileTask(
|
||||||
|
project,
|
||||||
|
metadataCompilationData.compileKotlinTaskName,
|
||||||
|
/*FIXME*/ emptyList(),
|
||||||
|
{ fragment.kotlinSourceRoots },
|
||||||
|
lazyOf(true)
|
||||||
|
)
|
||||||
|
|
||||||
|
KotlinCommonSourceSetProcessor(
|
||||||
|
metadataCompilationData,
|
||||||
|
KotlinTasksProvider(),
|
||||||
|
project.getKotlinPluginVersion() ?: "undefined"
|
||||||
|
).run()
|
||||||
|
|
||||||
|
return metadataCompilationData
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createExtractMetadataTask(
|
||||||
|
project: Project,
|
||||||
|
fragment: KotlinGradleFragment,
|
||||||
|
transformation: FragmentGranularMetadataResolver
|
||||||
|
) {
|
||||||
|
project.tasks.register(
|
||||||
|
transformFragmentMetadataTaskName(fragment),
|
||||||
|
TransformKotlinGranularMetadataForFragment::class.java,
|
||||||
|
fragment,
|
||||||
|
transformation
|
||||||
|
).configure { task ->
|
||||||
|
task.dependsOn(Callable {
|
||||||
|
fragment.refinesClosure.mapNotNull { refined ->
|
||||||
|
if (refined !== fragment)
|
||||||
|
project.tasks.named(transformFragmentMetadataTaskName(refined))
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: use this function once more than one platform is supported
|
||||||
|
private fun disableMetadataCompilationIfNotYetSupported(
|
||||||
|
metadataCompilationData: KotlinFragmentMetadataCompilationData
|
||||||
|
) {
|
||||||
|
val fragment = metadataCompilationData.fragment
|
||||||
|
val platforms = fragment.containingModule.variantsContainingFragment(fragment).map { it.platformType }.toSet()
|
||||||
|
if (platforms != setOf(KotlinPlatformType.native) && platforms.size == 1
|
||||||
|
|| platforms == setOf(KotlinPlatformType.jvm, KotlinPlatformType.androidJvm)
|
||||||
|
) {
|
||||||
|
fragment.containingModule.project.tasks.named(metadataCompilationData.compileKotlinTaskName).configure {
|
||||||
|
it.enabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun transformFragmentMetadataTaskName(fragment: KotlinModuleFragment) =
|
||||||
|
lowerCamelCaseName("resolve", fragment.disambiguateName("Metadata"))
|
||||||
+4
-22
@@ -5,36 +5,18 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
|
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
|
||||||
|
|
||||||
import org.gradle.api.*
|
|
||||||
import org.gradle.api.file.FileCollection
|
|
||||||
import org.gradle.api.file.SourceDirectorySet
|
|
||||||
import org.gradle.api.plugins.BasePluginConvention
|
|
||||||
import org.gradle.api.tasks.TaskProvider
|
import org.gradle.api.tasks.TaskProvider
|
||||||
import org.gradle.jvm.tasks.Jar
|
import org.gradle.jvm.tasks.Jar
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
import org.jetbrains.kotlin.gradle.plugin.Kotlin2JvmSourceSetProcessor
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl
|
import org.jetbrains.kotlin.gradle.plugin.mpp.addSourcesToKotlinCompileTask
|
||||||
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.*
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||||
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
|
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
|
||||||
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
|
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
|
||||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
import org.jetbrains.kotlin.project.model.refinesClosure
|
||||||
import org.jetbrains.kotlin.project.model.*
|
|
||||||
import org.jetbrains.kotlin.project.model.utils.variantsContainingFragment
|
import org.jetbrains.kotlin.project.model.utils.variantsContainingFragment
|
||||||
import java.util.concurrent.Callable
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
//region Fragment
|
|
||||||
|
|
||||||
//endregion Fragment
|
|
||||||
|
|
||||||
//region Variant
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
open class KotlinJvmVariantFactory(module: KotlinGradleModule) :
|
open class KotlinJvmVariantFactory(module: KotlinGradleModule) :
|
||||||
AbstractKotlinGradleVariantWithRuntimeDependenciesFactory<KotlinJvmVariant>(module) {
|
AbstractKotlinGradleVariantWithRuntimeDependenciesFactory<KotlinJvmVariant>(module) {
|
||||||
override fun instantiateFragment(name: String) = KotlinJvmVariant(module, name)
|
override fun instantiateFragment(name: String) = KotlinJvmVariant(module, name)
|
||||||
|
|||||||
+83
-89
@@ -15,13 +15,13 @@ import org.gradle.api.plugins.BasePlugin
|
|||||||
import org.gradle.api.tasks.TaskProvider
|
import org.gradle.api.tasks.TaskProvider
|
||||||
import org.gradle.api.tasks.bundling.Jar
|
import org.gradle.api.tasks.bundling.Jar
|
||||||
import org.gradle.api.tasks.bundling.Zip
|
import org.gradle.api.tasks.bundling.Zip
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
import org.jetbrains.kotlin.gradle.dsl.*
|
||||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.*
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||||
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.pm20.KotlinPm20ProjectExtension
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.*
|
import org.jetbrains.kotlin.gradle.plugin.sources.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.internal.*
|
import org.jetbrains.kotlin.gradle.targets.native.internal.*
|
||||||
@@ -38,7 +38,8 @@ internal const val ALL_COMPILE_METADATA_CONFIGURATION_NAME = "allSourceSetsCompi
|
|||||||
internal const val ALL_RUNTIME_METADATA_CONFIGURATION_NAME = "allSourceSetsRuntimeDependenciesMetadata"
|
internal const val ALL_RUNTIME_METADATA_CONFIGURATION_NAME = "allSourceSetsRuntimeDependenciesMetadata"
|
||||||
|
|
||||||
internal val Project.isKotlinGranularMetadataEnabled: Boolean
|
internal val Project.isKotlinGranularMetadataEnabled: Boolean
|
||||||
get() = PropertiesProvider(rootProject).enableGranularSourceSetsMetadata == true
|
get() = project.topLevelExtension is KotlinPm20ProjectExtension ||
|
||||||
|
PropertiesProvider(rootProject).enableGranularSourceSetsMetadata == true
|
||||||
|
|
||||||
internal val Project.isCompatibilityMetadataVariantEnabled: Boolean
|
internal val Project.isCompatibilityMetadataVariantEnabled: Boolean
|
||||||
get() = PropertiesProvider(this).enableCompatibilityMetadataVariant == true
|
get() = PropertiesProvider(this).enableCompatibilityMetadataVariant == true
|
||||||
@@ -231,7 +232,7 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
|
|||||||
val generateMetadata = project.createGenerateProjectStructureMetadataTask()
|
val generateMetadata = project.createGenerateProjectStructureMetadataTask()
|
||||||
|
|
||||||
allMetadataJar.configure {
|
allMetadataJar.configure {
|
||||||
it.from(generateMetadata.map { it.resultXmlFile }) { spec ->
|
it.from(generateMetadata.map { it.resultFile }) { spec ->
|
||||||
spec.into("META-INF").rename { MULTIPLATFORM_PROJECT_METADATA_JSON_FILE_NAME }
|
spec.into("META-INF").rename { MULTIPLATFORM_PROJECT_METADATA_JSON_FILE_NAME }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -437,91 +438,28 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
|
|||||||
): FileCollection {
|
): FileCollection {
|
||||||
val project = compilation.target.project
|
val project = compilation.target.project
|
||||||
|
|
||||||
// Adjust metadata compilation to support source set hierarchies, i.e. use both the outputs of dependsOn source set compilation
|
val sourceSet = compilation.defaultSourceSet
|
||||||
// and their dependencies metadata transformed for compilation:
|
|
||||||
return project.files(
|
|
||||||
project.provider {
|
|
||||||
val sourceSet = compilation.defaultSourceSet
|
|
||||||
|
|
||||||
val transformationTaskHolders = sourceSet.withAllDependsOnSourceSets().mapNotNull { hierarchySourceSet ->
|
val dependsOnCompilationOutputs = lazy {
|
||||||
project.locateTask<TransformKotlinGranularMetadata>(transformGranularMetadataTaskName(hierarchySourceSet.name))
|
sourceSet.withAllDependsOnSourceSets().mapNotNull { hierarchySourceSet ->
|
||||||
}
|
val dependencyCompilation = project.getMetadataCompilationForSourceSet(hierarchySourceSet)
|
||||||
|
dependencyCompilation?.output?.classesDirs.takeIf { hierarchySourceSet != sourceSet }
|
||||||
val allResolutionsByComponentId: Map<ComponentIdentifier, List<MetadataDependencyResolution>> =
|
|
||||||
mutableMapOf<ComponentIdentifier, MutableList<MetadataDependencyResolution>>().apply {
|
|
||||||
transformationTaskHolders.forEach {
|
|
||||||
val resolutions = it.get().metadataDependencyResolutions
|
|
||||||
resolutions.forEach { resolution ->
|
|
||||||
getOrPut(resolution.dependency.id) { mutableListOf() }.add(resolution)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val transformedFilesByResolution: Map<MetadataDependencyResolution, FileCollection> =
|
|
||||||
transformationTaskHolders.flatMap { it.get().filesByResolution.toList() }.toMap()
|
|
||||||
|
|
||||||
val dependsOnCompilationOutputs = sourceSet.resolveAllDependsOnSourceSets().mapNotNull { hierarchySourceSet ->
|
|
||||||
val dependencyCompilation = project.getMetadataCompilationForSourceSet(hierarchySourceSet)
|
|
||||||
dependencyCompilation?.output?.classesDirs
|
|
||||||
}
|
|
||||||
|
|
||||||
val artifactView = fromFiles.incoming.artifactView { view ->
|
|
||||||
view.componentFilter { id ->
|
|
||||||
allResolutionsByComponentId[id].let { resolutions ->
|
|
||||||
resolutions == null || resolutions.any { it !is MetadataDependencyResolution.ExcludeAsUnrequested }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mutableSetOf<Any /* File | FileCollection */>().apply {
|
|
||||||
addAll(dependsOnCompilationOutputs)
|
|
||||||
artifactView.artifacts.forEach { artifact ->
|
|
||||||
val resolutions = allResolutionsByComponentId[artifact.id.componentIdentifier]
|
|
||||||
if (resolutions == null) {
|
|
||||||
add(artifact.file)
|
|
||||||
} else {
|
|
||||||
val chooseVisibleSourceSets =
|
|
||||||
resolutions.filterIsInstance<MetadataDependencyResolution.ChooseVisibleSourceSets>()
|
|
||||||
|
|
||||||
if (chooseVisibleSourceSets.isNotEmpty()) {
|
|
||||||
// Wrap the list into a FileCollection, as some older Gradle version failed to resolve the classpath
|
|
||||||
add(project.files(chooseVisibleSourceSets.map { transformedFilesByResolution.getValue(it) }))
|
|
||||||
} else if (resolutions.any { it is MetadataDependencyResolution.KeepOriginalDependency }) {
|
|
||||||
add(artifact.file)
|
|
||||||
} // else: all dependency transformations exclude this dependency as unrequested; don't add any files
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a build dependency on the granular metadata transformations of the dependency source sets
|
|
||||||
add(project.files().builtBy(transformationTaskHolders))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
/*
|
|
||||||
val transformedFilesByOriginalFiles = project.provider {
|
|
||||||
transformationTaskHolders
|
|
||||||
.flatMap { it.get().filesByOriginalFiles.toList() }
|
|
||||||
.groupBy({ it.first }, valueTransform = { it.second })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val builtBySet = mutableSetOf<FileCollection>()
|
val resolvedMetadataFilesProviders = lazy {
|
||||||
val resultFiles = project.files(Callable {
|
val transformationTaskHolders = sourceSet.withAllDependsOnSourceSets().mapNotNull { hierarchySourceSet ->
|
||||||
val originalFiles = fromFiles.toSet()
|
project.locateTask<TransformKotlinGranularMetadata>(transformGranularMetadataTaskName(hierarchySourceSet.name))
|
||||||
val filesToAdd = mutableSetOf<File>()
|
|
||||||
val filesToExclude = mutableSetOf<File>()
|
|
||||||
|
|
||||||
transformedFilesByOriginalFiles.get().forEach { (original, replacement) ->
|
|
||||||
if (original.all { it in originalFiles }) {
|
|
||||||
builtBySet.addAll(replacement)
|
|
||||||
filesToAdd += replacement.flatMap { it.files }
|
|
||||||
filesToExclude += original
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
transformationTaskHolders.map { SourceSetResolvedMetadataProvider(it) }
|
||||||
|
}
|
||||||
|
|
||||||
originalFiles - filesToExclude + filesToAdd
|
return createTransformedMetadataClasspath(
|
||||||
})
|
project,
|
||||||
return resultFiles.builtBy(builtBySet)
|
fromFiles,
|
||||||
*/
|
dependsOnCompilationOutputs,
|
||||||
|
resolvedMetadataFilesProviders
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createCommonMainElementsConfiguration(target: KotlinMetadataTarget) {
|
private fun createCommonMainElementsConfiguration(target: KotlinMetadataTarget) {
|
||||||
@@ -545,11 +483,69 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
|
|||||||
project.artifacts.add(name, project.tasks.getByName(target.legacyArtifactsTaskName))
|
project.artifacts.add(name, project.tasks.getByName(target.legacyArtifactsTaskName))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun Project.createGenerateProjectStructureMetadataTask(): TaskProvider<GenerateProjectStructureMetadata> =
|
internal fun Project.createGenerateProjectStructureMetadataTask(moduleClassifier: String? = null): TaskProvider<GenerateProjectStructureMetadata> =
|
||||||
project.registerTask("generateProjectStructureMetadata") { task ->
|
project.registerTask(lowerCamelCaseName("generate", moduleClassifier, "ProjectStructureMetadata")) { task ->
|
||||||
task.lazyKotlinProjectStructureMetadata = lazy { checkNotNull(buildKotlinProjectStructureMetadata(project)) }
|
task.lazyKotlinProjectStructureMetadata = lazy { checkNotNull(buildKotlinProjectStructureMetadata(project)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal interface ResolvedMetadataFilesProvider {
|
||||||
|
val buildDependencies: Iterable<TaskProvider<*>>
|
||||||
|
val metadataResolutions: Iterable<MetadataDependencyResolution>
|
||||||
|
val metadataFilesByResolution: Map<MetadataDependencyResolution, FileCollection>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun createTransformedMetadataClasspath(
|
||||||
|
project: Project,
|
||||||
|
fromFiles: Configuration,
|
||||||
|
parentCompiledMetadataFiles: Lazy<Iterable<FileCollection>>,
|
||||||
|
metadataResolutionProviders: Lazy<Iterable<ResolvedMetadataFilesProvider>>
|
||||||
|
): FileCollection {
|
||||||
|
return project.files(
|
||||||
|
project.provider {
|
||||||
|
val allResolutionsByComponentId: Map<ComponentIdentifier, List<MetadataDependencyResolution>> =
|
||||||
|
mutableMapOf<ComponentIdentifier, MutableList<MetadataDependencyResolution>>().apply {
|
||||||
|
metadataResolutionProviders.value.forEach {
|
||||||
|
it.metadataResolutions.forEach { resolution ->
|
||||||
|
getOrPut(resolution.dependency.id) { mutableListOf() }.add(resolution)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val transformedFilesByResolution: Map<MetadataDependencyResolution, FileCollection> =
|
||||||
|
metadataResolutionProviders.value.flatMap { it.metadataFilesByResolution.toList() }.toMap()
|
||||||
|
|
||||||
|
val artifactView = fromFiles.incoming.artifactView { view ->
|
||||||
|
view.componentFilter { id ->
|
||||||
|
allResolutionsByComponentId[id].let { resolutions ->
|
||||||
|
resolutions == null || resolutions.any { it !is MetadataDependencyResolution.ExcludeAsUnrequested }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutableSetOf<Any /* File | FileCollection */>().apply {
|
||||||
|
addAll(metadataResolutionProviders.value.map { project.files().builtBy(it.buildDependencies) })
|
||||||
|
addAll(parentCompiledMetadataFiles.value)
|
||||||
|
artifactView.artifacts.forEach { artifact ->
|
||||||
|
val resolutions = allResolutionsByComponentId[artifact.id.componentIdentifier]
|
||||||
|
if (resolutions == null) {
|
||||||
|
add(artifact.file)
|
||||||
|
} else {
|
||||||
|
val chooseVisibleSourceSets =
|
||||||
|
resolutions.filterIsInstance<MetadataDependencyResolution.ChooseVisibleSourceSets>()
|
||||||
|
|
||||||
|
if (chooseVisibleSourceSets.isNotEmpty()) {
|
||||||
|
// Wrap the list into a FileCollection, as some older Gradle version failed to resolve the classpath
|
||||||
|
add(project.files(chooseVisibleSourceSets.map { transformedFilesByResolution.getValue(it) }))
|
||||||
|
} else if (resolutions.any { it is MetadataDependencyResolution.KeepOriginalDependency }) {
|
||||||
|
add(artifact.file)
|
||||||
|
} // else: all dependency transformations exclude this dependency as unrequested; don't add any files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun isSharedNativeSourceSet(project: Project, sourceSet: KotlinSourceSet): Boolean {
|
internal fun isSharedNativeSourceSet(project: Project, sourceSet: KotlinSourceSet): Boolean {
|
||||||
@@ -560,9 +556,7 @@ internal fun isSharedNativeSourceSet(project: Project, sourceSet: KotlinSourceSe
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun dependsOnClosureWithInterCompilationDependencies(project: Project, sourceSet: KotlinSourceSet): Set<KotlinSourceSet> =
|
internal fun dependsOnClosureWithInterCompilationDependencies(project: Project, sourceSet: KotlinSourceSet): Set<KotlinSourceSet> =
|
||||||
sourceSet.getSourceSetHierarchy().toMutableSet().apply {
|
sourceSet.resolveAllDependsOnSourceSets().toMutableSet().apply {
|
||||||
/** exclude self from the results of [getSourceSetHierarchy] */
|
|
||||||
remove(sourceSet)
|
|
||||||
addAll(getVisibleSourceSetsFromAssociateCompilations(project, sourceSet))
|
addAll(getVisibleSourceSetsFromAssociateCompilations(project, sourceSet))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-1
@@ -34,6 +34,8 @@ 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.KotlinTarget
|
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinCommonCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinCommonCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinFragmentMetadataCompilationData
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.refinesClosure
|
||||||
import org.jetbrains.kotlin.gradle.utils.getValue
|
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets
|
import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets
|
||||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||||
@@ -60,7 +62,9 @@ open class KotlinCompileCommon : AbstractKotlinCompile<K2MetadataCompilerArgumen
|
|||||||
|
|
||||||
args.moduleName = this@KotlinCompileCommon.moduleName
|
args.moduleName = this@KotlinCompileCommon.moduleName
|
||||||
|
|
||||||
if ((taskData.compilation as? KotlinCommonCompilation)?.isKlibCompilation == true) {
|
if ((taskData.compilation as? KotlinCommonCompilation)?.isKlibCompilation == true ||
|
||||||
|
taskData.compilation is KotlinFragmentMetadataCompilationData
|
||||||
|
) {
|
||||||
args.expectActualLinker = true
|
args.expectActualLinker = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,6 +101,14 @@ open class KotlinCompileCommon : AbstractKotlinCompile<K2MetadataCompilerArgumen
|
|||||||
val defaultKotlinSourceSet: KotlinSourceSet = compilation.defaultSourceSet
|
val defaultKotlinSourceSet: KotlinSourceSet = compilation.defaultSourceSet
|
||||||
outputPathsFromMetadataCompilationsOf(defaultKotlinSourceSet.resolveAllDependsOnSourceSets())
|
outputPathsFromMetadataCompilationsOf(defaultKotlinSourceSet.resolveAllDependsOnSourceSets())
|
||||||
}
|
}
|
||||||
|
is KotlinFragmentMetadataCompilationData -> {
|
||||||
|
val fragment = compilation.fragment
|
||||||
|
project.files(
|
||||||
|
fragment.refinesClosure.minus(fragment).map {
|
||||||
|
compilation.metadataCompilationRegistry.byFragment(it).output.classesDirs
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
else -> error("unexpected compilation type") // FIXME support PM20 variant
|
else -> error("unexpected compilation type") // FIXME support PM20 variant
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-9
@@ -307,15 +307,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
|
|
||||||
@get:Internal // takes part in the compiler arguments
|
@get:Internal // takes part in the compiler arguments
|
||||||
val friendPaths: FileCollection = project.files(
|
val friendPaths: FileCollection = project.files(
|
||||||
project.provider {
|
project.provider { taskData.compilation.friendPaths }
|
||||||
taskData.compilation.run {
|
|
||||||
if (this !is AbstractKotlinCompilation<*>) return@run project.files() // FIXME support PM20
|
|
||||||
mutableListOf<FileCollection>().also { allCollections ->
|
|
||||||
associateWithTransitiveClosure.forEach { allCollections.add(it.output.classesDirs) }
|
|
||||||
allCollections.add(friendArtifacts)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
private val kotlinLogger by lazy { GradleKotlinLogger(logger) }
|
private val kotlinLogger by lazy { GradleKotlinLogger(logger) }
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ package org.jetbrains.kotlin.project.model
|
|||||||
// TODO think about state management: unresolved -> (known dependency graph?) ... -> completely resolved
|
// TODO think about state management: unresolved -> (known dependency graph?) ... -> completely resolved
|
||||||
// it seems to be important to learn whether or not the model is final
|
// it seems to be important to learn whether or not the model is final
|
||||||
interface ModuleDependencyResolver {
|
interface ModuleDependencyResolver {
|
||||||
fun resolveDependency(moduleDependency: KotlinModuleDependency): KotlinModule?
|
fun resolveDependency(requestingModule: KotlinModule, moduleDependency: KotlinModuleDependency): KotlinModule?
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO merge with ModuleDependencyResolver?
|
// TODO merge with ModuleDependencyResolver?
|
||||||
@@ -34,4 +34,6 @@ sealed class DependencyGraphResolution(val requestingModule: KotlinModule) {
|
|||||||
class DependencyGraphNode(
|
class DependencyGraphNode(
|
||||||
val module: KotlinModule,
|
val module: KotlinModule,
|
||||||
val dependenciesByFragment: Map<KotlinModuleFragment, Iterable<DependencyGraphNode>>
|
val dependenciesByFragment: Map<KotlinModuleFragment, Iterable<DependencyGraphNode>>
|
||||||
)
|
) {
|
||||||
|
override fun toString(): String = "node ${module}"
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@ open class KotlinAttributeKey(
|
|||||||
|
|
||||||
object KotlinPlatformTypeAttribute : KotlinAttributeKey("org.jetbrains.kotlin.platform.type") {
|
object KotlinPlatformTypeAttribute : KotlinAttributeKey("org.jetbrains.kotlin.platform.type") {
|
||||||
const val JVM = "jvm"
|
const val JVM = "jvm"
|
||||||
|
const val ANDROID_JVM = "androidJvm"
|
||||||
const val JS = "js"
|
const val JS = "js"
|
||||||
const val NATIVE = "native"
|
const val NATIVE = "native"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ interface KotlinModule {
|
|||||||
// TODO: isSynthetic?
|
// TODO: isSynthetic?
|
||||||
}
|
}
|
||||||
|
|
||||||
class BasicKotlinModule(
|
open class BasicKotlinModule(
|
||||||
override val moduleIdentifier: KotlinModuleIdentifier
|
override val moduleIdentifier: KotlinModuleIdentifier
|
||||||
) : KotlinModule {
|
) : KotlinModule {
|
||||||
override val fragments = mutableListOf<BasicKotlinModuleFragment>()
|
override val fragments = mutableListOf<BasicKotlinModuleFragment>()
|
||||||
|
|||||||
Reference in New Issue
Block a user