All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradlePlugin.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-Beta1
Show newest version
/*
 * Copyright 2010-2021 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.pm20

import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.NamedDomainObjectProvider
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.component.SoftwareComponentFactory
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies
import org.jetbrains.kotlin.gradle.kpm.idea.IdeaKpmProjectModelBuilder
import org.jetbrains.kotlin.gradle.kpm.idea.default
import org.jetbrains.kotlin.gradle.kpm.idea.locateOrRegisterIdeaKpmBuildProjectModelTask
import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility
import javax.inject.Inject

abstract class KotlinPm20GradlePlugin @Inject constructor(
    @Inject private val softwareComponentFactory: SoftwareComponentFactory,
    @Inject private val toolingModelBuilderRegistry: ToolingModelBuilderRegistry
) : Plugin {
    override fun apply(project: Project) {
        checkGradleCompatibility("the Kotlin Multiplatform plugin", GradleVersion.version("6.1"))

        // Gradle sets up the attribute schema for consuming JVM dependencies in the JavaBasePlugin
        project.plugins.apply(JavaBasePlugin::class.java)

        createDefaultModules(project)
        customizeKotlinDependencies(project)
        registerDefaultVariantFactories(project)
        setupFragmentsMetadataForKpmModules(project)
        setupKpmModulesPublication(project)
        setupToolingModelBuilder(project)
    }

    private fun createDefaultModules(project: Project) {
        project.pm20Extension.apply {
            modules.create(GradleKpmModule.MAIN_MODULE_NAME)
            modules.create(GradleKpmModule.TEST_MODULE_NAME)
            main { makePublic() }
        }
    }

    private fun setupPublicationForModule(module: GradleKpmModule) {
        val project = module.project

        val metadataElements = project.configurations.getByName(metadataElementsConfigurationName(module))
        val sourceElements = project.configurations.getByName(sourceElementsConfigurationName(module))

        val componentName = rootPublicationComponentName(module)
        val rootSoftwareComponent = softwareComponentFactory.adhoc(componentName).also {
            project.components.add(it)
            it.addVariantsFromConfiguration(metadataElements) { }
            it.addVariantsFromConfiguration(sourceElements) { }
        }

        module.ifMadePublic {
            val metadataDependencyConfiguration = resolvableMetadataConfiguration(module)
            project.pluginManager.withPlugin("maven-publish") {
                project.extensions.getByType(PublishingExtension::class.java).publications.create(
                    componentName,
                    MavenPublication::class.java
                ) { publication ->
                    publication.from(rootSoftwareComponent)
                    publication.versionMapping { versionMapping ->
                        versionMapping.allVariants {
                            it.fromResolutionOf(metadataDependencyConfiguration)
                        }
                    }
                }
            }
        }
    }

    private fun setupToolingModelBuilder(project: Project) {
        toolingModelBuilderRegistry.register(project.pm20Extension.ideaKpmProjectModelBuilder)
        project.locateOrRegisterIdeaKpmBuildProjectModelTask()
    }
}

fun rootPublicationComponentName(module: GradleKpmModule) =
    module.disambiguateName("root")

open class KotlinPm20ProjectExtension(project: Project) : KotlinTopLevelExtension(project) {

    internal val kpmModelContainer = GradleKpmDefaultProjectModelContainer.create(project)

    internal val ideaKpmProjectModelBuilder by lazy { IdeaKpmProjectModelBuilder.default(this) }

    val modules: NamedDomainObjectContainer
        get() = kpmModelContainer.modules

    @Suppress("unused") // DSL function
    fun mainAndTest(configure: GradleKpmModule.() -> Unit) {
        main(configure)
        test(configure)
    }

    val main: GradleKpmModule
        get() = modules.getByName(GradleKpmModule.MAIN_MODULE_NAME)

    val test: GradleKpmModule
        get() = modules.getByName(GradleKpmModule.TEST_MODULE_NAME)

    fun main(configure: GradleKpmModule.() -> Unit = { }) = main.apply(configure)
    fun test(configure: GradleKpmModule.() -> Unit = { }) = test.apply(configure)

    @PublishedApi
    @JvmName("isAllowCommonizer")
    internal fun isAllowCommonizerForIde(@Suppress("UNUSED_PARAMETER") project: Project): Boolean = false
}

val GradleKpmModule.jvm: GradleKpmJvmVariant
    get() = fragments.maybeCreate("jvm", GradleKpmJvmVariant::class.java)

fun GradleKpmModule.jvm(configure: GradleKpmJvmVariant.() -> Unit): GradleKpmJvmVariant = jvm.apply(configure)

fun KotlinPm20ProjectExtension.jvm(configure: KotlinFragmentSlice.() -> Unit) {
    val getOrCreateVariant: GradleKpmModule.() -> GradleKpmJvmVariant = { jvm }
    mainAndTest { getOrCreateVariant(this) }
    val slice = KotlinFragmentSlice(this, getOrCreateVariant)
    configure(slice)
}

open class KotlinFragmentSlice(
    val pm20ProjectExtension: KotlinPm20ProjectExtension,
    val getOrCreateFragment: (GradleKpmModule) -> T
) {
    fun inMain(configure: T.() -> Unit) {
        pm20ProjectExtension.modules.getByName(GradleKpmModule.MAIN_MODULE_NAME).apply {
            getOrCreateFragment(this).configure()
        }
    }

    fun inTest(configure: T.() -> Unit) {
        pm20ProjectExtension.modules.getByName(GradleKpmModule.TEST_MODULE_NAME).apply {
            getOrCreateFragment(this).configure()
        }
    }

    fun inMainAndTest(configure: T.() -> Unit) {
        pm20ProjectExtension.mainAndTest { getOrCreateFragment(this).configure() }
    }

    fun inAllModules(configure: T.() -> Unit) {
        pm20ProjectExtension.modules.all {
            getOrCreateFragment(it).configure()
        }
    }

    fun inModule(moduleName: String, configure: T.() -> Unit) {
        pm20ProjectExtension.modules.getByName(moduleName).apply { getOrCreateFragment(this).configure() }
    }

    fun inModule(module: NamedDomainObjectProvider, configure: T.() -> Unit) {
        module.get().apply { inModule(this, configure) }
    }

    fun inModule(module: GradleKpmModule, configure: T.() -> Unit) {
        getOrCreateFragment(module).configure()
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy