[Gradle] Implement SourceSetTreeClassifier API
- This new API will be configurable for 'External Kotlin Targets'
- This change also moves targetHierarchy.android {} into the androidTarget
to avoid potential confusion around the KGP managed AndroidTarget vs
the Google implementation.
KT-58710
This commit is contained in:
committed by
Space Team
parent
dbfa8d4c29
commit
ff7e4f7986
@@ -142,16 +142,6 @@ public abstract interface class org/jetbrains/kotlin/gradle/dsl/KaptJavacOption
|
||||
public abstract fun option (Ljava/lang/Object;Ljava/lang/Object;)V
|
||||
}
|
||||
|
||||
public abstract interface class org/jetbrains/kotlin/gradle/dsl/KotlinAndroidTargetHierarchyDsl {
|
||||
public abstract fun getInstrumentedTest ()Lorg/jetbrains/kotlin/gradle/dsl/KotlinAndroidVariantHierarchyDsl;
|
||||
public abstract fun getMain ()Lorg/jetbrains/kotlin/gradle/dsl/KotlinAndroidVariantHierarchyDsl;
|
||||
public abstract fun getUnitTest ()Lorg/jetbrains/kotlin/gradle/dsl/KotlinAndroidVariantHierarchyDsl;
|
||||
}
|
||||
|
||||
public abstract interface class org/jetbrains/kotlin/gradle/dsl/KotlinAndroidVariantHierarchyDsl {
|
||||
public abstract fun getSourceSetTree ()Lorg/gradle/api/provider/Property;
|
||||
}
|
||||
|
||||
public abstract interface class org/jetbrains/kotlin/gradle/dsl/KotlinArtifact : org/gradle/api/Named, org/gradle/api/plugins/ExtensionAware {
|
||||
public abstract fun getArtifactName ()Ljava/lang/String;
|
||||
public abstract fun getModules ()Ljava/util/Set;
|
||||
@@ -530,11 +520,9 @@ public abstract interface class org/jetbrains/kotlin/gradle/dsl/KotlinNativeXCFr
|
||||
}
|
||||
|
||||
public abstract interface class org/jetbrains/kotlin/gradle/dsl/KotlinTargetHierarchyDsl {
|
||||
public abstract fun android (Lkotlin/jvm/functions/Function1;)V
|
||||
public abstract fun apply (Lorg/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchyDescriptor;Lkotlin/jvm/functions/Function1;)V
|
||||
public abstract fun custom (Lkotlin/jvm/functions/Function1;)V
|
||||
public abstract fun default (Lkotlin/jvm/functions/Function1;)V
|
||||
public abstract fun getAndroid ()Lorg/jetbrains/kotlin/gradle/dsl/KotlinAndroidTargetHierarchyDsl;
|
||||
}
|
||||
|
||||
public final class org/jetbrains/kotlin/gradle/dsl/KotlinTargetHierarchyDsl$DefaultImpls {
|
||||
@@ -1105,6 +1093,7 @@ public abstract interface class org/jetbrains/kotlin/gradle/plugin/KotlinTargetH
|
||||
public abstract fun withAndroidNativeArm64 ()V
|
||||
public abstract fun withAndroidNativeX64 ()V
|
||||
public abstract fun withAndroidNativeX86 ()V
|
||||
public abstract fun withAndroidTarget ()V
|
||||
public abstract fun withApple ()V
|
||||
public abstract fun withCompilations (Lkotlin/jvm/functions/Function1;)V
|
||||
public abstract fun withIos ()V
|
||||
|
||||
-68
@@ -170,72 +170,4 @@ interface KotlinTargetHierarchyDsl {
|
||||
* ```
|
||||
*/
|
||||
fun custom(describe: KotlinTargetHierarchyBuilder.Root.() -> Unit)
|
||||
|
||||
/**
|
||||
* 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
|
||||
* targetHierarchy.android {
|
||||
* instrumentedTest.sourceSetTree.set(SourceSetTree.test)
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* #### Example 2: Setting up androidInstrumentedTest -> commonTest and removing 'unitTests' from the 'test' [SourceSetTree]
|
||||
* ```kotlin
|
||||
* targetHierarchy.android {
|
||||
* instrumentedTest.sourceSetTree.set(SourceSetTree.test)
|
||||
* unitTest.sourceSetTree.set(SourceSetTree.unitTest) // ! <- Anything *other* than 'test'
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@ExperimentalKotlinGradlePluginApi
|
||||
fun android(configure: KotlinAndroidTargetHierarchyDsl.() -> Unit)
|
||||
|
||||
/**
|
||||
* See [android]
|
||||
*/
|
||||
@ExperimentalKotlinGradlePluginApi
|
||||
val android: KotlinAndroidTargetHierarchyDsl
|
||||
}
|
||||
|
||||
|
||||
@ExperimentalKotlinGradlePluginApi
|
||||
interface KotlinAndroidTargetHierarchyDsl {
|
||||
val main: KotlinAndroidVariantHierarchyDsl
|
||||
val unitTest: KotlinAndroidVariantHierarchyDsl
|
||||
val instrumentedTest: KotlinAndroidVariantHierarchyDsl
|
||||
}
|
||||
|
||||
@ExperimentalKotlinGradlePluginApi
|
||||
interface KotlinAndroidVariantHierarchyDsl {
|
||||
/**
|
||||
* Configures under which [SourceSetTree] the currently configured Android Variant shall be placed.
|
||||
* e.g.
|
||||
*
|
||||
* ```kotlin
|
||||
* kotlin {
|
||||
* targetHierarchy.android {
|
||||
* 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>
|
||||
}
|
||||
@@ -231,6 +231,7 @@ public abstract interface class org/jetbrains/kotlin/gradle/plugin/mpp/external/
|
||||
public abstract fun getConfigure ()Lkotlin/jvm/functions/Function1;
|
||||
public abstract fun getDefaultSourceSet ()Lorg/jetbrains/kotlin/gradle/plugin/KotlinSourceSet;
|
||||
public abstract fun getFriendArtifactResolver ()Lorg/jetbrains/kotlin/gradle/plugin/mpp/external/ExternalKotlinCompilationDescriptor$FriendArtifactResolver;
|
||||
public abstract fun getSourceSetTreeClassifier ()Lorg/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier;
|
||||
}
|
||||
|
||||
public abstract interface class org/jetbrains/kotlin/gradle/plugin/mpp/external/ExternalKotlinCompilationDescriptor$CompilationAssociator {
|
||||
@@ -254,6 +255,7 @@ public final class org/jetbrains/kotlin/gradle/plugin/mpp/external/ExternalKotli
|
||||
public final fun getCompileTaskName ()Ljava/lang/String;
|
||||
public final fun getDefaultSourceSet ()Lorg/jetbrains/kotlin/gradle/plugin/KotlinSourceSet;
|
||||
public final fun getFriendArtifactResolver ()Lorg/jetbrains/kotlin/gradle/plugin/mpp/external/ExternalKotlinCompilationDescriptor$FriendArtifactResolver;
|
||||
public final fun getSourceSetTreeClassifier ()Lorg/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier;
|
||||
public final fun setCompilationAssociator (Lorg/jetbrains/kotlin/gradle/plugin/mpp/external/ExternalKotlinCompilationDescriptor$CompilationAssociator;)V
|
||||
public final fun setCompilationFactory (Lorg/jetbrains/kotlin/gradle/plugin/mpp/external/ExternalKotlinCompilationDescriptor$CompilationFactory;)V
|
||||
public final fun setCompilationName (Ljava/lang/String;)V
|
||||
@@ -261,6 +263,7 @@ public final class org/jetbrains/kotlin/gradle/plugin/mpp/external/ExternalKotli
|
||||
public final fun setCompileTaskName (Ljava/lang/String;)V
|
||||
public final fun setDefaultSourceSet (Lorg/jetbrains/kotlin/gradle/plugin/KotlinSourceSet;)V
|
||||
public final fun setFriendArtifactResolver (Lorg/jetbrains/kotlin/gradle/plugin/mpp/external/ExternalKotlinCompilationDescriptor$FriendArtifactResolver;)V
|
||||
public final fun setSourceSetTreeClassifier (Lorg/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier;)V
|
||||
}
|
||||
|
||||
public final class org/jetbrains/kotlin/gradle/plugin/mpp/external/ExternalKotlinCompilationDescriptorKt {
|
||||
@@ -312,3 +315,44 @@ public final class org/jetbrains/kotlin/gradle/plugin/mpp/external/ExternalKotli
|
||||
public static final fun ExternalKotlinTargetDescriptor (Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlin/gradle/plugin/mpp/external/ExternalKotlinTargetDescriptor;
|
||||
}
|
||||
|
||||
public abstract class org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier {
|
||||
}
|
||||
|
||||
public final class org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier$Default : org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier {
|
||||
public static final field INSTANCE Lorg/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier$Default;
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier$Name : org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier {
|
||||
public fun <init> (Ljava/lang/String;)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
public final fun copy (Ljava/lang/String;)Lorg/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier$Name;
|
||||
public static synthetic fun copy$default (Lorg/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier$Name;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier$Name;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getName ()Ljava/lang/String;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier$None : org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier {
|
||||
public static final field INSTANCE Lorg/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier$None;
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier$Property : org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier {
|
||||
public fun <init> (Lorg/gradle/api/provider/Property;)V
|
||||
public final fun getProperty ()Lorg/gradle/api/provider/Property;
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier$Value : org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier {
|
||||
public fun <init> (Lorg/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchy$SourceSetTree;)V
|
||||
public final fun component1 ()Lorg/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchy$SourceSetTree;
|
||||
public final fun copy (Lorg/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchy$SourceSetTree;)Lorg/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier$Value;
|
||||
public static synthetic fun copy$default (Lorg/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier$Value;Lorg/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchy$SourceSetTree;ILjava/lang/Object;)Lorg/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/SourceSetTreeClassifier$Value;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getTree ()Lorg/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchy$SourceSetTree;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
|
||||
+11
-11
@@ -53,7 +53,7 @@ abstract class KotlinMultiplatformExtension(project: Project) :
|
||||
}
|
||||
|
||||
internal val internalKotlinTargetHierarchy by lazy {
|
||||
KotlinTargetHierarchyDslImpl(project.objects, targets, sourceSets)
|
||||
KotlinTargetHierarchyDslImpl(targets, sourceSets)
|
||||
}
|
||||
|
||||
@ExperimentalKotlinGradlePluginApi
|
||||
@@ -76,13 +76,13 @@ abstract class KotlinMultiplatformExtension(project: Project) :
|
||||
fun <T : KotlinTarget> targetFromPreset(
|
||||
preset: KotlinTargetPreset<T>,
|
||||
name: String = preset.name,
|
||||
configure: T.() -> Unit = { }
|
||||
configure: T.() -> Unit = { },
|
||||
): T = configureOrCreate(name, preset, configure)
|
||||
|
||||
fun <T : KotlinTarget> targetFromPreset(
|
||||
preset: KotlinTargetPreset<T>,
|
||||
name: String,
|
||||
configure: Action<T>
|
||||
configure: Action<T>,
|
||||
) = targetFromPreset(preset, name) { configure.execute(this) }
|
||||
|
||||
fun <T : KotlinTarget> targetFromPreset(preset: KotlinTargetPreset<T>) = targetFromPreset(preset, preset.name) { }
|
||||
@@ -100,37 +100,37 @@ interface TargetsFromPresetExtension : NamedDomainObjectCollection<KotlinTarget>
|
||||
fun <T : KotlinTarget> fromPreset(
|
||||
preset: KotlinTargetPreset<T>,
|
||||
name: String,
|
||||
configureAction: T.() -> Unit = {}
|
||||
configureAction: T.() -> Unit = {},
|
||||
): T
|
||||
|
||||
fun <T : KotlinTarget> fromPreset(
|
||||
preset: KotlinTargetPreset<T>,
|
||||
name: String
|
||||
name: String,
|
||||
): T = fromPreset(preset, name, {})
|
||||
|
||||
fun <T : KotlinTarget> fromPreset(
|
||||
preset: KotlinTargetPreset<T>,
|
||||
name: String,
|
||||
configureAction: Action<T>
|
||||
configureAction: Action<T>,
|
||||
): T
|
||||
}
|
||||
|
||||
internal abstract class DefaultTargetsFromPresetExtension @Inject constructor(
|
||||
private val targetsContainer: () -> KotlinTargetsContainerWithPresets,
|
||||
val targets: NamedDomainObjectCollection<KotlinTarget>
|
||||
val targets: NamedDomainObjectCollection<KotlinTarget>,
|
||||
) : TargetsFromPresetExtension,
|
||||
NamedDomainObjectCollection<KotlinTarget> by targets {
|
||||
|
||||
override fun <T : KotlinTarget> fromPreset(
|
||||
preset: KotlinTargetPreset<T>,
|
||||
name: String,
|
||||
configureAction: T.() -> Unit
|
||||
configureAction: T.() -> Unit,
|
||||
): T = targetsContainer().configureOrCreate(name, preset, configureAction)
|
||||
|
||||
override fun <T : KotlinTarget> fromPreset(
|
||||
preset: KotlinTargetPreset<T>,
|
||||
name: String,
|
||||
configureAction: Action<T>
|
||||
configureAction: Action<T>,
|
||||
) = fromPreset(preset, name) {
|
||||
configureAction.execute(this)
|
||||
}
|
||||
@@ -142,7 +142,7 @@ internal fun KotlinTarget.isProducedFromPreset(kotlinTargetPreset: KotlinTargetP
|
||||
internal fun <T : KotlinTarget> KotlinTargetsContainerWithPresets.configureOrCreate(
|
||||
targetName: String,
|
||||
targetPreset: KotlinTargetPreset<T>,
|
||||
configure: T.() -> Unit
|
||||
configure: T.() -> Unit,
|
||||
): T {
|
||||
val existingTarget = targets.findByName(targetName)
|
||||
when {
|
||||
@@ -172,7 +172,7 @@ internal fun <T : KotlinTarget> KotlinTargetsContainerWithPresets.configureOrCre
|
||||
|
||||
internal fun KotlinTargetsContainerWithPresets.configureOrCreateAndroidTargetAndReportDeprecation(
|
||||
targetName: String,
|
||||
configure: KotlinAndroidTarget.() -> Unit
|
||||
configure: KotlinAndroidTarget.() -> Unit,
|
||||
): KotlinAndroidTarget {
|
||||
val targetPreset = presets.getByName("android") as KotlinAndroidTargetPreset
|
||||
val result = configureOrCreate(targetName, targetPreset, configure)
|
||||
|
||||
+13
-10
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin.Companio
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.addBuildListenerForXcode
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.internal.runDeprecationDiagnostics
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.copyAttributes
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.orNull
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.checkSourceSetVisibilityRequirements
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.internal
|
||||
@@ -85,7 +86,7 @@ class KotlinMultiplatformPlugin : Plugin<Project> {
|
||||
}
|
||||
|
||||
private fun exportProjectStructureMetadataForOtherBuilds(
|
||||
extension: KotlinMultiplatformExtension
|
||||
extension: KotlinMultiplatformExtension,
|
||||
) {
|
||||
GlobalProjectStructureMetadataStorage.registerProjectStructureMetadata(extension.project) {
|
||||
extension.kotlinProjectStructureMetadata
|
||||
@@ -168,22 +169,24 @@ class KotlinMultiplatformPlugin : Plugin<Project> {
|
||||
|
||||
|
||||
private fun configureSourceSets(project: Project) = with(project.multiplatformExtension) {
|
||||
val production = sourceSets.create(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
||||
val test = sourceSets.create(KotlinSourceSet.COMMON_TEST_SOURCE_SET_NAME)
|
||||
/* Create 'commonMain' and 'commonTest' SourceSets */
|
||||
sourceSets.create(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
||||
sourceSets.create(KotlinSourceSet.COMMON_TEST_SOURCE_SET_NAME)
|
||||
|
||||
/* Create default 'dependsOn' to commonMain/commonTest (or even common{SourceSetTree}) */
|
||||
targets.all { target ->
|
||||
project.launchInStage(KotlinPluginLifecycle.Stage.FinaliseRefinesEdges) {
|
||||
/* Only setup default refines edges when no KotlinTargetHierarchy was applied */
|
||||
if (project.multiplatformExtension.internalKotlinTargetHierarchy.appliedDescriptors.isNotEmpty()) return@launchInStage
|
||||
|
||||
target.compilations.findByName(KotlinCompilation.MAIN_COMPILATION_NAME)?.let { mainCompilation ->
|
||||
mainCompilation.defaultSourceSet.takeIf { it != production }?.dependsOn(production)
|
||||
}
|
||||
|
||||
target.compilations.findByName(KotlinCompilation.TEST_COMPILATION_NAME)?.let { testCompilation ->
|
||||
testCompilation.defaultSourceSet.takeIf { it != test }?.dependsOn(test)
|
||||
target.compilations.forEach { compilation ->
|
||||
val sourceSetTree = KotlinTargetHierarchy.SourceSetTree.orNull(compilation) ?: return@forEach
|
||||
val commonSourceSet = sourceSets.findByName(lowerCamelCaseName("common", sourceSetTree.name)) ?: return@forEach
|
||||
compilation.defaultSourceSet.dependsOn(commonSourceSet)
|
||||
}
|
||||
}
|
||||
|
||||
/* Report the platform to tbe build stats service */
|
||||
val targetName = if (target is KotlinNativeTarget)
|
||||
target.konanTarget.name
|
||||
else
|
||||
@@ -277,7 +280,7 @@ private fun sourcesJarTask(
|
||||
project: Project,
|
||||
sourceSets: Future<Map<String, Iterable<File>>>,
|
||||
taskNamePrefix: String,
|
||||
artifactNameAppendix: String
|
||||
artifactNameAppendix: String,
|
||||
): TaskProvider<Jar> =
|
||||
sourcesJarTaskNamed(lowerCamelCaseName(taskNamePrefix, "sourcesJar"), taskNamePrefix, project, sourceSets, artifactNameAppendix)
|
||||
|
||||
|
||||
+6
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.DecoratedKotlinCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinCompilationDescriptor.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.SourceSetTreeClassifier
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
/**
|
||||
@@ -54,6 +55,7 @@ interface ExternalKotlinCompilationDescriptor<T : DecoratedExternalKotlinCompila
|
||||
val compilationFactory: CompilationFactory<T>
|
||||
val friendArtifactResolver: FriendArtifactResolver<T>?
|
||||
val compilationAssociator: CompilationAssociator<T>?
|
||||
val sourceSetTreeClassifier: SourceSetTreeClassifier
|
||||
val configure: ((T) -> Unit)?
|
||||
}
|
||||
|
||||
@@ -70,6 +72,7 @@ fun <T : DecoratedExternalKotlinCompilation> ExternalKotlinCompilationDescriptor
|
||||
compilationFactory = compilationFactory,
|
||||
friendArtifactResolver = friendArtifactResolver,
|
||||
compilationAssociator = compilationAssociator,
|
||||
sourceSetTreeClassifier = sourceSetTreeClassifier,
|
||||
configure = this.configure
|
||||
)
|
||||
}
|
||||
@@ -84,6 +87,8 @@ class ExternalKotlinCompilationDescriptorBuilder<T : DecoratedExternalKotlinComp
|
||||
var compilationFactory: CompilationFactory<T> by Delegates.notNull()
|
||||
var friendArtifactResolver: FriendArtifactResolver<T>? = null
|
||||
var compilationAssociator: CompilationAssociator<T>? = null
|
||||
var sourceSetTreeClassifier: SourceSetTreeClassifier = SourceSetTreeClassifier.Default
|
||||
|
||||
internal var configure: ((T) -> Unit)? = null
|
||||
|
||||
fun configure(action: (T) -> Unit) = apply {
|
||||
@@ -101,5 +106,6 @@ private data class ExternalKotlinCompilationDescriptorImpl<T : DecoratedExternal
|
||||
override val compilationFactory: CompilationFactory<T>,
|
||||
override val friendArtifactResolver: FriendArtifactResolver<T>?,
|
||||
override val compilationAssociator: CompilationAssociator<T>?,
|
||||
override val sourceSetTreeClassifier: SourceSetTreeClassifier,
|
||||
override val configure: ((T) -> Unit)?,
|
||||
) : ExternalKotlinCompilationDescriptor<T>
|
||||
+6
-5
@@ -12,9 +12,9 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.DefaultKotlinCompi
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationAssociator
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationSourceSetsContainer
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.KotlinCompilationImplFactory.KotlinCompilationTaskNamesContainerFactory
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.decoratedInstance
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.external.DecoratedExternalKotlinCompilation.Delegate
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.sourceSetTreeClassifier
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||
*/
|
||||
@ExternalKotlinTargetApi
|
||||
fun <T : DecoratedExternalKotlinCompilation> DecoratedExternalKotlinTarget.createCompilation(
|
||||
descriptor: ExternalKotlinCompilationDescriptor<T>
|
||||
descriptor: ExternalKotlinCompilationDescriptor<T>,
|
||||
): T {
|
||||
val compilationImplFactory = KotlinCompilationImplFactory(
|
||||
compilerOptionsFactory = when (platformType) {
|
||||
@@ -42,7 +42,7 @@ fun <T : DecoratedExternalKotlinCompilation> DecoratedExternalKotlinTarget.creat
|
||||
KotlinPlatformType.wasm -> KotlinMultiplatformCommonCompilerOptionsFactory
|
||||
},
|
||||
compilationSourceSetsContainerFactory = { _, _ -> KotlinCompilationSourceSetsContainer(descriptor.defaultSourceSet) },
|
||||
compilationTaskNamesContainerFactory = KotlinCompilationTaskNamesContainerFactory { target, compilationName ->
|
||||
compilationTaskNamesContainerFactory = { target, compilationName ->
|
||||
val default = DefaultKotlinCompilationTaskNamesContainerFactory.create(target, compilationName)
|
||||
default.copy(
|
||||
compileTaskName = descriptor.compileTaskName ?: default.compileTaskName,
|
||||
@@ -70,6 +70,7 @@ fun <T : DecoratedExternalKotlinCompilation> DecoratedExternalKotlinTarget.creat
|
||||
|
||||
val compilationImpl = compilationImplFactory.create(this, descriptor.compilationName)
|
||||
val decoratedCompilation = descriptor.compilationFactory.create(Delegate(compilationImpl))
|
||||
decoratedCompilation.sourceSetTreeClassifier = descriptor.sourceSetTreeClassifier
|
||||
descriptor.configure?.invoke(decoratedCompilation)
|
||||
this.delegate.compilations.add(decoratedCompilation)
|
||||
|
||||
@@ -83,13 +84,13 @@ fun <T : DecoratedExternalKotlinCompilation> DecoratedExternalKotlinTarget.creat
|
||||
*/
|
||||
@ExternalKotlinTargetApi
|
||||
fun <T : DecoratedExternalKotlinCompilation> DecoratedExternalKotlinTarget.createCompilation(
|
||||
descriptor: ExternalKotlinCompilationDescriptorBuilder<T>.() -> Unit
|
||||
descriptor: ExternalKotlinCompilationDescriptorBuilder<T>.() -> Unit,
|
||||
): T {
|
||||
return createCompilation(ExternalKotlinCompilationDescriptor(descriptor))
|
||||
}
|
||||
|
||||
private fun DecoratedExternalKotlinTarget.setupCompileTask(
|
||||
compilation: DecoratedExternalKotlinCompilation
|
||||
compilation: DecoratedExternalKotlinCompilation,
|
||||
) {
|
||||
val tasksProvider = KotlinTasksProvider()
|
||||
val compilationInfo = KotlinCompilationInfo(compilation)
|
||||
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.plugin.mpp.targetHierarchy
|
||||
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy.SourceSetTree
|
||||
import org.jetbrains.kotlin.gradle.plugin.awaitFinalValue
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.android.AndroidVariantType
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.android.type
|
||||
|
||||
internal suspend fun SourceSetTree.Companion.orNull(compilation: KotlinCompilation<*>): SourceSetTree? =
|
||||
when (compilation) {
|
||||
is KotlinJvmAndroidCompilation -> orNull(compilation.target, compilation.androidVariant.type)
|
||||
else -> when (compilation.name) {
|
||||
"main" -> main
|
||||
"test" -> test
|
||||
else -> SourceSetTree(compilation.name)
|
||||
}
|
||||
}
|
||||
|
||||
internal suspend fun SourceSetTree.Companion.orNull(
|
||||
target: KotlinAndroidTarget,
|
||||
variantType: AndroidVariantType
|
||||
): SourceSetTree? {
|
||||
val multiplatform = target.project.multiplatformExtensionOrNull ?: return null
|
||||
return when (variantType) {
|
||||
AndroidVariantType.Main ->
|
||||
multiplatform.targetHierarchy.android.main.sourceSetTree.awaitFinalValue() ?: main
|
||||
AndroidVariantType.UnitTest ->
|
||||
multiplatform.targetHierarchy.android.unitTest.sourceSetTree.awaitFinalValue() ?: test
|
||||
AndroidVariantType.InstrumentedTest ->
|
||||
multiplatform.targetHierarchy.android.instrumentedTest.sourceSetTree.awaitFinalValue() ?: instrumentedTest
|
||||
AndroidVariantType.Unknown -> null
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -61,17 +61,17 @@ private class KotlinTargetHierarchyBuilderRootImpl(
|
||||
|
||||
|
||||
override fun sourceSetTrees(vararg tree: KotlinTargetHierarchy.SourceSetTree) {
|
||||
builder.modules = tree.toHashSet()
|
||||
builder.sourceSetTrees = tree.toHashSet()
|
||||
}
|
||||
|
||||
override fun withSourceSetTree(vararg tree: KotlinTargetHierarchy.SourceSetTree) {
|
||||
builder.modules = builder.modules.orEmpty().plus(tree)
|
||||
builder.sourceSetTrees = builder.sourceSetTrees.orEmpty().plus(tree)
|
||||
}
|
||||
|
||||
override fun excludeSourceSetTree(vararg tree: KotlinTargetHierarchy.SourceSetTree) {
|
||||
val modules = tree.toHashSet()
|
||||
if (modules.isEmpty()) return
|
||||
builder.modules = builder.modules.orEmpty() - modules
|
||||
builder.sourceSetTrees = builder.sourceSetTrees.orEmpty() - modules
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ private class KotlinTargetHierarchyBuilderImpl(
|
||||
val children = mutableSetOf<KotlinTargetHierarchyBuilderImpl>()
|
||||
val childrenClosure get() = closure { it.children }
|
||||
|
||||
var modules: Set<KotlinTargetHierarchy.SourceSetTree>? = null
|
||||
var sourceSetTrees: Set<KotlinTargetHierarchy.SourceSetTree>? = null
|
||||
private var includePredicate: ((KotlinCompilation<*>) -> Boolean) = { false }
|
||||
private var excludePredicate: ((KotlinCompilation<*>) -> Boolean) = { false }
|
||||
|
||||
@@ -104,9 +104,9 @@ private class KotlinTargetHierarchyBuilderImpl(
|
||||
}
|
||||
|
||||
suspend fun contains(compilation: KotlinCompilation<*>): Boolean {
|
||||
modules?.let { modules ->
|
||||
val module = KotlinTargetHierarchy.SourceSetTree.orNull(compilation) ?: return false
|
||||
if (module !in modules) return false
|
||||
sourceSetTrees?.let { sourceSetTrees ->
|
||||
val sourceSetTree = KotlinTargetHierarchy.SourceSetTree.orNull(compilation) ?: return false
|
||||
if (sourceSetTree !in sourceSetTrees) return false
|
||||
}
|
||||
|
||||
/* Return eagerly, when compilation is explicitly excluded */
|
||||
|
||||
+4
-22
@@ -7,16 +7,13 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy
|
||||
|
||||
import org.gradle.api.DomainObjectCollection
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.provider.Property
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidTargetHierarchyDsl
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidVariantHierarchyDsl
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinTargetHierarchyDsl
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.utils.property
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchyBuilder
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchyDescriptor
|
||||
|
||||
internal class KotlinTargetHierarchyDslImpl(
|
||||
objects: ObjectFactory,
|
||||
private val targets: DomainObjectCollection<KotlinTarget>,
|
||||
private val sourceSets: NamedDomainObjectContainer<KotlinSourceSet>,
|
||||
) : KotlinTargetHierarchyDsl {
|
||||
@@ -24,8 +21,6 @@ internal class KotlinTargetHierarchyDslImpl(
|
||||
private val _appliedDescriptors = mutableListOf<KotlinTargetHierarchyDescriptor>()
|
||||
val appliedDescriptors: List<KotlinTargetHierarchyDescriptor> get() = _appliedDescriptors
|
||||
|
||||
override val android: KotlinAndroidTargetHierarchyDsl = KotlinAndroidTargetHierarchyDslImpl(objects)
|
||||
|
||||
override fun apply(
|
||||
hierarchyDescriptor: KotlinTargetHierarchyDescriptor,
|
||||
describeExtension: (KotlinTargetHierarchyBuilder.Root.() -> Unit)?,
|
||||
@@ -42,21 +37,8 @@ internal class KotlinTargetHierarchyDslImpl(
|
||||
override fun custom(describe: KotlinTargetHierarchyBuilder.Root.() -> Unit) {
|
||||
apply(KotlinTargetHierarchyDescriptor(describe))
|
||||
}
|
||||
|
||||
override fun android(configure: KotlinAndroidTargetHierarchyDsl.() -> Unit) {
|
||||
android.configure()
|
||||
}
|
||||
}
|
||||
|
||||
private fun KotlinTargetHierarchyDescriptor.extendIfNotNull(describe: (KotlinTargetHierarchyBuilder.Root.() -> Unit)?) =
|
||||
if (describe == null) this else extend(describe)
|
||||
|
||||
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 {
|
||||
override val sourceSetTree: Property<KotlinTargetHierarchy.SourceSetTree> = objects.property()
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.plugin.mpp.targetHierarchy
|
||||
|
||||
import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy.SourceSetTree
|
||||
import org.jetbrains.kotlin.gradle.plugin.awaitFinalValue
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilationFactory
|
||||
import org.jetbrains.kotlin.tooling.core.extrasLazyProperty
|
||||
|
||||
/**
|
||||
* Classifier providing the corresponding [SourceSetTree] associated with any given [KotlinCompilation]
|
||||
*
|
||||
* ### Example: Overwriting 'test' compilations [SourceSetTreeClassifier]:
|
||||
* Consider the following setup:
|
||||
* ```kotlin
|
||||
* kotlin {
|
||||
* val testCompilation = jvm().compilations.getByName("test")
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* In this example, we know that the 'jvm/test' compilation will have a 'jvmTest' SourceSet which
|
||||
* will depend on 'commonTest' and therefore is part of the 'test' [SourceSetTree].
|
||||
*
|
||||
* When another [SourceSetTreeClassifier] is specified, this behaviour is changed.
|
||||
* Using the External Kotlin Target API:
|
||||
* ```kotlin
|
||||
* myTarget.createCompilation {
|
||||
* compilationName = "test"
|
||||
* sourceSetTreeClassifier = SourceSetTreeClassifier.Name("unitTest")
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* This will create a compilation called 'test' which however will be considered part of the 'unitTest' SourceSetTree.
|
||||
* The SourceSet of this 'jvm/test' compilation will still be called 'jvmTest' but since its part of the 'unitTest [SourceSetTree],
|
||||
* there will not be a dependsOn edge to 'commonTest', but (if present) 'commonUnitTest'
|
||||
*/
|
||||
@ExternalKotlinTargetApi
|
||||
sealed class SourceSetTreeClassifier {
|
||||
|
||||
/**
|
||||
* Default Classifier: The name of the compilation will be used to infer the [SourceSetTree]:
|
||||
* 'main' compilations will be part of [SourceSetTree.main]
|
||||
* 'test' compilations will be part of [SourceSetTree.test]
|
||||
* ...
|
||||
*/
|
||||
@ExternalKotlinTargetApi
|
||||
object Default : SourceSetTreeClassifier() {
|
||||
override fun toString(): String = "Default"
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the given compilations is not part of any 'named' [SourceSetTree].
|
||||
* Neither [KotlinTargetHierarchy] will be applied nor default dependsOn edges shall be set.
|
||||
*/
|
||||
@ExternalKotlinTargetApi
|
||||
object None : SourceSetTreeClassifier() {
|
||||
override fun toString(): String = "None"
|
||||
}
|
||||
|
||||
/**
|
||||
* Predefined [SourceSetTree] using the [tree] specified.
|
||||
*/
|
||||
@ExternalKotlinTargetApi
|
||||
data class Value(val tree: SourceSetTree) : SourceSetTreeClassifier()
|
||||
|
||||
/**
|
||||
* Predefined [SourceSetTree] using the [name] specified
|
||||
*/
|
||||
@ExternalKotlinTargetApi
|
||||
data class Name(val name: String) : SourceSetTreeClassifier()
|
||||
|
||||
/**
|
||||
* Wrapper around [org.gradle.api.provider.Property] of a given [SourceSetTree] in order to
|
||||
* make the [SourceSetTree] configurable.
|
||||
*/
|
||||
@ExternalKotlinTargetApi
|
||||
class Property(val property: org.gradle.api.provider.Property<SourceSetTree>) : SourceSetTreeClassifier() {
|
||||
override fun toString(): String {
|
||||
return property.toString()
|
||||
}
|
||||
}
|
||||
|
||||
internal suspend fun classify(compilation: KotlinCompilation<*>): SourceSetTree? {
|
||||
return when (this) {
|
||||
is Default -> SourceSetTree(compilation.name)
|
||||
is Property -> property.awaitFinalValue()
|
||||
is Value -> tree
|
||||
is Name -> SourceSetTree(name)
|
||||
is None -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the classifier configured for a given compilation.
|
||||
* This is writable, as Android requires overwriting of this default behaviour.
|
||||
*
|
||||
* - The KGP maintained target will set the classifier within the [KotlinJvmAndroidCompilationFactory]
|
||||
* - The external Android target will set this classifier within the 'createCompilation'
|
||||
*
|
||||
* It is therefore safe to access this value as soon as a compilation is provided
|
||||
*/
|
||||
internal var KotlinCompilation<*>.sourceSetTreeClassifier: SourceSetTreeClassifier by extrasLazyProperty {
|
||||
SourceSetTreeClassifier.Default
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the [SourceSetTree] of a given [KotlinCompilation]:
|
||||
* Uses the [sourceSetTreeClassifier] under the hood.
|
||||
* See [SourceSetTreeClassifier]
|
||||
*/
|
||||
internal suspend fun SourceSetTree.Companion.orNull(compilation: KotlinCompilation<*>) =
|
||||
compilation.sourceSetTreeClassifier.classify(compilation)
|
||||
+8
-3
@@ -11,10 +11,9 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy
|
||||
import org.jetbrains.kotlin.gradle.plugin.awaitFinalValue
|
||||
import org.jetbrains.kotlin.gradle.plugin.launchInStage
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.orNull
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.android.AndroidBaseSourceSetName
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.android.AndroidVariantType
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.android.type
|
||||
@@ -38,7 +37,13 @@ internal object MultiplatformLayoutV2DependsOnConfigurator : KotlinAndroidSource
|
||||
return@launchInStage
|
||||
}
|
||||
|
||||
val sourceSetTree = KotlinTargetHierarchy.SourceSetTree.orNull(target, variantType) ?: return@launchInStage
|
||||
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.Unknown -> null
|
||||
} ?: return@launchInStage
|
||||
|
||||
val commonSourceSetName = lowerCamelCaseName("common", sourceSetTree.name)
|
||||
val commonSourceSet = target.project.kotlinExtension.sourceSets.findByName(commonSourceSetName) ?: return@launchInStage
|
||||
kotlinSourceSet.dependsOn(commonSourceSet)
|
||||
|
||||
+112
-9
@@ -7,14 +7,13 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import com.android.build.gradle.api.BaseVariant
|
||||
import org.gradle.api.InvalidUserDataException
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.attributes.Attribute
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy.SourceSetTree
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.copyAttributes
|
||||
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
|
||||
import org.jetbrains.kotlin.gradle.utils.forAllAndroidVariants
|
||||
@@ -26,7 +25,7 @@ import javax.inject.Inject
|
||||
|
||||
abstract class KotlinAndroidTarget @Inject constructor(
|
||||
final override val targetName: String,
|
||||
project: Project
|
||||
project: Project,
|
||||
) : AbstractKotlinTarget(project) {
|
||||
|
||||
final override val disambiguationClassifier: String = targetName
|
||||
@@ -37,6 +36,109 @@ 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)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
|
||||
/** 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.
|
||||
@@ -241,7 +343,7 @@ abstract class KotlinAndroidTarget @Inject constructor(
|
||||
private fun createSourcesElementsIfNeeded(
|
||||
variantName: String,
|
||||
apiElementsConfigurationName: String,
|
||||
sourcesElementsConfigurationName: String
|
||||
sourcesElementsConfigurationName: String,
|
||||
): Configuration {
|
||||
val existingConfiguration = project.configurations.findByName(sourcesElementsConfigurationName)
|
||||
if (existingConfiguration != null) return existingConfiguration
|
||||
@@ -261,7 +363,7 @@ abstract class KotlinAndroidTarget @Inject constructor(
|
||||
/** We filter this variant out as it is never requested on the consumer side, while keeping it leads to ambiguity between Android and
|
||||
* JVM variants due to non-nesting sets of unmatched attributes. */
|
||||
private fun filterOutAndroidVariantAttribute(
|
||||
attribute: Attribute<*>
|
||||
attribute: Attribute<*>,
|
||||
): Boolean =
|
||||
attribute.name != "com.android.build.gradle.internal.attributes.VariantAttr" &&
|
||||
attribute.name != "com.android.build.api.attributes.VariantAttr"
|
||||
@@ -269,7 +371,7 @@ abstract class KotlinAndroidTarget @Inject constructor(
|
||||
private fun filterOutAndroidBuildTypeAttribute(
|
||||
it: Attribute<*>,
|
||||
valueString: String,
|
||||
isSinglePublishedVariant: Boolean
|
||||
isSinglePublishedVariant: Boolean,
|
||||
) = when {
|
||||
PropertiesProvider(project).keepAndroidBuildTypeAttribute -> true
|
||||
it.name != "com.android.build.api.attributes.BuildTypeAttr" -> true
|
||||
@@ -281,6 +383,7 @@ abstract class KotlinAndroidTarget @Inject constructor(
|
||||
}
|
||||
|
||||
private fun filterOutAndroidAgpVersionAttribute(
|
||||
attribute: Attribute<*>
|
||||
attribute: Attribute<*>,
|
||||
): Boolean = attribute.name != "com.android.build.api.attributes.AgpVersionAttr"
|
||||
}
|
||||
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
@file:Suppress("PackageDirectoryMismatch") // Old package for compatibility
|
||||
|
||||
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 {
|
||||
/**
|
||||
* Configures under which [SourceSetTree] the currently configured Android Variant shall be placed.
|
||||
* e.g.
|
||||
*
|
||||
* ```kotlin
|
||||
* kotlin {
|
||||
* targetHierarchy.android {
|
||||
* 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 {
|
||||
override val sourceSetTree: Property<SourceSetTree> = objects.property()
|
||||
}
|
||||
+18
-2
@@ -12,10 +12,15 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinAndroidCompi
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.AndroidCompilationSourceSetsContainerFactory
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.KotlinCompilationImplFactory
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.KotlinJvmCompilerOptionsFactory
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.SourceSetTreeClassifier
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.SourceSetTreeClassifier.Property
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.sourceSetTreeClassifier
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.android.AndroidVariantType
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.android.type
|
||||
|
||||
class KotlinJvmAndroidCompilationFactory internal constructor(
|
||||
override val target: KotlinAndroidTarget,
|
||||
private val variant: BaseVariant
|
||||
private val variant: BaseVariant,
|
||||
) : KotlinCompilationFactory<KotlinJvmAndroidCompilation> {
|
||||
|
||||
override val itemClass: Class<KotlinJvmAndroidCompilation>
|
||||
@@ -34,6 +39,17 @@ class KotlinJvmAndroidCompilationFactory internal constructor(
|
||||
)
|
||||
|
||||
override fun create(name: String): KotlinJvmAndroidCompilation {
|
||||
return project.objects.newInstance(itemClass, compilationImplFactory.create(target, name), variant)
|
||||
return project.objects.newInstance(itemClass, compilationImplFactory.create(target, name), variant).also { compilation ->
|
||||
configureSourceSetTreeClassifier(compilation)
|
||||
}
|
||||
}
|
||||
|
||||
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.Unknown -> SourceSetTreeClassifier.None
|
||||
}
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
@file:Suppress("FunctionName", "DuplicatedCode")
|
||||
|
||||
package org.jetbrains.kotlin.gradle.unitTests
|
||||
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy.SourceSetTree
|
||||
import org.jetbrains.kotlin.gradle.plugin.launchInStage
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.external.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinCompilationDescriptor.CompilationFactory
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinTargetDescriptor.TargetFactory
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.SourceSetTreeClassifier
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.orNull
|
||||
import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP
|
||||
import org.jetbrains.kotlin.gradle.util.runLifecycleAwareTest
|
||||
import org.jetbrains.kotlin.gradle.utils.property
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNull
|
||||
|
||||
class ExternalKotlinTargetApiTests {
|
||||
|
||||
class FakeTarget(delegate: Delegate) : DecoratedExternalKotlinTarget(delegate)
|
||||
class FakeCompilation(delegate: Delegate) : DecoratedExternalKotlinCompilation(delegate)
|
||||
|
||||
val project = buildProjectWithMPP()
|
||||
val kotlin = project.multiplatformExtension
|
||||
|
||||
private fun ExternalKotlinTargetDescriptorBuilder<FakeTarget>.defaults() {
|
||||
targetName = "fake"
|
||||
platformType = KotlinPlatformType.jvm
|
||||
targetFactory = TargetFactory(::FakeTarget)
|
||||
}
|
||||
|
||||
private fun ExternalKotlinCompilationDescriptorBuilder<FakeCompilation>.defaults() {
|
||||
compilationName = "fake"
|
||||
compilationFactory = CompilationFactory(::FakeCompilation)
|
||||
defaultSourceSet = kotlin.sourceSets.maybeCreate("fake")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - sourceSetClassifier - default`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||
val target = kotlin.createExternalKotlinTarget<FakeTarget> { defaults() }
|
||||
val compilation = target.createCompilation<FakeCompilation> { defaults() }
|
||||
|
||||
assertEquals(SourceSetTree("fake"), SourceSetTree.orNull(compilation))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - sourceSetClassifier - custom name`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||
val target = kotlin.createExternalKotlinTarget<FakeTarget> { defaults() }
|
||||
val compilation = target.createCompilation<FakeCompilation> {
|
||||
defaults()
|
||||
sourceSetTreeClassifier = SourceSetTreeClassifier.Name("mySourceSetTree")
|
||||
}
|
||||
|
||||
assertEquals(SourceSetTree("mySourceSetTree"), SourceSetTree.orNull(compilation))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - sourceSetClassifier - custom property`() = buildProjectWithMPP().runLifecycleAwareTest {
|
||||
val myProperty = project.objects.property<SourceSetTree>()
|
||||
val nullProperty = project.objects.property<SourceSetTree>()
|
||||
|
||||
val target = kotlin.createExternalKotlinTarget<FakeTarget> { defaults() }
|
||||
|
||||
val mainCompilation = target.createCompilation<FakeCompilation> {
|
||||
defaults()
|
||||
sourceSetTreeClassifier = SourceSetTreeClassifier.Property(myProperty)
|
||||
}
|
||||
|
||||
val auxCompilation = target.createCompilation<FakeCompilation>() {
|
||||
compilationName = "aux"
|
||||
compilationFactory = CompilationFactory(::FakeCompilation)
|
||||
defaultSourceSet = kotlin.sourceSets.create("aux")
|
||||
sourceSetTreeClassifier = SourceSetTreeClassifier.Property(nullProperty)
|
||||
}
|
||||
|
||||
launchInStage(KotlinPluginLifecycle.Stage.FinaliseDsl) {
|
||||
myProperty.set(SourceSetTree.main)
|
||||
}
|
||||
|
||||
assertEquals(SourceSetTree.main, SourceSetTree.orNull(mainCompilation))
|
||||
assertNull(SourceSetTree.orNull(auxCompilation))
|
||||
}
|
||||
}
|
||||
+4
-8
@@ -15,7 +15,7 @@ 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.targetHierarchy.KotlinAndroidVariantHierarchyDslImpl
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidVariantHierarchyDslImpl
|
||||
import org.jetbrains.kotlin.gradle.util.*
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
@@ -38,7 +38,7 @@ class KotlinAndroidTargetHierarchyDsl {
|
||||
afterEvaluate { dsl.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("x")) }
|
||||
dsl.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("-set-before-after-evaluate-"))
|
||||
assertEquals("x", dsl.sourceSetTree.awaitFinalValue()?.name)
|
||||
assertEquals(KotlinPluginLifecycle.Stage.FinaliseDsl, currentKotlinPluginLifecycle().stage)
|
||||
assertEquals(KotlinPluginLifecycle.Stage.AfterFinaliseDsl, currentKotlinPluginLifecycle().stage)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -51,9 +51,7 @@ class KotlinAndroidTargetHierarchyDsl {
|
||||
|
||||
val kotlin = project.multiplatformExtension
|
||||
project.runLifecycleAwareTest {
|
||||
kotlin.androidTarget()
|
||||
|
||||
kotlin.targetHierarchy.android {
|
||||
kotlin.androidTarget().targetHierarchy {
|
||||
unitTest.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree.test)
|
||||
instrumentedTest.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree.test)
|
||||
}
|
||||
@@ -75,9 +73,7 @@ class KotlinAndroidTargetHierarchyDsl {
|
||||
|
||||
val kotlin = project.multiplatformExtension
|
||||
project.runLifecycleAwareTest {
|
||||
kotlin.androidTarget()
|
||||
|
||||
kotlin.targetHierarchy.android {
|
||||
kotlin.androidTarget().targetHierarchy {
|
||||
unitTest.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("xxx"))
|
||||
instrumentedTest.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("yyy"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user