Fix stdlib default dependencies with Android
* In Android test-related source sets, add an implementation dependency, not an api one, because adding dependencies to the api configurations leads to warnings from AGP * Add the default stdlib dependency only to the Android main source set, as duplicating it elsewhere leads to issue with publishing the project with the `maven` plugin (duplicate conf2ScopeMappings)
This commit is contained in:
+50
-10
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.internal
|
||||
|
||||
import com.android.build.gradle.TestedExtension
|
||||
import com.android.build.gradle.api.TestVariant
|
||||
import com.android.build.gradle.api.UnitTestVariant
|
||||
import org.gradle.api.Project
|
||||
@@ -16,15 +17,15 @@ import org.gradle.api.tasks.testing.Test
|
||||
import org.gradle.api.tasks.testing.junit.JUnitOptions
|
||||
import org.gradle.api.tasks.testing.junitplatform.JUnitPlatformOptions
|
||||
import org.gradle.api.tasks.testing.testng.TestNGOptions
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.execution.KotlinAggregateExecutionSource
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationSourceSetUtil
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.getSourceSetHierarchy
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
|
||||
@@ -53,14 +54,18 @@ private fun configureDefaultVersionsResolutionStrategy(project: Project) {
|
||||
}
|
||||
|
||||
//region stdlib
|
||||
internal fun configureStdlibDefaultDependency(project: Project) {
|
||||
internal fun configureStdlibDefaultDependency(project: Project) = project.whenEvaluated {
|
||||
if (!PropertiesProvider(project).stdlibDefaultDependency)
|
||||
return
|
||||
return@whenEvaluated
|
||||
|
||||
project.kotlinExtension.sourceSets.all { kotlinSourceSet ->
|
||||
val apiConfiguration = project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, KotlinDependencyScope.API_SCOPE)
|
||||
val scope = if (isRelatedToAndroidTestSourceSet(project, kotlinSourceSet)) // AGP deprecates API configurations in test source sets
|
||||
KotlinDependencyScope.IMPLEMENTATION_SCOPE
|
||||
else KotlinDependencyScope.API_SCOPE
|
||||
|
||||
apiConfiguration.withDependencies { dependencies ->
|
||||
val scopeConfiguration = project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, scope)
|
||||
|
||||
scopeConfiguration.withDependencies { dependencies ->
|
||||
val sourceSetDependencyConfigurations =
|
||||
KotlinDependencyScope.values().map { project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, it) }
|
||||
|
||||
@@ -77,8 +82,8 @@ internal fun configureStdlibDefaultDependency(project: Project) {
|
||||
|
||||
val sourceSetStdlibPlatformType = when {
|
||||
platformTypes.isEmpty() -> KotlinPlatformType.common
|
||||
setOf(KotlinPlatformType.jvm, KotlinPlatformType.androidJvm).containsAll(platformTypes) -> KotlinPlatformType.jvm
|
||||
platformTypes.size == 1 -> platformTypes.single()
|
||||
setOf(KotlinPlatformType.jvm, KotlinPlatformType.androidJvm).containsAll(platformTypes) -> KotlinPlatformType.jvm
|
||||
else -> KotlinPlatformType.common
|
||||
}
|
||||
|
||||
@@ -88,7 +93,9 @@ internal fun configureStdlibDefaultDependency(project: Project) {
|
||||
|
||||
if (!isStdlibAddedByUser) {
|
||||
val stdlibModuleName = when (sourceSetStdlibPlatformType) {
|
||||
KotlinPlatformType.jvm, KotlinPlatformType.androidJvm -> jvmStdlibModuleForJvmCompilations(compilations)
|
||||
KotlinPlatformType.jvm -> stdlibModuleForJvmCompilations(compilations)
|
||||
KotlinPlatformType.androidJvm ->
|
||||
if (kotlinSourceSet.name == androidMainSourceSetName(project)) stdlibModuleForJvmCompilations(compilations) else null
|
||||
KotlinPlatformType.js -> "kotlin-stdlib-js"
|
||||
KotlinPlatformType.native -> null
|
||||
KotlinPlatformType.common -> // there's no platform compilation that the source set is default for
|
||||
@@ -107,9 +114,42 @@ internal fun configureStdlibDefaultDependency(project: Project) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.findAndroidTarget(): KotlinAndroidTarget? {
|
||||
val kotlinExtension = project.kotlinExtension
|
||||
return when (kotlinExtension) {
|
||||
is KotlinMultiplatformExtension -> kotlinExtension.targets.withType(KotlinAndroidTarget::class.java).single()
|
||||
is KotlinAndroidProjectExtension -> kotlinExtension.target
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun androidMainSourceSetName(project: Project): String {
|
||||
val target = project.findAndroidTarget() ?: error("No Android target found")
|
||||
return AbstractAndroidProjectHandler.kotlinSourceSetNameForAndroidSourceSet(target, "main")
|
||||
}
|
||||
|
||||
private fun isRelatedToAndroidTestSourceSet(project: Project, kotlinSourceSet: KotlinSourceSet): Boolean {
|
||||
val androidExtension = project.extensions.findByName("android") as? TestedExtension ?: return false
|
||||
val androidTarget = project.findAndroidTarget() ?: return false
|
||||
|
||||
if (androidTarget.compilations.any {
|
||||
(it.androidVariant is UnitTestVariant || it.androidVariant is TestVariant) && it.defaultSourceSet === kotlinSourceSet
|
||||
}
|
||||
) return true
|
||||
|
||||
(androidExtension.testVariants + androidExtension.unitTestVariants).forEach { variant ->
|
||||
if (variant.sourceSets.any {
|
||||
kotlinSourceSet.name == AbstractAndroidProjectHandler.kotlinSourceSetNameForAndroidSourceSet(androidTarget, it.name)
|
||||
}
|
||||
) return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private val stdlibModules = setOf("kotlin-stdlib-common", "kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8", "kotlin-stdlib-js")
|
||||
|
||||
private fun jvmStdlibModuleForJvmCompilations(compilations: Iterable<KotlinCompilation<*>>): String {
|
||||
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"
|
||||
}
|
||||
|
||||
+7
-2
@@ -735,6 +735,11 @@ class KotlinConfigurationTools internal constructor(
|
||||
)
|
||||
|
||||
abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTools: KotlinConfigurationTools) {
|
||||
companion object {
|
||||
fun kotlinSourceSetNameForAndroidSourceSet(kotlinAndroidTarget: KotlinAndroidTarget, androidSourceSetName: String) =
|
||||
lowerCamelCaseName(kotlinAndroidTarget.disambiguationClassifier, androidSourceSetName)
|
||||
}
|
||||
|
||||
protected val logger = Logging.getLogger(this.javaClass)
|
||||
|
||||
abstract fun getFlavorNames(variant: BaseVariant): List<String>
|
||||
@@ -762,7 +767,7 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool
|
||||
ext.sourceSets.all { sourceSet ->
|
||||
logger.kotlinDebug("Creating KotlinBaseSourceSet for source set $sourceSet")
|
||||
val kotlinSourceSet = project.kotlinExtension.sourceSets.maybeCreate(
|
||||
lowerCamelCaseName(kotlinAndroidTarget.disambiguationClassifier, sourceSet.name)
|
||||
kotlinSourceSetNameForAndroidSourceSet(kotlinAndroidTarget, sourceSet.name)
|
||||
).apply {
|
||||
kotlin.srcDir(project.file(project.file("src/${sourceSet.name}/kotlin")))
|
||||
kotlin.srcDirs(sourceSet.java.srcDirs)
|
||||
@@ -862,7 +867,7 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool
|
||||
* see [org.jetbrains.kotlin.gradle.plugin.AbstractAndroidProjectHandler.configureTarget]
|
||||
*/
|
||||
(project.extensions.getByName("android") as BaseExtension).sourceSets.forEach { androidSourceSet ->
|
||||
val kotlinSourceSetName = lowerCamelCaseName(kotlinAndroidTarget.disambiguationClassifier, androidSourceSet.name)
|
||||
val kotlinSourceSetName = kotlinSourceSetNameForAndroidSourceSet(kotlinAndroidTarget, androidSourceSet.name)
|
||||
project.kotlinExtension.sourceSets.findByName(kotlinSourceSetName)?.let { kotlinSourceSet ->
|
||||
addDependenciesToAndroidSourceSet(
|
||||
androidSourceSet,
|
||||
|
||||
Reference in New Issue
Block a user