[Gradle] Remove metadata dependencies transformation for runtimeOnly

Kotlin Metadata KLIBs cannot be used in runtime thus
we don't have to transform composite JARs that contain
metadata per source set for runtimeOnly dependencies scopes.

^KT-55230 Fixed
This commit is contained in:
Anton Lakotka
2022-12-02 11:37:15 +01:00
committed by Space Team
parent 5db9c2990a
commit 98678bce0a
9 changed files with 48 additions and 82 deletions
@@ -28,6 +28,7 @@ interface KotlinSourceSet : Named, HasKotlinDependencies {
val apiMetadataConfigurationName: String val apiMetadataConfigurationName: String
val implementationMetadataConfigurationName: String val implementationMetadataConfigurationName: String
val compileOnlyMetadataConfigurationName: String val compileOnlyMetadataConfigurationName: String
@Deprecated(message = "KT-55230: RuntimeOnly scope is not supported for metadata dependency transformation")
val runtimeOnlyMetadataConfigurationName: String val runtimeOnlyMetadataConfigurationName: String
override val relatedConfigurationNames: List<String> override val relatedConfigurationNames: List<String>
@@ -36,7 +37,6 @@ interface KotlinSourceSet : Named, HasKotlinDependencies {
apiMetadataConfigurationName, apiMetadataConfigurationName,
implementationMetadataConfigurationName, implementationMetadataConfigurationName,
compileOnlyMetadataConfigurationName, compileOnlyMetadataConfigurationName,
runtimeOnlyMetadataConfigurationName
) )
companion object { companion object {
@@ -12,12 +12,12 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver
import org.jetbrains.kotlin.gradle.plugin.ide.IdeaKotlinBinaryCoordinates import org.jetbrains.kotlin.gradle.plugin.ide.IdeaKotlinBinaryCoordinates
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution
import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfigurationForSourceSets
import org.jetbrains.kotlin.gradle.plugin.sources.project import org.jetbrains.kotlin.gradle.plugin.sources.project
object IdeOriginalMetadataDependencyResolver : IdeDependencyResolver { object IdeOriginalMetadataDependencyResolver : IdeDependencyResolver {
override fun resolve(sourceSet: KotlinSourceSet): Set<IdeaKotlinDependency> { override fun resolve(sourceSet: KotlinSourceSet): Set<IdeaKotlinDependency> {
val metadataDependenciesConfiguration = resolvableMetadataConfiguration(sourceSet.project, listOf(sourceSet),) val metadataDependenciesConfiguration = resolvableMetadataConfigurationForSourceSets(sourceSet.project, listOf(sourceSet))
val keptOriginalDependencyResolutionIds = sourceSet.resolveMetadata<MetadataDependencyResolution.KeepOriginalDependency>() val keptOriginalDependencyResolutionIds = sourceSet.resolveMetadata<MetadataDependencyResolution.KeepOriginalDependency>()
.map { it.dependency.id }.toSet() .map { it.dependency.id }.toSet()
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution.Choos
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
import org.jetbrains.kotlin.gradle.targets.metadata.ALL_RUNTIME_METADATA_CONFIGURATION_NAME
import org.jetbrains.kotlin.gradle.targets.metadata.dependsOnClosureWithInterCompilationDependencies import org.jetbrains.kotlin.gradle.targets.metadata.dependsOnClosureWithInterCompilationDependencies
import java.util.* import java.util.*
@@ -106,6 +105,12 @@ internal class GranularMetadataTransformation(
/** A configuration that holds the dependencies of the appropriate scope for all Kotlin source sets in the project */ /** A configuration that holds the dependencies of the appropriate scope for all Kotlin source sets in the project */
private val parentTransformations: Lazy<Iterable<GranularMetadataTransformation>> private val parentTransformations: Lazy<Iterable<GranularMetadataTransformation>>
) { ) {
init {
require(KotlinDependencyScope.RUNTIME_ONLY_SCOPE !in sourceSetRequestedScopes) {
"KT-55230: RuntimeOnly scope is not supported for metadata dependency transformation"
}
}
val metadataDependencyResolutions: Iterable<MetadataDependencyResolution> by lazy { doTransform() } val metadataDependencyResolutions: Iterable<MetadataDependencyResolution> by lazy { doTransform() }
// Keep parents of each dependency, too. We need a dependency's parent when it's an MPP's metadata module dependency: // Keep parents of each dependency, too. We need a dependency's parent when it's an MPP's metadata module dependency:
@@ -119,11 +124,8 @@ internal class GranularMetadataTransformation(
requestedDependencies(project, kotlinSourceSet, sourceSetRequestedScopes) requestedDependencies(project, kotlinSourceSet, sourceSetRequestedScopes)
} }
private val allSourceSetsConfiguration: Configuration =
commonMetadataDependenciesConfigurationForScopes(project, sourceSetRequestedScopes)
internal val configurationToResolve: Configuration by lazy { internal val configurationToResolve: Configuration by lazy {
resolvableMetadataConfiguration(project, allSourceSetsConfiguration, requestedDependencies) resolvableMetadataConfigurationForDependencies(project, requestedDependencies)
} }
private fun doTransform(): Iterable<MetadataDependencyResolution> { private fun doTransform(): Iterable<MetadataDependencyResolution> {
@@ -305,18 +307,12 @@ internal fun ResolvedComponentResult.toProjectOrNull(currentProject: Project): P
} }
} }
internal fun resolvableMetadataConfiguration( internal fun resolvableMetadataConfigurationForSourceSets(
project: Project, project: Project,
sourceSets: Iterable<KotlinSourceSet>, sourceSets: Iterable<KotlinSourceSet>,
scopes: Iterable<KotlinDependencyScope> = setOf( ): Configuration = resolvableMetadataConfigurationForDependencies(
KotlinDependencyScope.API_SCOPE,
KotlinDependencyScope.IMPLEMENTATION_SCOPE,
KotlinDependencyScope.COMPILE_ONLY_SCOPE
)
): Configuration = resolvableMetadataConfiguration(
project, project,
commonMetadataDependenciesConfigurationForScopes(project, scopes), sourceSets.flatMapTo(mutableListOf()) { requestedDependencies(project, it, KotlinDependencyScope.compileScopes) }
sourceSets.flatMapTo(mutableListOf()) { requestedDependencies(project, it, scopes) }
) )
/** If a source set is not a published source set, its dependencies are not included in [allSourceSetsConfiguration]. /** If a source set is not a published source set, its dependencies are not included in [allSourceSetsConfiguration].
@@ -324,11 +320,12 @@ internal fun resolvableMetadataConfiguration(
* we need to create a new configuration with the dependencies from both [allSourceSetsConfiguration] and the * we need to create a new configuration with the dependencies from both [allSourceSetsConfiguration] and the
* other [requestedDependencies] */ * other [requestedDependencies] */
// TODO: optimize by caching the resulting configurations? // TODO: optimize by caching the resulting configurations?
internal fun resolvableMetadataConfiguration( internal fun resolvableMetadataConfigurationForDependencies(
project: Project, project: Project,
allSourceSetsConfiguration: Configuration,
requestedDependencies: Iterable<Dependency> requestedDependencies: Iterable<Dependency>
): Configuration { ): Configuration {
val allSourceSetsConfiguration = project.configurations.getByName(ALL_COMPILE_METADATA_CONFIGURATION_NAME)
var modifiedConfiguration: Configuration? = null var modifiedConfiguration: Configuration? = null
val originalDependencies = allSourceSetsConfiguration.allDependencies val originalDependencies = allSourceSetsConfiguration.allDependencies
@@ -348,20 +345,6 @@ internal fun resolvableMetadataConfiguration(
return modifiedConfiguration ?: allSourceSetsConfiguration return modifiedConfiguration ?: allSourceSetsConfiguration
} }
/** The configuration that contains the dependencies of the corresponding scopes (and maybe others)
* from all published source sets. */
internal fun commonMetadataDependenciesConfigurationForScopes(
project: Project,
scopes: Iterable<KotlinDependencyScope>
): Configuration {
// TODO: what if 'runtimeOnly' is combined with 'compileOnly'? prohibit this or merge the two? we never do that now, though
val configurationName = if (KotlinDependencyScope.RUNTIME_ONLY_SCOPE in scopes)
ALL_RUNTIME_METADATA_CONFIGURATION_NAME
else
ALL_COMPILE_METADATA_CONFIGURATION_NAME
return project.configurations.getByName(configurationName)
}
internal fun requestedDependencies( internal fun requestedDependencies(
project: Project, project: Project,
sourceSet: KotlinSourceSet, sourceSet: KotlinSourceSet,
@@ -12,6 +12,7 @@ import org.gradle.work.NormalizeLineEndings
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.sources.KotlinDependencyScope
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope.* import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope.*
import org.jetbrains.kotlin.gradle.plugin.sources.internal import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.targets.metadata.ALL_COMPILE_METADATA_CONFIGURATION_NAME import org.jetbrains.kotlin.gradle.targets.metadata.ALL_COMPILE_METADATA_CONFIGURATION_NAME
@@ -87,7 +88,7 @@ open class MetadataDependencyTransformationTask
GranularMetadataTransformation( GranularMetadataTransformation(
project, project,
kotlinSourceSet, kotlinSourceSet,
listOf(API_SCOPE, IMPLEMENTATION_SCOPE, COMPILE_ONLY_SCOPE), KotlinDependencyScope.compileScopes,
lazy { lazy {
dependsOnClosureWithInterCompilationDependencies(kotlinSourceSet).map { dependsOnClosureWithInterCompilationDependencies(kotlinSourceSet).map {
project.tasks.withType(MetadataDependencyTransformationTask::class.java) project.tasks.withType(MetadataDependencyTransformationTask::class.java)
@@ -11,8 +11,7 @@ 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.pm20ExtensionOrNull import org.jetbrains.kotlin.gradle.dsl.pm20ExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfigurationForSourceSets
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
import org.jetbrains.kotlin.project.model.* import org.jetbrains.kotlin.project.model.*
internal fun resolvableMetadataConfiguration( internal fun resolvableMetadataConfiguration(
@@ -22,10 +21,9 @@ internal fun resolvableMetadataConfiguration(
internal fun configurationToResolveMetadataDependencies(project: Project, requestingModule: KpmModule): Configuration = internal fun configurationToResolveMetadataDependencies(project: Project, requestingModule: KpmModule): Configuration =
when { when {
project.pm20ExtensionOrNull != null -> resolvableMetadataConfiguration(requestingModule as GradleKpmModule) project.pm20ExtensionOrNull != null -> resolvableMetadataConfiguration(requestingModule as GradleKpmModule)
else -> resolvableMetadataConfiguration( else -> resolvableMetadataConfigurationForSourceSets(
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
) )
} }
@@ -54,6 +54,7 @@ abstract class DefaultKotlinSourceSet @Inject constructor(
override val compileOnlyMetadataConfigurationName: String override val compileOnlyMetadataConfigurationName: String
get() = lowerCamelCaseName(compileOnlyConfigurationName, METADATA_CONFIGURATION_NAME_SUFFIX) get() = lowerCamelCaseName(compileOnlyConfigurationName, METADATA_CONFIGURATION_NAME_SUFFIX)
@Deprecated(message = "KT-55230: RuntimeOnly scope is not supported for metadata dependency transformation")
override val runtimeOnlyMetadataConfigurationName: String override val runtimeOnlyMetadataConfigurationName: String
get() = lowerCamelCaseName(runtimeOnlyConfigurationName, METADATA_CONFIGURATION_NAME_SUFFIX) get() = lowerCamelCaseName(runtimeOnlyConfigurationName, METADATA_CONFIGURATION_NAME_SUFFIX)
@@ -143,8 +144,8 @@ abstract class DefaultKotlinSourceSet @Inject constructor(
@Suppress("unused") // Used in IDE import @Suppress("unused") // Used in IDE import
fun getDependenciesTransformation(configurationName: String): Iterable<MetadataDependencyTransformation> { fun getDependenciesTransformation(configurationName: String): Iterable<MetadataDependencyTransformation> {
val scope = KotlinDependencyScope.values().find { val scope = KotlinDependencyScope.compileScopes.find {
project.sourceSetMetadataConfigurationByScope(this, it).name == configurationName project.sourceSetMetadataConfigurationByScope(this, it)?.name == configurationName
} ?: return emptyList() } ?: return emptyList()
return getDependenciesTransformation(scope) return getDependenciesTransformation(scope)
@@ -53,12 +53,12 @@ internal fun Project.compilationDependencyConfigurationByScope(
} }
) )
internal fun Project.sourceSetMetadataConfigurationByScope(sourceSet: KotlinSourceSet, scope: KotlinDependencyScope): Configuration = internal fun Project.sourceSetMetadataConfigurationByScope(sourceSet: KotlinSourceSet, scope: KotlinDependencyScope): Configuration? {
project.configurations.getByName( val configurationName = when (scope) {
when (scope) { API_SCOPE -> sourceSet.apiMetadataConfigurationName
API_SCOPE -> sourceSet.apiMetadataConfigurationName IMPLEMENTATION_SCOPE -> sourceSet.implementationMetadataConfigurationName
IMPLEMENTATION_SCOPE -> sourceSet.implementationMetadataConfigurationName COMPILE_ONLY_SCOPE -> sourceSet.compileOnlyMetadataConfigurationName
COMPILE_ONLY_SCOPE -> sourceSet.compileOnlyMetadataConfigurationName RUNTIME_ONLY_SCOPE -> return null // KT-55230: RuntimeOnly scope is not supported for metadata dependency transformation
RUNTIME_ONLY_SCOPE -> sourceSet.runtimeOnlyMetadataConfigurationName }
} return project.configurations.getByName(configurationName)
) }
@@ -79,7 +79,6 @@ internal class DefaultKotlinSourceSetFactory(
apiConfigurationName to apiMetadataConfigurationName, apiConfigurationName to apiMetadataConfigurationName,
implementationConfigurationName to implementationMetadataConfigurationName, implementationConfigurationName to implementationMetadataConfigurationName,
compileOnlyConfigurationName to compileOnlyMetadataConfigurationName, compileOnlyConfigurationName to compileOnlyMetadataConfigurationName,
runtimeOnlyConfigurationName to runtimeOnlyMetadataConfigurationName,
null to intransitiveMetadataConfigurationName null to intransitiveMetadataConfigurationName
) )
} }
@@ -32,7 +32,6 @@ import java.util.concurrent.Callable
internal const val COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME = "commonMainMetadataElements" internal const val COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME = "commonMainMetadataElements"
internal const val ALL_COMPILE_METADATA_CONFIGURATION_NAME = "allSourceSetsCompileDependenciesMetadata" internal const val ALL_COMPILE_METADATA_CONFIGURATION_NAME = "allSourceSetsCompileDependenciesMetadata"
internal const val ALL_RUNTIME_METADATA_CONFIGURATION_NAME = "allSourceSetsRuntimeDependenciesMetadata"
internal val Project.isKotlinGranularMetadataEnabled: Boolean internal val Project.isKotlinGranularMetadataEnabled: Boolean
get() = project.pm20ExtensionOrNull != null || with(PropertiesProvider(rootProject)) { get() = project.pm20ExtensionOrNull != null || with(PropertiesProvider(rootProject)) {
@@ -80,7 +79,7 @@ class KotlinMetadataTargetConfigurator :
compileKotlinTaskProvider.configure { it.onlyIf { isCompatibilityMetadataVariantEnabled } } compileKotlinTaskProvider.configure { it.onlyIf { isCompatibilityMetadataVariantEnabled } }
} }
createMergedAllSourceSetsConfigurations(target) createAllCompileMetadataConfiguration(target)
val allMetadataJar = target.project.tasks.withType<Jar>().named(ALL_METADATA_JAR_NAME) val allMetadataJar = target.project.tasks.withType<Jar>().named(ALL_METADATA_JAR_NAME)
createMetadataCompilationsForCommonSourceSets(target, allMetadataJar) createMetadataCompilationsForCommonSourceSets(target, allMetadataJar)
@@ -271,16 +270,15 @@ class KotlinMetadataTargetConfigurator :
} }
} }
private fun createMergedAllSourceSetsConfigurations(target: KotlinMetadataTarget): Unit = with(target.project) { private fun createAllCompileMetadataConfiguration(target: KotlinMetadataTarget): Unit {
listOf(ALL_COMPILE_METADATA_CONFIGURATION_NAME, ALL_RUNTIME_METADATA_CONFIGURATION_NAME).forEach { configurationName -> val project = target.project
project.configurations.create(configurationName).apply { project.configurations.create(ALL_COMPILE_METADATA_CONFIGURATION_NAME).apply {
isCanBeConsumed = false isCanBeConsumed = false
isCanBeResolved = true isCanBeResolved = true
usesPlatformOf(target) usesPlatformOf(target)
attributes.attribute(USAGE_ATTRIBUTE, project.usageByName(KotlinUsages.KOTLIN_METADATA)) attributes.attribute(USAGE_ATTRIBUTE, project.usageByName(KotlinUsages.KOTLIN_METADATA))
attributes.attribute(CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) attributes.attribute(CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY))
}
} }
} }
@@ -361,7 +359,7 @@ class KotlinMetadataTargetConfigurator :
sourceSet: KotlinSourceSet, sourceSet: KotlinSourceSet,
isSourceSetPublished: Boolean isSourceSetPublished: Boolean
) { ) {
KotlinDependencyScope.values().forEach { scope -> KotlinDependencyScope.compileScopes.forEach { scope ->
val granularMetadataTransformation = GranularMetadataTransformation( val granularMetadataTransformation = GranularMetadataTransformation(
project, project,
sourceSet, sourceSet,
@@ -378,29 +376,15 @@ class KotlinMetadataTargetConfigurator :
val sourceSetDependencyConfigurationByScope = project.configurations.sourceSetDependencyConfigurationByScope(sourceSet, scope) val sourceSetDependencyConfigurationByScope = project.configurations.sourceSetDependencyConfigurationByScope(sourceSet, scope)
if (isSourceSetPublished) { if (isSourceSetPublished) {
if (scope != KotlinDependencyScope.COMPILE_ONLY_SCOPE) { project.addExtendsFromRelation(
project.addExtendsFromRelation( ALL_COMPILE_METADATA_CONFIGURATION_NAME,
ALL_RUNTIME_METADATA_CONFIGURATION_NAME, sourceSetDependencyConfigurationByScope.name
sourceSetDependencyConfigurationByScope.name )
)
}
if (scope != KotlinDependencyScope.RUNTIME_ONLY_SCOPE) {
project.addExtendsFromRelation(
ALL_COMPILE_METADATA_CONFIGURATION_NAME,
sourceSetDependencyConfigurationByScope.name
)
}
} }
val sourceSetMetadataConfigurationByScope = project.sourceSetMetadataConfigurationByScope(sourceSet, scope) val sourceSetMetadataConfigurationByScope = project.sourceSetMetadataConfigurationByScope(sourceSet, scope)
granularMetadataTransformation.applyToConfiguration(sourceSetMetadataConfigurationByScope) if (sourceSetMetadataConfigurationByScope != null) {
if (scope != KotlinDependencyScope.COMPILE_ONLY_SCOPE) { granularMetadataTransformation.applyToConfiguration(sourceSetMetadataConfigurationByScope)
project.addExtendsFromRelation(
sourceSetMetadataConfigurationByScope.name,
ALL_COMPILE_METADATA_CONFIGURATION_NAME
)
}
if (scope != KotlinDependencyScope.RUNTIME_ONLY_SCOPE) {
project.addExtendsFromRelation( project.addExtendsFromRelation(
sourceSetMetadataConfigurationByScope.name, sourceSetMetadataConfigurationByScope.name,
ALL_COMPILE_METADATA_CONFIGURATION_NAME ALL_COMPILE_METADATA_CONFIGURATION_NAME