[Gradle][KT-53342] AndroidCompilationDetails/MultiplatformAndroidSourceSetLayoutV2: Select proper defaultSourceSetName

This commit is contained in:
sebastian.sellmair
2022-08-03 13:04:24 +02:00
committed by Space
parent f68c05c1fb
commit 03dab74d47
5 changed files with 130 additions and 3 deletions
@@ -0,0 +1,21 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.testbase.*
import org.junit.jupiter.api.DisplayName
@MppGradlePluginTests
@DisplayName("Multiplatform Build Reproducibility")
class MultiplatformAndroidSourceSetLayoutV2IT : KGPBaseTest() {
@GradleAndroidTest
@AndroidTestVersions(minVersion = "7.0.4")
fun testProjectWithFlavors(gradleVersion: GradleVersion, agpVersion: String, jdkVersion: JdkVersions.ProvidedJdk) {
val buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion)
}
}
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.internal.KotlinCompilationsModuleGroups
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.*
import org.jetbrains.kotlin.gradle.plugin.sources.android.kotlinAndroidSourceSetLayout
import org.jetbrains.kotlin.gradle.plugin.sources.defaultSourceSetLanguageSettingsChecker
import org.jetbrains.kotlin.gradle.plugin.sources.dependsOnClosure
import org.jetbrains.kotlin.gradle.plugin.sources.getVisibleSourceSetsFromAssociateCompilations
@@ -523,6 +524,10 @@ class AndroidCompilationDetails(
override val friendArtifacts: FileCollection
get() = target.project.files(super.friendArtifacts, compilation.testedVariantArtifacts)
override val defaultSourceSetName: String by lazy {
project.kotlinAndroidSourceSetLayout.naming.defaultKotlinSourceSetName(this) ?: super.defaultSourceSetName
}
/*
* Example of how multiplatform dependencies from common would get to Android test classpath:
* commonMainImplementation -> androidDebugImplementation -> debugImplementation -> debugAndroidTestCompileClasspath
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.gradle.plugin.sources.android
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.AndroidCompilationDetails
internal interface KotlinAndroidSourceSetNaming {
@@ -30,6 +31,14 @@ internal interface KotlinAndroidSourceSetNaming {
type: AndroidVariantType
): String
/**
* Returns the name of the default KotlinSourceSet for a given Android compilation.
* Returns `null`, if this naming schema does not know about it. In this case, the
* 'default' defaultSourceSetName will be constructed by the compilation.
*/
fun defaultKotlinSourceSetName(compilation: AndroidCompilationDetails): String? = null
/**
* Always capable of creating the [KotlinSourceSet]'s name based upon the disambiguationClassifier and androidSourceSetName alone.
*/
@@ -5,9 +5,13 @@
package org.jetbrains.kotlin.gradle.plugin.sources.android
import org.gradle.api.logging.Logging
import org.jetbrains.kotlin.gradle.plugin.mpp.AndroidCompilationDetails
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
internal object MultiplatformLayoutV2KotlinAndroidSourceSetNaming : KotlinAndroidSourceSetNaming {
private val logger = Logging.getLogger(this::class.java)
private val AndroidBaseSourceSetName.kotlinName
get() = when (this) {
AndroidBaseSourceSetName.Main -> "main"
@@ -31,6 +35,24 @@ internal object MultiplatformLayoutV2KotlinAndroidSourceSetNaming : KotlinAndroi
return lowerCamelCaseName(disambiguationClassifier, replaceAndroidBaseSourceSetName(androidSourceSetName, type))
}
override fun defaultKotlinSourceSetName(compilation: AndroidCompilationDetails): String? {
val kotlinSourceSetName: String? = run {
val baseSourceSetName = compilation.androidVariant.type.androidBaseSourceSetName ?: return@run null
val androidSourceSetName = lowerCamelCaseName(
baseSourceSetName.takeIf { it != AndroidBaseSourceSetName.Main }?.name,
compilation.androidVariant.flavorName,
compilation.androidVariant.buildType.name
)
val androidSourceSet = compilation.androidVariant.sourceSets.find { it.name == androidSourceSetName } ?: return@run null
compilation.project.findKotlinSourceSet(androidSourceSet)?.name
}
if (kotlinSourceSetName == null) {
logger.warn("Can't determine 'defaultKotlinSourceSet' for android compilation: ${compilation.androidVariant.name}")
}
return kotlinSourceSetName
}
private fun replaceAndroidBaseSourceSetName(
androidSourceSetName: String,
type: AndroidVariantType
@@ -14,14 +14,14 @@ import org.gradle.api.internal.project.ProjectInternal
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.kotlin.gradle.applyMultiplatformPlugin
import org.jetbrains.kotlin.gradle.plugin.forEachVariant
import org.jetbrains.kotlin.gradle.plugin.sources.android.androidTest
import org.jetbrains.kotlin.gradle.plugin.sources.android.main
import org.jetbrains.kotlin.gradle.plugin.sources.android.test
import org.jetbrains.kotlin.gradle.plugin.mpp.AndroidCompilationDetails
import org.jetbrains.kotlin.gradle.plugin.sources.android.*
import org.jetbrains.kotlin.gradle.setMultiplatformAndroidSourceSetLayoutVersion
import org.jetbrains.kotlin.gradle.utils.androidExtension
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
class MultiplatformAndroidSourceSetLayoutV2Test {
@@ -243,4 +243,74 @@ class MultiplatformAndroidSourceSetLayoutV2Test {
project.evaluate()
assertEquals(project.file("custom.xml"), android.sourceSets.main.manifest.srcFile)
}
@Test
fun `test - defaultKotlinSourceSetName - is determined for all compilations`() {
kotlin.android()
android.flavorDimensions.add("market")
android.flavorDimensions.add("price")
android.productFlavors.create("german").dimension = "market"
android.productFlavors.create("usa").dimension = "market"
android.productFlavors.create("paid").dimension = "price"
android.productFlavors.create("free").dimension = "price"
project.evaluate()
kotlin.android().compilations.all { compilation ->
val compilationDetails = compilation.compilationDetails as AndroidCompilationDetails
val defaultKotlinSourceSetName = multiplatformAndroidSourceSetLayoutV2.naming.defaultKotlinSourceSetName(compilationDetails)
assertNotNull(
defaultKotlinSourceSetName,
"Expected non-null 'defaultKotlinSourceSetName' for compilation ${compilationDetails.compilation.name}"
)
val kotlinSourceSet = kotlin.sourceSets.getByName(defaultKotlinSourceSetName)
assertEquals(
setOf(compilation.androidVariant.name), kotlinSourceSet.androidSourceSetInfo.androidVariantNames,
"Expected KotlinSourceSet ${kotlinSourceSet.name} to only mention androidVariant ${compilation.androidVariant.name}"
)
}
}
@Test
fun `test - defaultKotlinSourceSetName`() {
kotlin.android()
android.flavorDimensions.add("market")
android.flavorDimensions.add("price")
android.productFlavors.create("german").dimension = "market"
android.productFlavors.create("usa").dimension = "market"
android.productFlavors.create("paid").dimension = "price"
android.productFlavors.create("free").dimension = "price"
project.evaluate()
assertEquals(
"androidGermanFreeDebug",
kotlin.android().compilations.getByName("germanFreeDebug").defaultSourceSet.name
)
assertEquals(
"androidUsaFreeDebug",
kotlin.android().compilations.getByName("usaFreeDebug").defaultSourceSet.name
)
assertEquals(
"androidGermanPaidRelease",
kotlin.android().compilations.getByName("germanPaidRelease").defaultSourceSet.name
)
assertEquals(
"androidUsaPaidRelease",
kotlin.android().compilations.getByName("usaPaidRelease").defaultSourceSet.name
)
assertEquals(
"androidUnitTestGermanFreeDebug",
kotlin.android().compilations.getByName("germanFreeDebugUnitTest").defaultSourceSet.name
)
assertEquals(
"androidInstrumentedTestGermanFreeDebug",
kotlin.android().compilations.getByName("germanFreeDebugAndroidTest").defaultSourceSet.name
)
}
}