[Gradle] ExternalKotlinTarget Api: Implement 'configureIdeImport' API

^KT-55010 Verification Pending
This commit is contained in:
Sebastian Sellmair
2022-11-17 10:32:17 +01:00
committed by Space Team
parent 19f4e39ee7
commit 83af85706d
10 changed files with 112 additions and 11 deletions
@@ -7,6 +7,7 @@ dependencies {
compileOnly(gradleKotlinDsl())
compileOnly("com.android.tools.build:gradle:7.2.1")
compileOnly(project(":kotlin-gradle-plugin"))
compileOnly(project(":kotlin-gradle-plugin-idea"))
}
configureKotlinCompileTasksGradleCompatibility()
@@ -0,0 +1,23 @@
/*
* 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.android
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.external.extras
import org.jetbrains.kotlin.tooling.core.extrasKeyOf
class AndroidKotlinSourceSet {
companion object {
private val extrasKey = extrasKeyOf<AndroidKotlinSourceSet>()
var KotlinSourceSet.android: AndroidKotlinSourceSet?
get() = extras[extrasKey]
internal set(value) {
if (value != null) extras[extrasKey] = value
else extras.remove(extrasKey)
}
}
}
@@ -14,10 +14,12 @@ import org.gradle.api.attributes.java.TargetJvmEnvironment
import org.gradle.api.attributes.java.TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.named
import org.jetbrains.kotlin.gradle.android.AndroidKotlinSourceSet.Companion.android
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.kpm.external.ExternalVariantApi
import org.jetbrains.kotlin.gradle.kpm.external.project
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport
import org.jetbrains.kotlin.gradle.plugin.mpp.external.*
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinTargetDescriptor.TargetFactory
@@ -81,6 +83,15 @@ fun KotlinMultiplatformExtension.androidTargetPrototype(): PrototypeAndroidTarge
configuration.attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.androidJvm)
configuration.attributes.attribute(TARGET_JVM_ENVIRONMENT_ATTRIBUTE, project.objects.named(TargetJvmEnvironment.ANDROID))
}
configureIdeImport {
registerDependencyResolver(
AndroidBootClasspathIdeDependencyResolver(project),
constraint = IdeMultiplatformImport.SourceSetConstraint { sourceSet -> sourceSet.android != null },
phase = IdeMultiplatformImport.DependencyResolutionPhase.BinaryDependencyResolution,
level = IdeMultiplatformImport.DependencyResolutionLevel.Default
)
}
}
/*
@@ -9,8 +9,29 @@ import com.android.build.gradle.BaseExtension
import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.gradle.kotlin.dsl.getByType
import org.jetbrains.kotlin.gradle.android.AndroidKotlinSourceSet.Companion.android
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryCoordinates
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency
import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver
import org.jetbrains.kotlin.tooling.core.mutableExtrasOf
import java.util.concurrent.Callable
internal fun Project.androidBootClasspath(): FileCollection {
return project.files(Callable { project.extensions.getByType<BaseExtension>().bootClasspath })
}
}
internal class AndroidBootClasspathIdeDependencyResolver(private val project: Project) : IdeDependencyResolver {
override fun resolve(sourceSet: KotlinSourceSet): Set<IdeaKotlinDependency> {
if (sourceSet.android == null) return emptySet()
return project.androidBootClasspath().files.map { file ->
IdeaKotlinResolvedBinaryDependency(
binaryType = IdeaKotlinDependency.CLASSPATH_BINARY_TYPE,
binaryFile = file,
extras = mutableExtrasOf(),
coordinates = IdeaKotlinBinaryCoordinates("com.android", "sdk", "7.4")
)
}.toSet()
}
}
@@ -6,16 +6,22 @@
package org.jetbrains.kotlin.gradle.android
import com.android.build.gradle.internal.publishing.AndroidArtifacts
import com.android.build.gradle.internal.publishing.AndroidArtifacts.ARTIFACT_TYPE
import org.gradle.api.attributes.java.TargetJvmEnvironment
import org.gradle.api.attributes.java.TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE
import org.gradle.kotlin.dsl.named
import org.jetbrains.kotlin.gradle.android.AndroidKotlinSourceSet.Companion.android
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinCompilationDescriptor
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinCompilationDescriptor.DecoratedKotlinCompilationFactory
import org.jetbrains.kotlin.gradle.plugin.mpp.external.createCompilation
internal fun PrototypeAndroidTarget.createAndroidCompilation(name: String): PrototypeAndroidCompilation {
return createCompilation {
compilationName = name
defaultSourceSet = kotlin.sourceSets.maybeCreate(camelCase("prototype", targetName, name))
defaultSourceSet = kotlin.sourceSets.maybeCreate(camelCase("prototype", targetName, name)).apply {
android = AndroidKotlinSourceSet()
}
decoratedKotlinCompilationFactory = DecoratedKotlinCompilationFactory(::PrototypeAndroidCompilation)
compileTaskName = camelCase("prototype", "compile", targetName, name)
@@ -35,14 +41,14 @@ internal fun PrototypeAndroidTarget.createAndroidCompilation(name: String): Prot
configure { compilation ->
/* Setup attributes for the compile dependencies */
compilation.configurations.compileDependencyConfiguration.apply {
attributes.attribute(AndroidArtifacts.ARTIFACT_TYPE, AndroidArtifacts.ArtifactType.CLASSES_JAR.type)
attributes.attribute(TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE, project.objects.named(TargetJvmEnvironment.ANDROID))
attributes.attribute(ARTIFACT_TYPE, AndroidArtifacts.ArtifactType.CLASSES_JAR.type)
attributes.attribute(TARGET_JVM_ENVIRONMENT_ATTRIBUTE, project.objects.named(TargetJvmEnvironment.ANDROID))
}
/* Setup attributes for the runtime dependencies */
compilation.configurations.runtimeDependencyConfiguration?.apply {
attributes.attribute(AndroidArtifacts.ARTIFACT_TYPE, AndroidArtifacts.ArtifactType.CLASSES_JAR.type)
attributes.attribute(TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE, project.objects.named(TargetJvmEnvironment.ANDROID))
attributes.attribute(ARTIFACT_TYPE, AndroidArtifacts.ArtifactType.CLASSES_JAR.type)
attributes.attribute(TARGET_JVM_ENVIRONMENT_ATTRIBUTE, project.objects.named(TargetJvmEnvironment.ANDROID))
}
}
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.external
import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinTargetDescriptor.TargetFactory
import kotlin.properties.Delegates
@@ -21,12 +22,13 @@ interface ExternalKotlinTargetDescriptor<T : DecoratedExternalKotlinTarget> {
val platformType: KotlinPlatformType
val targetFactory: TargetFactory<T>
val configure: ((T) -> Unit)?
val apiElements: ExternalKotlinTargetConfigurationDescriptor<T>
val runtimeElements: ExternalKotlinTargetConfigurationDescriptor<T>
val apiElementsPublished: ExternalKotlinTargetConfigurationDescriptor<T>
val runtimeElementsPublished: ExternalKotlinTargetConfigurationDescriptor<T>
val configure: ((T) -> Unit)?
val configureIdeImport: (IdeMultiplatformImport.() -> Unit)?
}
@ExternalKotlinTargetApi
@@ -56,6 +58,20 @@ class ExternalKotlinTargetDescriptorBuilder<T : DecoratedExternalKotlinTarget> i
var configure: ((T) -> Unit)? = null
fun configure(action: (T) -> Unit) {
val configure = this.configure
if (configure == null) this.configure = action
else this.configure = { configure(it); action(it) }
}
var configureIdeImport: (IdeMultiplatformImport.() -> Unit)? = null
fun configureIdeImport(action: IdeMultiplatformImport.() -> Unit) {
val configureIdeImport = this.configureIdeImport
if (configureIdeImport == null) this.configureIdeImport = action
else this.configureIdeImport = { configureIdeImport(); action() }
}
internal fun build(): ExternalKotlinTargetDescriptor<T> = ExternalKotlinTargetDescriptorImpl(
targetName = targetName,
platformType = platformType,
@@ -64,7 +80,8 @@ class ExternalKotlinTargetDescriptorBuilder<T : DecoratedExternalKotlinTarget> i
runtimeElements = runtimeElements.build(),
apiElementsPublished = apiElementsPublished.build(),
runtimeElementsPublished = runtimeElementsPublished.build(),
configure = configure
configure = configure,
configureIdeImport = configureIdeImport
)
}
@@ -77,6 +94,7 @@ private data class ExternalKotlinTargetDescriptorImpl<T : DecoratedExternalKotli
override val apiElementsPublished: ExternalKotlinTargetConfigurationDescriptor<T>,
override val runtimeElementsPublished: ExternalKotlinTargetConfigurationDescriptor<T>,
override val configure: ((T) -> Unit)?,
override val configureIdeImport: (IdeMultiplatformImport.() -> Unit)?,
) : ExternalKotlinTargetDescriptor<T>
@@ -0,0 +1,14 @@
/*
* 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.plugin.mpp.external
import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.tooling.core.MutableExtras
@ExternalKotlinTargetApi
val KotlinSourceSet.extras: MutableExtras get() = this.internal.extras
@@ -13,6 +13,7 @@ import org.gradle.api.attributes.Usage
import org.gradle.jvm.tasks.Jar
import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.ide.kotlinIdeMultiplatformImport
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.markConsumable
import org.jetbrains.kotlin.gradle.plugin.usesPlatformOf
@@ -77,6 +78,7 @@ fun <T : DecoratedExternalKotlinTarget> KotlinMultiplatformExtension.createExter
descriptor.runtimeElements.configure?.invoke(decorated, runtimeElementsConfiguration)
descriptor.apiElementsPublished.configure?.invoke(decorated, apiElementsPublishedConfiguration)
descriptor.runtimeElementsPublished.configure?.invoke(decorated, runtimeElementsPublishedConfiguration)
descriptor.configureIdeImport?.invoke(project.kotlinIdeMultiplatformImport)
targets.add(decorated)
decorated.logger.info("Created ${descriptor.platformType} target")
@@ -11,14 +11,15 @@ import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.file.SourceDirectorySet
import org.jetbrains.kotlin.build.DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.tooling.core.MutableExtras
import org.jetbrains.kotlin.tooling.core.closure
import org.jetbrains.kotlin.tooling.core.mutableExtrasOf
import java.io.File
import java.util.*
import javax.inject.Inject
@@ -30,6 +31,8 @@ abstract class DefaultKotlinSourceSet @Inject constructor(
val displayName: String
) : AbstractKotlinSourceSet() {
override val extras: MutableExtras = mutableExtrasOf()
override val apiConfigurationName: String
get() = disambiguateName(API)
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.utils.MutableObservableSet
import org.jetbrains.kotlin.gradle.utils.ObservableSet
import org.jetbrains.kotlin.tooling.core.MutableExtras
internal val KotlinSourceSet.internal: InternalKotlinSourceSet
get() = (this as? InternalKotlinSourceSet) ?: throw IllegalArgumentException(
@@ -22,6 +23,7 @@ internal interface InternalKotlinSourceSet : KotlinSourceSet {
val dependsOnClosure: ObservableSet<KotlinSourceSet>
val withDependsOnClosure: ObservableSet<KotlinSourceSet>
val compilations: MutableObservableSet<KotlinCompilation<*>>
val extras: MutableExtras
}
internal val KotlinSourceSet.project: Project get() = this.internal.project
internal val KotlinSourceSet.project: Project get() = this.internal.project