Add kotlin-stdlib dependency in a lazy way

^KT-41642 In Progress
This commit is contained in:
Yahor Berdnikau
2022-02-12 10:28:32 +01:00
committed by Space
parent 895a8ff149
commit 4441033134
11 changed files with 247 additions and 163 deletions
@@ -30,7 +30,7 @@ class KotlinSpecificDependenciesIT : KGPBaseTest() {
fun testStdlibByDefaultJvm(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
removeDependencies(buildGradle)
checkTaskCompileClasspath("compileKotlin", listOf("kotlin-stdlib" /*any of them*/))
checkTaskCompileClasspath("compileKotlin", listOf("kotlin-stdlib"))
}
}
@@ -66,7 +66,7 @@ class KotlinSpecificDependenciesIT : KGPBaseTest() {
checkTaskCompileClasspath(
"compileKotlinJs",
listOf("kotlin-stdlib"),
listOf("kotlin-stdlib-js"),
isBuildGradleKts = true
)
}
@@ -115,7 +115,7 @@ class KotlinSpecificDependenciesIT : KGPBaseTest() {
buildJdk = jdkVersion.location
) {
removeDependencies(buildGradle)
checkTaskCompileClasspath("compileDebugKotlin", listOf("kotlin-stdlib" /*any of them*/))
checkTaskCompileClasspath("compileDebugKotlin", listOf("kotlin-stdlib"))
}
}
@@ -192,28 +192,6 @@ class KotlinSpecificDependenciesIT : KGPBaseTest() {
}
}
@DisplayName("Adds kotlin-stdlib variant based on jvmTarget value")
@JvmGradlePluginTests
@GradleTest
fun testStdlibBasedOnJdk(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
removeDependencies(buildGradle)
buildGradle.modify { "$it\nkotlin.target.compilations[\"main\"].kotlinOptions { jvmTarget = \"1.6\" }" }
val version = defaultBuildOptions.kotlinVersion
checkTaskCompileClasspath(
"compileKotlin",
listOf("kotlin-stdlib-$version"),
listOf("kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8")
)
buildGradle.modify { "$it\nkotlin.target.compilations[\"main\"].kotlinOptions { jvmTarget = \"11\" }" }
checkTaskCompileClasspath(
"compileKotlin",
listOf("kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8"),
)
}
}
@JvmGradlePluginTests
@DisplayName("Explicit kotlin-stdlib version overrides default one")
@GradleTest
@@ -224,19 +202,54 @@ class KotlinSpecificDependenciesIT : KGPBaseTest() {
"""
kotlin.target.compilations["main"].kotlinOptions.jvmTarget = "1.8"
dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib") }
dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") }
""".trimIndent()
)
// Check that the explicit stdlib overrides the plugin's choice of stdlib-jdk8
checkTaskCompileClasspath(
"compileKotlin",
listOf("kotlin-stdlib-${defaultBuildOptions.kotlinVersion}"),
listOf("kotlin-stdlib-jdk8")
listOf("kotlin-stdlib-jdk8-${defaultBuildOptions.kotlinVersion}")
)
}
}
@JvmGradlePluginTests
@DisplayName("KT-41642: adding stdlib should not resolve dependencies eagerly")
@GradleTest
fun testStdlibEagerDependencies(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
// Disabling auto-adding kotlin.test dependencies
gradleProperties.appendText(
"""
kotlin.test.infer.jvm.variant=false
""".trimIndent()
)
buildGradle.appendText(
//language=Groovy
"""
configurations.each { config ->
config.dependencies.addAllLater(
project.objects.listProperty(Dependency.class).value(
project.provider {
throw new Throwable("Dependency resolved in ${'$'}{config.name}!")
}
)
)
}
""".trimIndent()
)
build("help") {
assertOutputDoesNotContain("Dependency resolved in")
}
}
}
@AndroidGradlePluginTests
@DisplayName("Android: Kotlin test single dependency in unit tests")
@GradleAndroidTest
@@ -497,7 +510,7 @@ class KotlinSpecificDependenciesIT : KGPBaseTest() {
checkTaskCompileClasspath(
"compileTestKotlin",
listOf("kotlin-stdlib-", "kotlin-reflect-", "kotlin-test-").map { it + customVersion }
listOf("kotlin-stdlib-jdk8-", "kotlin-reflect-", "kotlin-test-").map { it + customVersion }
)
}
}
@@ -620,11 +633,15 @@ class KotlinSpecificDependenciesIT : KGPBaseTest() {
""".trimIndent()
)
build("${subproject?.prependIndent(":").orEmpty()}:$printingTaskName") {
build("${subproject?.prependIndent(":").orEmpty()}:$printingTaskName", forceOutput = true) {
val itemsLine = output.lines().single { "###$printingTaskName" in it }.substringAfter(printingTaskName)
val items = itemsLine.removeSurrounding("[", "]").split(", ").toSet()
checkAnyItemsContains.forEach { pattern -> assertTrue { items.any { pattern in it } } }
checkNoItemContains.forEach { pattern -> assertFalse { items.any { pattern in it } } }
checkAnyItemsContains.forEach { pattern ->
assertTrue("Dependencies does not contain $pattern") { items.any { pattern in it } }
}
checkNoItemContains.forEach { pattern ->
assertFalse("Dependencies contain $pattern") { items.any { pattern in it } }
}
}
}
@@ -106,7 +106,7 @@ class PublishingIT : KGPBaseTest() {
) {
assertTasksExecuted(":compileKotlin", ":compileTestKotlin")
val pomLines = projectPath.resolve("build/publications/myLibrary/pom-default.xml").readLines()
val stdlibVersionLineNumber = pomLines.indexOfFirst { "<artifactId>kotlin-stdlib-jdk8</artifactId>" in it } + 1
val stdlibVersionLineNumber = pomLines.indexOfFirst { "<artifactId>kotlin-stdlib</artifactId>" in it } + 1
val versionLine = pomLines[stdlibVersionLineNumber]
assertTrue { "<version>${buildOptions.kotlinVersion}</version>" in versionLine }
}
@@ -96,6 +96,9 @@ dependencies {
functionalTestImplementation(project(":kotlin-gradle-plugin-kpm-android"))
functionalTestImplementation(project(":kotlin-tooling-metadata"))
functionalTestImplementation(testFixtures(project(":kotlin-gradle-plugin-idea")))
functionalTestImplementation("com.github.gundy:semver4j:0.16.4:nodeps") {
exclude(group = "*")
}
}
testCompileOnly(project(":compiler"))
@@ -11,6 +11,8 @@ import org.gradle.api.InvalidUserDataException
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.artifacts.*
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.testing.AbstractTestTask
import org.gradle.api.tasks.testing.Test
import org.gradle.api.tasks.testing.junit.JUnitOptions
@@ -32,40 +34,60 @@ import org.jetbrains.kotlin.gradle.plugin.sources.android.androidSourceSetInfoOr
import org.jetbrains.kotlin.gradle.plugin.sources.dependsOnClosure
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
import org.jetbrains.kotlin.gradle.plugin.sources.withDependsOnClosure
import org.jetbrains.kotlin.gradle.targets.js.npm.SemVer
import org.jetbrains.kotlin.gradle.targets.jvm.JvmCompilationsTestRunSource
import org.jetbrains.kotlin.gradle.tasks.locateTask
import org.jetbrains.kotlin.gradle.testing.KotlinTaskTestRun
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.gradle.utils.providerWithLazyConvention
import org.jetbrains.kotlin.gradle.utils.withType
internal const val KOTLIN_MODULE_GROUP = "org.jetbrains.kotlin"
internal const val KOTLIN_COMPILER_EMBEDDABLE = "kotlin-compiler-embeddable"
internal const val PLATFORM_INTEGERS_SUPPORT_LIBRARY = "platform-integers"
internal fun customizeKotlinDependencies(project: Project) {
configureStdlibDefaultDependency(project)
if (project.topLevelExtension is KotlinProjectExtension) { // TODO: extend this logic to PM20
val topLevelExtension = project.topLevelExtension
val coreLibrariesVersion = project.objects.providerWithLazyConvention {
topLevelExtension.coreLibrariesVersion
}
if (PropertiesProvider(project).stdlibDefaultDependency)
project.configureStdlibDefaultDependency(topLevelExtension, coreLibrariesVersion)
if (topLevelExtension is KotlinProjectExtension) { // TODO: extend this logic to PM20
configureKotlinTestDependency(project)
}
configureDefaultVersionsResolutionStrategy(project)
project.configurations.configureDefaultVersionsResolutionStrategy(
coreLibrariesVersion
)
excludeStdlibAndKotlinTestCommonFromPlatformCompilations(project)
}
private fun configureDefaultVersionsResolutionStrategy(project: Project) {
project.configurations.all { configuration ->
// Use the API introduced in Gradle 4.4 to modify the dependencies directly before they are resolved:
configuration.withDependencies { dependencySet ->
val coreLibrariesVersion = project.topLevelExtension.coreLibrariesVersion
dependencySet.filterIsInstance<ExternalDependency>()
.filter { it.group == KOTLIN_MODULE_GROUP && it.version.isNullOrEmpty() }
.forEach { it.version { constraint -> constraint.require(coreLibrariesVersion) } }
}
private fun ConfigurationContainer.configureDefaultVersionsResolutionStrategy(
coreLibrariesVersion: Provider<String>
) = all { configuration ->
configuration.withDependencies { dependencySet ->
dependencySet
.withType<ExternalDependency>()
.configureEach { dependency ->
if (dependency.group == KOTLIN_MODULE_GROUP &&
dependency.version.isNullOrEmpty()
) {
dependency.version {
it.require(coreLibrariesVersion.get())
}
}
}
}
}
private fun excludeStdlibAndKotlinTestCommonFromPlatformCompilations(project: Project) {
val multiplatformExtension = project.multiplatformExtensionOrNull ?: return
multiplatformExtension.targets.matching { it !is KotlinMetadataTarget }.all {
multiplatformExtension.targets.matching { it !is KotlinMetadataTarget }.configureEach {
it.excludeStdlibAndKotlinTestCommonFromPlatformCompilations()
}
}
@@ -97,134 +119,162 @@ private fun KotlinTarget.excludeStdlibAndKotlinTestCommonFromPlatformCompilation
}
//region stdlib
internal fun configureStdlibDefaultDependency(project: Project) = with(project) {
if (!PropertiesProvider(project).stdlibDefaultDependency)
return
private fun Project.configureStdlibDefaultDependency(
topLevelExtension: KotlinTopLevelExtension,
coreLibrariesVersion: Provider<String>
) {
val scopesToHandleConfigurations = listOf(KotlinDependencyScope.API_SCOPE, KotlinDependencyScope.IMPLEMENTATION_SCOPE)
val extension = topLevelExtension
when {
project.hasKpmModel -> addStdlibToKpmProject(project)
extension is KotlinProjectExtension -> {
extension.sourceSets.all { kotlinSourceSet ->
scopesToHandleConfigurations.forEach { scope ->
val scopeConfiguration = project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, scope)
project.tryWithDependenciesIfUnresolved(scopeConfiguration) { dependencies ->
val scopeToAddStdlibDependency =
if (isRelatedToAndroidTestSourceSet(kotlinSourceSet)
) // AGP deprecates API configurations in test source sets
KotlinDependencyScope.IMPLEMENTATION_SCOPE
else KotlinDependencyScope.API_SCOPE
if (scope != scopeToAddStdlibDependency)
return@tryWithDependenciesIfUnresolved
chooseAndAddStdlibDependency(project, kotlinSourceSet, dependencies)
}
}
project.hasKpmModel -> addStdlibToKpmProject(project, coreLibrariesVersion)
topLevelExtension is KotlinSingleTargetExtension<*> -> topLevelExtension
.target
.addStdlibDependency(configurations, dependencies, coreLibrariesVersion)
topLevelExtension is KotlinMultiplatformExtension -> topLevelExtension
.targets
.configureEach { target ->
target.addStdlibDependency(configurations, dependencies, coreLibrariesVersion)
}
}
}
}
private fun addStdlibToKpmProject(
project: Project
project: Project,
coreLibrariesVersion: Provider<String>
) {
project.kpmModules.matching { it.name == GradleKpmModule.MAIN_MODULE_NAME }.configureEach { main ->
main.fragments.matching { it.name == GradleKpmFragment.COMMON_FRAGMENT_NAME }.configureEach { common ->
project.kpmModules.named(GradleKpmModule.MAIN_MODULE_NAME) { main ->
main.fragments.named(GradleKpmFragment.COMMON_FRAGMENT_NAME) { common ->
common.dependencies {
api(project.kotlinDependency("kotlin-stdlib-common", project.topLevelExtension.coreLibrariesVersion))
api(project.dependencies.kotlinDependency("kotlin-stdlib-common", coreLibrariesVersion.get()))
}
}
main.variants.configureEach { variant ->
val dependency = when (variant.platformType) {
val dependencyHandler = project.dependencies
val stdlibModule = when (variant.platformType) {
KotlinPlatformType.common -> error("variants are not expected to be common")
KotlinPlatformType.jvm -> "kotlin-stdlib" // TODO get JDK from JVM variants
KotlinPlatformType.jvm -> chooseStdlibJvmDependency(coreLibrariesVersion)
KotlinPlatformType.js -> "kotlin-stdlib-js"
KotlinPlatformType.wasm -> "kotlin-stdlib-wasm"
KotlinPlatformType.androidJvm -> null // TODO: expect support on the AGP side?
KotlinPlatformType.native -> null
}
if (dependency != null) {
if (stdlibModule != null) {
variant.dependencies {
api(project.kotlinDependency(dependency, project.topLevelExtension.coreLibrariesVersion))
api(dependencyHandler.kotlinDependency(stdlibModule, coreLibrariesVersion.get()))
}
}
}
}
}
private fun chooseAndAddStdlibDependency(
project: Project,
kotlinSourceSet: KotlinSourceSet,
dependencies: DependencySet
private fun KotlinTarget.addStdlibDependency(
configurations: ConfigurationContainer,
dependencies: DependencyHandler,
coreLibrariesVersion: Provider<String>
) {
val sourceSetDependencyConfigurations =
KotlinDependencyScope.values().map { project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, it) }
compilations.configureEach { compilation ->
compilation.allKotlinSourceSets.forEach { kotlinSourceSet ->
val scope = if (compilation.isTest() ||
(this is KotlinAndroidTarget &&
kotlinSourceSet.isRelatedToAndroidTestSourceSet()
)
) {
KotlinDependencyScope.IMPLEMENTATION_SCOPE
} else {
KotlinDependencyScope.API_SCOPE
}
val scopeConfiguration = configurations
.sourceSetDependencyConfigurationByScope(kotlinSourceSet, scope)
val hierarchySourceSetsDependencyConfigurations = kotlinSourceSet.dependsOnClosure.flatMap { hierarchySourceSet ->
KotlinDependencyScope.values().map { scope ->
project.sourceSetDependencyConfigurationByScope(hierarchySourceSet, scope)
scopeConfiguration.withDependencies { dependencySet ->
// Check if stdlib is directly added to SourceSet
if (isStdlibAddedByUser(configurations, stdlibModules, kotlinSourceSet)) return@withDependencies
val stdlibModule = compilation
.platformType
.stdlibPlatformType(coreLibrariesVersion, this, kotlinSourceSet)
?: return@withDependencies
// Check if stdlib module is added to SourceSets hierarchy
if (
isStdlibAddedByUser(
configurations,
setOf(stdlibModule),
*kotlinSourceSet.dependsOnClosure.toTypedArray()
)
) return@withDependencies
dependencySet.addLater(
coreLibrariesVersion.map {
dependencies.kotlinDependency(stdlibModule, it)
}
)
}
}
}
val compilations = CompilationSourceSetUtil.compilationsBySourceSets(project).getValue(kotlinSourceSet)
.filter { it.target !is KotlinMetadataTarget }
if (compilations.isEmpty())
// source set doesn't take part in any compilation; prohibit this in the future; also, this caused KT-40559 in Android libraries
return
val platformTypes = compilations.mapTo(mutableSetOf()) { it.platformType }
val sourceSetStdlibPlatformType = when {
platformTypes.size == 1 -> platformTypes.single()
setOf(KotlinPlatformType.jvm, KotlinPlatformType.androidJvm).containsAll(platformTypes) -> KotlinPlatformType.jvm
else -> KotlinPlatformType.common
}
val isStdlibAddedByUser = sourceSetDependencyConfigurations
.flatMap { it.allNonProjectDependencies() }
.any { dependency -> dependency.group == KOTLIN_MODULE_GROUP && dependency.name in stdlibModules }
if (!isStdlibAddedByUser) {
val stdlibModuleName = when (sourceSetStdlibPlatformType) {
KotlinPlatformType.jvm -> stdlibModuleForJvmCompilations(compilations)
KotlinPlatformType.androidJvm ->
if (kotlinSourceSet.androidSourceSetInfoOrNull?.androidSourceSetName == AndroidBaseSourceSetName.Main.name)
stdlibModuleForJvmCompilations(compilations) else null
KotlinPlatformType.js -> "kotlin-stdlib-js"
KotlinPlatformType.wasm -> "kotlin-stdlib-wasm"
KotlinPlatformType.native -> null
KotlinPlatformType.common -> // there's no platform compilation that the source set is default for
"kotlin-stdlib-common"
}
// If the exact same module is added in the source sets hierarchy, possibly even with a different scope, we don't add it
val moduleAddedInHierarchy = hierarchySourceSetsDependencyConfigurations.any {
it.allNonProjectDependencies()
.any { dependency -> dependency.group == KOTLIN_MODULE_GROUP && dependency.name == stdlibModuleName }
}
if (stdlibModuleName != null && !moduleAddedInHierarchy)
dependencies.add(project.kotlinDependency(stdlibModuleName, project.kotlinExtension.coreLibrariesVersion))
}
}
private fun isRelatedToAndroidTestSourceSet(kotlinSourceSet: KotlinSourceSet): Boolean {
val androidVariantType = kotlinSourceSet.androidSourceSetInfoOrNull?.androidVariantType ?: return false
return androidVariantType in setOf(AndroidVariantType.UnitTest, AndroidVariantType.InstrumentedTest)
private fun isStdlibAddedByUser(
configurations: ConfigurationContainer,
stdlibModules: Set<String>,
vararg sourceSets: KotlinSourceSet
): Boolean {
return sourceSets
.asSequence()
.flatMap { sourceSet ->
KotlinDependencyScope.values().map { scope ->
configurations.sourceSetDependencyConfigurationByScope(sourceSet, scope)
}.asSequence()
}
.flatMap { it.allNonProjectDependencies().asSequence() }
.any { dependency ->
dependency.group == KOTLIN_MODULE_GROUP && dependency.name in stdlibModules
}
}
private fun KotlinPlatformType.stdlibPlatformType(
coreLibrariesVersion: Provider<String>,
kotlinTarget: KotlinTarget,
kotlinSourceSet: KotlinSourceSet
): String? = when (this) {
KotlinPlatformType.jvm -> chooseStdlibJvmDependency(coreLibrariesVersion)
KotlinPlatformType.androidJvm -> {
if (kotlinTarget is KotlinAndroidTarget &&
kotlinSourceSet.androidSourceSetInfoOrNull?.androidSourceSetName == AndroidBaseSourceSetName.Main.name
) {
chooseStdlibJvmDependency(coreLibrariesVersion)
} else {
null
}
}
KotlinPlatformType.js -> "kotlin-stdlib-js"
KotlinPlatformType.wasm -> "kotlin-stdlib-wasm"
KotlinPlatformType.native -> null
KotlinPlatformType.common -> // there's no platform compilation that the source set is default for
"kotlin-stdlib-common"
}
private val kotlin180Version = SemVer(1.toBigInteger(), 8.toBigInteger(), 0.toBigInteger())
private fun chooseStdlibJvmDependency(
coreLibrariesVersion: Provider<String>
): String {
// Current 'SemVer.satisfies' release always returns `false` for any "-SNAPSHOT" version.
return if (SemVer.from(coreLibrariesVersion.get()) < kotlin180Version) {
"kotlin-stdlib-jdk8"
} else {
"kotlin-stdlib"
}
}
private val androidTestVariants = setOf(AndroidVariantType.UnitTest, AndroidVariantType.InstrumentedTest)
private fun KotlinSourceSet.isRelatedToAndroidTestSourceSet(): Boolean {
val androidVariant = androidSourceSetInfoOrNull?.androidVariantType ?: return false
return androidVariant in androidTestVariants
}
private val stdlibModules = setOf("kotlin-stdlib-common", "kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8", "kotlin-stdlib-js")
private fun stdlibModuleForJvmCompilations(compilations: Iterable<KotlinCompilation<*>>): String {
val jvmTargets = compilations.map { (it.kotlinOptions as KotlinJvmOptions).jvmTarget }
return if ("1.6" in jvmTargets) "kotlin-stdlib" else "kotlin-stdlib-jdk8"
}
//endregion
//region kotlin-test
@@ -246,7 +296,7 @@ internal fun configureKotlinTestDependency(project: Project) {
val versionOrNullBySourceSet = mutableMapOf<KotlinSourceSet, String?>()
project.kotlinExtension.sourceSets.all { kotlinSourceSet ->
val configuration = project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, scope)
val configuration = project.configurations.sourceSetDependencyConfigurationByScope(kotlinSourceSet, scope)
var finalizingDependencies = false
configuration.nonProjectDependencies().matching(::isKotlinTestRootDependency).apply {
@@ -272,7 +322,7 @@ internal fun configureKotlinTestDependency(project: Project) {
if (!isAtLeast1_5(effectiveVersion)) continue
val clarifyCapability = kotlinTestCapabilityForJvmSourceSet(project, kotlinSourceSet) ?: continue
val clarifiedDependency =
(project.kotlinDependency(KOTLIN_TEST_ROOT_MODULE_NAME, version) as ExternalDependency).apply {
(project.dependencies.kotlinDependency(KOTLIN_TEST_ROOT_MODULE_NAME, version) as ExternalDependency).apply {
if (version == null) {
version { constraint -> constraint.require(project.kotlinExtension.coreLibrariesVersion) }
}
@@ -356,8 +406,8 @@ private fun KotlinTargetWithTests<*, *>.findTestRunsByCompilation(byCompilation:
}
//endregion
internal fun Project.kotlinDependency(moduleName: String, versionOrNull: String?) =
project.dependencies.create("$KOTLIN_MODULE_GROUP:$moduleName${versionOrNull?.prependIndent(":").orEmpty()}")
internal fun DependencyHandler.kotlinDependency(moduleName: String, versionOrNull: String?) =
create("$KOTLIN_MODULE_GROUP:$moduleName${versionOrNull?.prependIndent(":").orEmpty()}")
private fun Project.tryWithDependenciesIfUnresolved(configuration: Configuration, action: (DependencySet) -> Unit) {
fun reportAlreadyResolved() {
@@ -365,7 +365,7 @@ internal fun requestedDependencies(
): Iterable<Dependency> {
fun collectScopedDependenciesFromSourceSet(sourceSet: KotlinSourceSet): Set<Dependency> =
requestedScopes.flatMapTo(mutableSetOf()) { scope ->
project.sourceSetDependencyConfigurationByScope(sourceSet, scope).incoming.dependencies
project.configurations.sourceSetDependencyConfigurationByScope(sourceSet, scope).incoming.dependencies
}
val otherContributingSourceSets = dependsOnClosureWithInterCompilationDependencies(project, sourceSet)
@@ -179,7 +179,7 @@ private fun buildKotlinProjectStructureMetadata(extension: KotlinMultiplatformEx
else listOf(sourceSet)
val sourceSetExportedDependencies = scopes.flatMap { scope ->
sourceSetsToIncludeDependencies.flatMap { hierarchySourceSet ->
project.sourceSetDependencyConfigurationByScope(hierarchySourceSet, scope).allDependencies.toList()
project.configurations.sourceSetDependencyConfigurationByScope(hierarchySourceSet, scope).allDependencies.toList()
}
}
sourceSet.name to sourceSetExportedDependencies.map { ModuleIds.fromDependency(it) }.toSet()
@@ -136,7 +136,10 @@ private fun dependenciesForPomRewriting(target: AbstractKotlinTarget): Provider<
val project = target.project
// Only the commonMain API dependencies can be published for consumers who can't read Gradle project metadata
val commonMainApi = project.sourceSetDependencyConfigurationByScope(commonMain, KotlinDependencyScope.API_SCOPE)
val commonMainApi = project.configurations.sourceSetDependencyConfigurationByScope(
commonMain,
KotlinDependencyScope.API_SCOPE
)
val commonMainDependencies = commonMainApi.allDependencies
commonMainDependencies.map { ModuleCoordinates(it.group, it.name, it.version) }.toSet()
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.plugin.sources
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ConfigurationContainer
import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
@@ -23,19 +24,21 @@ internal enum class KotlinDependencyScope(val scopeName: String) {
RUNTIME_ONLY_SCOPE(RUNTIME_ONLY);
companion object {
val compileScopes = listOf(KotlinDependencyScope.API_SCOPE, KotlinDependencyScope.IMPLEMENTATION_SCOPE, KotlinDependencyScope.COMPILE_ONLY_SCOPE)
val compileScopes = listOf(API_SCOPE, IMPLEMENTATION_SCOPE, COMPILE_ONLY_SCOPE)
}
}
internal fun Project.sourceSetDependencyConfigurationByScope(sourceSet: HasKotlinDependencies, scope: KotlinDependencyScope): Configuration =
project.configurations.getByName(
when (scope) {
API_SCOPE -> sourceSet.apiConfigurationName
IMPLEMENTATION_SCOPE -> sourceSet.implementationConfigurationName
COMPILE_ONLY_SCOPE -> sourceSet.compileOnlyConfigurationName
RUNTIME_ONLY_SCOPE -> sourceSet.runtimeOnlyConfigurationName
}
)
internal fun ConfigurationContainer.sourceSetDependencyConfigurationByScope(
kotlinDependenciesContainer: HasKotlinDependencies,
scope: KotlinDependencyScope
): Configuration = getByName(
when (scope) {
API_SCOPE -> kotlinDependenciesContainer.apiConfigurationName
IMPLEMENTATION_SCOPE -> kotlinDependenciesContainer.implementationConfigurationName
COMPILE_ONLY_SCOPE -> kotlinDependenciesContainer.compileOnlyConfigurationName
RUNTIME_ONLY_SCOPE -> kotlinDependenciesContainer.runtimeOnlyConfigurationName
}
)
internal fun Project.compilationDependencyConfigurationByScope(
compilation: KotlinCompilation<*>,
@@ -182,7 +182,7 @@ internal class KotlinCompilationNpmResolver(
)
all.extendsFrom(compilationConfiguration)
compilation.allKotlinSourceSets.forEach { sourceSet ->
val sourceSetConfiguration = project.sourceSetDependencyConfigurationByScope(sourceSet, scope)
val sourceSetConfiguration = project.configurations.sourceSetDependencyConfigurationByScope(sourceSet, scope)
all.extendsFrom(sourceSetConfiguration)
}
}
@@ -248,7 +248,12 @@ class KotlinMetadataTargetConfigurator :
val apiElementsConfiguration = configurations.getByName(target.apiElementsConfigurationName)
// With the metadata target, we publish all API dependencies of all the published source sets together:
apiElementsConfiguration.extendsFrom(sourceSetDependencyConfigurationByScope(sourceSet, KotlinDependencyScope.API_SCOPE))
apiElementsConfiguration.extendsFrom(
configurations.sourceSetDependencyConfigurationByScope(
sourceSet,
KotlinDependencyScope.API_SCOPE
)
)
/** For Kotlin/Native-shared source sets, we also add the implementation dependencies to apiElements, because Kotlin/Native
* can't have any implementation dependencies, all dependencies used for compilation must be shipped along with the klib.
@@ -260,7 +265,10 @@ class KotlinMetadataTargetConfigurator :
if (isSharedNativeCompilation) {
sourceSet.withDependsOnClosure.forEach { hierarchySourceSet ->
apiElementsConfiguration.extendsFrom(
sourceSetDependencyConfigurationByScope(hierarchySourceSet, KotlinDependencyScope.IMPLEMENTATION_SCOPE)
configurations.sourceSetDependencyConfigurationByScope(
hierarchySourceSet,
KotlinDependencyScope.IMPLEMENTATION_SCOPE
)
)
}
}
@@ -368,7 +376,7 @@ class KotlinMetadataTargetConfigurator :
if (sourceSet is DefaultKotlinSourceSet)
sourceSet.dependencyTransformations[scope] = granularMetadataTransformation
val sourceSetDependencyConfigurationByScope = project.sourceSetDependencyConfigurationByScope(sourceSet, scope)
val sourceSetDependencyConfigurationByScope = project.configurations.sourceSetDependencyConfigurationByScope(sourceSet, scope)
if (isSourceSetPublished) {
if (scope != KotlinDependencyScope.COMPILE_ONLY_SCOPE) {
@@ -470,7 +478,7 @@ class KotlinMetadataTargetConfigurator :
attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target))
attributes.attribute(CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY))
val commonMainApiConfiguration = project.sourceSetDependencyConfigurationByScope(
val commonMainApiConfiguration = project.configurations.sourceSetDependencyConfigurationByScope(
project.kotlinExtension.sourceSets.getByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME),
KotlinDependencyScope.API_SCOPE
)
@@ -199,7 +199,7 @@ internal class KaptWithoutKotlincConfig : KaptConfig<KaptWithoutKotlincTask> {
val kaptDependency = "org.jetbrains.kotlin:kotlin-annotation-processing-gradle:${project.getKotlinPluginVersion()}"
listOf(
project.dependencies.create(kaptDependency),
project.kotlinDependency(
project.dependencies.kotlinDependency(
"kotlin-stdlib",
project.topLevelExtension.coreLibrariesVersion
)