Fix MPP source set dependencies missing in Android tests (KT-29343)
Add Kotlin source set dependencies to the Android source sets, and also add aggregated Kotlin compilation dependencies to the dedicated Android source sets of the Android variants. Issue #KT-29343 Fixed
This commit is contained in:
+55
-4
@@ -1,10 +1,7 @@
|
|||||||
package org.jetbrains.kotlin.gradle
|
package org.jetbrains.kotlin.gradle
|
||||||
|
|
||||||
import org.gradle.api.logging.LogLevel
|
import org.gradle.api.logging.LogLevel
|
||||||
import org.jetbrains.kotlin.gradle.util.AGPVersion
|
import org.jetbrains.kotlin.gradle.util.*
|
||||||
import org.jetbrains.kotlin.gradle.util.getFileByName
|
|
||||||
import org.jetbrains.kotlin.gradle.util.getFilesByNames
|
|
||||||
import org.jetbrains.kotlin.gradle.util.modify
|
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -211,6 +208,60 @@ open class KotlinAndroid32GradleIT : KotlinAndroid3GradleIT() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAndroidMppProductionDependenciesInTests() = with(Project("new-mpp-android", GradleVersionRequired.AtLeast("4.7"))) {
|
||||||
|
// Test the fix for KT-29343
|
||||||
|
setupWorkingDir()
|
||||||
|
|
||||||
|
gradleBuildScript("lib").appendText(
|
||||||
|
"\n" + """
|
||||||
|
kotlin.sourceSets {
|
||||||
|
commonMain {
|
||||||
|
dependencies {
|
||||||
|
implementation kotlin("stdlib-common")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
androidLibDebug {
|
||||||
|
dependencies {
|
||||||
|
implementation kotlin("reflect")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
androidLibRelease {
|
||||||
|
dependencies {
|
||||||
|
implementation kotlin("test-junit")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
val kotlinVersion = defaultBuildOptions().kotlinVersion
|
||||||
|
testResolveAllConfigurations("lib") {
|
||||||
|
assertSuccessful()
|
||||||
|
|
||||||
|
// commonMain:
|
||||||
|
assertContains(">> :lib:debugCompileClasspath --> kotlin-stdlib-common-$kotlinVersion.jar")
|
||||||
|
assertContains(">> :lib:releaseCompileClasspath --> kotlin-stdlib-common-$kotlinVersion.jar")
|
||||||
|
assertContains(">> :lib:debugAndroidTestCompileClasspath --> kotlin-stdlib-common-$kotlinVersion.jar")
|
||||||
|
assertContains(">> :lib:debugUnitTestCompileClasspath --> kotlin-stdlib-common-$kotlinVersion.jar")
|
||||||
|
assertContains(">> :lib:releaseUnitTestCompileClasspath --> kotlin-stdlib-common-$kotlinVersion.jar")
|
||||||
|
|
||||||
|
// androidLibDebug:
|
||||||
|
assertContains(">> :lib:debugCompileClasspath --> kotlin-reflect-$kotlinVersion.jar")
|
||||||
|
assertNotContains(">> :lib:releaseCompileClasspath --> kotlin-reflect-$kotlinVersion.jar")
|
||||||
|
assertContains(">> :lib:debugAndroidTestCompileClasspath --> kotlin-reflect-$kotlinVersion.jar")
|
||||||
|
assertContains(">> :lib:debugUnitTestCompileClasspath --> kotlin-reflect-$kotlinVersion.jar")
|
||||||
|
assertNotContains(">> :lib:releaseUnitTestCompileClasspath --> kotlin-reflect-$kotlinVersion.jar")
|
||||||
|
|
||||||
|
// androidLibRelease:
|
||||||
|
assertNotContains(">> :lib:debugCompileClasspath --> kotlin-test-junit-$kotlinVersion.jar")
|
||||||
|
assertContains(">> :lib:releaseCompileClasspath --> kotlin-test-junit-$kotlinVersion.jar")
|
||||||
|
assertNotContains(">> :lib:debugAndroidTestCompileClasspath --> kotlin-test-junit-$kotlinVersion.jar")
|
||||||
|
assertNotContains(">> :lib:debugUnitTestCompileClasspath --> kotlin-test-junit-$kotlinVersion.jar")
|
||||||
|
assertContains(">> :lib:releaseUnitTestCompileClasspath --> kotlin-test-junit-$kotlinVersion.jar")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCustomAttributesInAndroidTargets() = with(Project("new-mpp-android", GradleVersionRequired.AtLeast("5.0"))) {
|
fun testCustomAttributesInAndroidTargets() = with(Project("new-mpp-android", GradleVersionRequired.AtLeast("5.0"))) {
|
||||||
// Test the fix for KT-27714
|
// Test the fix for KT-27714
|
||||||
|
|||||||
+81
@@ -2,6 +2,7 @@ package org.jetbrains.kotlin.gradle.plugin
|
|||||||
|
|
||||||
import com.android.build.gradle.BaseExtension
|
import com.android.build.gradle.BaseExtension
|
||||||
import com.android.build.gradle.BasePlugin
|
import com.android.build.gradle.BasePlugin
|
||||||
|
import com.android.build.gradle.api.AndroidSourceSet
|
||||||
import com.android.build.gradle.api.BaseVariant
|
import com.android.build.gradle.api.BaseVariant
|
||||||
import com.android.builder.model.SourceProvider
|
import com.android.builder.model.SourceProvider
|
||||||
import groovy.lang.Closure
|
import groovy.lang.Closure
|
||||||
@@ -794,6 +795,86 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
|
|||||||
applySubplugins(project, compilation, variant, subpluginEnvironment)
|
applySubplugins(project, compilation, variant, subpluginEnvironment)
|
||||||
}
|
}
|
||||||
checkAndroidAnnotationProcessorDependencyUsage(project)
|
checkAndroidAnnotationProcessorDependencyUsage(project)
|
||||||
|
|
||||||
|
addKotlinDependenciesToAndroidSourceSets(project, kotlinAndroidTarget)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Android variants have their configurations extendsFrom relation set up in a way that only some of the configurations of the
|
||||||
|
* variants propagate the dependencies from production variants to test ones. To make this dependency propagation work for the Kotlin
|
||||||
|
* source set dependencies as well, we need to add them to the Android source sets' api/implementation-like configurations,
|
||||||
|
* not just the classpath-like configurations of the variants.
|
||||||
|
*/
|
||||||
|
private fun addKotlinDependenciesToAndroidSourceSets(
|
||||||
|
project: Project,
|
||||||
|
kotlinAndroidTarget: KotlinAndroidTarget
|
||||||
|
) {
|
||||||
|
fun addDependenciesToAndroidSourceSet(
|
||||||
|
androidSourceSet: AndroidSourceSet,
|
||||||
|
apiConfigurationName: String,
|
||||||
|
implementationConfigurationName: String,
|
||||||
|
compileOnlyConfigurationName: String,
|
||||||
|
runtimeOnlyConfigurationName: String
|
||||||
|
) {
|
||||||
|
project.addExtendsFromRelation(androidSourceSet.apiConfigurationName, apiConfigurationName)
|
||||||
|
project.addExtendsFromRelation(androidSourceSet.implementationConfigurationName, implementationConfigurationName)
|
||||||
|
project.addExtendsFromRelation(androidSourceSet.compileOnlyConfigurationName, compileOnlyConfigurationName)
|
||||||
|
project.addExtendsFromRelation(androidSourceSet.runtimeOnlyConfigurationName, runtimeOnlyConfigurationName)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** First, just add the dependencies from Kotlin source sets created for the Android source sets,
|
||||||
|
* see [org.jetbrains.kotlin.gradle.plugin.AbstractAndroidProjectHandler.configureTarget]
|
||||||
|
*/
|
||||||
|
(project.extensions.getByName("android") as BaseExtension).sourceSets.forEach { androidSourceSet ->
|
||||||
|
val kotlinSourceSetName = lowerCamelCaseName(kotlinAndroidTarget.disambiguationClassifier, androidSourceSet.name)
|
||||||
|
project.kotlinExtension.sourceSets.findByName(kotlinSourceSetName)?.let { kotlinSourceSet ->
|
||||||
|
addDependenciesToAndroidSourceSet(
|
||||||
|
androidSourceSet,
|
||||||
|
kotlinSourceSet.apiConfigurationName,
|
||||||
|
kotlinSourceSet.implementationConfigurationName,
|
||||||
|
kotlinSourceSet.compileOnlyConfigurationName,
|
||||||
|
kotlinSourceSet.runtimeOnlyConfigurationName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then also add the Kotlin compilation dependencies (which include the dependencies from all source sets that
|
||||||
|
// take part in the compilation) to Android source sets that are only included into a single variant corresponding
|
||||||
|
// to that compilation. This is needed in order for the dependencies to get propagated to
|
||||||
|
// the test variants; see KT-29343;
|
||||||
|
|
||||||
|
// Trivial mapping of Android variants to Android source set names is impossible here,
|
||||||
|
// because some variants have their dedicated source sets with mismatching names,
|
||||||
|
// e.g. variant 'fooBarDebugAndroidTest' <-> source set 'androidTestFooBarDebug'
|
||||||
|
|
||||||
|
// In single-platform projects, the Kotlin compilations already reference the Android plugin's configurations by the names,
|
||||||
|
// so there are no such separate things as the configurations of the compilations, and there's no need to setup the
|
||||||
|
// extendsFrom relationship.
|
||||||
|
if (kotlinAndroidTarget.disambiguationClassifier != null) {
|
||||||
|
|
||||||
|
val sourceSetToVariants = mutableMapOf<AndroidSourceSet, MutableList<V>>().apply {
|
||||||
|
forEachVariant(project) { variant ->
|
||||||
|
for (sourceSet in getSourceProviders(variant)) {
|
||||||
|
val androidSourceSet = sourceSet as? AndroidSourceSet ?: continue
|
||||||
|
getOrPut(androidSourceSet) { mutableListOf() }.add(variant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((androidSourceSet, variants) in sourceSetToVariants) {
|
||||||
|
val variant = variants.singleOrNull()
|
||||||
|
?: continue // skip source sets that are included in multiple Android variants
|
||||||
|
|
||||||
|
val compilation = kotlinAndroidTarget.compilations.getByName(getVariantName(variant))
|
||||||
|
addDependenciesToAndroidSourceSet(
|
||||||
|
androidSourceSet,
|
||||||
|
compilation.apiConfigurationName,
|
||||||
|
compilation.implementationConfigurationName,
|
||||||
|
compilation.compileOnlyConfigurationName,
|
||||||
|
compilation.runtimeOnlyConfigurationName
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user