[Gradle] Reshape API surface for setting Android SourceSetTrees

^KT-58710 Verification Pending
This commit is contained in:
Sebastian Sellmair
2023-05-16 13:22:38 +02:00
committed by Space Team
parent e1d48847dc
commit 2dcaad2d03
6 changed files with 59 additions and 136 deletions
@@ -5,10 +5,8 @@
package org.jetbrains.kotlin.gradle.dsl
import org.gradle.api.provider.Property
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy.SourceSetTree
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchyBuilder
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchyDescriptor
@@ -38,9 +38,9 @@ internal object MultiplatformLayoutV2DependsOnConfigurator : KotlinAndroidSource
}
val sourceSetTree = when (variantType) {
AndroidVariantType.Main -> target.targetHierarchy.main.sourceSetTree.awaitFinalValue()
AndroidVariantType.UnitTest -> target.targetHierarchy.unitTest.sourceSetTree.awaitFinalValue()
AndroidVariantType.InstrumentedTest -> target.targetHierarchy.instrumentedTest.sourceSetTree.awaitFinalValue()
AndroidVariantType.Main -> target.mainVariant.sourceSetTree.awaitFinalValue()
AndroidVariantType.UnitTest -> target.unitTestVariant.sourceSetTree.awaitFinalValue()
AndroidVariantType.InstrumentedTest -> target.instrumentedTestVariant.sourceSetTree.awaitFinalValue()
AndroidVariantType.Unknown -> null
} ?: return@launchInStage
@@ -36,110 +36,53 @@ abstract class KotlinAndroidTarget @Inject constructor(
override val compilations: NamedDomainObjectContainer<out KotlinJvmAndroidCompilation> =
project.container(KotlinJvmAndroidCompilation::class.java)
/**
* Configure Android specific settings within the context of [KotlinTargetHierarchy].
* The difference between Android and other targets is that the build author is free to choose
* the names of compilations, whereas Android is using predefined SourceSet names.
*
* ### Default dependsOn edges
* By default, Kotlin Multiplatform will set the following default dependsOn edges:
* - `androidMain` -> `commonMain`
* - `androidUnitTest` -> `commonTest`
*
* In this default setup, SourceSets like `androidInstrumentedTest` will *not* dependOn `commonTest`.
* This API can be used to change the default behavior
*
* #### Example 1: Setting up androidInstrumentedTest -> commonTest
* This can be done by putting the 'androidInstrumentedTest' variants into the 'test' [SourceSetTree]:
* ```kotlin
* androidTarget().targetHierarchy {
* instrumentedTest.sourceSetTree.set(SourceSetTree.test)
* }
* ```
*
* #### Example 2: Setting up androidInstrumentedTest -> commonTest and removing 'unitTests' from the 'test' [SourceSetTree]
* ```kotlin
* androidTarget().targetHierarchy {
* instrumentedTest.sourceSetTree.set(SourceSetTree.test)
* unitTest.sourceSetTree.set(SourceSetTree.unitTest) // ! <- Anything *other* than 'test'
* }
* ```
*/
@ExperimentalKotlinGradlePluginApi
val targetHierarchy: KotlinAndroidTargetHierarchyDsl = KotlinAndroidTargetHierarchyDslImpl(project.objects).apply {
main.sourceSetTree.convention(SourceSetTree.main)
unitTest.sourceSetTree.convention(SourceSetTree.test)
instrumentedTest.sourceSetTree.convention(SourceSetTree.instrumentedTest)
val mainVariant: KotlinAndroidTargetVariantDsl = KotlinAndroidTargetVariantDslImpl(project.objects).apply {
sourceSetTree.convention(SourceSetTree.main)
}
/**
* Configure Android specific settings within the context of [KotlinTargetHierarchy].
* The difference between Android and other targets is that the build author is free to choose
* the names of compilations, whereas Android is using predefined SourceSet names.
*
* ### Default dependsOn edges
* By default, Kotlin Multiplatform will set the following default dependsOn edges:
* - `androidMain` -> `commonMain`
* - `androidUnitTest` -> `commonTest`
*
* In this default setup, SourceSets like `androidInstrumentedTest` will *not* dependOn `commonTest`.
* This API can be used to change the default behavior
*
* #### Example 1: Setting up androidInstrumentedTest -> commonTest
* This can be done by putting the 'androidInstrumentedTest' variants into the 'test' [SourceSetTree]:
* ```kotlin
* androidTarget().targetHierarchy {
* instrumentedTest.sourceSetTree.set(SourceSetTree.test)
* }
* ```
*
* #### Example 2: Setting up androidInstrumentedTest -> commonTest and removing 'unitTests' from the 'test' [SourceSetTree]
* ```kotlin
* androidTarget().targetHierarchy {
* instrumentedTest.sourceSetTree.set(SourceSetTree.test)
* unitTest.sourceSetTree.set(SourceSetTree.unitTest) // ! <- Anything *other* than 'test'
* }
* ```
*/
@ExperimentalKotlinGradlePluginApi
fun targetHierarchy(configure: Action<KotlinAndroidTargetHierarchyDsl>) {
configure.execute(targetHierarchy)
fun mainVariant(action: Action<KotlinAndroidTargetVariantDsl>) {
action.execute(mainVariant)
}
/**
* Configure Android specific settings within the context of [KotlinTargetHierarchy].
* The difference between Android and other targets is that the build author is free to choose
* the names of compilations, whereas Android is using predefined SourceSet names.
*
* ### Default dependsOn edges
* By default, Kotlin Multiplatform will set the following default dependsOn edges:
* - `androidMain` -> `commonMain`
* - `androidUnitTest` -> `commonTest`
*
* In this default setup, SourceSets like `androidInstrumentedTest` will *not* dependOn `commonTest`.
* This API can be used to change the default behavior
*
* #### Example 1: Setting up androidInstrumentedTest -> commonTest
* This can be done by putting the 'androidInstrumentedTest' variants into the 'test' [SourceSetTree]:
* ```kotlin
* androidTarget().targetHierarchy {
* instrumentedTest.sourceSetTree.set(SourceSetTree.test)
* }
* ```
*
* #### Example 2: Setting up androidInstrumentedTest -> commonTest and removing 'unitTests' from the 'test' [SourceSetTree]
* ```kotlin
* androidTarget().targetHierarchy {
* instrumentedTest.sourceSetTree.set(SourceSetTree.test)
* unitTest.sourceSetTree.set(SourceSetTree.unitTest) // ! <- Anything *other* than 'test'
* }
* ```
*/
@ExperimentalKotlinGradlePluginApi
fun targetHierarchy(configure: KotlinAndroidTargetHierarchyDsl.() -> Unit) {
targetHierarchy.configure()
fun mainVariant(configure: KotlinAndroidTargetVariantDsl.() -> Unit) {
mainVariant.configure()
}
@ExperimentalKotlinGradlePluginApi
val unitTestVariant: KotlinAndroidTargetVariantDsl = KotlinAndroidTargetVariantDslImpl(project.objects).apply {
sourceSetTree.convention(SourceSetTree.test)
}
@ExperimentalKotlinGradlePluginApi
fun unitTestVariant(action: Action<KotlinAndroidTargetVariantDsl>) {
action.execute(unitTestVariant)
}
@ExperimentalKotlinGradlePluginApi
fun unitTestVariant(configure: KotlinAndroidTargetVariantDsl.() -> Unit) {
unitTestVariant.configure()
}
@ExperimentalKotlinGradlePluginApi
val instrumentedTestVariant: KotlinAndroidTargetVariantDsl = KotlinAndroidTargetVariantDslImpl(project.objects).apply {
sourceSetTree.convention(SourceSetTree.instrumentedTest)
}
@ExperimentalKotlinGradlePluginApi
fun instrumentedTestVariant(action: Action<KotlinAndroidTargetVariantDsl>) {
action.execute(instrumentedTestVariant)
}
@ExperimentalKotlinGradlePluginApi
fun instrumentedTestVariant(configure: KotlinAndroidTargetVariantDsl.() -> Unit) {
instrumentedTestVariant.configure()
}
/** Names of the Android library variants that should be published from the target's project within the default publications which are
* set up if the `maven-publish` Gradle plugin is applied.
*
@@ -9,47 +9,30 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.KotlinTargetHierarchyDsl
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy.SourceSetTree
import org.jetbrains.kotlin.gradle.utils.property
@ExperimentalKotlinGradlePluginApi
interface KotlinAndroidTargetHierarchyDsl {
val main: KotlinAndroidVariantHierarchyDsl
val unitTest: KotlinAndroidVariantHierarchyDsl
val instrumentedTest: KotlinAndroidVariantHierarchyDsl
}
@ExperimentalKotlinGradlePluginApi
interface KotlinAndroidVariantHierarchyDsl {
interface KotlinAndroidTargetVariantDsl {
/**
* Configures under which [SourceSetTree] the currently configured Android Variant shall be placed.
* e.g.
*
* ```kotlin
* kotlin {
* targetHierarchy.android {
* instrumentedTest.sourceSetTree.set(SourceSetTree.test)
* androidTarget().instrumentedTest {
* sourceSetTree.set(SourceSetTree.test)
* }
* }
* ```
*
* Will ensure that all android instrumented tests (androidInstrumentedTest, androidInstrumentedTestDebug, ...)
* will be placed into the 'test' SourceSet tree (with 'commonTest' as root)
*
* See [KotlinTargetHierarchyDsl.android]
*/
val sourceSetTree: Property<SourceSetTree>
}
internal class KotlinAndroidTargetHierarchyDslImpl(objects: ObjectFactory) : KotlinAndroidTargetHierarchyDsl {
override val main: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(objects)
override val unitTest: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(objects)
override val instrumentedTest: KotlinAndroidVariantHierarchyDsl = KotlinAndroidVariantHierarchyDslImpl(objects)
}
internal class KotlinAndroidVariantHierarchyDslImpl(objects: ObjectFactory) : KotlinAndroidVariantHierarchyDsl {
internal class KotlinAndroidTargetVariantDslImpl(objects: ObjectFactory) : KotlinAndroidTargetVariantDsl {
override val sourceSetTree: Property<SourceSetTree> = objects.property()
}
}
@@ -46,10 +46,10 @@ class KotlinJvmAndroidCompilationFactory internal constructor(
private fun configureSourceSetTreeClassifier(compilation: KotlinJvmAndroidCompilation) {
compilation.sourceSetTreeClassifier = when (variant.type) {
AndroidVariantType.Main -> Property(target.targetHierarchy.main.sourceSetTree)
AndroidVariantType.UnitTest -> Property(target.targetHierarchy.unitTest.sourceSetTree)
AndroidVariantType.InstrumentedTest -> Property(target.targetHierarchy.instrumentedTest.sourceSetTree)
AndroidVariantType.Main -> Property(target.mainVariant.sourceSetTree)
AndroidVariantType.UnitTest -> Property(target.unitTestVariant.sourceSetTree)
AndroidVariantType.InstrumentedTest -> Property(target.instrumentedTestVariant.sourceSetTree)
AndroidVariantType.Unknown -> SourceSetTreeClassifier.None
}
}
}
}
@@ -15,17 +15,16 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterFinal
import org.jetbrains.kotlin.gradle.plugin.awaitFinalValue
import org.jetbrains.kotlin.gradle.plugin.currentKotlinPluginLifecycle
import org.jetbrains.kotlin.gradle.plugin.kotlinPluginLifecycle
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidVariantHierarchyDslImpl
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTargetVariantDslImpl
import org.jetbrains.kotlin.gradle.util.*
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFails
class KotlinAndroidTargetHierarchyDsl {
@Test
fun `test - module - not set`() = buildProjectWithMPP().runLifecycleAwareTest {
val dsl = KotlinAndroidVariantHierarchyDslImpl(project.objects)
val dsl = KotlinAndroidTargetVariantDslImpl(project.objects)
project.kotlinPluginLifecycle.launch {
assertNull(dsl.sourceSetTree.orNull)
assertNull(dsl.sourceSetTree.awaitFinalValue())
@@ -34,7 +33,7 @@ class KotlinAndroidTargetHierarchyDsl {
@Test
fun `test - module - can be set in users afterEvaluate`() = buildProjectWithMPP().runLifecycleAwareTest {
val dsl = KotlinAndroidVariantHierarchyDslImpl(project.objects)
val dsl = KotlinAndroidTargetVariantDslImpl(project.objects)
afterEvaluate { dsl.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("x")) }
dsl.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("-set-before-after-evaluate-"))
assertEquals("x", dsl.sourceSetTree.awaitFinalValue()?.name)
@@ -51,9 +50,9 @@ class KotlinAndroidTargetHierarchyDsl {
val kotlin = project.multiplatformExtension
project.runLifecycleAwareTest {
kotlin.androidTarget().targetHierarchy {
unitTest.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree.test)
instrumentedTest.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree.test)
kotlin.androidTarget {
unitTestVariant.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree.test)
instrumentedTestVariant.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree.test)
}
AfterFinaliseRefinesEdges.await()
@@ -73,9 +72,9 @@ class KotlinAndroidTargetHierarchyDsl {
val kotlin = project.multiplatformExtension
project.runLifecycleAwareTest {
kotlin.androidTarget().targetHierarchy {
unitTest.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("xxx"))
instrumentedTest.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("yyy"))
kotlin.androidTarget {
unitTestVariant.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("xxx"))
instrumentedTestVariant.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("yyy"))
}
kotlin.targetHierarchy.default {