[Gradle] Implement sources.jar resolvers

^KT-55289 Verification Pending
This commit is contained in:
Sebastian Sellmair
2022-12-07 08:57:07 +01:00
committed by Space Team
parent ff73e7a37a
commit bd229584e4
9 changed files with 222 additions and 29 deletions
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLI
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_PLATFORM_INTEGER_COMMONIZATION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_BY_DEFAULT
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_SUPPORT
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_IMPORT_ENABLE_SLOW_SOURCES_JAR_RESOLVER
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_NATIVE_DEPENDENCY_PROPAGATION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_STDLIB_DEFAULT_DEPENDENCY
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_STDLIB_JDK_VARIANTS_VERSION_ALIGNMENT
@@ -361,6 +362,9 @@ internal class PropertiesProvider private constructor(private val project: Proje
val enableIntransitiveMetadataConfiguration: Boolean
get() = booleanProperty("kotlin.mpp.enableIntransitiveMetadataConfiguration") ?: false
val enableSlowIdeSourcesJarResolver: Boolean
get() = booleanProperty(KOTLIN_MPP_IMPORT_ENABLE_SLOW_SOURCES_JAR_RESOLVER) ?: true
/**
* Dependencies caching strategy for all targets that support caches.
*/
@@ -505,6 +509,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
const val KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_VERSION = "kotlin.mpp.androidSourceSetLayoutVersion"
const val KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_VERSION_1_NO_WARN = "${KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_VERSION}1.nowarn"
const val KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_ANDROID_STYLE_NO_WARN = "kotlin.mpp.androidSourceSetLayoutV2AndroidStyleDirs.nowarn"
const val KOTLIN_MPP_IMPORT_ENABLE_SLOW_SOURCES_JAR_RESOLVER = "kotlin.mpp.import.enableSlowSourcesJarResolver"
const val KOTLIN_NATIVE_DEPENDENCY_PROPAGATION = "kotlin.native.enableDependencyPropagation"
const val KOTLIN_MPP_ENABLE_OPTIMISTIC_NUMBER_COMMONIZATION = "kotlin.mpp.enableOptimisticNumberCommonization"
const val KOTLIN_MPP_ENABLE_PLATFORM_INTEGER_COMMONIZATION = "kotlin.mpp.enablePlatformIntegerCommonization"
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.gradle.plugin.ide
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport.SourceSetConstraint
import org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers.*
import org.jetbrains.kotlin.gradle.plugin.ide.dependencyTransformers.IdePlatformStdlibCommonDependencyFilter
@@ -102,6 +103,36 @@ internal fun IdeMultiplatformImport(extension: KotlinProjectExtension): IdeMulti
level = IdeMultiplatformImport.DependencyResolutionLevel.Overwrite
)
registerDependencyResolver(
resolver = IdeNativeStdlibSourcesResolver,
constraint = SourceSetConstraint.isNative,
phase = IdeMultiplatformImport.DependencyResolutionPhase.SourceDependencyResolution,
level = IdeMultiplatformImport.DependencyResolutionLevel.Default
)
registerDependencyResolver(
resolver = IdePlatformSourcesResolver(),
constraint = SourceSetConstraint.isSinglePlatformType,
phase = IdeMultiplatformImport.DependencyResolutionPhase.SourceDependencyResolution,
level = IdeMultiplatformImport.DependencyResolutionLevel.Default
)
registerDependencyResolver(
resolver = IdeMetadataSourcesResolver(),
constraint = !SourceSetConstraint.isSinglePlatformType,
phase = IdeMultiplatformImport.DependencyResolutionPhase.BinaryDependencyResolution,
level = IdeMultiplatformImport.DependencyResolutionLevel.Default
)
if (extension.project.kotlinPropertiesProvider.enableSlowIdeSourcesJarResolver) {
registerDependencyResolver(
resolver = IdeSlowSourcesAndDocumentationResolver,
constraint = SourceSetConstraint.unconstrained,
phase = IdeMultiplatformImport.DependencyResolutionPhase.BinaryDependencyResolution,
level = IdeMultiplatformImport.DependencyResolutionLevel.Default
)
}
registerDependencyTransformer(
transformer = IdePlatformStdlibCommonDependencyFilter,
constraint = SourceSetConstraint.isSinglePlatformType,
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2022 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.
*/
@file:Suppress("FunctionName")
package org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers
import org.gradle.api.attributes.Category
import org.gradle.api.attributes.DocsType
import org.gradle.api.attributes.Usage
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.sources.project
import org.jetbrains.kotlin.gradle.utils.named
internal fun IdeMetadataSourcesResolver(): IdePlatformDependencyResolver = IdePlatformDependencyResolver(
binaryType = IdeaKotlinDependency.SOURCES_BINARY_TYPE,
artifactResolutionStrategy = IdePlatformDependencyResolver.ArtifactResolutionStrategy.PlatformLikeSourceSet(
setupPlatformResolutionAttributes = {
attribute(KotlinPlatformType.attribute, KotlinPlatformType.common)
attribute(Usage.USAGE_ATTRIBUTE, it.project.objects.named(Usage.JAVA_RUNTIME))
},
setupArtifactViewAttributes = {
attribute(Category.CATEGORY_ATTRIBUTE, it.project.objects.named(Category.DOCUMENTATION))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, it.project.objects.named(DocsType.SOURCES))
}
)
)
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers
import org.gradle.api.Project
import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging
import org.jetbrains.kotlin.commonizer.KonanDistribution
@@ -47,9 +48,7 @@ internal object IdeNativeStdlibDependencyResolver : IdeDependencyResolver {
IdeaKotlinResolvedBinaryDependency(
binaryType = IdeaKotlinDependency.CLASSPATH_BINARY_TYPE,
binaryFile = binaryFile,
coordinates = IdeaKotlinBinaryCoordinates(
"org.jetbrains.kotlin.native", "stdlib", sourceSet.project.konanVersion.toString(),
)
coordinates = nativeStdlibCoordinates(sourceSet.project)
).apply {
this.isNativeDistribution = true
this.isNativeStdlib = true
@@ -57,4 +56,8 @@ internal object IdeNativeStdlibDependencyResolver : IdeDependencyResolver {
}
)
}
fun nativeStdlibCoordinates(project: Project): IdeaKotlinBinaryCoordinates = IdeaKotlinBinaryCoordinates(
"org.jetbrains.kotlin.native", "stdlib", project.konanVersion.toString(),
)
}
@@ -0,0 +1,35 @@
/*
* Copyright 2010-2022 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.ide.dependencyResolvers
import org.jetbrains.kotlin.commonizer.KonanDistribution
import org.jetbrains.kotlin.commonizer.sourcesDir
import org.jetbrains.kotlin.compilerRunner.konanHome
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency
import org.jetbrains.kotlin.gradle.idea.tcs.extras.isNativeDistribution
import org.jetbrains.kotlin.gradle.idea.tcs.extras.isNativeStdlib
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver
import org.jetbrains.kotlin.gradle.plugin.sources.project
object IdeNativeStdlibSourcesResolver : IdeDependencyResolver {
override fun resolve(sourceSet: KotlinSourceSet): Set<IdeaKotlinDependency> {
return KonanDistribution(sourceSet.project.konanHome).sourcesDir.listFiles().orEmpty()
/* Ignore org.jetbrains.kotlinx. in this case */
.filter { file -> file.name.startsWith("kotlin") }
.map { file ->
IdeaKotlinResolvedBinaryDependency(
binaryType = IdeaKotlinDependency.SOURCES_BINARY_TYPE,
binaryFile = file,
coordinates = IdeNativeStdlibDependencyResolver.nativeStdlibCoordinates(sourceSet.project)
).apply {
isNativeStdlib = true
isNativeDistribution = true
}
}.toSet()
}
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers
import org.gradle.api.artifacts.ArtifactView
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.component.LibraryBinaryIdentifier
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.gradle.api.artifacts.component.ModuleComponentSelector
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmFragment
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmVariant
import org.jetbrains.kotlin.gradle.plugin.sources.*
import org.jetbrains.kotlin.gradle.targets.metadata.ALL_COMPILE_METADATA_CONFIGURATION_NAME
import org.jetbrains.kotlin.tooling.core.extrasReadWriteProperty
import org.jetbrains.kotlin.tooling.core.mutableExtrasOf
internal class IdePlatformDependencyResolver(
@@ -43,8 +45,8 @@ internal class IdePlatformDependencyResolver(
* @param setupArtifactViewAttributes: Additional attributes that will be used to create an [ArtifactView] for resolving the dependencies.
*/
data class Compilation(
internal val compilationSelector: (Set<KotlinCompilation<*>>) -> KotlinCompilation<*>? =
{ compilations -> compilations.singleOrNull { it.platformType != KotlinPlatformType.common } },
internal val compilationSelector: (KotlinSourceSet) -> KotlinCompilation<*>? =
{ sourceSet -> sourceSet.internal.compilations.singleOrNull { it.platformType != KotlinPlatformType.common } },
internal val setupArtifactViewAttributes: AttributeContainer.(sourceSet: KotlinSourceSet) -> Unit = {}
) : ArtifactResolutionStrategy()
@@ -136,7 +138,7 @@ internal class IdePlatformDependencyResolver(
}
private fun ArtifactResolutionStrategy.Compilation.createArtifactView(sourceSet: InternalKotlinSourceSet): ArtifactView? {
val compilation = compilationSelector(sourceSet.compilations) ?: return null
val compilation = compilationSelector(sourceSet) ?: return null
/*
Prevent case where this resolver was configured to resolve dependencies for a metadata compilation:
@@ -155,36 +157,46 @@ internal class IdePlatformDependencyResolver(
private fun ArtifactResolutionStrategy.PlatformLikeSourceSet.createArtifactView(sourceSet: InternalKotlinSourceSet): ArtifactView? {
if (sourceSet !is DefaultKotlinSourceSet) return null
val sourceSetCompileDependencies = sourceSet.project.configurations.detachedConfiguration()
sourceSetCompileDependencies.attributes.setupPlatformResolutionAttributes(sourceSet)
((sourceSet.getAdditionalVisibleSourceSets() + sourceSet).withDependsOnClosure).forEach { visibleSourceSet ->
sourceSetCompileDependencies.dependencies.addAll(
sourceSet.project.configurations.getByName(visibleSourceSet.apiConfigurationName).allDependencies
val platformLikeCompileDependenciesConfiguration = sourceSet.platformLikeCompileDependenciesConfiguration ?: run {
/* Create new 'platform like compileDependencies configuration */
val configuration = sourceSet.project.configurations.detachedConfiguration()
configuration.attributes.setupPlatformResolutionAttributes(sourceSet)
((sourceSet.getAdditionalVisibleSourceSets() + sourceSet).withDependsOnClosure).forEach { visibleSourceSet ->
configuration.dependencies.addAll(
sourceSet.project.configurations.getByName(visibleSourceSet.apiConfigurationName).allDependencies
)
configuration.dependencies.addAll(
sourceSet.project.configurations.getByName(visibleSourceSet.implementationConfigurationName).allDependencies
)
configuration.dependencies.addAll(
sourceSet.project.configurations.getByName(visibleSourceSet.compileOnlyConfigurationName).allDependencies
)
}
/* Ensure consistent dependency resolution result within the whole module */
configuration.shouldResolveConsistentlyWith(
sourceSet.project.configurations.getByName(ALL_COMPILE_METADATA_CONFIGURATION_NAME)
)
sourceSetCompileDependencies.dependencies.addAll(
sourceSet.project.configurations.getByName(visibleSourceSet.implementationConfigurationName).allDependencies
)
sourceSetCompileDependencies.dependencies.addAll(
sourceSet.project.configurations.getByName(visibleSourceSet.compileOnlyConfigurationName).allDependencies
)
sourceSet.platformLikeCompileDependenciesConfiguration = configuration
configuration
}
/* Ensure consistent dependency resolution result within the whole module */
sourceSetCompileDependencies.shouldResolveConsistentlyWith(
sourceSet.project.configurations.getByName(ALL_COMPILE_METADATA_CONFIGURATION_NAME)
)
return sourceSetCompileDependencies.incoming.artifactView { view ->
return platformLikeCompileDependenciesConfiguration.incoming.artifactView { view ->
view.isLenient = true
view.attributes.setupArtifactViewAttributes(sourceSet)
}
}
private companion object {
val logger: Logger = Logging.getLogger(IdePlatformDependencyResolver::class.java)
/* This special 'platform like compileDependency configurations' can be attached to the SourceSet and re-used */
var InternalKotlinSourceSet.platformLikeCompileDependenciesConfiguration: Configuration?
by extrasReadWriteProperty("platformLikeCompileDependenciesConfiguration")
}
}
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2022 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.
*/
@file:Suppress("FunctionName")
package org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers
import org.gradle.api.attributes.Category
import org.gradle.api.attributes.DocsType
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency
import org.jetbrains.kotlin.gradle.plugin.sources.project
import org.jetbrains.kotlin.gradle.utils.named
internal fun IdePlatformSourcesResolver(): IdePlatformDependencyResolver = IdePlatformDependencyResolver(
binaryType = IdeaKotlinDependency.SOURCES_BINARY_TYPE,
artifactResolutionStrategy = IdePlatformDependencyResolver.ArtifactResolutionStrategy.Compilation(
setupArtifactViewAttributes = {
attribute(Category.CATEGORY_ATTRIBUTE, it.project.objects.named(Category.DOCUMENTATION))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, it.project.objects.named(DocsType.SOURCES))
}
)
)
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2022 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.ide.dependencyResolvers
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.gradle.api.artifacts.result.ArtifactResolutionResult
import org.gradle.api.artifacts.result.ResolvedArtifactResult
import org.gradle.api.component.Artifact
import org.gradle.jvm.JvmLibrary
import org.gradle.language.base.artifact.SourcesArtifact
import org.gradle.language.java.artifact.JavadocArtifact
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver
import org.jetbrains.kotlin.gradle.plugin.ide.IdeaKotlinBinaryCoordinates
import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfigurationForSourceSets
import org.jetbrains.kotlin.gradle.plugin.sources.project
internal object IdeSlowSourcesAndDocumentationResolver : IdeDependencyResolver {
override fun resolve(sourceSet: KotlinSourceSet): Set<IdeaKotlinDependency> {
val project = sourceSet.project
val configuration = resolvableMetadataConfigurationForSourceSets(sourceSet.project, listOf(sourceSet))
val resolutionResult = project.dependencies.createArtifactResolutionQuery()
.forComponents(configuration.incoming.resolutionResult.allComponents.map { it.id })
.withArtifacts(JvmLibrary::class.java, SourcesArtifact::class.java, JavadocArtifact::class.java)
.execute()
return resolve(resolutionResult, SourcesArtifact::class.java, IdeaKotlinDependency.SOURCES_BINARY_TYPE) +
resolve(resolutionResult, JavadocArtifact::class.java, IdeaKotlinDependency.DOCUMENTATION_BINARY_TYPE)
}
fun resolve(
resolutionResult: ArtifactResolutionResult, artifactType: Class<out Artifact>, binaryType: String
): Set<IdeaKotlinResolvedBinaryDependency> {
return resolutionResult.resolvedComponents.flatMap { resolved ->
resolved.getArtifacts(artifactType)
.filterIsInstance<ResolvedArtifactResult>()
.mapNotNull { artifact ->
val id = artifact.id.componentIdentifier as? ModuleComponentIdentifier ?: return@mapNotNull null
IdeaKotlinResolvedBinaryDependency(
coordinates = IdeaKotlinBinaryCoordinates(id),
binaryType = binaryType,
binaryFile = artifact.file
)
}
}.toSet()
}
}
@@ -5,10 +5,7 @@
package org.jetbrains.kotlin.commonizer
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_COMMON_LIBS_DIR
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_KLIB_DIR
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
import org.jetbrains.kotlin.konan.library.*
import java.io.File
public data class KonanDistribution(val root: File) {
@@ -26,3 +23,6 @@ public val KonanDistribution.klibDir: File
public val KonanDistribution.platformLibsDir: File
get() = klibDir.resolve(KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR)
public val KonanDistribution.sourcesDir: File
get() = root.resolve(KONAN_DISTRIBUTION_SOURCES_DIR)