Build source sets hierarchy in Android projects

Instead of simply adding all Kotlin source sets participating in an
Android compilation, as was appropriate until we introduced the
dependsOn relation, we should now build a proper source sets hierarchy.
This commit is contained in:
Sergey Igushkin
2018-09-12 19:08:41 +03:00
parent 43a4b84b44
commit 269410d7aa
3 changed files with 64 additions and 11 deletions
@@ -8,6 +8,7 @@ import org.jetbrains.kotlin.gradle.util.modify
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.junit.Test
import java.io.File
import kotlin.test.assertEquals
class KotlinAndroidGradleIT : AbstractKotlinAndroidGradleTests(androidGradlePluginVersion = "2.3.0") {
@@ -22,6 +23,36 @@ class KotlinAndroid32GradleIT : KotlinAndroid3GradleIT(androidGradlePluginVersio
@Test
fun testAndroidWithNewMppApp() = with(Project("new-mpp-android")) {
build("printSourceSetDependsOnRelations") {
val dependsOnReportRegex = "(\\w+?) dependsOn \\[(.*?)]".toRegex()
val dependsOnRelations = dependsOnReportRegex
.findAll(output)
.associate { it.groupValues[1] to it.groupValues[2].split(", ").toSet() }
val expectedDependsOnRelations = listOf(
"androidLibMain" to setOf("commonMain"),
"androidLibDebug" to setOf("commonMain", "androidLibMain"), // compilation
"androidLibRelease" to setOf("commonMain", "androidLibMain"), // compilation
"androidLibTest" to setOf("commonTest"),
"androidLibTestDebug" to setOf("commonTest"),
"androidLibTestRelease" to setOf("commonTest"),
"androidLibAndroidTestDebug" to setOf("commonTest"),
"androidLibAndroidTest" to setOf("commonTest"),
"androidLibDebugAndroidTest" to setOf("commonTest", "androidLibAndroidTest", "androidLibAndroidTestDebug"), // compilation
"androidLibDebugUnitTest" to setOf("commonTest", "androidLibTest", "androidLibTestDebug"), // compilation
"androidLibReleaseUnitTest" to setOf("commonTest", "androidLibTest", "androidLibTestRelease") // compilation
)
for ((sourceSetName, expectedDependsOn) in expectedDependsOnRelations) {
assertEquals(
expectedDependsOn,
dependsOnRelations[sourceSetName],
"source set $sourceSetName should depend on $expectedDependsOn"
)
}
}
build("assemble", "compileDebugUnitTestJavaWithJavac") {
assertSuccessful()
@@ -51,4 +51,12 @@ kotlin {
fromPreset(presets.jvm, 'jvmLib')
fromPreset(presets.js, 'jsLib')
}
}
task printSourceSetDependsOnRelations {
doFirst {
kotlin.sourceSets.each { sourceSet ->
println sourceSet.name + " dependsOn " + sourceSet.dependsOn.collect { it.name }
}
}
}
@@ -718,17 +718,9 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
kotlinTask.destinationDir = File(project.buildDir, "tmp/kotlin-classes/$variantDataName")
kotlinTask.description = "Compiles the $variantDataName kotlin."
// Register the source only after the task is created, because tne task is required for that:
compilation.source(defaultSourceSet)
configureSources(kotlinTask, variantData, compilation)
// In MPPs, add the common main Kotlin sources to non-test variants, the common test sources to test variants
val commonSourceSetName = if (getTestedVariantData(variantData) == null)
KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME else
KotlinSourceSet.COMMON_TEST_SOURCE_SET_NAME
project.kotlinExtension.sourceSets.findByName(commonSourceSetName)?.let {
compilation.source(it)
}
// Register the source only after the task is created and source set relations are built:
compilation.source(defaultSourceSet)
wireKotlinTasks(project, compilation, androidPlugin, androidExt, variantData, javaTask, kotlinTask)
}
@@ -752,10 +744,32 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
private fun configureSources(compileTask: AbstractCompile, variantData: V, compilation: KotlinCompilation?) {
val logger = compileTask.project.logger
val commonSourceSet = compilation?.run {
target.project.kotlinExtension.sourceSets.run {
// In MPPs, add the common main Kotlin sources to dependsOn of non-test variants, the common test sources to test variants
val commonSourceSetName = if (getTestedVariantData(variantData) == null)
KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME else
KotlinSourceSet.COMMON_TEST_SOURCE_SET_NAME
findByName(commonSourceSetName)?.also { common ->
getByName(compilation.defaultSourceSetName).dependsOn(common)
}
}
}
val defaultSourceSet = compilation?.run {
target.project.kotlinExtension.sourceSets.getByName(defaultSourceSetName)
}
for (provider in getSourceProviders(variantData)) {
val kotlinSourceSet = provider.getConvention(KOTLIN_DSL_NAME) as? KotlinSourceSet ?: continue
if (compilation != null) {
compilation.source(kotlinSourceSet)
if (commonSourceSet != null) {
kotlinSourceSet.dependsOn(commonSourceSet)
}
if (kotlinSourceSet != defaultSourceSet) {
defaultSourceSet!!.dependsOn(kotlinSourceSet)
}
} else {
compileTask.source(kotlinSourceSet.kotlin)
}