[Gradle] Create archive tasks for custom compilations
This change is needed for kotlin-test in order to support correct project dependencies in kotlin.git repository. ^KT-62943 Verification Pending
This commit is contained in:
committed by
Space Team
parent
e747793e62
commit
f2ddae533e
+6
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.Companion.jsCompi
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_ABI_SNAPSHOT
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_COMPILER_KEEP_INCREMENTAL_COMPILATION_CACHES_IN_MEMORY
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_COMPILER_USE_PRECISE_COMPILATION_RESULTS_BACKUP
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_CREATE_ARCHIVE_TASKS_FOR_CUSTOM_COMPILATIONS
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_CREATE_DEFAULT_MULTIPLATFORM_PUBLICATIONS
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_EXPERIMENTAL_TRY_K2
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_INTERNAL_DIAGNOSTICS_SHOW_STACKTRACE
|
||||
@@ -477,6 +478,9 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
val createDefaultMultiplatformPublications: Boolean
|
||||
get() = booleanProperty(KOTLIN_CREATE_DEFAULT_MULTIPLATFORM_PUBLICATIONS) ?: true
|
||||
|
||||
val createArchiveTasksForCustomCompilations: Boolean
|
||||
get() = booleanProperty(KOTLIN_CREATE_ARCHIVE_TASKS_FOR_CUSTOM_COMPILATIONS) ?: false
|
||||
|
||||
val runKotlinCompilerViaBuildToolsApi: Boolean
|
||||
get() = booleanProperty(KOTLIN_RUN_COMPILER_VIA_BUILD_TOOLS_API) ?: false
|
||||
|
||||
@@ -636,6 +640,8 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
val KOTLIN_INTERNAL_DIAGNOSTICS_SHOW_STACKTRACE = property("$KOTLIN_INTERNAL_NAMESPACE.diagnostics.showStacktrace")
|
||||
val KOTLIN_SUPPRESS_GRADLE_PLUGIN_ERRORS = property("$KOTLIN_INTERNAL_NAMESPACE.suppressGradlePluginErrors")
|
||||
val MPP_13X_FLAGS_SET_BY_PLUGIN = property("$KOTLIN_INTERNAL_NAMESPACE.mpp.13X.flags.setByPlugin")
|
||||
val KOTLIN_CREATE_ARCHIVE_TASKS_FOR_CUSTOM_COMPILATIONS =
|
||||
property("$KOTLIN_INTERNAL_NAMESPACE.mpp.createArchiveTasksForCustomCompilations")
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+5
@@ -27,6 +27,11 @@ internal interface InternalKotlinCompilation<out T : KotlinCommonOptions> : Kotl
|
||||
val configurations: KotlinCompilationConfigurationsContainer
|
||||
val friendPaths: Iterable<FileCollection>
|
||||
val processResourcesTaskName: String?
|
||||
|
||||
/**
|
||||
* @see [org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationArchiveTasks]
|
||||
*/
|
||||
val archiveTaskName: String?
|
||||
}
|
||||
|
||||
internal val <T : KotlinCommonOptions> KotlinCompilation<T>.internal: InternalKotlinCompilation<T>
|
||||
|
||||
+2
@@ -164,6 +164,8 @@ internal class KotlinCompilationImpl constructor(
|
||||
|
||||
//endregion
|
||||
|
||||
override val archiveTaskName: String?
|
||||
get() = project.kotlinCompilationArchiveTasksOrNull?.getArchiveTaskOrNull(this)?.name
|
||||
|
||||
//region CompilerOptions & KotlinOptions
|
||||
|
||||
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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.compilationImpl
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
||||
import org.gradle.api.tasks.bundling.Jar
|
||||
import org.gradle.api.tasks.bundling.Zip
|
||||
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinProjectSetupAction
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.isTest
|
||||
import org.jetbrains.kotlin.gradle.utils.CurrentBuildIdentifier
|
||||
import org.jetbrains.kotlin.gradle.utils.currentBuild
|
||||
import org.jetbrains.kotlin.gradle.utils.libsDirectory
|
||||
|
||||
/**
|
||||
* **WARNING!** This is internal Kotlin Gradle Plugin API, it is not supported outside JetBrains.
|
||||
*
|
||||
* Extension DSL to access Archive Tasks for custom compilations
|
||||
* These archive tasks can be exported as artifacts via consumable configuration.
|
||||
* And IDE will correctly import them.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* // project :lib
|
||||
* kotlin {
|
||||
* jvm {
|
||||
* val customCompilation by compilations.creating
|
||||
* val archiveTask = kotlinCompilationArchiveTasks
|
||||
* .getArchiveTaskOrNull(customCompilation)!!
|
||||
*
|
||||
* val jvmCustomApiElements by configurations.creating {
|
||||
* isCanBeConsumed = true
|
||||
* }
|
||||
* project.artifacts.add(jvmCustomApiElements.name, archiveTask)
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // project :app
|
||||
* kotlin {
|
||||
* jvm()
|
||||
* sourceSets {
|
||||
* jvmMain {
|
||||
* dependencies {
|
||||
* // This dependency will be correctly resolved in IDE
|
||||
* // as Module dependency to `lib.jvmCustom` source set
|
||||
* compileOnly(project(":lib", configuration = "jvmCustomApiElements"))
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@InternalKotlinGradlePluginApi
|
||||
interface KotlinCompilationArchiveTasks {
|
||||
/**
|
||||
* Returns archive task associated with [kotlinCompilation] instance.
|
||||
*
|
||||
* This method searches via Identity class (Project path, target and compilation names) of Compilations not by reference.
|
||||
* So it is safe to pass decorated or wrapped instances.
|
||||
*/
|
||||
fun getArchiveTaskOrNull(kotlinCompilation: KotlinCompilation<*>): TaskProvider<out AbstractArchiveTask>?
|
||||
}
|
||||
|
||||
internal val KotlinRegisterCompilationArchiveTasksExtension = KotlinProjectSetupAction {
|
||||
if (!project.kotlinPropertiesProvider.createArchiveTasksForCustomCompilations) return@KotlinProjectSetupAction
|
||||
project.extensions.add(
|
||||
KotlinCompilationArchiveTasks::class.java,
|
||||
"kotlinCompilationsArchiveTasks",
|
||||
KotlinCompilationArchiveTasksImpl(project.currentBuild)
|
||||
)
|
||||
}
|
||||
|
||||
private val Project.kotlinCompilationArchiveTasksImplOrNull: KotlinCompilationArchiveTasksImpl?
|
||||
get() = extensions.findByName("kotlinCompilationsArchiveTasks") as? KotlinCompilationArchiveTasksImpl?
|
||||
|
||||
internal val Project.kotlinCompilationArchiveTasksOrNull: KotlinCompilationArchiveTasks? get() = kotlinCompilationArchiveTasksImplOrNull
|
||||
|
||||
private class KotlinCompilationArchiveTasksImpl(
|
||||
private val currentBuild: CurrentBuildIdentifier
|
||||
) : KotlinCompilationArchiveTasks {
|
||||
private val tasksMap: MutableMap<Key, TaskProvider<out AbstractArchiveTask>> = mutableMapOf()
|
||||
|
||||
private data class Key(
|
||||
val targetName: String,
|
||||
val compilationName: String
|
||||
) {
|
||||
constructor(kotlinCompilation: KotlinCompilation<*>) : this(
|
||||
targetName = kotlinCompilation.target.targetName,
|
||||
compilationName = kotlinCompilation.compilationName
|
||||
)
|
||||
}
|
||||
|
||||
fun store(kotlinCompilation: KotlinCompilation<*>, task: TaskProvider<out AbstractArchiveTask>) {
|
||||
require(kotlinCompilation.project in currentBuild) { "Compilation $kotlinCompilation is not from current project" }
|
||||
tasksMap[Key(kotlinCompilation)] = task
|
||||
}
|
||||
|
||||
override fun getArchiveTaskOrNull(kotlinCompilation: KotlinCompilation<*>): TaskProvider<out AbstractArchiveTask>? {
|
||||
if (kotlinCompilation.project !in currentBuild) return null
|
||||
return tasksMap[Key(kotlinCompilation)]
|
||||
}
|
||||
}
|
||||
|
||||
internal val KotlinCreateCompilationArchivesTask = KotlinCompilationSideEffect { compilation ->
|
||||
if (compilation.isMain() || compilation.isTest()) return@KotlinCompilationSideEffect
|
||||
if (compilation.target is KotlinMetadataTarget) return@KotlinCompilationSideEffect
|
||||
// Pessimistically exclude Android target to avoid any conflicts
|
||||
if (compilation.target.platformType == KotlinPlatformType.androidJvm) return@KotlinCompilationSideEffect
|
||||
|
||||
val project = compilation.project
|
||||
if (!project.kotlinPropertiesProvider.createArchiveTasksForCustomCompilations) return@KotlinCompilationSideEffect
|
||||
|
||||
val archiveTask = if (compilation.target.platformType == KotlinPlatformType.jvm) {
|
||||
project.tasks.register(compilation.disambiguateName("jar"), Jar::class.java) { task ->
|
||||
task.from(compilation.output.allOutputs)
|
||||
task.archiveBaseName.convention(compilation.target.disambiguateName(compilation.name))
|
||||
}
|
||||
} else {
|
||||
project.tasks.register(compilation.disambiguateName("klib"), Zip::class.java) { task ->
|
||||
task.from(compilation.output.allOutputs)
|
||||
task.archiveBaseName.convention(compilation.target.disambiguateName(compilation.name))
|
||||
task.destinationDirectory.convention(project.libsDirectory)
|
||||
task.archiveExtension.set("klib")
|
||||
}
|
||||
}
|
||||
|
||||
project.kotlinCompilationArchiveTasksImplOrNull?.store(compilation, archiveTask)
|
||||
}
|
||||
+2
@@ -109,6 +109,7 @@ internal fun Project.registerKotlinPluginExtensions() {
|
||||
register(project, CInteropCommonizedCInteropApiElementsConfigurationsSetupAction)
|
||||
register(project, AddBuildListenerForXCodeSetupAction)
|
||||
register(project, CreateFatFrameworksSetupAction)
|
||||
register(project, KotlinRegisterCompilationArchiveTasksExtension)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +133,7 @@ internal fun Project.registerKotlinPluginExtensions() {
|
||||
register(project, KotlinCreateNativeCompileTasksSideEffect)
|
||||
register(project, KotlinCompilationProcessorSideEffect)
|
||||
register(project, KotlinCreateNativeCInteropTasksSideEffect)
|
||||
register(project, KotlinCreateCompilationArchivesTask)
|
||||
}
|
||||
|
||||
KotlinTargetArtifact.extensionPoint.apply {
|
||||
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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")
|
||||
|
||||
package org.jetbrains.kotlin.gradle.unitTests
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_CREATE_ARCHIVE_TASKS_FOR_CUSTOM_COMPILATIONS
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationArchiveTasks
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.internal
|
||||
import org.jetbrains.kotlin.gradle.util.*
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.fail
|
||||
|
||||
class KotlinCompilationArchiveTasksTest {
|
||||
private fun Project.enableKotlinCompilationArchiveTasksCreation(enabled: Boolean = true) {
|
||||
propertiesExtension.set(KOTLIN_CREATE_ARCHIVE_TASKS_FOR_CUSTOM_COMPILATIONS, enabled.toString())
|
||||
}
|
||||
|
||||
private val Project.kotlinCompilationsArchiveTasks: KotlinCompilationArchiveTasks
|
||||
get() = extensions.getByName("kotlinCompilationsArchiveTasks") as KotlinCompilationArchiveTasks
|
||||
|
||||
val testProject: Project = buildProject {
|
||||
enableKotlinCompilationArchiveTasksCreation()
|
||||
applyMultiplatformPlugin()
|
||||
|
||||
kotlin {
|
||||
jvm()
|
||||
linuxX64()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `custom jvm compilation has archive task`() {
|
||||
testProject.kotlin {
|
||||
jvm {
|
||||
val customCompilation = compilations.create("custom")
|
||||
val archiveTaskProvider = project.kotlinCompilationsArchiveTasks.getArchiveTaskOrNull(customCompilation)
|
||||
assertNotNull(archiveTaskProvider)
|
||||
val archiveFile = archiveTaskProvider.get().archiveFile.get().asFile
|
||||
if (!archiveFile.endsWith("libs/jvmCustom.jar")) fail("Unexpected archive file for compilation $customCompilation")
|
||||
|
||||
assertEquals(archiveTaskProvider.name, customCompilation.internal.archiveTaskName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `custom native compilation has archive`() {
|
||||
testProject.kotlin {
|
||||
linuxX64 {
|
||||
val customCompilation = compilations.create("custom")
|
||||
val archiveTaskProvider = project.kotlinCompilationsArchiveTasks.getArchiveTaskOrNull(customCompilation)
|
||||
assertNotNull(archiveTaskProvider)
|
||||
val archiveFile = archiveTaskProvider.get().archiveFile.get().asFile
|
||||
if (!archiveFile.endsWith("libs/linuxX64Custom.klib"))
|
||||
fail("Unexpected archive file for compilation $customCompilation: $archiveFile")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `main and test compilations should not have archive task`() {
|
||||
testProject.multiplatformExtension.targets.flatMap { it.compilations }.forEach { compilation ->
|
||||
if (compilation.internal.archiveTaskName != null)
|
||||
fail("Archive tasks should not be created for default compilations, but $compilation has it")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `archive tasks should not be created for custom compilation when feature flag is not set`() {
|
||||
val project = buildProject {
|
||||
enableKotlinCompilationArchiveTasksCreation(enabled = false)
|
||||
applyMultiplatformPlugin()
|
||||
kotlin {
|
||||
jvm().compilations.create("custom")
|
||||
linuxX64().compilations.create("custom")
|
||||
}
|
||||
}
|
||||
project.multiplatformExtension.targets.flatMap { it.compilations }.forEach { compilation ->
|
||||
if (compilation.internal.archiveTaskName != null)
|
||||
fail("Archive tasks should not be created")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `archive tasks should not be created for any android compilation`() {
|
||||
val project = buildProject {
|
||||
enableKotlinCompilationArchiveTasksCreation()
|
||||
applyMultiplatformPlugin()
|
||||
androidLibrary {
|
||||
compileSdk = 33
|
||||
productFlavors {
|
||||
create("customFlavor")
|
||||
}
|
||||
}
|
||||
kotlin {
|
||||
linuxX64()
|
||||
androidTarget()
|
||||
}
|
||||
}
|
||||
|
||||
project.multiplatformExtension.androidTarget().compilations.forEach { compilation ->
|
||||
if (compilation.internal.archiveTaskName != null)
|
||||
fail("Archive tasks should not be created for $compilation")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user