[Gradle] Initial 'externalTargetApi' w/ compilable Android prototype
^KT-54766 Verification Pending
This commit is contained in:
committed by
Space Team
parent
33adebe5bf
commit
9599c16d95
+12
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
@RequiresOptIn(
|
||||||
|
message = "This API is intended to be used by Google to maintain KotlinTargets outside of kotlin.git",
|
||||||
|
level = RequiresOptIn.Level.ERROR
|
||||||
|
)
|
||||||
|
annotation class ExternalKotlinTargetApi
|
||||||
@@ -9,9 +9,16 @@ dependencies {
|
|||||||
compileOnly(project(":kotlin-gradle-plugin"))
|
compileOnly(project(":kotlin-gradle-plugin"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This module is just for local development / prototyping and demos */
|
configureKotlinCompileTasksGradleCompatibility()
|
||||||
if (!kotlinBuildProperties.isTeamcityBuild) {
|
|
||||||
tasks.register("install") {
|
kotlin {
|
||||||
dependsOn(tasks.named("publishToMavenLocal"))
|
sourceSets.all {
|
||||||
|
languageSettings.optIn("org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This module is just for local development / prototyping and demos */
|
||||||
|
if (!kotlinBuildProperties.isTeamcityBuild) {
|
||||||
|
publish()
|
||||||
|
standardPublicJars()
|
||||||
|
}
|
||||||
|
|||||||
+161
@@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("DEPRECATION", "DuplicatedCode")
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.android
|
||||||
|
|
||||||
|
import com.android.build.gradle.AppExtension
|
||||||
|
import com.android.build.gradle.internal.publishing.AndroidArtifacts
|
||||||
|
import org.gradle.api.attributes.Usage
|
||||||
|
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.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.mpp.external.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinTargetDescriptor.DecoratedExternalTargetFactory
|
||||||
|
|
||||||
|
@OptIn(ExternalVariantApi::class)
|
||||||
|
fun KotlinMultiplatformExtension.androidTargetPrototype(): PrototypeAndroidTarget {
|
||||||
|
val project = this.project
|
||||||
|
val androidExtension = project.extensions.getByType<AppExtension>()
|
||||||
|
|
||||||
|
/*
|
||||||
|
Set a variant filter and only allow 'debug'.
|
||||||
|
Reason: This prototype will not deal w/ buildTypes or flavors.
|
||||||
|
Only 'debug' will be supported. As of agreed w/ AGP team, this is the initial goal
|
||||||
|
for the APIs.
|
||||||
|
*/
|
||||||
|
androidExtension.variantFilter { variant ->
|
||||||
|
if (variant.name != "debug") {
|
||||||
|
variant.ignore = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create our 'AndroidTarget':
|
||||||
|
This uses the 'KotlinPlatformType.jvm' instead of androidJvm, since from the perspective of
|
||||||
|
Kotlin, this is just another 'jvm' like target (using the jvm compiler)
|
||||||
|
*/
|
||||||
|
val androidTarget = createExternalKotlinTarget<PrototypeAndroidTarget> {
|
||||||
|
targetName = "android"
|
||||||
|
platformType = KotlinPlatformType.jvm
|
||||||
|
decoratedExternalTargetFactory = DecoratedExternalTargetFactory { externalTarget ->
|
||||||
|
PrototypeAndroidTarget(externalTarget, PrototypeAndroidDsl(31))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Whilst using the .all hook, we only expect the single 'debug' variant to be available through this API.
|
||||||
|
*/
|
||||||
|
androidExtension.applicationVariants.all { applicationVariant ->
|
||||||
|
project.logger.quiet("Setting up applicationVariant: ${applicationVariant.name}")
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create Compilations: main, unitTest and instrumentedTest
|
||||||
|
(as proposed in the new Multiplatform/Android SourceSetLayout v2)
|
||||||
|
*/
|
||||||
|
val mainCompilation = androidTarget.createAndroidCompilation("main")
|
||||||
|
val unitTestCompilation = androidTarget.createAndroidCompilation("unitTest")
|
||||||
|
val instrumentedTestCompilation = androidTarget.createAndroidCompilation("instrumentedTest")
|
||||||
|
|
||||||
|
/*
|
||||||
|
Associate unitTest/instrumentedTest compilations with main
|
||||||
|
*/
|
||||||
|
unitTestCompilation.associateWith(mainCompilation)
|
||||||
|
instrumentedTestCompilation.associateWith(mainCompilation)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Setup dependsOn edges as in Multiplatform/Android SourceSetLayout v2:
|
||||||
|
android/main dependsOn commonMain
|
||||||
|
android/unitTest dependsOn commonTest
|
||||||
|
android/instrumentedTest *does not depend on a common SourceSet*
|
||||||
|
*/
|
||||||
|
mainCompilation.defaultSourceSet.dependsOn(sourceSets.getByName("commonMain"))
|
||||||
|
unitTestCompilation.defaultSourceSet.dependsOn(sourceSets.getByName("commonTest"))
|
||||||
|
|
||||||
|
/*
|
||||||
|
Wire the Kotlin Compilations output (.class files) into the Android artifacts
|
||||||
|
by using the 'registerPreJavacGeneratedBytecode' function
|
||||||
|
*/
|
||||||
|
applicationVariant.registerPreJavacGeneratedBytecode(mainCompilation.output.classesDirs)
|
||||||
|
applicationVariant.unitTestVariant.registerPreJavacGeneratedBytecode(unitTestCompilation.output.classesDirs)
|
||||||
|
applicationVariant.testVariant.registerPreJavacGeneratedBytecode(instrumentedTestCompilation.output.classesDirs)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add dependencies coming from Kotlin to Android by adding all dependencies from Kotlin to the variants
|
||||||
|
compileConfiguration or runtimeConfiguration
|
||||||
|
*/
|
||||||
|
applicationVariant.compileConfiguration.extendsFrom(mainCompilation.configurations.compileDependencyConfiguration)
|
||||||
|
applicationVariant.runtimeConfiguration.extendsFrom(mainCompilation.configurations.runtimeDependencyConfiguration)
|
||||||
|
applicationVariant.unitTestVariant.compileConfiguration.extendsFrom(unitTestCompilation.configurations.compileDependencyConfiguration)
|
||||||
|
applicationVariant.unitTestVariant.runtimeConfiguration.extendsFrom(unitTestCompilation.configurations.runtimeDependencyConfiguration)
|
||||||
|
applicationVariant.testVariant.compileConfiguration.extendsFrom(instrumentedTestCompilation.configurations.compileDependencyConfiguration)
|
||||||
|
applicationVariant.testVariant.runtimeConfiguration.extendsFrom(instrumentedTestCompilation.configurations.runtimeDependencyConfiguration)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add the 'android boot classpath' to the compilation dependencies to compile against
|
||||||
|
*/
|
||||||
|
mainCompilation.configurations.compileDependencyConfiguration.dependencies.add(
|
||||||
|
project.dependencies.create(project.androidBootClasspath())
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Setup apiElements configuration:
|
||||||
|
Usage: JAVA_API
|
||||||
|
jvmEnvironment: Android
|
||||||
|
variants:
|
||||||
|
- classes (provides access to the compiled .class files)
|
||||||
|
artifactType: CLASSES_JAR
|
||||||
|
*/
|
||||||
|
project.configurations.getByName(androidTarget.apiElementsConfigurationName).apply {
|
||||||
|
attributes.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_API))
|
||||||
|
attributes.attribute(TARGET_JVM_ENVIRONMENT_ATTRIBUTE, project.objects.named(TargetJvmEnvironment.ANDROID))
|
||||||
|
outgoing.variants.create("classes").let { variant ->
|
||||||
|
variant.attributes.attribute(AndroidArtifacts.ARTIFACT_TYPE, AndroidArtifacts.ArtifactType.CLASSES_JAR.type)
|
||||||
|
variant.artifact(mainCompilation.output.classesDirs.singleFile) {
|
||||||
|
it.builtBy(mainCompilation.output.classesDirs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Setup runtimeElements configuration:
|
||||||
|
Usage: JAVA_RUNTIME
|
||||||
|
jvmEnvironment: Android
|
||||||
|
variants:
|
||||||
|
- classes (provides access to the compiled .class files)
|
||||||
|
artifactType: CLASSES_JAR
|
||||||
|
*/
|
||||||
|
project.configurations.getByName(androidTarget.runtimeElementsConfigurationName).apply {
|
||||||
|
attributes.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
|
||||||
|
attributes.attribute(TARGET_JVM_ENVIRONMENT_ATTRIBUTE, project.objects.named(TargetJvmEnvironment.ANDROID))
|
||||||
|
outgoing.variants.create("classes").let { variant ->
|
||||||
|
variant.attributes.attribute(AndroidArtifacts.ARTIFACT_TYPE, AndroidArtifacts.ArtifactType.CLASSES_JAR.type)
|
||||||
|
variant.artifact(mainCompilation.output.classesDirs.singleFile) {
|
||||||
|
it.builtBy(mainCompilation.output.classesDirs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
"Disable" configurations from plain Android plugin
|
||||||
|
This hack will not be necessary in the final implementation
|
||||||
|
*/
|
||||||
|
project.configurations.findByName("${applicationVariant.name}ApiElements")?.isCanBeConsumed = false
|
||||||
|
project.configurations.findByName("${applicationVariant.name}RuntimeElements")?.isCanBeConsumed = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return androidTarget
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("DEPRECATION", "OVERRIDE_DEPRECATION")
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.android
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinCompilation
|
||||||
|
|
||||||
|
class PrototypeAndroidCompilation(delegate: Delegate) : ExternalKotlinCompilation(delegate) {
|
||||||
|
override val kotlinOptions: KotlinCommonOptions
|
||||||
|
get() = super.kotlinOptions as KotlinJvmOptions
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override val compilerOptions: HasCompilerOptions<KotlinJvmCompilerOptions>
|
||||||
|
get() = super.compilerOptions as HasCompilerOptions<KotlinJvmCompilerOptions>
|
||||||
|
|
||||||
|
var androidCompilationSpecificStuff = 10
|
||||||
|
}
|
||||||
|
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* 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.gradle.api.NamedDomainObjectContainer
|
||||||
|
import org.gradle.kotlin.dsl.getByType
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.external.DecoratedExternalKotlinTarget
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinTarget
|
||||||
|
|
||||||
|
data class PrototypeAndroidDsl(
|
||||||
|
var compileSdk: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
class PrototypeAndroidTarget(
|
||||||
|
private val target: ExternalKotlinTarget,
|
||||||
|
val androidDsl: PrototypeAndroidDsl
|
||||||
|
) : DecoratedExternalKotlinTarget(target) {
|
||||||
|
internal val kotlin = target.project.extensions.getByType<KotlinMultiplatformExtension>()
|
||||||
|
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
override val compilations: NamedDomainObjectContainer<PrototypeAndroidCompilation>
|
||||||
|
get() = target.compilations as NamedDomainObjectContainer<PrototypeAndroidCompilation>
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.android.build.gradle.BaseExtension
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.kotlin.dsl.getByType
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
|
internal fun Project.androidBootClasspath(): FileCollection {
|
||||||
|
return project.files(Callable { project.extensions.getByType<BaseExtension>().bootClasspath })
|
||||||
|
}
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.android.build.gradle.internal.publishing.AndroidArtifacts
|
||||||
|
import org.gradle.api.attributes.java.TargetJvmEnvironment
|
||||||
|
import org.gradle.kotlin.dsl.named
|
||||||
|
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))
|
||||||
|
decoratedKotlinCompilationFactory = DecoratedKotlinCompilationFactory(::PrototypeAndroidCompilation)
|
||||||
|
compileTaskName = camelCase("prototype", "compile", targetName, name)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Replace Kotlin's compilation association (main <-> test) with noop,
|
||||||
|
since Android goes through adding a dependency on the project itself
|
||||||
|
*/
|
||||||
|
compilationAssociator = ExternalKotlinCompilationDescriptor.CompilationAssociator { first, second ->
|
||||||
|
first.configurations.compileDependencyConfiguration.extendsFrom(
|
||||||
|
second.configurations.apiConfiguration,
|
||||||
|
second.configurations.implementationConfiguration,
|
||||||
|
second.configurations.compileOnlyConfiguration
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure the compilation before it is accessible for user code */
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("DEPRECATION")
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.android
|
||||||
|
|
||||||
|
fun camelCase(vararg parts: String): String {
|
||||||
|
if (parts.isEmpty()) return ""
|
||||||
|
return parts.joinToString("") { it.capitalize() }.decapitalize()
|
||||||
|
}
|
||||||
+2
-1
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsCompilerAttribute
|
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsCompilerAttribute
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
|
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
|
||||||
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
|
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
|
||||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
import org.jetbrains.kotlin.gradle.utils.*
|
import org.jetbrains.kotlin.gradle.utils.*
|
||||||
@@ -143,7 +144,7 @@ abstract class AbstractKotlinTargetConfigurator<KotlinTargetType : KotlinTarget>
|
|||||||
compilation.compileKotlinTaskProvider.map { it.outputs.files }
|
compilation.compileKotlinTaskProvider.map { it.outputs.files }
|
||||||
})
|
})
|
||||||
|
|
||||||
if (compilation is KotlinJvmCompilation && compilation.target.withJavaEnabled) {
|
if (compilation is KotlinJvmCompilation && (compilation.target as? KotlinJvmTarget)?.withJavaEnabled == true) {
|
||||||
it.inputs.files({ compilation.compileJavaTaskProvider?.map { it.outputs.files } })
|
it.inputs.files({ compilation.compileJavaTaskProvider?.map { it.outputs.files } })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+54
-62
@@ -20,16 +20,9 @@ import org.gradle.api.internal.component.SoftwareComponentInternal
|
|||||||
import org.gradle.api.internal.component.UsageContext
|
import org.gradle.api.internal.component.UsageContext
|
||||||
import org.gradle.api.internal.project.ProjectInternal
|
import org.gradle.api.internal.project.ProjectInternal
|
||||||
import org.gradle.api.publish.maven.MavenPublication
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
import org.gradle.api.tasks.TaskProvider
|
|
||||||
import org.gradle.jvm.tasks.Jar
|
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
import org.jetbrains.kotlin.gradle.plugin.*
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsSubTargetContainerDsl
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsSubTargetDsl
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.dependsOn
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
|
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
|
||||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
|
||||||
@@ -84,61 +77,7 @@ abstract class AbstractKotlinTarget(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override val components: Set<SoftwareComponent> by lazy {
|
override val components: Set<SoftwareComponent> by lazy {
|
||||||
buildAdhocComponentsFromKotlinVariants(kotlinComponents)
|
project.buildAdhocComponentsFromKotlinVariants(kotlinComponents)
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildAdhocComponentsFromKotlinVariants(kotlinVariants: Set<KotlinTargetComponent>): Set<SoftwareComponent> {
|
|
||||||
val softwareComponentFactoryClass = SoftwareComponentFactory::class.java
|
|
||||||
// TODO replace internal API access with injection (not possible until we have this class on the compile classpath)
|
|
||||||
val softwareComponentFactory = (project as ProjectInternal).services.get(softwareComponentFactoryClass)
|
|
||||||
|
|
||||||
return kotlinVariants.map { kotlinVariant ->
|
|
||||||
val adhocVariant = softwareComponentFactory.adhoc(kotlinVariant.name)
|
|
||||||
|
|
||||||
project.whenEvaluated {
|
|
||||||
(kotlinVariant as SoftwareComponentInternal).usages.filterIsInstance<KotlinUsageContext>().forEach { kotlinUsageContext ->
|
|
||||||
val publishedConfigurationName = publishedConfigurationName(kotlinUsageContext.name)
|
|
||||||
val configuration = project.configurations.findByName(publishedConfigurationName)
|
|
||||||
?: project.configurations.create(publishedConfigurationName).also { configuration ->
|
|
||||||
configuration.isCanBeConsumed = false
|
|
||||||
configuration.isCanBeResolved = false
|
|
||||||
configuration.extendsFrom(project.configurations.getByName(kotlinUsageContext.dependencyConfigurationName))
|
|
||||||
configuration.artifacts.addAll(kotlinUsageContext.artifacts)
|
|
||||||
|
|
||||||
val attributes = kotlinUsageContext.attributes
|
|
||||||
attributes.keySet().forEach {
|
|
||||||
// capture type parameter T
|
|
||||||
fun <T> copyAttribute(key: Attribute<T>, from: AttributeContainer, to: AttributeContainer) {
|
|
||||||
to.attribute(key, from.getAttribute(key)!!)
|
|
||||||
}
|
|
||||||
copyAttribute(it, attributes, configuration.attributes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
adhocVariant.addVariantsFromConfiguration(configuration) { configurationVariantDetails ->
|
|
||||||
val mavenScope = when (kotlinUsageContext.usage.name) {
|
|
||||||
"java-api-jars" -> "compile"
|
|
||||||
"java-runtime-jars" -> "runtime"
|
|
||||||
else -> error("unexpected usage value '${kotlinUsageContext.usage.name}'")
|
|
||||||
}
|
|
||||||
configurationVariantDetails.mapToMavenScope(mavenScope)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
adhocVariant as SoftwareComponent
|
|
||||||
|
|
||||||
object : ComponentWithVariants, ComponentWithCoordinates, SoftwareComponentInternal {
|
|
||||||
override fun getCoordinates() =
|
|
||||||
(kotlinVariant as? ComponentWithCoordinates)?.coordinates ?: error("kotlinVariant is not ComponentWithCoordinates")
|
|
||||||
|
|
||||||
override fun getVariants(): Set<SoftwareComponent> =
|
|
||||||
(kotlinVariant as? KotlinVariantWithMetadataVariant)?.variants.orEmpty()
|
|
||||||
|
|
||||||
override fun getName(): String = adhocVariant.name
|
|
||||||
override fun getUsages(): MutableSet<out UsageContext> = (adhocVariant as SoftwareComponentInternal).usages
|
|
||||||
}
|
|
||||||
}.toSet()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun createKotlinVariant(
|
protected open fun createKotlinVariant(
|
||||||
@@ -228,3 +167,56 @@ internal fun KotlinTarget.disambiguateName(simpleName: String) =
|
|||||||
|
|
||||||
internal fun javaApiUsageForMavenScoping() = "java-api-jars"
|
internal fun javaApiUsageForMavenScoping() = "java-api-jars"
|
||||||
|
|
||||||
|
internal fun Project.buildAdhocComponentsFromKotlinVariants(kotlinVariants: Set<KotlinTargetComponent>): Set<SoftwareComponent> {
|
||||||
|
val softwareComponentFactoryClass = SoftwareComponentFactory::class.java
|
||||||
|
// TODO replace internal API access with injection (not possible until we have this class on the compile classpath)
|
||||||
|
val softwareComponentFactory = (project as ProjectInternal).services.get(softwareComponentFactoryClass)
|
||||||
|
|
||||||
|
return kotlinVariants.map { kotlinVariant ->
|
||||||
|
val adhocVariant = softwareComponentFactory.adhoc(kotlinVariant.name)
|
||||||
|
|
||||||
|
project.whenEvaluated {
|
||||||
|
(kotlinVariant as SoftwareComponentInternal).usages.filterIsInstance<KotlinUsageContext>().forEach { kotlinUsageContext ->
|
||||||
|
val publishedConfigurationName = publishedConfigurationName(kotlinUsageContext.name)
|
||||||
|
val configuration = project.configurations.findByName(publishedConfigurationName)
|
||||||
|
?: project.configurations.create(publishedConfigurationName).also { configuration ->
|
||||||
|
configuration.isCanBeConsumed = false
|
||||||
|
configuration.isCanBeResolved = false
|
||||||
|
configuration.extendsFrom(project.configurations.getByName(kotlinUsageContext.dependencyConfigurationName))
|
||||||
|
configuration.artifacts.addAll(kotlinUsageContext.artifacts)
|
||||||
|
|
||||||
|
val attributes = kotlinUsageContext.attributes
|
||||||
|
attributes.keySet().forEach {
|
||||||
|
// capture type parameter T
|
||||||
|
fun <T> copyAttribute(key: Attribute<T>, from: AttributeContainer, to: AttributeContainer) {
|
||||||
|
to.attribute(key, from.getAttribute(key)!!)
|
||||||
|
}
|
||||||
|
copyAttribute(it, attributes, configuration.attributes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adhocVariant.addVariantsFromConfiguration(configuration) { configurationVariantDetails ->
|
||||||
|
val mavenScope = when (kotlinUsageContext.usage.name) {
|
||||||
|
"java-api-jars" -> "compile"
|
||||||
|
"java-runtime-jars" -> "runtime"
|
||||||
|
else -> error("unexpected usage value '${kotlinUsageContext.usage.name}'")
|
||||||
|
}
|
||||||
|
configurationVariantDetails.mapToMavenScope(mavenScope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adhocVariant as SoftwareComponent
|
||||||
|
|
||||||
|
object : ComponentWithVariants, ComponentWithCoordinates, SoftwareComponentInternal {
|
||||||
|
override fun getCoordinates() =
|
||||||
|
(kotlinVariant as? ComponentWithCoordinates)?.coordinates ?: error("kotlinVariant is not ComponentWithCoordinates")
|
||||||
|
|
||||||
|
override fun getVariants(): Set<SoftwareComponent> =
|
||||||
|
(kotlinVariant as? KotlinVariantWithMetadataVariant)?.variants.orEmpty()
|
||||||
|
|
||||||
|
override fun getName(): String = adhocVariant.name
|
||||||
|
override fun getUsages(): MutableSet<out UsageContext> = (adhocVariant as SoftwareComponentInternal).usages
|
||||||
|
}
|
||||||
|
}.toSet()
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
|
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinDependencyHandler
|
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinDependencyHandler
|
||||||
|
|
||||||
internal interface KotlinCompilationConfigurationsContainer {
|
interface KotlinCompilationConfigurationsContainer {
|
||||||
val deprecatedCompileConfiguration: Configuration?
|
val deprecatedCompileConfiguration: Configuration?
|
||||||
val deprecatedRuntimeConfiguration: Configuration?
|
val deprecatedRuntimeConfiguration: Configuration?
|
||||||
val apiConfiguration: Configuration
|
val apiConfiguration: Configuration
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@ internal class DefaultKotlinCompilationFriendPathsResolver(
|
|||||||
|
|
||||||
/* Resolution of friend artifacts */
|
/* Resolution of friend artifacts */
|
||||||
|
|
||||||
interface FriendArtifactResolver {
|
fun interface FriendArtifactResolver {
|
||||||
fun resolveFriendArtifacts(compilation: InternalKotlinCompilation<*>): FileCollection
|
fun resolveFriendArtifacts(compilation: InternalKotlinCompilation<*>): FileCollection
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+1
-3
@@ -25,10 +25,8 @@ import org.jetbrains.kotlin.gradle.tasks.locateTask
|
|||||||
import org.jetbrains.kotlin.gradle.utils.ObservableSet
|
import org.jetbrains.kotlin.gradle.utils.ObservableSet
|
||||||
import org.jetbrains.kotlin.tooling.core.MutableExtras
|
import org.jetbrains.kotlin.tooling.core.MutableExtras
|
||||||
import org.jetbrains.kotlin.tooling.core.mutableExtrasOf
|
import org.jetbrains.kotlin.tooling.core.mutableExtrasOf
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
|
internal class KotlinCompilationImpl constructor(
|
||||||
internal class KotlinCompilationImpl @Inject constructor(
|
|
||||||
private val params: Params
|
private val params: Params
|
||||||
) : InternalKotlinCompilation<KotlinCommonOptions> {
|
) : InternalKotlinCompilation<KotlinCommonOptions> {
|
||||||
|
|
||||||
|
|||||||
+14
@@ -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.KotlinTarget
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
abstract class DecoratedExternalKotlinTarget(
|
||||||
|
internal val delegate: ExternalKotlinTarget
|
||||||
|
) : KotlinTarget by delegate
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("DEPRECATION")
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.plugin.mpp.external
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.DecoratedKotlinCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationImpl
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
abstract class ExternalKotlinCompilation(delegate: Delegate) :
|
||||||
|
DecoratedKotlinCompilation<KotlinCommonOptions>(delegate.compilation) {
|
||||||
|
class Delegate internal constructor(internal val compilation: KotlinCompilationImpl)
|
||||||
|
}
|
||||||
+98
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* 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.gradle.api.file.FileCollection
|
||||||
|
import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.DecoratedKotlinCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinCompilationDescriptor.*
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
interface ExternalKotlinCompilationDescriptor<T : ExternalKotlinCompilation> {
|
||||||
|
fun interface DecoratedKotlinCompilationFactory<T : DecoratedKotlinCompilation<*>> {
|
||||||
|
fun create(delegate: ExternalKotlinCompilation.Delegate): T
|
||||||
|
}
|
||||||
|
|
||||||
|
fun interface FriendArtifactResolver<T : ExternalKotlinCompilation> {
|
||||||
|
fun resolveFriendPaths(compilation: T): FileCollection
|
||||||
|
}
|
||||||
|
|
||||||
|
fun interface CompilationAssociator<T : ExternalKotlinCompilation> {
|
||||||
|
fun associate(compilation: T, main: ExternalKotlinCompilation)
|
||||||
|
}
|
||||||
|
|
||||||
|
val compilationName: String
|
||||||
|
val compileTaskName: String?
|
||||||
|
val compileAllTaskName: String?
|
||||||
|
val defaultSourceSet: KotlinSourceSet
|
||||||
|
val decoratedKotlinCompilationFactory: DecoratedKotlinCompilationFactory<T>
|
||||||
|
val friendArtifactResolver: FriendArtifactResolver<T>?
|
||||||
|
val compilationAssociator: CompilationAssociator<T>?
|
||||||
|
val configure: ((T) -> Unit)?
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
fun <T : ExternalKotlinCompilation> ExternalKotlinCompilationDescriptor(
|
||||||
|
configure: ExternalKotlinCompilationDescriptorBuilder<T>.() -> Unit
|
||||||
|
): ExternalKotlinCompilationDescriptor<T> {
|
||||||
|
return ExternalKotlinCompilationDescriptorBuilderImpl<T>().also(configure).run {
|
||||||
|
ExternalKotlinCompilationDescriptorImpl(
|
||||||
|
compilationName = compilationName,
|
||||||
|
compileTaskName = compileTaskName,
|
||||||
|
compileAllTaskName = compileAllTaskName,
|
||||||
|
defaultSourceSet = defaultSourceSet,
|
||||||
|
decoratedKotlinCompilationFactory = decoratedKotlinCompilationFactory,
|
||||||
|
friendArtifactResolver = friendArtifactResolver,
|
||||||
|
compilationAssociator = compilationAssociator,
|
||||||
|
configure = this.configure
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
interface ExternalKotlinCompilationDescriptorBuilder<T : ExternalKotlinCompilation> {
|
||||||
|
var compilationName: String
|
||||||
|
var compileTaskName: String?
|
||||||
|
var compileAllTaskName: String?
|
||||||
|
var defaultSourceSet: KotlinSourceSet
|
||||||
|
var decoratedKotlinCompilationFactory: DecoratedKotlinCompilationFactory<T>
|
||||||
|
var friendArtifactResolver: FriendArtifactResolver<T>?
|
||||||
|
var compilationAssociator: CompilationAssociator<T>?
|
||||||
|
var configure: ((T) -> Unit)?
|
||||||
|
fun configure(action: (T) -> Unit) = apply {
|
||||||
|
val configure = this.configure
|
||||||
|
if (configure == null) this.configure = action
|
||||||
|
else this.configure = { configure(it); action(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
private class ExternalKotlinCompilationDescriptorBuilderImpl<T : ExternalKotlinCompilation> :
|
||||||
|
ExternalKotlinCompilationDescriptorBuilder<T> {
|
||||||
|
override var compilationName: String by Delegates.notNull()
|
||||||
|
override var compileTaskName: String? = null
|
||||||
|
override var compileAllTaskName: String? = null
|
||||||
|
override var defaultSourceSet: KotlinSourceSet by Delegates.notNull()
|
||||||
|
override var decoratedKotlinCompilationFactory: DecoratedKotlinCompilationFactory<T> by Delegates.notNull()
|
||||||
|
override var friendArtifactResolver: FriendArtifactResolver<T>? = null
|
||||||
|
override var compilationAssociator: CompilationAssociator<T>? = null
|
||||||
|
override var configure: ((T) -> Unit)? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
private data class ExternalKotlinCompilationDescriptorImpl<T : ExternalKotlinCompilation>(
|
||||||
|
override val compilationName: String,
|
||||||
|
override val compileTaskName: String?,
|
||||||
|
override val compileAllTaskName: String?,
|
||||||
|
override val defaultSourceSet: KotlinSourceSet,
|
||||||
|
override val decoratedKotlinCompilationFactory: DecoratedKotlinCompilationFactory<T>,
|
||||||
|
override val friendArtifactResolver: FriendArtifactResolver<T>?,
|
||||||
|
override val compilationAssociator: CompilationAssociator<T>?,
|
||||||
|
override val configure: ((T) -> Unit)?
|
||||||
|
) : ExternalKotlinCompilationDescriptor<T>
|
||||||
+85
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* 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.gradle.api.Action
|
||||||
|
import org.gradle.api.NamedDomainObjectContainer
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.api.artifacts.Configuration
|
||||||
|
import org.gradle.api.attributes.AttributeContainer
|
||||||
|
import org.gradle.api.component.SoftwareComponent
|
||||||
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
|
import org.gradle.api.tasks.TaskProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.buildAdhocComponentsFromKotlinVariants
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
class ExternalKotlinTarget internal constructor(
|
||||||
|
override val project: Project,
|
||||||
|
override val targetName: String,
|
||||||
|
override val platformType: KotlinPlatformType,
|
||||||
|
val defaultConfiguration: Configuration,
|
||||||
|
val apiElementsConfiguration: Configuration,
|
||||||
|
val runtimeElementsConfiguration: Configuration,
|
||||||
|
override val publishable: Boolean,
|
||||||
|
internal val kotlinComponents: Set<KotlinTargetComponent>,
|
||||||
|
private val artifactsTaskLocator: ArtifactsTaskLocator,
|
||||||
|
) : KotlinTarget {
|
||||||
|
|
||||||
|
fun interface ArtifactsTaskLocator {
|
||||||
|
fun locate(target: ExternalKotlinTarget): TaskProvider<out Task>
|
||||||
|
}
|
||||||
|
|
||||||
|
val kotlin = project.multiplatformExtension
|
||||||
|
|
||||||
|
override val useDisambiguationClassifierAsSourceSetNamePrefix: Boolean = true
|
||||||
|
|
||||||
|
override val overrideDisambiguationClassifierOnIdeImport: String? = null
|
||||||
|
|
||||||
|
val artifactsTask: TaskProvider<out Task> by lazy {
|
||||||
|
artifactsTaskLocator.locate(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val artifactsTaskName: String
|
||||||
|
get() = artifactsTask.name
|
||||||
|
|
||||||
|
override val defaultConfigurationName: String
|
||||||
|
get() = defaultConfiguration.name
|
||||||
|
|
||||||
|
override val apiElementsConfigurationName: String
|
||||||
|
get() = apiElementsConfiguration.name
|
||||||
|
|
||||||
|
override val runtimeElementsConfigurationName: String
|
||||||
|
get() = runtimeElementsConfiguration.name
|
||||||
|
|
||||||
|
override val components: Set<SoftwareComponent> by lazy {
|
||||||
|
project.buildAdhocComponentsFromKotlinVariants(kotlinComponents)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val compilations: NamedDomainObjectContainer<ExternalKotlinCompilation> by lazy {
|
||||||
|
project.container(ExternalKotlinCompilation::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mavenPublication(action: Action<MavenPublication>) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override val preset: Nothing? = null
|
||||||
|
|
||||||
|
override fun getAttributes(): AttributeContainer {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun onCreated() {
|
||||||
|
artifactsTask
|
||||||
|
components
|
||||||
|
}
|
||||||
|
}
|
||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* 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.KotlinPlatformType
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinTargetDescriptor.DecoratedExternalTargetFactory
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
interface ExternalKotlinTargetDescriptor<T : DecoratedExternalKotlinTarget> {
|
||||||
|
|
||||||
|
fun interface DecoratedExternalTargetFactory<T : DecoratedExternalKotlinTarget> {
|
||||||
|
fun create(target: ExternalKotlinTarget): T
|
||||||
|
}
|
||||||
|
|
||||||
|
val targetName: String
|
||||||
|
val platformType: KotlinPlatformType
|
||||||
|
val decoratedExternalTargetFactory: DecoratedExternalTargetFactory<T>
|
||||||
|
val configure: ((T) -> Unit)?
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
interface ExternalKotlinTargetDescriptorBuilder<T : DecoratedExternalKotlinTarget> {
|
||||||
|
var targetName: String
|
||||||
|
var platformType: KotlinPlatformType
|
||||||
|
var decoratedExternalTargetFactory: DecoratedExternalTargetFactory<T>
|
||||||
|
var configure: ((T) -> Unit)?
|
||||||
|
fun configure(action: (T) -> Unit) = apply {
|
||||||
|
val configure = this.configure
|
||||||
|
if (configure == null) this.configure = action
|
||||||
|
else this.configure = { configure(it); action(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
fun <T : DecoratedExternalKotlinTarget> ExternalKotlinTargetDescriptor(
|
||||||
|
configure: ExternalKotlinTargetDescriptorBuilder<T>.() -> Unit
|
||||||
|
): ExternalKotlinTargetDescriptor<T> {
|
||||||
|
return ExternalKotlinTargetDescriptorBuilderImpl<T>().also(configure).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
private class ExternalKotlinTargetDescriptorBuilderImpl<T : DecoratedExternalKotlinTarget> : ExternalKotlinTargetDescriptorBuilder<T> {
|
||||||
|
override var targetName: String by Delegates.notNull()
|
||||||
|
override var platformType: KotlinPlatformType by Delegates.notNull()
|
||||||
|
override var decoratedExternalTargetFactory: DecoratedExternalTargetFactory<T> by Delegates.notNull()
|
||||||
|
override var configure: ((T) -> Unit)? = null
|
||||||
|
|
||||||
|
fun build(): ExternalKotlinTargetDescriptorImpl<T> = ExternalKotlinTargetDescriptorImpl(
|
||||||
|
targetName = targetName,
|
||||||
|
platformType = platformType,
|
||||||
|
decoratedExternalTargetFactory = decoratedExternalTargetFactory,
|
||||||
|
configure = configure
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
private data class ExternalKotlinTargetDescriptorImpl<T : DecoratedExternalKotlinTarget>(
|
||||||
|
override val targetName: String,
|
||||||
|
override val platformType: KotlinPlatformType,
|
||||||
|
override val decoratedExternalTargetFactory: DecoratedExternalTargetFactory<T>,
|
||||||
|
override val configure: ((T) -> Unit)?
|
||||||
|
) : ExternalKotlinTargetDescriptor<T>
|
||||||
|
|
||||||
|
|
||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* 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.Kotlin2JvmSourceSetProcessor
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationInfo
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.DefaultKotlinCompilationAssociator
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.DefaultKotlinCompilationFriendPathsResolver
|
||||||
|
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.ExternalKotlinCompilation.Delegate
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.configuration.KotlinCompileConfig
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
fun <T : ExternalKotlinCompilation> DecoratedExternalKotlinTarget.createCompilation(
|
||||||
|
descriptor: ExternalKotlinCompilationDescriptor<T>
|
||||||
|
): T {
|
||||||
|
val compilationImplFactory = KotlinCompilationImplFactory(
|
||||||
|
compilerOptionsFactory = when (platformType) {
|
||||||
|
KotlinPlatformType.common -> KotlinMultiplatformCommonCompilerOptionsFactory
|
||||||
|
KotlinPlatformType.jvm -> KotlinJvmCompilerOptionsFactory
|
||||||
|
KotlinPlatformType.androidJvm -> KotlinJvmCompilerOptionsFactory
|
||||||
|
KotlinPlatformType.js -> KotlinJsCompilerOptionsFactory
|
||||||
|
KotlinPlatformType.native -> KotlinNativeCompilerOptionsFactory
|
||||||
|
KotlinPlatformType.wasm -> KotlinMultiplatformCommonCompilerOptionsFactory
|
||||||
|
},
|
||||||
|
compilationSourceSetsContainerFactory = { _, _ -> KotlinCompilationSourceSetsContainer(descriptor.defaultSourceSet) },
|
||||||
|
compilationTaskNamesContainerFactory = KotlinCompilationTaskNamesContainerFactory { target, compilationName ->
|
||||||
|
val default = DefaultKotlinCompilationTaskNamesContainerFactory.create(target, compilationName)
|
||||||
|
default.copy(
|
||||||
|
compileTaskName = descriptor.compileTaskName ?: default.compileTaskName,
|
||||||
|
compileAllTaskName = descriptor.compileAllTaskName ?: default.compileAllTaskName
|
||||||
|
)
|
||||||
|
},
|
||||||
|
compilationAssociator = descriptor.compilationAssociator?.let { declaredAssociator ->
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
KotlinCompilationAssociator { _, first, second ->
|
||||||
|
declaredAssociator.associate(first.decoratedInstance as T, second.decoratedInstance as ExternalKotlinCompilation)
|
||||||
|
}
|
||||||
|
} ?: DefaultKotlinCompilationAssociator,
|
||||||
|
compilationFriendPathsResolver = DefaultKotlinCompilationFriendPathsResolver(
|
||||||
|
DefaultKotlinCompilationFriendPathsResolver.FriendArtifactResolver.composite(
|
||||||
|
DefaultKotlinCompilationFriendPathsResolver.DefaultFriendArtifactResolver,
|
||||||
|
descriptor.friendArtifactResolver?.let { declaredResolver ->
|
||||||
|
DefaultKotlinCompilationFriendPathsResolver.FriendArtifactResolver { compilation ->
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
declaredResolver.resolveFriendPaths(compilation as T)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val compilationImpl = compilationImplFactory.create(this, descriptor.compilationName)
|
||||||
|
val decoratedCompilation = descriptor.decoratedKotlinCompilationFactory.create(Delegate(compilationImpl))
|
||||||
|
descriptor.configure?.invoke(decoratedCompilation)
|
||||||
|
this.delegate.compilations.add(decoratedCompilation)
|
||||||
|
|
||||||
|
|
||||||
|
val tasksProvider = KotlinTasksProvider()
|
||||||
|
val compilationInfo = KotlinCompilationInfo(decoratedCompilation)
|
||||||
|
|
||||||
|
val config = KotlinCompileConfig(compilationInfo)
|
||||||
|
config.configureTask { task ->
|
||||||
|
task.useModuleDetection.value(true).disallowChanges()
|
||||||
|
task.destinationDirectory.set(project.layout.buildDirectory.dir("tmp/kotlin-classes/debug"))
|
||||||
|
}
|
||||||
|
|
||||||
|
Kotlin2JvmSourceSetProcessor(tasksProvider, compilationInfo).run()
|
||||||
|
project.logger.quiet("Registered: ${compilationInfo.compileKotlinTaskName}")
|
||||||
|
|
||||||
|
return decoratedCompilation
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
fun <T : ExternalKotlinCompilation> DecoratedExternalKotlinTarget.createCompilation(
|
||||||
|
descriptor: ExternalKotlinCompilationDescriptorBuilder<T>.() -> Unit
|
||||||
|
): T {
|
||||||
|
return createCompilation(ExternalKotlinCompilationDescriptor(descriptor))
|
||||||
|
}
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:OptIn(ExternalKotlinTargetApi::class)
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.plugin.mpp.external
|
||||||
|
|
||||||
|
import org.gradle.jvm.tasks.Jar
|
||||||
|
import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
fun <T : DecoratedExternalKotlinTarget> KotlinMultiplatformExtension.createExternalKotlinTarget(
|
||||||
|
descriptor: ExternalKotlinTargetDescriptor<T>
|
||||||
|
): T {
|
||||||
|
val defaultConfiguration = project.configurations.maybeCreate(lowerCamelCaseName(descriptor.targetName, "default"))
|
||||||
|
val apiElementsConfiguration = project.configurations.maybeCreate(lowerCamelCaseName(descriptor.targetName, "apiElements"))
|
||||||
|
val runtimeElementsConfiguration = project.configurations.maybeCreate(lowerCamelCaseName(descriptor.targetName, "runtimeElements"))
|
||||||
|
val artifactsTaskLocator = ExternalKotlinTarget.ArtifactsTaskLocator { target ->
|
||||||
|
target.project.locateOrRegisterTask<Jar>(lowerCamelCaseName(descriptor.targetName, "jar"))
|
||||||
|
}
|
||||||
|
|
||||||
|
val target = ExternalKotlinTarget(
|
||||||
|
project = project,
|
||||||
|
targetName = descriptor.targetName,
|
||||||
|
platformType = descriptor.platformType,
|
||||||
|
defaultConfiguration = defaultConfiguration,
|
||||||
|
apiElementsConfiguration = apiElementsConfiguration,
|
||||||
|
runtimeElementsConfiguration = runtimeElementsConfiguration,
|
||||||
|
publishable = true,
|
||||||
|
kotlinComponents = emptySet(),
|
||||||
|
artifactsTaskLocator = artifactsTaskLocator
|
||||||
|
)
|
||||||
|
|
||||||
|
val decorated = descriptor.decoratedExternalTargetFactory.create(target)
|
||||||
|
target.onCreated()
|
||||||
|
descriptor.configure?.invoke(decorated)
|
||||||
|
targets.add(decorated)
|
||||||
|
return decorated
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExternalKotlinTargetApi
|
||||||
|
fun <T : DecoratedExternalKotlinTarget> KotlinMultiplatformExtension.createExternalKotlinTarget(
|
||||||
|
descriptor: ExternalKotlinTargetDescriptorBuilder<T>.() -> Unit
|
||||||
|
): T {
|
||||||
|
return createExternalKotlinTarget(ExternalKotlinTargetDescriptor(descriptor))
|
||||||
|
}
|
||||||
+8
-3
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle
|
package org.jetbrains.kotlin.gradle
|
||||||
|
|
||||||
|
import com.android.build.api.dsl.ApplicationExtension
|
||||||
import com.android.build.gradle.LibraryExtension
|
import com.android.build.gradle.LibraryExtension
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.internal.project.ProjectInternal
|
import org.gradle.api.internal.project.ProjectInternal
|
||||||
@@ -13,7 +14,6 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
|||||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
import org.jetbrains.kotlin.gradle.kpm.applyKpmPlugin
|
import org.jetbrains.kotlin.gradle.kpm.applyKpmPlugin
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformJvmPlugin
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformJvmPlugin
|
||||||
import org.jetbrains.kotlin.gradle.plugin.extraProperties
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension
|
||||||
|
|
||||||
fun buildProject(
|
fun buildProject(
|
||||||
@@ -51,8 +51,13 @@ fun Project.kotlin(code: KotlinMultiplatformExtension.() -> Unit) {
|
|||||||
|
|
||||||
fun Project.androidLibrary(code: LibraryExtension.() -> Unit) {
|
fun Project.androidLibrary(code: LibraryExtension.() -> Unit) {
|
||||||
plugins.findPlugin("com.android.library") ?: plugins.apply("com.android.library")
|
plugins.findPlugin("com.android.library") ?: plugins.apply("com.android.library")
|
||||||
val androidExtension = project.extensions.findByName("android") as? LibraryExtension
|
val androidExtension = project.extensions.getByName("android") as LibraryExtension
|
||||||
?: throw IllegalStateException("Android library extension is missing in project")
|
androidExtension.code()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Project.androidApplication(code: ApplicationExtension.() -> Unit) {
|
||||||
|
plugins.findPlugin("com.android.application") ?: plugins.apply("com.android.application")
|
||||||
|
val androidExtension = project.extensions.getByName("android") as ApplicationExtension
|
||||||
androidExtension.code()
|
androidExtension.code()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("FunctionName")
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.externalTargetApi
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.android.androidTargetPrototype
|
||||||
|
import org.jetbrains.kotlin.gradle.androidApplication
|
||||||
|
import org.jetbrains.kotlin.gradle.buildProjectWithMPP
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.kpm.idea.mavenCentralCacheRedirector
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class ExternalAndroidTargetPrototypeSmokeTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `apply prototype - evaluate - compilations exist`() {
|
||||||
|
val project = buildProjectWithMPP()
|
||||||
|
project.androidApplication { compileSdk = 31 }
|
||||||
|
val androidTargetPrototype = project.multiplatformExtension.androidTargetPrototype()
|
||||||
|
project.evaluate()
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
setOf("main", "unitTest", "instrumentedTest"),
|
||||||
|
androidTargetPrototype.compilations.map { it.name }.toSet()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `apply prototype - evaluate - configurations can be resolved`() {
|
||||||
|
val project = buildProjectWithMPP()
|
||||||
|
project.androidApplication { compileSdk = 31 }
|
||||||
|
|
||||||
|
val androidTargetPrototype = project.multiplatformExtension.androidTargetPrototype()
|
||||||
|
project.repositories.mavenLocal()
|
||||||
|
project.repositories.mavenCentralCacheRedirector()
|
||||||
|
project.evaluate()
|
||||||
|
|
||||||
|
androidTargetPrototype.compilations.all { compilation ->
|
||||||
|
compilation.compileDependencyFiles.files
|
||||||
|
compilation.runtimeDependencyFiles?.files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user