diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt index bde30e11d09..3421e246486 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt @@ -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 } } + } } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/PublishingIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/PublishingIT.kt index 67d61baee6a..3994e34729f 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/PublishingIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/PublishingIT.kt @@ -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 { "kotlin-stdlib-jdk8" in it } + 1 + val stdlibVersionLineNumber = pomLines.indexOfFirst { "kotlin-stdlib" in it } + 1 val versionLine = pomLines[stdlibVersionLineNumber] assertTrue { "${buildOptions.kotlinVersion}" in versionLine } } diff --git a/libraries/tools/kotlin-gradle-plugin/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin/build.gradle.kts index c147c3466fd..1e1880535e2 100644 --- a/libraries/tools/kotlin-gradle-plugin/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin/build.gradle.kts @@ -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")) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt index 9051d3922b0..5f188723923 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt @@ -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() - .filter { it.group == KOTLIN_MODULE_GROUP && it.version.isNullOrEmpty() } - .forEach { it.version { constraint -> constraint.require(coreLibrariesVersion) } } - } +private fun ConfigurationContainer.configureDefaultVersionsResolutionStrategy( + coreLibrariesVersion: Provider +) = all { configuration -> + configuration.withDependencies { dependencySet -> + dependencySet + .withType() + .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 +) { - 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 ) { - 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 ) { - 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, + 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, + 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 { + // 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>): 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() 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() { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt index 5c839f24b7a..dec55697e09 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt @@ -365,7 +365,7 @@ internal fun requestedDependencies( ): Iterable { fun collectScopedDependenciesFromSourceSet(sourceSet: KotlinSourceSet): Set = requestedScopes.flatMapTo(mutableSetOf()) { scope -> - project.sourceSetDependencyConfigurationByScope(sourceSet, scope).incoming.dependencies + project.configurations.sourceSetDependencyConfigurationByScope(sourceSet, scope).incoming.dependencies } val otherContributingSourceSets = dependsOnClosureWithInterCompilationDependencies(project, sourceSet) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt index ce03e5331e0..a355c5ff7d5 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt @@ -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() diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/Publishing.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/Publishing.kt index d733cf983c6..b10471def28 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/Publishing.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/Publishing.kt @@ -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() } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinDependencyScope.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinDependencyScope.kt index 17a568a7d66..402df591927 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinDependencyScope.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinDependencyScope.kt @@ -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<*>, diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt index 229e01ec2de..34f1c202413 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt @@ -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) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt index e20b819e38f..b0e046b4dac 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt @@ -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 ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptConfig.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptConfig.kt index 170aae4b52d..5b0da729815 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptConfig.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptConfig.kt @@ -199,7 +199,7 @@ internal class KaptWithoutKotlincConfig : KaptConfig { 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 )