Gradle HMPP support fixes after review

* Add version to project structure metadata
* Use a data class for module dependencies in project structure
* Use task registering API for new tasks
* Simplify code
* Extract compatibility wrappers
* Fix multi-file dependencies that transformations silently ignored
This commit is contained in:
Sergey Igushkin
2019-05-31 17:44:30 +03:00
parent 5d7bd6c01a
commit 988df517dd
11 changed files with 150 additions and 78 deletions
@@ -5,11 +5,12 @@
package org.jetbrains.kotlin.gradle
import org.jetbrains.kotlin.gradle.internals.MULTIPLATFORM_PROJECT_METADATA_FILE_NAME
import org.jetbrains.kotlin.gradle.internals.parseKotlinSourceSetMetadataFromXml
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinProjectStructureMetadata
import org.jetbrains.kotlin.gradle.plugin.mpp.MULTIPLATFORM_PROJECT_METADATA_FILE_NAME
import org.jetbrains.kotlin.gradle.plugin.mpp.ModuleDependencyIdentifier
import org.jetbrains.kotlin.gradle.util.modify
import org.jetbrains.kotlin.konan.file.File
import java.io.File
import java.util.zip.ZipFile
import javax.xml.parsers.DocumentBuilderFactory
import kotlin.test.Test
@@ -79,9 +80,6 @@ class HierarchicalMppIT : BaseGradleIT() {
}
private fun checkMyLibFoo(compiledProject: CompiledProject, subprojectPrefix: String? = null) = with(compiledProject) {
val taskPrefix = subprojectPrefix?.let { ":$it" }.orEmpty()
val directoryPrefix = subprojectPrefix?.let { "$it/" }.orEmpty()
assertSuccessful()
assertTasksExecuted(expectedTasks(subprojectPrefix))
@@ -297,7 +295,11 @@ class HierarchicalMppIT : BaseGradleIT() {
"linuxAndJsMain" to setOf("commonMain"),
"commonMain" to emptySet()
),
sourceSetModuleDependencies = sourceSetModuleDependencies
sourceSetModuleDependencies = sourceSetModuleDependencies.mapValues { (_, pairs) ->
pairs.map {
ModuleDependencyIdentifier(it.first, it.second)
}.toSet()
}
)
}
@@ -41,4 +41,4 @@ open class GenerateProjectStructureMetadata : DefaultTask() {
}
}
const val MULTIPLATFORM_PROJECT_METADATA_FILE_NAME = "kotlin-project-structure-metadata.xml"
internal const val MULTIPLATFORM_PROJECT_METADATA_FILE_NAME = "kotlin-project-structure-metadata.xml"
@@ -239,9 +239,11 @@ internal class GranularMetadataTransformation(
// concrete view on them:
val requestedTransitiveDependencies: Set<ModuleId> =
mutableSetOf<ModuleId>().apply {
projectStructureMetadata.sourceSetModuleDependencies
.filterKeys { it in allVisibleSourceSets }
.forEach { addAll(it.value) }
projectStructureMetadata.sourceSetModuleDependencies.forEach { (sourceSetName, moduleDependencies) ->
if (sourceSetName in allVisibleSourceSets) {
addAll(moduleDependencies.map { ModuleId(it.groupId, it.moduleId) })
}
}
}
val transitiveDependenciesToVisit = module.children.filterTo(mutableSetOf()) {
@@ -29,9 +29,7 @@ import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubplugin
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild
import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.presetName
@@ -284,7 +282,7 @@ internal fun applyUserDefinedAttributes(target: AbstractKotlinTarget) {
// based on the target's components:
val outputConfigurationsWithCompilations =
target.kotlinComponents.filterIsInstance<KotlinVariant>().flatMap { kotlinVariant ->
kotlinVariant.usages.filterIsInstance<KotlinUsageContext>().mapNotNull { usageContext ->
kotlinVariant.usages.mapNotNull { usageContext ->
project.configurations.findByName(usageContext.dependencyConfigurationName)?.let { configuration ->
configuration to usageContext.compilation
}
@@ -323,8 +321,8 @@ internal fun sourcesJarTask(
(project.tasks.findByName(taskName) as? Jar)?.let { return it }
val result = project.tasks.create(taskName, Jar::class.java) { sourcesJar ->
sourcesJar.appendix = artifactNameAppendix
sourcesJar.classifier = "sources"
sourcesJar.setArchiveAppendixCompatible { artifactNameAppendix }
sourcesJar.setArchiveClassifierCompatible { "sources" }
}
project.whenEvaluated {
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.targets.metadata.getPublishedPlatformCompilations
import org.w3c.dom.Document
@@ -15,6 +16,11 @@ import org.w3c.dom.Node
import org.w3c.dom.NodeList
import javax.xml.parsers.DocumentBuilderFactory
data class ModuleDependencyIdentifier(
val groupId: String,
val moduleId: String
)
data class KotlinProjectStructureMetadata(
@Input
val sourceSetNamesByVariantName: Map<String, Set<String>>,
@@ -22,9 +28,21 @@ data class KotlinProjectStructureMetadata(
@Input
val sourceSetsDependsOnRelation: Map<String, Set<String>>,
@Internal
val sourceSetModuleDependencies: Map<String, Set<ModuleDependencyIdentifier>>,
@Input
val sourceSetModuleDependencies: Map<String, Set<Pair<String, String>>>
)
val formatVersion: String = FORMAT_VERSION_0_1
) {
@Suppress("UNUSED") // Gradle input
@get:Input
internal val sourceSetModuleDependenciesInput: Map<String, Set<Pair<String, String>>>
get() = sourceSetModuleDependencies.mapValues { (_, ids) -> ids.map { (group, module) -> group to module }.toSet() }
companion object {
internal const val FORMAT_VERSION_0_1 = "0.1"
}
}
internal fun buildKotlinProjectStructureMetadata(project: Project): KotlinProjectStructureMetadata? {
val sourceSetsWithMetadataCompilations =
@@ -43,19 +61,21 @@ internal fun buildKotlinProjectStructureMetadata(project: Project): KotlinProjec
},
sourceSetModuleDependencies = sourceSetsWithMetadataCompilations.keys.associate { sourceSet ->
sourceSet.name to project.configurations.getByName(sourceSet.apiConfigurationName).allDependencies.map {
it.group.orEmpty() to it.name
ModuleDependencyIdentifier(it.group.orEmpty(), it.name)
}.toSet()
}
)
}
internal fun KotlinProjectStructureMetadata.toXmlDocument(): Document {
val document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument().apply {
return DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument().apply {
fun Node.node(name: String, action: Element.() -> Unit) = appendChild(createElement(name).apply(action))
fun Node.textNode(name: String, value: String) =
appendChild(createElement(name).apply { appendChild(createTextNode(value)) })
node("projectStructure") {
textNode("formatVersion", formatVersion)
node("variants") {
sourceSetNamesByVariantName.forEach { (variantName, sourceSets) ->
node("variant") {
@@ -74,14 +94,13 @@ internal fun KotlinProjectStructureMetadata.toXmlDocument(): Document {
textNode("dependsOn", dependsOn)
}
sourceSetModuleDependencies[sourceSet].orEmpty().forEach { moduleDependency ->
textNode("moduleDependency", moduleDependency.first + ":" + moduleDependency.second)
textNode("moduleDependency", moduleDependency.groupId + ":" + moduleDependency.moduleId)
}
}
}
}
}
}
return document
}
private val NodeList.elements: Iterable<Element> get() = (0 until length).map { this@elements.item(it) }.filterIsInstance<Element>()
@@ -89,6 +108,8 @@ private val NodeList.elements: Iterable<Element> get() = (0 until length).map {
internal fun parseKotlinSourceSetMetadataFromXml(document: Document): KotlinProjectStructureMetadata? {
val projectStructureNode = document.getElementsByTagName("projectStructure").elements.single()
val formatVersion = projectStructureNode.getElementsByTagName("formatVersion").item(0).textContent
val variantsNode = projectStructureNode.getElementsByTagName("variants").item(0) ?: return null
val sourceSetsByVariant = mutableMapOf<String, Set<String>>()
@@ -101,7 +122,7 @@ internal fun parseKotlinSourceSetMetadataFromXml(document: Document): KotlinProj
}
val sourceSetDependsOnRelation = mutableMapOf<String, Set<String>>()
val sourceSetModuleDependencies = mutableMapOf<String, Set<Pair<String, String>>>()
val sourceSetModuleDependencies = mutableMapOf<String, Set<ModuleDependencyIdentifier>>()
val sourceSetsNode = projectStructureNode.getElementsByTagName("sourceSets").item(0) ?: return null
@@ -109,12 +130,15 @@ internal fun parseKotlinSourceSetMetadataFromXml(document: Document): KotlinProj
val sourceSetName = sourceSetNode.getElementsByTagName("name").elements.single().textContent
val dependsOn = mutableSetOf<String>()
val moduleDependencies = mutableSetOf<Pair<String, String>>()
val moduleDependencies = mutableSetOf<ModuleDependencyIdentifier>()
sourceSetNode.childNodes.elements.forEach {
when (it.tagName) {
"dependsOn" -> dependsOn.add(it.textContent)
"moduleDependency" -> moduleDependencies.add(it.textContent.split(":").let { (first, second) -> first to second })
sourceSetNode.childNodes.elements.forEach { node ->
when (node.tagName) {
"dependsOn" -> dependsOn.add(node.textContent)
"moduleDependency" -> {
val (groupId, moduleId) = node.textContent.split(":")
moduleDependencies.add(ModuleDependencyIdentifier(groupId, moduleId))
}
}
}
@@ -125,6 +149,7 @@ internal fun parseKotlinSourceSetMetadataFromXml(document: Document): KotlinProj
return KotlinProjectStructureMetadata(
sourceSetsByVariant,
sourceSetDependsOnRelation,
sourceSetModuleDependencies
sourceSetModuleDependencies,
formatVersion
)
}
@@ -61,8 +61,7 @@ class DefaultKotlinUsageContext(
override val compilation: KotlinCompilation<*>,
private val usage: Usage,
override val dependencyConfigurationName: String,
private val overrideConfigurationArtifacts: Set<PublishArtifact>? = null,
private val filterConfigurationAttributes: (Attribute<*>) -> Boolean = { true }
private val overrideConfigurationArtifacts: Set<PublishArtifact>? = null
) : KotlinUsageContext {
private val kotlinTarget: KotlinTarget get() = compilation.target
@@ -107,7 +106,7 @@ class DefaultKotlinUsageContext(
}
configurationAttributes.keySet()
.filter { filterConfigurationAttributes(it) && it != ProjectLocalConfigurations.ATTRIBUTE }
.filter { it != ProjectLocalConfigurations.ATTRIBUTE }
.forEach { copyAttribute(it, configurationAttributes, result) }
return result
@@ -26,16 +26,20 @@ internal class SourceSetVisibilityProvider(
fun getVisibleSourceSets(
visibleFrom: KotlinSourceSet,
dependencyScopes: Iterable<KotlinDependencyScope>,
mppDependency: ResolvedDependency,
resolvedMppDependency: ResolvedDependency,
dependencyProjectStructureMetadata: KotlinProjectStructureMetadata,
otherProject: Project?
resolvedToOtherProject: Project?
): DependencySourceSetVisibilityResult {
val visibleByThisSourceSet =
getVisibleSourceSetsImpl(visibleFrom, dependencyScopes, mppDependency, dependencyProjectStructureMetadata, otherProject)
getVisibleSourceSetsImpl(
visibleFrom, dependencyScopes, resolvedMppDependency, dependencyProjectStructureMetadata, resolvedToOtherProject
)
val visibleByParents = visibleFrom.dependsOn
.flatMapTo(mutableSetOf()) {
getVisibleSourceSetsImpl(it, dependencyScopes, mppDependency, dependencyProjectStructureMetadata, otherProject)
getVisibleSourceSetsImpl(
it, dependencyScopes, resolvedMppDependency, dependencyProjectStructureMetadata, resolvedToOtherProject
)
}
return DependencySourceSetVisibilityResult(visibleByThisSourceSet, visibleByParents)
@@ -19,9 +19,12 @@ import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.sources.*
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask
import org.jetbrains.kotlin.gradle.tasks.locateTask
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.gradle.utils.setArchiveAppendixCompatible
import org.jetbrains.kotlin.gradle.utils.setArchiveClassifierCompatible
import java.io.File
import java.util.concurrent.Callable
@@ -88,14 +91,8 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
description = "Assembles a jar archive containing the metadata for all Kotlin source sets."
group = BasePlugin.BUILD_GROUP
@Suppress("DEPRECATION")
if (isGradleVersionAtLeast(5, 2)) {
archiveAppendix.convention(target.name.toLowerCase())
archiveClassifier.set("all")
} else {
appendix = target.name.toLowerCase()
classifier = "all"
}
setArchiveAppendixCompatible { target.name.toLowerCase() }
setArchiveClassifierCompatible { "all" }
}
}
}
@@ -127,7 +124,7 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
}
sourceSetsWithMetadataCompilations.forEach { (sourceSet, metadataCompilation) ->
val compileMetadataTransformationTasksForHierarchy = mutableSetOf<TransformKotlinGranularMetadata>()
val compileMetadataTransformationTasksForHierarchy = mutableSetOf<TaskHolder<TransformKotlinGranularMetadata>>()
// Adjust metadata compilation to support source set hierarchies, i.e. use both the outputs of dependsOn source set compilation
// and their dependencies metadata transformed for compilation:
@@ -137,8 +134,7 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
metadataCompilation.compileDependencyFiles += dependencyCompilation.output.classesDirs.filter { it.exists() }
}
project.tasks.withType(TransformKotlinGranularMetadata::class.java)
.findByName(transformGranularMetadataTaskName(hierarchySourceSet))
project.locateTask<TransformKotlinGranularMetadata>(transformGranularMetadataTaskName(hierarchySourceSet))
?.let(compileMetadataTransformationTasksForHierarchy::add)
}
@@ -149,10 +145,11 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
)
}
val generateMetadata =
createGenerateProjectStructureMetadataTask()
val generateMetadata = createGenerateProjectStructureMetadataTask()
allMetadataJar.from(project.files(Callable { generateMetadata.resultXmlFile }).builtBy(generateMetadata)) { spec ->
allMetadataJar.from(project.files(Callable {
generateMetadata.doGetTask().resultXmlFile
}).builtBy(generateMetadata.getTaskOrProvider())) { spec ->
spec.into("META-INF").rename { MULTIPLATFORM_PROJECT_METADATA_FILE_NAME }
}
}
@@ -182,7 +179,7 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
val metadataCompilation = when (sourceSet.name) {
// Historically, we already had a 'main' compilation in metadata targets; TODO consider removing it instead
KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME -> target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
else -> target.compilations.create(lowerCamelCaseName(sourceSet.name)) { compilation ->
else -> target.compilations.create(sourceSet.name) { compilation ->
compilation.addExactSourceSetsEagerly(setOf(sourceSet))
}
}
@@ -193,12 +190,7 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
spec.into(metadataCompilation.defaultSourceSet.name)
}
@Suppress("UnstableApiUsage")
project.tasks.create(
transformGranularMetadataTaskName(sourceSet),
TransformKotlinGranularMetadata::class.java,
sourceSet
)
project.createOrRegisterTask<TransformKotlinGranularMetadata>(transformGranularMetadataTaskName(sourceSet), listOf(sourceSet)) { }
return metadataCompilation
}
@@ -283,20 +275,30 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
private fun createTransformedMetadataClasspath(
fromFiles: Iterable<File>,
project: Project,
granularMetadataTransformationTasks: Set<TransformKotlinGranularMetadata>
transformationTaskHolders: Set<TaskHolder<TransformKotlinGranularMetadata>>
): FileCollection {
return project.files(Callable {
val resolutionsByArtifactFile = granularMetadataTransformationTasks
.flatMap { it.metadataDependencyResolutions }
.groupBy { it.dependency }
.filterKeys { it.moduleArtifacts.size == 1 } // TODO do we have modules that resolve to more than one artifact? use sets?
.mapKeys { (dependency, _) -> dependency.moduleArtifacts.single().file }
val allResolutionsByArtifactFile: Map<File, Iterable<MetadataDependencyResolution>> =
mutableMapOf<File, MutableList<MetadataDependencyResolution>>().apply {
transformationTaskHolders.forEach {
val resolutions = it.doGetTask().metadataDependencyResolutions
val transformedFiles = granularMetadataTransformationTasks.flatMap { it.filesByResolution.toList() }.toMap()
resolutions.forEach { resolution ->
val artifacts = resolution.dependency.moduleArtifacts.map { it.file }
artifacts.forEach { artifactFile ->
getOrPut(artifactFile) { mutableListOf() }.add(resolution)
}
}
}
}
val transformedFilesByResolution: Map<MetadataDependencyResolution, FileCollection> =
transformationTaskHolders.flatMap { it.doGetTask().filesByResolution.toList() }.toMap()
mutableSetOf<Any /* File | FileCollection */>().apply {
fromFiles.forEach { file ->
val resolutions = resolutionsByArtifactFile[file]
val resolutions = allResolutionsByArtifactFile[file]
if (resolutions == null) {
add(file)
} else {
@@ -304,14 +306,14 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
resolutions.filterIsInstance<MetadataDependencyResolution.ChooseVisibleSourceSets>()
if (chooseVisibleSourceSets.isNotEmpty()) {
add(chooseVisibleSourceSets.map { transformedFiles.getValue(it) })
add(chooseVisibleSourceSets.map { transformedFilesByResolution.getValue(it) })
} else if (resolutions.any { it is MetadataDependencyResolution.KeepOriginalDependency }) {
add(file)
}
} // else: all dependency transformations exclude this dependency as unrequested; don't add any files
}
}
}
}).builtBy(granularMetadataTransformationTasks)
}).builtBy(transformationTaskHolders.map { it.getTaskOrProvider() })
}
private fun getPublishedCommonSourceSets(project: Project): Set<KotlinSourceSet> {
@@ -333,8 +335,8 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
.keys
}
private fun Project.createGenerateProjectStructureMetadataTask(): GenerateProjectStructureMetadata =
tasks.create("generateProjectStructureMetadata", GenerateProjectStructureMetadata::class.java) { task ->
private fun Project.createGenerateProjectStructureMetadataTask(): TaskHolder<GenerateProjectStructureMetadata> =
project.createOrRegisterTask("generateProjectStructureMetadata") { task ->
task.lazyKotlinProjectStructureMetadata = lazy { checkNotNull(buildKotlinProjectStructureMetadata(project)) }
}
}
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.defaultSourceSetName
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
internal val useLazyTaskConfiguration = org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast(4, 9)
internal val canLocateTask = org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast(5, 0)
@@ -34,16 +35,33 @@ internal val canLocateTask = org.jetbrains.kotlin.gradle.utils.isGradleVersionAt
@JvmName("registerTaskOld")
@Deprecated("please use Project.createOrRegisterTask", ReplaceWith("project.createOrRegisterTask(name, body)"))
internal fun <T : Task> registerTask(project: Project, name: String, type: Class<T>, body: (T) -> (Unit)): TaskHolder<T> =
project.createOrRegisterTask(name, type, body)
project.createOrRegisterTask(name, type, emptyList(), body)
internal inline fun <reified T : Task> Project.createOrRegisterTask(name: String, noinline body: (T) -> (Unit)): TaskHolder<T> =
createOrRegisterTask(name, T::class.java, body)
internal inline fun <reified T : Task> Project.createOrRegisterTask(
name: String,
args: List<Any> = emptyList(),
noinline body: (T) -> (Unit)
): TaskHolder<T> =
createOrRegisterTask(name, T::class.java, args, body)
internal fun <T : Task> Project.createOrRegisterTask(name: String, type: Class<T>, body: (T) -> (Unit)): TaskHolder<T> {
internal fun <T : Task> Project.createOrRegisterTask(
name: String,
type: Class<T>,
constructorArgs: List<Any> = emptyList(), // note: args are only allowed with Gradle 4.7+
body: (T) -> (Unit)
): TaskHolder<T> {
return if (useLazyTaskConfiguration) {
TaskProviderHolder(name, project, project.tasks.register(name, type) { with(it, body) })
val provider = project.tasks.register(name, type, *constructorArgs.toTypedArray()).apply { configure(body) }
TaskProviderHolder(name, project, provider)
} else {
val result = LegacyTaskHolder(project.tasks.create(name, type))
val result = LegacyTaskHolder(if (constructorArgs.isEmpty()) {
project.tasks.create(name, type)
} else {
if (!isGradleVersionAtLeast(4, 7)) {
error("Cannot inject the arguments list into a task. This requires Gradle 4.7+.")
}
project.tasks.create(name, type, *constructorArgs.toTypedArray())
})
with(result.doGetTask(), body)
result
}
@@ -20,6 +20,7 @@ import org.gradle.api.GradleException
import org.gradle.api.Task
import org.gradle.api.tasks.TaskInputs
import org.gradle.api.tasks.TaskOutputs
import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.gradle.util.GradleVersion
internal val Task.inputsCompatible: TaskInputs get() = inputs
@@ -54,4 +55,22 @@ internal fun checkGradleCompatibility(minSupportedVersion: GradleVersion = Gradl
"Please use Gradle $minSupportedVersion or newer or previous version of Kotlin plugin."
)
}
}
internal fun AbstractArchiveTask.setArchiveAppendixCompatible(appendixProvider: () -> String) {
if (isGradleVersionAtLeast(5, 2)) {
archiveAppendix.set(project.provider { appendixProvider() })
} else {
@Suppress("DEPRECATION")
appendix = appendixProvider()
}
}
internal fun AbstractArchiveTask.setArchiveClassifierCompatible(classifierProvider: () -> String) {
if (isGradleVersionAtLeast(5, 2)) {
archiveClassifier.set(project.provider { classifierProvider() })
} else {
@Suppress("DEPRECATION")
classifier = classifierProvider()
}
}
@@ -9,4 +9,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinProjectStructureMetadata
import org.w3c.dom.Document
fun parseKotlinSourceSetMetadataFromXml(document: Document): KotlinProjectStructureMetadata? =
org.jetbrains.kotlin.gradle.plugin.mpp.parseKotlinSourceSetMetadataFromXml(document)
org.jetbrains.kotlin.gradle.plugin.mpp.parseKotlinSourceSetMetadataFromXml(document)
const val MULTIPLATFORM_PROJECT_METADATA_FILE_NAME =
org.jetbrains.kotlin.gradle.plugin.mpp.MULTIPLATFORM_PROJECT_METADATA_FILE_NAME