[Gradle] Remove KPM<->TCS Model Mapping

KT-54312
This commit is contained in:
Sebastian Sellmair
2022-09-27 16:30:10 +02:00
committed by Space Team
parent 8e2f6d0f3a
commit 35dacd6add
49 changed files with 152 additions and 1452 deletions
@@ -62,6 +62,9 @@ internal val Project.multiplatformExtension: KotlinMultiplatformExtension
internal val Project.pm20Extension: KotlinPm20ProjectExtension
get() = extensions.getByName(KOTLIN_PROJECT_EXTENSION_NAME).castIsolatedKotlinPluginClassLoaderAware()
internal val Project.pm20ExtensionOrNull: KotlinPm20ProjectExtension?
get() = extensions.findByName(KOTLIN_PROJECT_EXTENSION_NAME)?.castIsolatedKotlinPluginClassLoaderAware()
abstract class KotlinTopLevelExtension(internal val project: Project) : KotlinTopLevelExtensionConfig {
override lateinit var coreLibrariesVersion: String
@@ -147,12 +150,6 @@ open class KotlinProjectExtension @Inject constructor(project: Project) : Kotlin
internal set(value) {
DslObject(this).extensions.add("sourceSets", value)
}
internal val kpmModelContainer by lazy {
if (project.kotlinPropertiesProvider.experimentalKpmModelMapping) {
GradleKpmDefaultProjectModelContainer.create(project)
} else error("Model mapping is not enabled.")
}
}
abstract class KotlinSingleTargetExtension<TARGET : KotlinTarget>(project: Project) : KotlinProjectExtension(project) {
@@ -6,13 +6,19 @@
package org.jetbrains.kotlin.gradle.internal
import org.gradle.api.Project
import org.gradle.api.artifacts.*
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.ExternalDependency
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.dsl.topLevelExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationToRunnableFiles
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaCompilation
import org.jetbrains.kotlin.gradle.utils.providerWithLazyConvention
import org.jetbrains.kotlin.gradle.utils.withType
@@ -80,12 +86,8 @@ private fun KotlinTarget.excludeStdlibAndKotlinTestCommonFromPlatformCompilation
compilations.all {
listOfNotNull(
it.compileDependencyConfigurationName,
if (!PropertiesProvider(project).experimentalKpmModelMapping)
it.defaultSourceSet.apiMetadataConfigurationName
else null,
if (!PropertiesProvider(project).experimentalKpmModelMapping)
it.defaultSourceSet.implementationMetadataConfigurationName
else null,
it.defaultSourceSet.apiMetadataConfigurationName,
it.defaultSourceSet.implementationMetadataConfigurationName,
(it as? KotlinCompilationToRunnableFiles<*>)?.runtimeDependencyConfigurationName,
// Additional configurations for (old) jvmWithJava-preset. Remove it when we drop it completely
@@ -10,19 +10,13 @@ import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.ExternalDependency
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.dsl.KotlinJsProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.isTest
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmFragment
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmModule
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.kpmModules
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
import org.jetbrains.kotlin.gradle.plugin.sources.android.AndroidBaseSourceSetName
import org.jetbrains.kotlin.gradle.plugin.sources.android.AndroidVariantType
@@ -36,17 +30,18 @@ internal fun Project.configureStdlibDefaultDependency(
topLevelExtension: KotlinTopLevelExtension,
coreLibrariesVersion: Provider<String>
) {
when (topLevelExtension) {
is KotlinPm20ProjectExtension -> addStdlibToKpmProject(project, coreLibrariesVersion)
when {
project.hasKpmModel -> addStdlibToKpmProject(project, coreLibrariesVersion)
topLevelExtension is KotlinJsProjectExtension -> topLevelExtension.registerTargetObserver { target ->
is KotlinJsProjectExtension -> topLevelExtension.registerTargetObserver { target ->
target?.addStdlibDependency(configurations, dependencies, coreLibrariesVersion)
}
topLevelExtension is KotlinSingleTargetExtension<*> -> topLevelExtension
is KotlinSingleTargetExtension<*> -> topLevelExtension
.target
.addStdlibDependency(configurations, dependencies, coreLibrariesVersion)
topLevelExtension is KotlinMultiplatformExtension -> topLevelExtension
is KotlinMultiplatformExtension -> topLevelExtension
.targets
.configureEach { target ->
target.addStdlibDependency(configurations, dependencies, coreLibrariesVersion)
@@ -93,7 +88,7 @@ private fun addStdlibToKpmProject(
project: Project,
coreLibrariesVersion: Provider<String>
) {
project.kpmModules.named(GradleKpmModule.MAIN_MODULE_NAME) { main ->
project.pm20Extension.modules.named(GradleKpmModule.MAIN_MODULE_NAME) { main ->
main.fragments.named(GradleKpmFragment.COMMON_FRAGMENT_NAME) { common ->
common.dependencies {
api(project.dependencies.kotlinDependency("kotlin-stdlib-common", coreLibrariesVersion.get()))
@@ -143,7 +138,7 @@ private fun KotlinTarget.addStdlibDependency(
val stdlibModule = compilation
.platformType
.stdlibPlatformType( this, kotlinSourceSet)
.stdlibPlatformType(this, kotlinSourceSet)
?: return@withDependencies
// Check if stdlib module is added to SourceSets hierarchy
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation
import org.jetbrains.kotlin.konan.target.HostManager
@Suppress("unused")
@@ -18,13 +17,6 @@ internal fun IdeaKpmProjectBuildingContext.IdeaKpmPlatform(variant: GradleKpmVar
when (variant) {
is GradleKpmJvmVariant -> return IdeaKpmJvmPlatformImpl(variant.compilationData.kotlinOptions.jvmTarget ?: JvmTarget.DEFAULT.name)
is GradleKpmNativeVariantInternal -> return IdeaKpmNativePlatformImpl(variant.konanTarget.name)
is GradleKpmLegacyMappedVariant -> when (val compilation = variant.compilation) {
is KotlinJvmCompilation -> return IdeaKpmJvmPlatformImpl(compilation.kotlinOptions.jvmTarget ?: JvmTarget.DEFAULT.name)
is KotlinJvmAndroidCompilation -> return IdeaKpmJvmPlatformImpl(compilation.kotlinOptions.jvmTarget ?: JvmTarget.DEFAULT.name)
is KotlinNativeCompilation -> return IdeaKpmNativePlatformImpl(compilation.konanTarget.name)
is KotlinJsIrCompilation -> return IdeaKpmJsPlatformImpl(isIr = true)
is KotlinJsCompilation -> return IdeaKpmJsPlatformImpl(isIr = false)
}
}
/* Fallback calculation based on 'platformType' alone */
@@ -39,7 +39,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20GradlePlugin
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSetFactory
import org.jetbrains.kotlin.gradle.plugin.sources.kpm.FragmentMappedKotlinSourceSetFactory
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
import org.jetbrains.kotlin.gradle.report.BuildMetricsService
import org.jetbrains.kotlin.gradle.report.BuildReportsService
@@ -172,9 +171,7 @@ abstract class KotlinBasePluginWrapper : DefaultKotlinBasePlugin() {
abstract val pluginVariant: String
internal open fun kotlinSourceSetFactory(project: Project): NamedDomainObjectFactory<KotlinSourceSet> =
if (PropertiesProvider(project).experimentalKpmModelMapping)
FragmentMappedKotlinSourceSetFactory(project)
else DefaultKotlinSourceSetFactory(project)
DefaultKotlinSourceSetFactory(project)
override fun apply(project: Project) {
super.apply(project)
@@ -190,8 +190,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
val enableCompatibilityMetadataVariant: Boolean
get() {
return (booleanProperty("kotlin.mpp.enableCompatibilityMetadataVariant") ?: !mppHierarchicalStructureByDefault) &&
!experimentalKpmModelMapping
return (booleanProperty("kotlin.mpp.enableCompatibilityMetadataVariant") ?: !mppHierarchicalStructureByDefault)
}
val enableKotlinToolingMetadataArtifact: Boolean
@@ -209,9 +208,6 @@ internal class PropertiesProvider private constructor(private val project: Proje
val jsCompilerNoWarn: Boolean
get() = booleanProperty("$jsCompilerProperty.nowarn") ?: false
val experimentalKpmModelMapping: Boolean
get() = booleanProperty(PropertyNames.KOTLIN_KPM_EXPERIMENTAL_MODEL_MAPPING) ?: false
val ignoreDisabledNativeTargets: Boolean?
get() = booleanProperty(DisabledNativeTargetsReporter.DISABLE_WARNING_PROPERTY_NAME)
@@ -492,7 +488,6 @@ internal class PropertiesProvider private constructor(private val project: Proje
const val KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_VERSION_1_NO_WARN = "${KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_VERSION}1.nowarn"
const val KOTLIN_NATIVE_DEPENDENCY_PROPAGATION = "kotlin.native.enableDependencyPropagation"
const val KOTLIN_MPP_ENABLE_OPTIMISTIC_NUMBER_COMMONIZATION = "kotlin.mpp.enableOptimisticNumberCommonization"
const val KOTLIN_KPM_EXPERIMENTAL_MODEL_MAPPING = "kotlin.kpm.experimentalModelMapping"
const val KOTLIN_MPP_ENABLE_PLATFORM_INTEGER_COMMONIZATION = "kotlin.mpp.enablePlatformIntegerCommonization"
const val KOTLIN_ABI_SNAPSHOT = "kotlin.incremental.classpath.snapshot.enabled"
const val KOTLIN_JS_KARMA_BROWSERS = "kotlin.js.browser.karma.browsers"
@@ -25,7 +25,6 @@ import org.gradle.jvm.tasks.Jar
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
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
@@ -85,9 +84,7 @@ abstract class AbstractKotlinTarget(
}
override val components: Set<SoftwareComponent> by lazy {
if (!project.hasKpmModel) {
buildAdhocComponentsFromKotlinVariants(kotlinComponents)
} else emptySet()
buildAdhocComponentsFromKotlinVariants(kotlinComponents)
}
private fun buildAdhocComponentsFromKotlinVariants(kotlinVariants: Set<KotlinTargetComponent>): Set<SoftwareComponent> {
@@ -15,8 +15,6 @@ import org.gradle.api.artifacts.result.ResolvedComponentResult
import org.gradle.api.attributes.Attribute
import org.gradle.api.attributes.AttributeContainer
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.currentBuildId
@@ -123,10 +121,10 @@ private fun detectModules(targets: Iterable<KotlinTarget>, sourceSets: Iterable<
@Suppress("unused")
class GradleProjectModuleBuilder(private val addInferredSourceSetVisibilityAsExplicit: Boolean) {
private fun getModulesFromPm20Project(project: Project) = project.kpmModules.toList()
private fun getModulesFromPm20Project(project: Project) = project.pm20Extension.modules.toList()
fun buildModulesFromProject(project: Project): List<KpmModule> {
if (project.hasKpmModel)
if (project.pm20ExtensionOrNull != null)
return getModulesFromPm20Project(project)
val extension = project.multiplatformExtensionOrNull
@@ -318,7 +316,7 @@ class KpmGradleModuleVariantResolver : KpmModuleVariantResolver {
private fun getCompileDependenciesConfigurationForVariant(project: Project, requestingVariant: KpmVariant): Configuration =
when {
project.hasKpmModel -> {
project.pm20ExtensionOrNull != null -> {
(requestingVariant as GradleKpmVariant).compileDependenciesConfiguration
}
else -> {
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationDetailsImpl.MetadataMappedCompilationDetails
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileCommon
@@ -21,9 +20,6 @@ abstract class KotlinCommonCompilation @Inject constructor(
) : AbstractKotlinCompilation<KotlinMultiplatformCommonOptions>(compilationDetails),
KotlinMetadataCompilation<KotlinMultiplatformCommonOptions> {
override fun getName() =
if (compilationDetails is MetadataMappedCompilationDetails) defaultSourceSetName else super.compilationPurpose
@Suppress("DEPRECATION")
@Deprecated("Accessing task instance directly is deprecated", replaceWith = ReplaceWith("compileTaskProvider"))
override val compileKotlinTask: KotlinCompileCommon
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.JavaBasePlugin
@@ -20,10 +19,8 @@ import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin.Companion.sourceSetFreeCompilerArgsPropertyName
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationDetailsImpl.VariantMappedCompilationDetails
import org.jetbrains.kotlin.gradle.plugin.mpp.internal.handleHierarchicalStructureFlagsMigration
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.registerDefaultVariantFactories
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.setupFragmentsMetadataForKpmModules
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.setupKpmModulesPublication
@@ -55,18 +52,6 @@ class KotlinMultiplatformPlugin : Plugin<Project> {
project.plugins.apply(JavaBasePlugin::class.java)
if (project.hasKpmModel) {
setupFragmentsMetadataForKpmModules(project)
setupKpmModulesPublication(project)
registerDefaultVariantFactories(project)
with(project.kpmModules) {
create(GradleKpmModule.MAIN_MODULE_NAME) {
it.makePublic()
}
create(GradleKpmModule.TEST_MODULE_NAME)
}
}
val kotlinMultiplatformExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
setupDefaultPresets(project)
@@ -80,9 +65,8 @@ class KotlinMultiplatformPlugin : Plugin<Project> {
)
project.registerKotlinArtifactsExtension()
if (!project.hasKpmModel) {
configurePublishingWithMavenPublish(project)
}
configurePublishingWithMavenPublish(project)
kotlinMultiplatformExtension.targets.withType(AbstractKotlinTarget::class.java).all { applyUserDefinedAttributes(it) }
// propagate compiler plugin options to the source set language settings
@@ -122,6 +106,7 @@ class KotlinMultiplatformPlugin : Plugin<Project> {
1 -> sourceSetTargets.single().compilations.findByName(KotlinCompilation.MAIN_COMPILATION_NAME)
?: // use any of the compilations for now, looks OK for Android TODO maybe reconsider
compilations.first()
else -> metadataCompilation
}
}
@@ -163,8 +148,10 @@ class KotlinMultiplatformPlugin : Plugin<Project> {
val targetToAdd = when (konanTarget) {
in nativeTargetsWithHostTests ->
KotlinNativeTargetWithHostTestsPreset(konanTarget.presetName, project, konanTarget)
in nativeTargetsWithSimulatorTests ->
KotlinNativeTargetWithSimulatorTestsPreset(konanTarget.presetName, project, konanTarget)
else -> KotlinNativeTargetPreset(konanTarget.presetName, project, konanTarget)
}
@@ -216,52 +203,6 @@ class KotlinMultiplatformPlugin : Plugin<Project> {
*/
internal fun applyUserDefinedAttributes(target: AbstractKotlinTarget) {
val project = target.project
if (!project.hasKpmModel) {
applyUserDefinedAttributesWithLegacyModel(target)
} else {
applyUserDefinedAttributesWithKpm(target)
}
}
private fun applyUserDefinedAttributesWithKpm(
target: AbstractKotlinTarget,
) {
fun copyAttributesToVariant(variant: GradleKpmVariant, from: AttributeContainer) {
variant.gradleVariantNames.forEach { configurationOrVariantName ->
val configuration = variant.project.configurations.findByName(configurationOrVariantName)
?: return@forEach
copyAttributes(from, configuration.attributes)
}
}
val project = target.project
project.whenEvaluated {
multiplatformExtension.targets.all target@{ target ->
if (target is KotlinMetadataTarget)
return@target
target.compilations.all compilation@{ compilation ->
if (compilation is AbstractKotlinCompilation) {
val details = compilation.compilationDetails as? VariantMappedCompilationDetails<*>
?: return@compilation
copyAttributesToVariant(details.variant, compilation.attributes)
}
}
}
}
// Also handle the legacy-mapped variants, which are not accessible through the compilations in the loop above
project.kpmModules.getByName(GradleKpmModule.MAIN_MODULE_NAME).variants.withType(GradleKpmLegacyMappedVariant::class.java).all { variant ->
val compilation = variant.compilation
copyAttributesToVariant(variant, compilation.attributes)
}
}
private fun applyUserDefinedAttributesWithLegacyModel(
target: AbstractKotlinTarget,
) {
val project = target.project
project.whenEvaluated {
// To copy the attributes to the output configurations, find those output configurations and their producing compilations
// based on the target's components:
@@ -293,14 +234,20 @@ private fun applyUserDefinedAttributesWithLegacyModel(
}
internal fun sourcesJarTask(compilation: KotlinCompilation<*>, componentName: String, artifactNameAppendix: String): TaskProvider<Jar> =
sourcesJarTask(compilation.target.project, lazy { compilation.allKotlinSourceSets.associate { it.name to it.kotlin } }, componentName, artifactNameAppendix)
sourcesJarTask(
compilation.target.project,
lazy { compilation.allKotlinSourceSets.associate { it.name to it.kotlin } },
componentName,
artifactNameAppendix
)
private fun sourcesJarTask(
project: Project,
sourceSets: Lazy<Map<String, Iterable<File>>>,
taskNamePrefix: String,
artifactNameAppendix: String
): TaskProvider<Jar> = sourcesJarTaskNamed(lowerCamelCaseName(taskNamePrefix, "sourcesJar"), taskNamePrefix, project, sourceSets, artifactNameAppendix)
): TaskProvider<Jar> =
sourcesJarTaskNamed(lowerCamelCaseName(taskNamePrefix, "sourcesJar"), taskNamePrefix, project, sourceSets, artifactNameAppendix)
internal fun sourcesJarTaskNamed(
taskName: String,
@@ -15,7 +15,6 @@ import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Nested
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmModule
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
import org.jetbrains.kotlin.gradle.targets.metadata.dependsOnClosureWithInterCompilationDependencies
@@ -158,7 +157,6 @@ internal val KotlinMultiplatformExtension.kotlinProjectStructureMetadata: Kotlin
private fun buildKotlinProjectStructureMetadata(extension: KotlinMultiplatformExtension): KotlinProjectStructureMetadata {
val project = extension.project
require(!project.hasKpmModel) { "this function only works with the stable plugin" }
require(project.state.executed) { "Cannot build 'KotlinProjectStructureMetadata' during project configuration phase" }
val sourceSetsWithMetadataCompilations = extension.targets
@@ -11,17 +11,14 @@ import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.artifacts.component.*
import org.gradle.api.artifacts.result.ResolvedComponentResult
import org.gradle.api.publish.maven.MavenPublication
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.dsl.topLevelExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.PublishedModuleCoordinatesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.ComputedCapability
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.currentBuildId
import org.jetbrains.kotlin.gradle.utils.getValue
import org.jetbrains.kotlin.project.model.KpmModuleIdentifier
import org.jetbrains.kotlin.project.model.KpmLocalModuleIdentifier
import org.jetbrains.kotlin.project.model.KpmMavenModuleIdentifier
import org.jetbrains.kotlin.project.model.KpmModuleIdentifier
internal object ModuleIds {
fun fromDependency(dependency: Dependency): ModuleDependencyIdentifier = when (dependency) {
@@ -79,8 +76,8 @@ internal object ModuleIds {
val dependencyProject = thisProject.project(moduleIdentifier.projectId)
val topLevelExtension = dependencyProject.topLevelExtension
val getRootPublication: () -> MavenPublication? = when {
dependencyProject.hasKpmModel -> {
{ dependencyProject.kpmModelContainer.rootPublication }
dependencyProject.pm20ExtensionOrNull != null -> {
{ dependencyProject.pm20Extension.kpmModelContainer.rootPublication }
}
topLevelExtension is KotlinMultiplatformExtension -> {
{ topLevelExtension.rootSoftwareComponent.publicationDelegate }
@@ -88,8 +85,8 @@ internal object ModuleIds {
else -> error("unexpected top-level extension $topLevelExtension")
}
val capabilities = when {
dependencyProject.hasKpmModel -> listOfNotNull(ComputedCapability.capabilityStringFromModule(
dependencyProject.kpmModules.single { it.moduleIdentifier == moduleIdentifier }
dependencyProject.pm20ExtensionOrNull != null -> listOfNotNull(ComputedCapability.capabilityStringFromModule(
dependencyProject.pm20Extension.modules.single { it.moduleIdentifier == moduleIdentifier }
))
topLevelExtension is KotlinMultiplatformExtension -> emptyList()
else -> error("unexpected top-level extension $topLevelExtension")
@@ -9,9 +9,10 @@ import org.gradle.api.Project
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.artifacts.result.ResolvedComponentResult
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
import org.jetbrains.kotlin.gradle.dsl.pm20ExtensionOrNull
import org.jetbrains.kotlin.gradle.dsl.topLevelExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.kpmModules
import org.jetbrains.kotlin.project.model.KpmModuleIdentifier
import java.io.File
import java.io.InputStream
@@ -32,8 +33,8 @@ internal class ProjectMppDependencyProjectStructureMetadataExtractor(
override fun getProjectStructureMetadata(): KotlinProjectStructureMetadata? {
return when {
dependencyProject.topLevelExtensionOrNull == null -> null
dependencyProject.hasKpmModel -> buildProjectStructureMetadata(
dependencyProject.kpmModules.single { it.moduleIdentifier == moduleIdentifier }
dependencyProject.pm20ExtensionOrNull != null -> buildProjectStructureMetadata(
dependencyProject.pm20Extension.modules.single { it.moduleIdentifier == moduleIdentifier }
)
else -> dependencyProject.multiplatformExtensionOrNull?.kotlinProjectStructureMetadata
@@ -7,12 +7,11 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.pm20ExtensionOrNull
import org.jetbrains.kotlin.gradle.dsl.topLevelExtension
import org.jetbrains.kotlin.gradle.dsl.topLevelExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution.ChooseVisibleSourceSets.MetadataProvider.ProjectMetadataProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.kpmModules
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.metadataCompilationRegistryByModuleId
import org.jetbrains.kotlin.gradle.targets.native.internal.*
import org.jetbrains.kotlin.project.model.KpmModuleIdentifier
@@ -31,9 +30,9 @@ private class ProjectMetadataProviderImpl(
override fun getSourceSetCompiledMetadata(sourceSetName: String): FileCollection {
val projectExtension = dependencyProject.topLevelExtensionOrNull
return when {
dependencyProject.hasKpmModel -> {
dependencyProject.pm20ExtensionOrNull != null -> {
val moduleId = moduleIdentifier
val module = dependencyProject.kpmModules.single { it.moduleIdentifier == moduleId }
val module = dependencyProject.pm20Extension.modules.single { it.moduleIdentifier == moduleId }
val metadataCompilationRegistry = dependencyProject.metadataCompilationRegistryByModuleId.getValue(moduleId)
metadataCompilationRegistry.getForFragmentOrNull(module.fragments.getByName(sourceSetName))?.output?.classesDirs
?: dependencyProject.files()
@@ -1,45 +0,0 @@
/*
* 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.compilationDetailsImpl
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationDetails
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.AbstractKotlinFragmentMetadataCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.GradleKpmDependencyFilesHolder
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.ofMetadataCompilationDependencies
internal open class MetadataMappedCompilationDetails<T : KotlinCommonOptions>(
override val target: KotlinMetadataTarget,
defaultSourceSet: KotlinSourceSet,
final override val compilationData: AbstractKotlinFragmentMetadataCompilationData<T>
) : AbstractCompilationDetails<T>(defaultSourceSet) {
@Suppress("UNCHECKED_CAST")
override val compilation: KotlinCompilation<T>
get() = target.compilations.getByName(defaultSourceSet.name) as KotlinCompilation<T>
override val compileDependencyFilesHolder: GradleKpmDependencyFilesHolder =
GradleKpmDependencyFilesHolder.ofMetadataCompilationDependencies(compilationData)
override val kotlinDependenciesHolder: HasKotlinDependencies
get() = compilationData.fragment
override fun associateWith(other: CompilationDetails<*>) {
throw UnsupportedOperationException("not supported in the mapped model")
}
override val associateCompilations: Set<CompilationDetails<*>>
get() = emptySet()
override fun whenSourceSetAdded(sourceSet: KotlinSourceSet) {
if (sourceSet != defaultSourceSet)
throw UnsupportedOperationException("metadata compilations have predefined sources")
}
}
@@ -1,63 +0,0 @@
/*
* 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.compilationDetailsImpl
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationDetails
import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationDetailsWithRuntime
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmVariantInternal
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmVariantWithRuntimeInternal
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.GradleKpmDependencyFilesHolder
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.ofVariantCompileDependencies
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.ofVariantRuntimeDependencies
import org.jetbrains.kotlin.gradle.plugin.sources.kpm.FragmentMappedKotlinSourceSet
internal open class VariantMappedCompilationDetails<T : KotlinCommonOptions>(
open val variant: GradleKpmVariantInternal,
override val target: KotlinTarget,
defaultSourceSet: FragmentMappedKotlinSourceSet,
) : AbstractCompilationDetails<T>(defaultSourceSet) {
@Suppress("UNCHECKED_CAST")
override val compilationData: KotlinCompilationData<T>
get() = variant.compilationData as KotlinCompilationData<T>
override fun whenSourceSetAdded(sourceSet: KotlinSourceSet) {
compilation.defaultSourceSet.dependsOn(sourceSet)
}
override fun associateWith(other: CompilationDetails<*>) {
if (other !is VariantMappedCompilationDetails<*>)
error("a mapped variant can't be associated with a legacy one")
val otherModule = other.variant.containingModule
if (otherModule === variant.containingModule)
error("cannot associate $compilation with ${other.compilation} as they are mapped to the same $otherModule")
variant.containingModule.dependencies { implementation(otherModule) }
}
override val associateCompilations: Set<CompilationDetails<*>> get() = emptySet()
override val compileDependencyFilesHolder: GradleKpmDependencyFilesHolder
get() = GradleKpmDependencyFilesHolder.ofVariantCompileDependencies(variant)
override val kotlinDependenciesHolder: HasKotlinDependencies
get() = variant
}
internal open class VariantMappedCompilationDetailsWithRuntime<T : KotlinCommonOptions>(
override val variant: GradleKpmVariantWithRuntimeInternal,
target: KotlinTarget,
defaultSourceSet: FragmentMappedKotlinSourceSet
) : VariantMappedCompilationDetails<T>(variant, target, defaultSourceSet),
CompilationDetailsWithRuntime<T> {
override val runtimeDependencyFilesHolder: GradleKpmDependencyFilesHolder
get() = GradleKpmDependencyFilesHolder.ofVariantRuntimeDependencies(variant)
}
@@ -1,98 +0,0 @@
/*
* 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.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationDetailsImpl.VariantMappedCompilationDetails
import java.util.concurrent.Callable
internal open class GradleKpmAwareTargetConfigurator<T : KotlinTarget>(
private val legacyModelTargetConfigurator: AbstractKotlinTargetConfigurator<T>,
) : AbstractKotlinTargetConfigurator<T>(true),
KotlinTargetConfigurator<T> by legacyModelTargetConfigurator {
// NB: this override enforces calls to other overridden functions; without it, the delegate would call its own ones
override fun configureTarget(target: T) {
super<AbstractKotlinTargetConfigurator>.configureTarget(target)
doKpmSpecificConfigurationSteps(target)
}
protected open fun doKpmSpecificConfigurationSteps(target: T) {
setupMavenPublicationDsl(target)
}
private fun setupMavenPublicationDsl(target: T) {
if (target is AbstractKotlinTarget) {
target.compilations.all { compilation ->
val compilationDetails = (compilation as? AbstractKotlinCompilation)?.compilationDetails
if (compilationDetails is VariantMappedCompilationDetails<*> && compilationDetails.variant.containingModule.isMain) {
val variant = compilationDetails.variant
if (variant is GradleKpmSingleMavenPublishedModuleHolder) {
variant.whenPublicationAssigned { publication ->
target.publicationConfigureActions.all { action ->
action.execute(publication)
}
}
}
}
}
}
}
override fun defineConfigurationsForTarget(target: T) = Unit // done in KPM
override fun configureCompilationDefaults(target: T) {
// everything else is done in KPM, but KPM doesn't have resources processing yet
target.compilations.all { compilation ->
if (compilation is KotlinCompilationWithResources<*>) {
configureResourceProcessing(
compilation,
target.project.files(Callable { compilation.allKotlinSourceSets.map { it.resources } })
)
}
}
}
override fun configureCompilations(target: T) {
target.compilations.maybeCreate(KotlinCompilation.MAIN_COMPILATION_NAME)
if (legacyModelTargetConfigurator.createTestCompilation) {
target.compilations.maybeCreate(KotlinCompilation.TEST_COMPILATION_NAME)
}
}
override fun configureArchivesAndComponent(target: T) = Unit // done in KPM
override fun configureBuild(target: T) {
legacyModelTargetConfigurator.configureBuild(target)
}
override fun configureSourceSet(target: T) {
legacyModelTargetConfigurator.configureSourceSet(target)
}
}
internal class GradleKpmAwareTargetWithTestsConfigurator<R : KotlinTargetTestRun<*>, T : KotlinTargetWithTests<*, R>, C>(
private val legacyModelTargetWithTestsConfigurator: C
) :
GradleKpmAwareTargetConfigurator<T>(legacyModelTargetWithTestsConfigurator),
KotlinTargetWithTestsConfigurator<R, T>
where C : AbstractKotlinTargetConfigurator<T>,
C : KotlinTargetWithTestsConfigurator<R, T> {
override fun configureTarget(target: T) {
super<KotlinTargetWithTestsConfigurator>.configureTarget(target)
doKpmSpecificConfigurationSteps(target)
}
override val testRunClass: Class<R>
get() = legacyModelTargetWithTestsConfigurator.testRunClass
override fun createTestRun(name: String, target: T): R =
legacyModelTargetWithTestsConfigurator.createTestRun(name, target)
}
@@ -10,6 +10,7 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.result.ResolvedComponentResult
import org.gradle.api.artifacts.result.ResolvedDependencyResult
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.dsl.pm20ExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
import org.jetbrains.kotlin.project.model.*
@@ -20,7 +21,7 @@ internal fun resolvableMetadataConfiguration(
internal fun configurationToResolveMetadataDependencies(project: Project, requestingModule: KpmModule): Configuration =
when {
project.hasKpmModel -> resolvableMetadataConfiguration(requestingModule as GradleKpmModule)
project.pm20ExtensionOrNull != null -> resolvableMetadataConfiguration(requestingModule as GradleKpmModule)
else -> resolvableMetadataConfiguration(
project,
project.kotlinExtension.sourceSets, // take dependencies from all source sets; TODO introduce consistency scopes?
@@ -9,10 +9,7 @@ import org.gradle.api.artifacts.Configuration
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationDetailsImpl.VariantMappedCompilationDetailsWithRuntime
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName
import org.jetbrains.kotlin.gradle.plugin.sources.kpm.FragmentMappedKotlinSourceSet
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import javax.inject.Inject
abstract class GradleKpmJvmVariant @Inject constructor(
@@ -63,20 +60,3 @@ internal fun GradleKpmVariant.ownModuleName(): String {
val suffix = if (containingModule.moduleClassifier == null) "" else "_${containingModule.moduleClassifier}"
return filterModuleName("$baseName$suffix")
}
internal class KotlinMappedJvmCompilationFactory(
target: KotlinJvmTarget
) : KotlinJvmCompilationFactory(target) {
override fun create(name: String): KotlinJvmCompilation {
val module = target.project.kpmModules.maybeCreate(name)
val variant = module.fragments.create(target.name, GradleKpmJvmVariant::class.java)
return target.project.objects.newInstance(
KotlinJvmCompilation::class.java,
@Suppress("DEPRECATION")
(VariantMappedCompilationDetailsWithRuntime<KotlinJvmOptions>(
variant, target, getOrCreateDefaultSourceSet(name) as FragmentMappedKotlinSourceSet
))
)
}
}
@@ -1,252 +0,0 @@
/*
* 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.
*/
/*
* 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.Named
import org.gradle.api.NamedDomainObjectProvider
import org.gradle.api.artifacts.Configuration
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.FileCollection
import org.gradle.api.file.SourceDirectorySet
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.disambiguateName
import org.jetbrains.kotlin.gradle.plugin.mpp.publishedConfigurationName
import org.jetbrains.kotlin.gradle.plugin.sources.kpm.FragmentMappedKotlinSourceSet
import org.jetbrains.kotlin.gradle.utils.filesProvider
import org.jetbrains.kotlin.gradle.utils.withType
import org.jetbrains.kotlin.project.model.KotlinAttributeKey
import org.jetbrains.kotlin.project.model.KpmModuleDependency
import org.jetbrains.kotlin.tooling.core.MutableExtras
import org.jetbrains.kotlin.tooling.core.mutableExtrasOf
import javax.inject.Inject
internal abstract class GradleKpmLegacyMappedVariant @Inject constructor(
internal val compilation: KotlinCompilation<*>,
) : GradleKpmVariant {
override fun toString(): String = "variant mapped to $compilation"
private val fragmentForDefaultSourceSet =
(compilation.defaultSourceSet as FragmentMappedKotlinSourceSet).underlyingFragment
override val containingModule: GradleKpmModule get() = fragmentForDefaultSourceSet.containingModule
override val platformType: KotlinPlatformType
get() = compilation.platformType
override val compileDependenciesConfiguration: Configuration
get() = project.configurations.getByName(compilation.compileDependencyConfigurationName)
override var compileDependencyFiles: FileCollection
get() = compilation.compileDependencyFiles
set(value) {
compilation.compileDependencyFiles = value
}
override val compilationOutputs: KotlinCompilationOutput
get() = compilation.output
override val sourceArchiveTaskName: String
get() = defaultSourceArtifactTaskName // TODO: no such task yet
override val apiElementsConfiguration: Configuration
get() = if (compilation.isMain())
project.configurations.getByName(compilation.target.apiElementsConfigurationName) else
project.configurations.maybeCreate(disambiguateName("apiElements")).apply {
isCanBeConsumed = false
isCanBeResolved = false
}
override val gradleVariantNames: Set<String>
get() {
val allTargetComponents = (compilation.target as AbstractKotlinTarget).kotlinComponents
val allTargetUsages = allTargetComponents.flatMap {
when (it) {
is KotlinVariant -> it.usages
is JointAndroidKotlinTargetComponent -> it.usages
else -> emptyList()
}
}
val compilationUsages = allTargetUsages.filterIsInstance<DefaultKotlinUsageContext>().filter { it.compilation == compilation }
return compilationUsages.filter { it.includeIntoProjectStructureMetadata }
.flatMap { listOf(it.dependencyConfigurationName, publishedConfigurationName(it.dependencyConfigurationName)) }
.toSet()
}
override val kotlinSourceRoots: SourceDirectorySet
get() = compilation.defaultSourceSet.kotlin
override val languageSettings: LanguageSettingsBuilder
get() = compilation.defaultSourceSet.languageSettings
override val extras: MutableExtras = mutableExtrasOf()
override fun refines(other: GradleKpmFragment) {
fragmentForDefaultSourceSet.refines(other)
}
override fun refines(other: NamedDomainObjectProvider<GradleKpmFragment>) {
fragmentForDefaultSourceSet.refines(other)
}
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit) {
fragmentForDefaultSourceSet.dependencies(configure)
}
//FIXME map to the original name, require that the fragment for source set does not exist yet?
override val fragmentName: String
get() = fragmentForDefaultSourceSet.fragmentName + "Variant"
override val declaredRefinesDependencies: Iterable<GradleKpmFragment>
get() = fragmentForDefaultSourceSet.declaredRefinesDependencies
override val declaredModuleDependencies: Iterable<KpmModuleDependency>
get() = fragmentForDefaultSourceSet.declaredModuleDependencies
/** This configuration includes the dependencies from the refines-parents */
override val transitiveApiConfiguration: Configuration
get() = TODO("Not yet implemented")
/** This configuration includes the dependencies from the refines-parents */
override val transitiveImplementationConfiguration: Configuration
get() = TODO("Not yet implemented")
override val transitiveRuntimeOnlyConfiguration: Configuration
get() = TODO("Not yet implemented")
override val apiConfiguration: Configuration
get() = project.configurations.getByName(apiConfigurationName)
override val implementationConfiguration: Configuration
get() = project.configurations.getByName(implementationConfigurationName)
override val compileOnlyConfiguration: Configuration
get() = project.configurations.getByName(compileOnlyConfigurationName)
override val runtimeOnlyConfiguration: Configuration
get() = project.configurations.getByName(runtimeOnlyConfigurationName)
override val apiConfigurationName: String
get() = fragmentForDefaultSourceSet.apiConfigurationName
override val implementationConfigurationName: String
get() = fragmentForDefaultSourceSet.implementationConfigurationName
override val compileOnlyConfigurationName: String
get() = fragmentForDefaultSourceSet.compileOnlyConfigurationName
override val runtimeOnlyConfigurationName: String
get() = fragmentForDefaultSourceSet.runtimeOnlyConfigurationName
override val variantAttributes: Map<KotlinAttributeKey, String>
// TODO handle user attributes
get() = compilation.attributes.keySet().filter { it.name.startsWith("org.jetbrains.kotlin") }.associate {
val value = compilation.attributes.getAttribute(it)
KotlinAttributeKey(it.name) to ((value as? Named)?.name ?: value.toString())
}
}
internal abstract class GradleKpmLegacyMappedVariantWithRuntime @Inject constructor(private val compilationWithRuntime: KotlinCompilationToRunnableFiles<*>) :
GradleKpmLegacyMappedVariant(compilationWithRuntime),
GradleKpmVariantWithRuntime {
override val runtimeDependenciesConfiguration: Configuration
get() = project.configurations.getByName(compilationWithRuntime.runtimeDependencyConfigurationName)
override var runtimeDependencyFiles: FileCollection
get() = compilationWithRuntime.runtimeDependencyFiles
set(value) {
compilationWithRuntime.runtimeDependencyFiles = value
}
override val runtimeFiles: ConfigurableFileCollection
get() = project.filesProvider { listOf(runtimeFiles, compilationWithRuntime.output.allOutputs) }
override val runtimeElementsConfiguration: Configuration
get() = if (compilationWithRuntime.isMain())
project.configurations.getByName(compilationWithRuntime.target.runtimeElementsConfigurationName)
else project.configurations.maybeCreate(disambiguateName("runtimeElements"))
}
internal enum class PublicationRegistrationMode {
IMMEDIATE, AFTER_EVALUATE
}
internal fun mapTargetCompilationsToKpmVariants(target: AbstractKotlinTarget, publicationRegistration: PublicationRegistrationMode) {
target.compilations.all { compilation ->
val variant = if (compilation is KotlinCompilationToRunnableFiles)
target.project.objects.newInstance(
GradleKpmLegacyMappedVariantWithRuntime::class.java,
compilation
)
else target.project.objects.newInstance(
GradleKpmLegacyMappedVariant::class.java,
compilation
)
val defaultSourceSetFragment = (compilation.defaultSourceSet as FragmentMappedKotlinSourceSet).underlyingFragment
variant.refines(defaultSourceSetFragment)
val module = defaultSourceSetFragment.containingModule
module.fragments.add(variant)
}
fun whenPublicationShouldRegister(action: () -> Unit) =
when (publicationRegistration) {
PublicationRegistrationMode.IMMEDIATE -> action()
PublicationRegistrationMode.AFTER_EVALUATE -> target.project.whenEvaluated { action() }
}
whenPublicationShouldRegister {
val mainModule = target.project.kpmModules.getByName(GradleKpmModule.MAIN_MODULE_NAME)
target.kotlinComponents.forEach { kotlinComponent ->
val moduleHolder = GradleKpmDefaultSingleMavenPublishedModuleHolder(
mainModule,
kotlinComponent.defaultArtifactId.removePrefix(target.project.name.toLowerCase() + "-")
)
val usages = when (kotlinComponent) { // unfortunately, there's no common supertype with `usages`
is KotlinVariant -> kotlinComponent.usages
is JointAndroidKotlinTargetComponent -> kotlinComponent.usages
else -> error("unexpected type of kotlinComponent in legacy variant mapping: ${kotlinComponent.javaClass}")
}
moduleHolder.whenPublicationAssigned { publication ->
// Include Sources
kotlinComponent.sourcesArtifacts.forEach {
publication.artifact(it)
}
// Support the `mavenPublication { ... }` DSL in target:
target.publicationConfigureActions.all { action ->
action.execute(publication)
}
}
// FIXME: include additional variants into project structure metadata?
val request = GradleKpmBasicPlatformPublicationToMavenRequest(
kotlinComponent.name,
mainModule,
moduleHolder,
usages.map { usage ->
val variant = mainModule.variants.withType<GradleKpmLegacyMappedVariant>().single {
it.compilation == usage.compilation
}
(usage as? DefaultKotlinUsageContext) ?: error("unexpected KotlinUsageContext type: ${usage.javaClass}")
KpmGradleAdvancedConfigurationPublicationRequest(
variant,
target.project.configurations.getByName(usage.dependencyConfigurationName),
usage.overrideConfigurationAttributes,
usage.overrideConfigurationArtifacts,
usage.includeIntoProjectStructureMetadata
)
}
)
GradleKpmVariantPublishingConfigurator.get(target.project).configurePublishing(request)
}
}
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.gradle.api.NamedDomainObjectFactory
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
open class GradleKpmModuleFactory(private val project: Project) : NamedDomainObjectFactory<GradleKpmModule> {
override fun create(name: String): GradleKpmModule {
@@ -34,7 +35,7 @@ open class GradleKpmModuleFactory(private val project: Project) : NamedDomainObj
.matching { it.fragmentName == GradleKpmFragment.COMMON_FRAGMENT_NAME }
.configureEach { commonFragment ->
commonFragment.dependencies {
api(module.project.kpmModules.getByName(GradleKpmModule.MAIN_MODULE_NAME))
api(module.project.pm20Extension.modules.getByName(GradleKpmModule.MAIN_MODULE_NAME))
}
}
}
@@ -7,9 +7,8 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.gradle.api.artifacts.Configuration
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationDetailsImpl.VariantMappedCompilationDetails
import org.jetbrains.kotlin.gradle.plugin.sources.kpm.FragmentMappedKotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultCInteropSettings
import org.jetbrains.kotlin.gradle.plugin.mpp.publishedConfigurationName
import org.jetbrains.kotlin.konan.target.KonanTarget
abstract class GradleKpmNativeVariantInternal(
@@ -49,21 +48,3 @@ interface KotlinNativeCompilationData<T : KotlinCommonOptions> : KotlinCompilati
@Deprecated("Please declare explicit dependency on kotlinx-cli. This option is scheduled to be removed in 1.9.0")
val enableEndorsedLibs: Boolean
}
internal class KotlinMappedNativeCompilationFactory(
target: KotlinNativeTarget,
private val variantClass: Class<out GradleKpmNativeVariantInternal>
) : KotlinNativeCompilationFactory(target) {
override fun create(name: String): KotlinNativeCompilation {
val module = target.project.kpmModules.maybeCreate(name)
val variant = module.fragments.create(target.name, variantClass)
return target.project.objects.newInstance(
KotlinNativeCompilation::class.java,
target.konanTarget,
VariantMappedCompilationDetails<KotlinCommonOptions>(
variant, target, getOrCreateDefaultSourceSet(name) as FragmentMappedKotlinSourceSet
)
)
}
}
@@ -8,9 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.publish.maven.MavenPublication
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.dsl.topLevelExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
import org.jetbrains.kotlin.project.model.KpmModuleIdentifier
internal interface GradleKpmProjectModelContainer {
@@ -19,24 +17,8 @@ internal interface GradleKpmProjectModelContainer {
val rootPublication: MavenPublication?
}
internal val Project.kpmModelContainer: GradleKpmProjectModelContainer
get() = kpmModelContainerOrNull ?: error("Couldn't find KPM container for $project")
internal val Project.kpmModelContainerOrNull: GradleKpmProjectModelContainer?
get() = when (val ext = project.topLevelExtensionOrNull) {
is KotlinPm20ProjectExtension -> ext.kpmModelContainer
is KotlinProjectExtension -> if (PropertiesProvider(project).experimentalKpmModelMapping) ext.kpmModelContainer else null
else -> null
}
internal val Project.hasKpmModel: Boolean
get() = kpmModelContainerOrNull != null
internal val Project.kpmModules: NamedDomainObjectContainer<GradleKpmModule>
get() = kpmModelContainer.modules
internal val Project.metadataCompilationRegistryByModuleId: MutableMap<KpmModuleIdentifier, MetadataCompilationRegistry>
get() = kpmModelContainer.metadataCompilationRegistryByModuleId
get() = this.pm20Extension.kpmModelContainer.metadataCompilationRegistryByModuleId
internal class GradleKpmDefaultProjectModelContainer(
override val modules: NamedDomainObjectContainer<GradleKpmModule>,
@@ -5,9 +5,6 @@
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.sources.kpm.FragmentMappedKotlinSourceSet
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import java.io.File
@@ -26,18 +23,7 @@ object GradleKpmDefaultSourceDirectoriesConfigurator : GradleKpmSourceDirectorie
}
private fun fragmentDirectoryName(fragment: GradleKpmFragment): String {
val project = fragment.project
val isModelMappingEnabled = project.multiplatformExtensionOrNull != null
val kpmDefaultResult = lowerCamelCaseName(fragment.name, fragment.containingModule.name)
return if (!isModelMappingEnabled) {
kpmDefaultResult
} else {
val sourceSet =
project.kotlinExtension.sourceSets.find { it is FragmentMappedKotlinSourceSet && it.underlyingFragment == fragment }
if (sourceSet != null)
sourceSet.name
else kpmDefaultResult
}
return lowerCamelCaseName(fragment.name, fragment.containingModule.name)
}
fun defaultSourceFolder(fragment: GradleKpmFragment, type: String): File {
@@ -9,7 +9,8 @@ import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.file.FileCollection
import org.gradle.api.file.SourceDirectorySet
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KpmGradleModuleVariantResolver
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.allDependencyModules
@@ -53,7 +54,7 @@ interface GradleKpmVariantCompilationDataInternal<T : KotlinCommonOptions> : Gra
override val moduleName: String
get() = // TODO accurate module names that don't rely on all variants having a main counterpart
owner.containingModule.project.kpmModules
owner.containingModule.project.pm20Extension.modules
.getByName(GradleKpmModule.MAIN_MODULE_NAME).variants.findByName(owner.name)?.ownModuleName() ?: ownModuleName
override val ownModuleName: String
@@ -97,7 +97,7 @@ open class KotlinPm20ProjectExtension(project: Project) : KotlinTopLevelExtensio
internal val ideaKpmProjectModelBuilder by lazy { IdeaKpmProjectModelBuilder.default(this) }
val modules: NamedDomainObjectContainer<GradleKpmModule>
get() = project.kpmModules
get() = kpmModelContainer.modules
@Suppress("unused") // DSL function
fun mainAndTest(configure: GradleKpmModule.() -> Unit) {
@@ -6,9 +6,10 @@
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
internal fun registerDefaultVariantFactories(project: Project) {
project.kpmModules.configureEach { module ->
project.pm20Extension.modules.configureEach { module ->
module.fragments.registerFactory(
GradleKpmJvmVariant::class.java,
GradleKpmJvmVariantFactory(module)
@@ -11,18 +11,18 @@ import org.gradle.api.attributes.Category
import org.gradle.api.attributes.Usage
import org.gradle.api.tasks.TaskProvider
import org.gradle.jvm.tasks.Jar
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
import org.jetbrains.kotlin.gradle.plugin.KotlinCommonSourceSetProcessor
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.categoryByName
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.ComputedCapability
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.disambiguateName
import org.jetbrains.kotlin.gradle.plugin.usageByName
import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator
import org.jetbrains.kotlin.gradle.targets.metadata.createGenerateProjectStructureMetadataTask
import org.jetbrains.kotlin.gradle.targets.metadata.filesWithUnpackedArchives
import org.jetbrains.kotlin.gradle.tasks.*
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
import org.jetbrains.kotlin.gradle.tasks.registerTask
import org.jetbrains.kotlin.gradle.tasks.withType
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
import org.jetbrains.kotlin.gradle.utils.filesProvider
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.project.model.KpmFragment
import java.util.concurrent.Callable
internal fun setupFragmentsMetadataForKpmModules(project: Project) {
project.kpmModules.all { module ->
project.pm20Extension.modules.all { module ->
configureMetadataResolutionAndBuild(module)
configureMetadataExposure(module)
}
@@ -9,11 +9,12 @@ import org.gradle.api.Project
import org.gradle.api.component.SoftwareComponentFactory
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
import org.jetbrains.kotlin.gradle.tooling.buildKotlinToolingMetadataTask
import javax.inject.Inject
internal fun setupKpmModulesPublication(project: Project) {
project.kpmModules.all { module ->
project.pm20Extension.modules.all { module ->
setupPublicationForModule(module)
}
}
@@ -121,10 +121,7 @@ open class GradleKpmVariantPublishingConfigurator @Inject constructor(
// Collecting sources for multiple variants is not yet supported;
// TODO make callers provide the source variants?
// The MPP plugin doesn't publish the source artifacts as variants; keep that behavior for legacy-mapped variants for now
if (
publishFromVariants.size == 1 &&
publishFromVariants.none { it is GradleKpmLegacyMappedVariant }
) {
if (publishFromVariants.size == 1) {
val singlePublishedVariant = publishFromVariants.single()
configureSourceElementsPublishing(componentName, singlePublishedVariant)
}
@@ -1,111 +0,0 @@
/*
* 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.sources.kpm
import org.gradle.api.Action
import org.gradle.api.InvalidUserDataException
import org.gradle.api.Project
import org.gradle.api.file.SourceDirectorySet
import org.jetbrains.kotlin.build.DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.plugin.sources.AbstractKotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.sources.createDefaultSourceDirectorySet
import javax.inject.Inject
abstract class FragmentMappedKotlinSourceSet @Inject constructor(
private val sourceSetName: String,
private val project: Project,
internal val underlyingFragment: GradleKpmFragment
) : AbstractKotlinSourceSet() {
val displayName: String
get() = sourceSetName
override val apiConfigurationName: String get() = underlyingFragment.apiConfigurationName
override val implementationConfigurationName: String get() = underlyingFragment.implementationConfigurationName
override val compileOnlyConfigurationName: String get() = underlyingFragment.compileOnlyConfigurationName
override val runtimeOnlyConfigurationName: String get() = underlyingFragment.runtimeOnlyConfigurationName
// FIXME deprecate the property in the supertype?
override val apiMetadataConfigurationName: String
get() = error("should not be used with KPM mapped model")
override val implementationMetadataConfigurationName: String
get() = error("should not be used with KPM mapped model")
override val compileOnlyMetadataConfigurationName: String
get() = error("should not be used with KPM mapped model")
override val runtimeOnlyMetadataConfigurationName: String
get() = error("should not be used with KPM mapped model")
override val kotlin: SourceDirectorySet = underlyingFragment.kotlinSourceRoots
override val languageSettings: LanguageSettingsBuilder = underlyingFragment.languageSettings
override val resources: SourceDirectorySet = createDefaultSourceDirectorySet(project, "$name resources")
override fun kotlin(configure: SourceDirectorySet.() -> Unit): SourceDirectorySet = kotlin.apply {
configure(this)
}
override fun kotlin(configure: Action<SourceDirectorySet>): SourceDirectorySet =
kotlin { configure.execute(this) }
override fun languageSettings(configure: Action<LanguageSettingsBuilder>): LanguageSettingsBuilder = languageSettings.apply {
configure.execute(this)
}
override fun languageSettings(configure: LanguageSettingsBuilder.() -> Unit): LanguageSettingsBuilder =
languageSettings.apply { configure(this) }
override fun getName(): String = displayName
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit): Unit =
underlyingFragment.dependencies(configure)
override fun dependencies(configure: Action<KotlinDependencyHandler>) =
underlyingFragment.dependencies(configure)
override fun afterDependsOnAdded(other: KotlinSourceSet) {
if (other !is FragmentMappedKotlinSourceSet) {
throw InvalidUserDataException("Could set up dependsOn relationship with an unknown source set $other")
}
val otherFragment = other.underlyingFragment
underlyingFragment.refines(otherFragment)
}
override fun toString(): String = "source set $name"
override val requiresVisibilityOf: Set<KotlinSourceSet>
get() = emptySet()
override fun requiresVisibilityOf(other: KotlinSourceSet) {
throw UnsupportedOperationException("requiresVisibilityOf is not supported for the mapped model")
}
// region Ported with copy & paste
// FIXME move to fragment?
private val explicitlyAddedCustomSourceFilesExtensions = ArrayList<String>()
override val customSourceFilesExtensions: Iterable<String>
get() = Iterable {
val fromExplicitFilters = kotlin.filter.includes.mapNotNull { pattern ->
pattern.substringAfterLast('.')
}
val merged = (fromExplicitFilters + explicitlyAddedCustomSourceFilesExtensions).filterNot { extension ->
DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS.any { extension.equals(it, ignoreCase = true) }
|| extension.any { it == '\\' || it == '/' }
}.distinct()
merged.iterator()
}
override fun addCustomSourceFilesExtensions(extensions: List<String>) {
explicitlyAddedCustomSourceFilesExtensions.addAll(extensions)
}
//endregion
}
@@ -1,24 +0,0 @@
/*
* 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.sources.kpm
import org.gradle.api.NamedDomainObjectFactory
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.kpmModules
class FragmentMappedKotlinSourceSetFactory constructor(private val project: Project) :
NamedDomainObjectFactory<KotlinSourceSet> {
override fun create(name: String): FragmentMappedKotlinSourceSet {
val locator = SourceSetMappedFragmentLocator.get(project)
val location = locator.locateFragmentForSourceSet(project, name) ?: error("Couldn't map the source set name $name to KPM fragment")
val fragment = project.kpmModules.maybeCreate(location.moduleName).fragments.maybeCreate(location.fragmentName)
/** TODO setup JS-specific attributes similar to [org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSetFactory]*/
return project.objects.newInstance(FragmentMappedKotlinSourceSet::class.java, name, project, fragment)
}
}
@@ -1,87 +0,0 @@
/*
* 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.sources.kpm
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.topLevelExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTargetPreset
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmModule
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.kpmModules
interface SourceSetMappedFragmentLocator {
data class FragmentLocation(val moduleName: String, val fragmentName: String) {
init {
require(moduleName.isNotEmpty()) { "module name should not be empty, got empty one and fragment name $fragmentName" }
require(fragmentName.isNotEmpty()) { "fragment name should not be empty, got empty one and module name $moduleName" }
}
}
fun locateFragmentForSourceSet(project: Project, sourceSetName: String): FragmentLocation?
companion object {
fun get(project: Project): SourceSetMappedFragmentLocator = when (project.topLevelExtensionOrNull) {
is KotlinMultiplatformExtension -> MultiplatformSourceSetMappedFragmentLocator()
is KotlinSingleTargetExtension<*> -> error("KPM model mapping is not yet supported in single-platform projects; tried to apply to $project")
else -> error("couldn't provide model mapping utilities for project $project")
}
}
}
internal class MultiplatformSourceSetMappedFragmentLocator : SourceSetMappedFragmentLocator {
override fun locateFragmentForSourceSet(project: Project, sourceSetName: String): SourceSetMappedFragmentLocator.FragmentLocation {
val camelCaseParts = sourceSetName.camelCaseParts()
if (camelCaseParts.size < 2) {
return SourceSetMappedFragmentLocator.FragmentLocation(GradleKpmModule.MAIN_MODULE_NAME, sourceSetName)
}
val androidTarget = when (val ext = project.topLevelExtension) {
is KotlinAndroidProjectExtension -> ext.target
is KotlinMultiplatformExtension ->
ext.targets.withType(KotlinAndroidTarget::class.java).singleOrNull()
?: ext.presets.withType(KotlinAndroidTargetPreset::class.java).single().targetUnderConstruction
else -> null
}
val candidateModuleNames = (1..camelCaseParts.size).asSequence().map { camelCaseParts.takeLast(it).joinToString("").decapitalize() }
val moduleName =
run {
if (androidTarget != null && sourceSetName.startsWith(androidTarget.name))
androidSourceSetModuleName(androidTarget.name, sourceSetName)
else null
} ?: candidateModuleNames.lastOrNull { project.kpmModules.findByName(it) != null }
?: GradleKpmModule.MAIN_MODULE_NAME
val fragmentName =
if (sourceSetName.endsWith(moduleName, ignoreCase = true)) sourceSetName.dropLast(moduleName.length) else sourceSetName
return SourceSetMappedFragmentLocator.FragmentLocation(moduleName, fragmentName)
}
private fun androidSourceSetModuleName(targetName: String, sourceSetName: String): String? {
val compilationName = sourceSetName.removePrefix(targetName).takeIf { it != sourceSetName } ?: return null
return when {
"Test" in compilationName -> "test"
else -> GradleKpmModule.MAIN_MODULE_NAME
}
}
private fun String.camelCaseParts(): List<String> {
val capitalizedMatches = Regex("[A-Z][^A-Z]*").findAll(this).toList()
val firstNonCapitalizedWord = capitalizedMatches.firstOrNull()?.let { substring(it.range.first) } ?: this
return listOf(firstNonCapitalizedWord) + capitalizedMatches.map { it.value }
}
}
private class SingleTargetSourceSetMappedFragmentLocator : SourceSetMappedFragmentLocator {
override fun locateFragmentForSourceSet(project: Project, sourceSetName: String): SourceSetMappedFragmentLocator.FragmentLocation {
return SourceSetMappedFragmentLocator.FragmentLocation(sourceSetName, SINGLE_PLATFORM_FRAGMENT_NAME)
}
}
internal const val SINGLE_PLATFORM_FRAGMENT_NAME = "common"
@@ -9,9 +9,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPlugin.Companion.dynamicallyApplyWhenAndroidPluginIsApplied
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.PublicationRegistrationMode
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.mapTargetCompilationsToKpmVariants
import javax.inject.Inject
abstract class KotlinAndroidTargetPreset @Inject constructor(
@@ -32,10 +30,6 @@ abstract class KotlinAndroidTargetPreset @Inject constructor(
project.dynamicallyApplyWhenAndroidPluginIsApplied({ result })
if (project.hasKpmModel) {
mapTargetCompilationsToKpmVariants(result, PublicationRegistrationMode.AFTER_EVALUATE)
}
targetUnderConstruction = null
return result
@@ -10,9 +10,6 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.PublicationRegistrationMode
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.mapTargetCompilationsToKpmVariants
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTargetConfigurator
@@ -102,14 +99,6 @@ open class KotlinJsTargetPreset(
companion object {
const val PRESET_NAME = "js"
}
override fun createTarget(name: String): KotlinJsTarget {
val result = super.createTarget(name)
if (project.hasKpmModel) {
mapTargetCompilationsToKpmVariants(result, PublicationRegistrationMode.IMMEDIATE)
}
return result
}
}
class KotlinJsSingleTargetPreset(
@@ -10,9 +10,6 @@ import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinCompilationFactory
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTargetPreset
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.PublicationRegistrationMode
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.mapTargetCompilationsToKpmVariants
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.gradle.utils.runProjectConfigurationHealthCheckWhenEvaluated
@@ -66,14 +63,6 @@ open class KotlinJsIrTargetPreset(
override fun createKotlinTargetConfigurator(): AbstractKotlinTargetConfigurator<KotlinJsIrTarget> =
KotlinJsIrTargetConfigurator()
override fun createTarget(name: String): KotlinJsIrTarget {
val result = super.createTarget(name)
if (project.hasKpmModel) {
mapTargetCompilationsToKpmVariants(result, PublicationRegistrationMode.IMMEDIATE)
}
return result
}
override fun getName(): String = JS_PRESET_NAME
//TODO[Ilya Goncharov] remove public morozov
@@ -6,14 +6,12 @@
package org.jetbrains.kotlin.gradle.targets.js.ir
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.AbstractKotlinTargetConfigurator
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinCompilationFactory
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTargetPreset
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.PublicationRegistrationMode
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.mapTargetCompilationsToKpmVariants
import org.jetbrains.kotlin.gradle.utils.runProjectConfigurationHealthCheckWhenEvaluated
class KotlinWasmTargetPreset(
@@ -53,14 +51,6 @@ class KotlinWasmTargetPreset(
override fun createKotlinTargetConfigurator(): AbstractKotlinTargetConfigurator<KotlinJsIrTarget> =
KotlinJsIrTargetConfigurator()
override fun createTarget(name: String): KotlinJsIrTarget {
val result = super.createTarget(name)
if (project.hasKpmModel) {
mapTargetCompilationsToKpmVariants(result, PublicationRegistrationMode.IMMEDIATE)
}
return result
}
override fun getName(): String = WASM_PRESET_NAME
public override fun createCompilationFactory(
@@ -9,10 +9,6 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.plugin.AbstractKotlinTargetConfigurator
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinMappedJvmCompilationFactory
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmAwareTargetWithTestsConfigurator
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTargetConfigurator
@@ -28,16 +24,10 @@ class KotlinJvmTargetPreset(
override fun getName(): String = PRESET_NAME
override fun createCompilationFactory(forTarget: KotlinJvmTarget): KotlinCompilationFactory<KotlinJvmCompilation> =
if (PropertiesProvider(project).experimentalKpmModelMapping)
KotlinMappedJvmCompilationFactory(forTarget)
else KotlinJvmCompilationFactory(forTarget)
KotlinJvmCompilationFactory(forTarget)
override fun createKotlinTargetConfigurator(): AbstractKotlinTargetConfigurator<KotlinJvmTarget> {
val configurator = KotlinJvmTargetConfigurator()
return if (project.hasKpmModel)
GradleKpmAwareTargetWithTestsConfigurator(configurator)
else configurator
}
override fun createKotlinTargetConfigurator(): AbstractKotlinTargetConfigurator<KotlinJvmTarget> =
KotlinJvmTargetConfigurator()
override val platformType: KotlinPlatformType
get() = KotlinPlatformType.jvm
@@ -1,75 +0,0 @@
/*
* 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.targets.metadata
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformCommonOptions
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationDetailsImpl.MetadataMappedCompilationDetails
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.unambiguousNameInProject
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
import org.jetbrains.kotlin.project.model.utils.variantsContainingFragment
internal class GradleKpmMetadataTargetConfigurator(private val metadataTargetConfigurator: KotlinMetadataTargetConfigurator) :
GradleKpmAwareTargetConfigurator<KotlinMetadataTarget>(metadataTargetConfigurator) {
override fun configureTarget(target: KotlinMetadataTarget) {
super.configureTarget(target)
configureTargetWithKpm(target)
}
override fun configureCompilationDefaults(target: KotlinMetadataTarget) {
super.configureCompilationDefaults(target)
val mainCompilation = target.compilations.create(KotlinCompilation.MAIN_COMPILATION_NAME)
defineConfigurationsForCompilation(mainCompilation)
createLifecycleTask(mainCompilation)
metadataTargetConfigurator
.buildCompilationProcessor(mainCompilation)
.run()
mainCompilation.compileKotlinTaskProvider.configure { it.enabled = false }
}
private fun configureTargetWithKpm(target: KotlinMetadataTarget) {
target.project.whenEvaluated {
val mainModule = target.project.kpmModules.getByName(GradleKpmModule.MAIN_MODULE_NAME)
val metadataCompilations = target.project.metadataCompilationRegistryByModuleId.getValue(mainModule.moduleIdentifier)
mainModule.fragments.forEach { fragment ->
val compilationData = metadataCompilations.getForFragmentOrNull(fragment) ?: return@forEach
if (!compilationData.isActive) return@forEach
val defaultSourceSet = target.project.kotlinExtension.sourceSets.maybeCreate(fragment.unambiguousNameInProject)
val compilationDetails = MetadataMappedCompilationDetails(target, defaultSourceSet, compilationData)
val isNative = compilationData is KotlinNativeFragmentMetadataCompilationData
@Suppress("UNCHECKED_CAST")
val compilation = when {
isNative -> {
val konanTargets =
mainModule.variantsContainingFragment(fragment).map { (it as GradleKpmNativeVariantInternal).konanTarget }
target.project.objects.newInstance(
KotlinSharedNativeCompilation::class.java,
konanTargets,
compilationDetails as CompilationDetails<KotlinCommonOptions>
)
}
else -> target.project.objects
.newInstance(
KotlinCommonCompilation::class.java,
(compilationDetails as CompilationDetails<KotlinMultiplatformCommonOptions>)
)
}
target.compilations.add(compilation)
}
}
}
}
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationDetailsImpl.DefaultCompilationDetails
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.sources.*
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
import org.jetbrains.kotlin.gradle.targets.native.internal.*
@@ -37,14 +36,14 @@ internal const val ALL_COMPILE_METADATA_CONFIGURATION_NAME = "allSourceSetsCompi
internal const val ALL_RUNTIME_METADATA_CONFIGURATION_NAME = "allSourceSetsRuntimeDependenciesMetadata"
internal val Project.isKotlinGranularMetadataEnabled: Boolean
get() = project.hasKpmModel || with(PropertiesProvider(rootProject)) {
get() = project.pm20ExtensionOrNull != null || with(PropertiesProvider(rootProject)) {
mppHierarchicalStructureByDefault || // then we want to use KLIB granular compilation & artifacts even if it's just commonMain
hierarchicalStructureSupport ||
enableGranularSourceSetsMetadata == true
}
internal val Project.shouldCompileIntermediateSourceSetsToMetadata: Boolean
get() = project.hasKpmModel || with(PropertiesProvider(rootProject)) {
get() = project.pm20ExtensionOrNull != null || with(PropertiesProvider(rootProject)) {
when {
!hierarchicalStructureSupport && mppHierarchicalStructureByDefault -> false
else -> true
@@ -294,8 +293,6 @@ class KotlinMetadataTargetConfigurator :
): AbstractKotlinCompilation<*> {
val project = target.project
check(!project.hasKpmModel) { "KotlinMetadataTargetConfigurator cannot work with KPM!" }
val compilationName = sourceSet.name
val platformCompilations = sourceSet.internal.compilations
@@ -394,21 +391,19 @@ class KotlinMetadataTargetConfigurator :
}
}
if (!PropertiesProvider(project).experimentalKpmModelMapping) {
val sourceSetMetadataConfigurationByScope = project.sourceSetMetadataConfigurationByScope(sourceSet, scope)
granularMetadataTransformation.applyToConfiguration(sourceSetMetadataConfigurationByScope)
if (scope != KotlinDependencyScope.COMPILE_ONLY_SCOPE) {
project.addExtendsFromRelation(
sourceSetMetadataConfigurationByScope.name,
ALL_COMPILE_METADATA_CONFIGURATION_NAME
)
}
if (scope != KotlinDependencyScope.RUNTIME_ONLY_SCOPE) {
project.addExtendsFromRelation(
sourceSetMetadataConfigurationByScope.name,
ALL_COMPILE_METADATA_CONFIGURATION_NAME
)
}
val sourceSetMetadataConfigurationByScope = project.sourceSetMetadataConfigurationByScope(sourceSet, scope)
granularMetadataTransformation.applyToConfiguration(sourceSetMetadataConfigurationByScope)
if (scope != KotlinDependencyScope.COMPILE_ONLY_SCOPE) {
project.addExtendsFromRelation(
sourceSetMetadataConfigurationByScope.name,
ALL_COMPILE_METADATA_CONFIGURATION_NAME
)
}
if (scope != KotlinDependencyScope.RUNTIME_ONLY_SCOPE) {
project.addExtendsFromRelation(
sourceSetMetadataConfigurationByScope.name,
ALL_COMPILE_METADATA_CONFIGURATION_NAME
)
}
}
}
@@ -9,9 +9,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToCompilerOptions
import org.jetbrains.kotlin.gradle.targets.metadata.GradleKpmMetadataTargetConfigurator
import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator
class KotlinMetadataTargetPreset(
@@ -41,12 +39,8 @@ class KotlinMetadataTargetPreset(
const val PRESET_NAME = "metadata"
}
override fun createKotlinTargetConfigurator(): AbstractKotlinTargetConfigurator<KotlinMetadataTarget> {
val metadataConfigurator = KotlinMetadataTargetConfigurator()
return if (project.hasKpmModel)
GradleKpmMetadataTargetConfigurator(metadataConfigurator)
else metadataConfigurator
}
override fun createKotlinTargetConfigurator(): AbstractKotlinTargetConfigurator<KotlinMetadataTarget> =
KotlinMetadataTargetConfigurator()
override fun instantiateTarget(name: String): KotlinMetadataTarget {
return project.objects.newInstance(KotlinMetadataTarget::class.java, project)
@@ -60,11 +54,9 @@ class KotlinMetadataTargetPreset(
mainCompilation.source(commonMainSourceSet)
project.whenEvaluated {
if (!project.hasKpmModel) {
// Since there's no default source set, apply language settings from commonMain:
mainCompilation.compileTaskProvider.configure { compileKotlinMetadata ->
applyLanguageSettingsToCompilerOptions(commonMainSourceSet.languageSettings, compileKotlinMetadata.compilerOptions)
}
// Since there's no default source set, apply language settings from commonMain:
mainCompilation.compileTaskProvider.configure { compileKotlinMetadata ->
applyLanguageSettingsToCompilerOptions(commonMainSourceSet.languageSettings, compileKotlinMetadata.compilerOptions)
}
}
}
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationWithResources
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationDetailsImpl.MetadataMappedCompilationDetails
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinNativeCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinNativeFragmentMetadataCompilationData
import org.jetbrains.kotlin.gradle.targets.native.NativeCompilerOptions
@@ -111,9 +110,6 @@ abstract class KotlinSharedNativeCompilation @Inject constructor(
),
KotlinMetadataCompilation<KotlinCommonOptions> {
override fun getName() =
if (compilationDetails is MetadataMappedCompilationDetails) defaultSourceSetName else super.compilationPurpose
override val target: KotlinMetadataTarget get() = super.target as KotlinMetadataTarget
override val isActive: Boolean
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.KOTLIN_NA
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.registerEmbedAndSignAppleFrameworkTask
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmAwareTargetConfigurator
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
import org.jetbrains.kotlin.gradle.targets.native.*
@@ -579,22 +578,6 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
}
}
internal class GradleKpmNativeTargetConfigurator<T : KotlinNativeTarget>(private val nativeTargetConfigurator: KotlinNativeTargetConfigurator<T>) :
GradleKpmAwareTargetConfigurator<T>(nativeTargetConfigurator) {
override fun configureTarget(target: T) {
super.configureTarget(target)
configureBinariesTask(target)
}
private fun configureBinariesTask(target: T) {
target.project.registerTask<DefaultTask>(target.artifactsTaskName) {
it.group = BasePlugin.BUILD_GROUP
it.description = "Assembles outputs for target '${target.name}'."
}
}
}
abstract class KotlinNativeTargetWithTestsConfigurator<
TargetType : KotlinNativeTargetWithTests<TestRunType>,
TestRunType : KotlinNativeBinaryTestRun,
@@ -10,14 +10,10 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project
import org.jetbrains.kotlin.compilerRunner.konanHome
import org.jetbrains.kotlin.compilerRunner.konanVersion
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.targets.native.DisabledNativeTargetsReporter
import org.jetbrains.kotlin.gradle.targets.native.internal.*
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
import org.jetbrains.kotlin.gradle.utils.SingleActionPerProject
import org.jetbrains.kotlin.gradle.utils.setupNativeCompiler
import org.jetbrains.kotlin.konan.CompilerVersion
@@ -54,13 +50,7 @@ abstract class AbstractKotlinNativeTargetPreset<T : KotlinNativeTarget>(
disambiguationClassifier = name
preset = this@AbstractKotlinNativeTargetPreset
val compilationFactory =
if (project.hasKpmModel) {
val kpmVariantClass = kpmNativeVariantClass(konanTarget) ?: error("Can't find the KPM variant class for $konanTarget")
KotlinMappedNativeCompilationFactory(this, kpmVariantClass)
} else {
KotlinNativeCompilationFactory(this)
}
val compilationFactory = KotlinNativeCompilationFactory(this)
compilations = project.container(compilationFactory.itemClass, compilationFactory)
}
@@ -96,12 +86,8 @@ abstract class AbstractKotlinNativeTargetPreset<T : KotlinNativeTarget>(
open class KotlinNativeTargetPreset(name: String, project: Project, konanTarget: KonanTarget) :
AbstractKotlinNativeTargetPreset<KotlinNativeTarget>(name, project, konanTarget) {
override fun createTargetConfigurator(): AbstractKotlinTargetConfigurator<KotlinNativeTarget> {
val configurator = KotlinNativeTargetConfigurator<KotlinNativeTarget>()
return if (project.hasKpmModel)
GradleKpmNativeTargetConfigurator(configurator)
else configurator
}
override fun createTargetConfigurator(): AbstractKotlinTargetConfigurator<KotlinNativeTarget> =
KotlinNativeTargetConfigurator<KotlinNativeTarget>()
override fun instantiateTarget(name: String): KotlinNativeTarget {
return project.objects.newInstance(KotlinNativeTarget::class.java, project, konanTarget)
@@ -111,12 +97,8 @@ open class KotlinNativeTargetPreset(name: String, project: Project, konanTarget:
open class KotlinNativeTargetWithHostTestsPreset(name: String, project: Project, konanTarget: KonanTarget) :
AbstractKotlinNativeTargetPreset<KotlinNativeTargetWithHostTests>(name, project, konanTarget) {
override fun createTargetConfigurator(): AbstractKotlinTargetConfigurator<KotlinNativeTargetWithHostTests> {
val configurator = KotlinNativeTargetWithHostTestsConfigurator()
return if (project.hasKpmModel)
GradleKpmNativeTargetConfigurator(configurator)
else configurator
}
override fun createTargetConfigurator(): AbstractKotlinTargetConfigurator<KotlinNativeTargetWithHostTests> =
KotlinNativeTargetWithHostTestsConfigurator()
override fun instantiateTarget(name: String): KotlinNativeTargetWithHostTests =
project.objects.newInstance(KotlinNativeTargetWithHostTests::class.java, project, konanTarget)
@@ -125,12 +107,8 @@ open class KotlinNativeTargetWithHostTestsPreset(name: String, project: Project,
open class KotlinNativeTargetWithSimulatorTestsPreset(name: String, project: Project, konanTarget: KonanTarget) :
AbstractKotlinNativeTargetPreset<KotlinNativeTargetWithSimulatorTests>(name, project, konanTarget) {
override fun createTargetConfigurator(): AbstractKotlinTargetConfigurator<KotlinNativeTargetWithSimulatorTests> {
val configurator = KotlinNativeTargetWithSimulatorTestsConfigurator()
return if (project.hasKpmModel)
GradleKpmNativeTargetConfigurator(configurator)
else configurator
}
override fun createTargetConfigurator(): AbstractKotlinTargetConfigurator<KotlinNativeTargetWithSimulatorTests> =
KotlinNativeTargetWithSimulatorTestsConfigurator()
override fun instantiateTarget(name: String): KotlinNativeTargetWithSimulatorTests =
project.objects.newInstance(KotlinNativeTargetWithSimulatorTests::class.java, project, konanTarget)
@@ -13,16 +13,15 @@ import org.gradle.api.file.ProjectLayout
import org.gradle.api.internal.GeneratedSubclass
import org.gradle.api.tasks.*
import org.jetbrains.kotlin.compilerRunner.konanVersion
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmJvmVariant
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmModule
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmNativeVariantInternal
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmVariant
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsSubTargetContainerDsl
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import org.jetbrains.kotlin.gradle.targets.metadata.isCompatibilityMetadataVariantEnabled
@@ -38,18 +37,13 @@ import javax.inject.Inject
internal fun Project.registerBuildKotlinToolingMetadataTask() {
if (!project.kotlinPropertiesProvider.enableKotlinToolingMetadataArtifact) return
if (hasKpmModel) {
buildKotlinToolingMetadataForAllKpmModulesTask
} else {
buildKotlinToolingMetadataTask
}
if (project.pm20ExtensionOrNull != null) buildKotlinToolingMetadataForMainKpmModuleTask
else buildKotlinToolingMetadataTask
}
internal val Project.buildKotlinToolingMetadataForMainKpmModuleTask: TaskProvider<BuildKotlinToolingMetadataTask.FromKpmModule>?
get() {
require(hasKpmModel)
val mainModule = kpmModules.getByName(GradleKpmModule.MAIN_MODULE_NAME)
val mainModule = pm20Extension.modules.getByName(GradleKpmModule.MAIN_MODULE_NAME)
return mainModule.buildKotlinToolingMetadataTask
}
@@ -92,26 +86,27 @@ internal val GradleKpmModule.buildKotlinToolingMetadataTask: TaskProvider<BuildK
abstract class BuildKotlinToolingMetadataTask : DefaultTask() {
abstract class FromKpmModule
@Inject constructor (
@get:Internal
val module: GradleKpmModule,
private val projectLayout: ProjectLayout
) : BuildKotlinToolingMetadataTask() {
@Inject constructor(
@get:Internal
val module: GradleKpmModule,
private val projectLayout: ProjectLayout
) : BuildKotlinToolingMetadataTask() {
override val outputDirectory: File get() = projectLayout
.buildDirectory
.get()
.asFile
.resolve("kotlinToolingMetadata")
.resolve(module.name)
override val outputDirectory: File
get() = projectLayout
.buildDirectory
.get()
.asFile
.resolve("kotlinToolingMetadata")
.resolve(module.name)
override fun buildKotlinToolingMetadata() = module.getKotlinToolingMetadata()
}
abstract class FromKotlinExtension
@Inject constructor(
private val projectLayout: ProjectLayout
) : BuildKotlinToolingMetadataTask() {
@Inject constructor(
private val projectLayout: ProjectLayout
) : BuildKotlinToolingMetadataTask() {
override val outputDirectory: File get() = projectLayout.buildDirectory.get().asFile.resolve("kotlinToolingMetadata")
@@ -173,7 +168,7 @@ private fun Project.buildProjectSettings(): KotlinToolingMetadata.ProjectSetting
return KotlinToolingMetadata.ProjectSettings(
isHmppEnabled = project.isKotlinGranularMetadataEnabled,
isCompatibilityMetadataVariantEnabled = project.isCompatibilityMetadataVariantEnabled,
isKPMEnabled = project.hasKpmModel
isKPMEnabled = pm20ExtensionOrNull != null
)
}
@@ -197,19 +192,17 @@ private fun GradleKpmVariant.jvmExtrasOrNull() =
jvmTarget = compilationData.kotlinOptions.jvmTarget,
withJavaEnabled = false
)
is GradleKpmLegacyMappedVariant -> buildJvmExtrasOrNull(compilation.target)
else -> null
}
private fun GradleKpmVariant.androidExtrasOrNull() =
when (this) {
is GradleKpmLegacyMappedVariant -> buildAndroidExtrasOrNull(compilation.target)
else -> null
}
private fun GradleKpmVariant.jsExtrasOrNull() =
when (this) {
is GradleKpmLegacyMappedVariant -> buildJsExtrasOrNull(compilation.target)
else -> null
}
@@ -220,7 +213,7 @@ private fun GradleKpmVariant.nativeExtrasOrNull() =
konanVersion = project.konanVersion.toString(),
konanAbiVersion = KotlinAbiVersion.CURRENT.toString()
)
is GradleKpmLegacyMappedVariant -> buildNativeExtrasOrNull(compilation.target)
else -> null
}
@@ -7,11 +7,11 @@ package org.jetbrains.kotlin.gradle.tooling
import com.android.build.gradle.AppExtension
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.dsl.pm20ExtensionOrNull
internal fun Project.includeKotlinToolingMetadataInApk() {
plugins.withId("com.android.application") {
val buildKotlinToolingMetadataTask = if (hasKpmModel) {
val buildKotlinToolingMetadataTask = if (project.pm20ExtensionOrNull != null) {
buildKotlinToolingMetadataForMainKpmModuleTask
} else {
buildKotlinToolingMetadataTask
@@ -14,7 +14,6 @@ import org.gradle.api.plugins.ExtraPropertiesExtension
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_KPM_EXPERIMENTAL_MODEL_MAPPING
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_VERSION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_BY_DEFAULT
@@ -106,10 +105,6 @@ fun Project.enableHierarchicalStructureByDefault(enabled: Boolean = true) {
propertiesExtension.set(KOTLIN_MPP_HIERARCHICAL_STRUCTURE_BY_DEFAULT, enabled.toString())
}
fun Project.enableKpmModelMapping(enabled: Boolean = true) {
propertiesExtension.set(KOTLIN_KPM_EXPERIMENTAL_MODEL_MAPPING, enabled.toString())
}
fun Project.enableDefaultStdlibDependency(enabled: Boolean = true) {
project.propertiesExtension.set(KOTLIN_STDLIB_DEFAULT_DEPENDENCY, enabled.toString())
}
@@ -5,31 +5,21 @@
package org.jetbrains.kotlin.gradle.kpm
import com.android.build.api.dsl.ApplicationExtension
import com.android.build.gradle.BaseExtension
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.kotlin.compilerRunner.konanVersion
import org.jetbrains.kotlin.gradle.addBuildEventsListenerRegistryMock
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.enableKpmModelMapping
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.*
import org.gradle.kotlin.dsl.create
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.jvm
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.native
import org.jetbrains.kotlin.gradle.plugin.KotlinPm20PluginWrapper
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.tooling.buildKotlinToolingMetadataTask
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.library.KotlinAbiVersion
import org.jetbrains.kotlin.tooling.KotlinToolingMetadata
import org.jetbrains.kotlin.tooling.toJsonString
import org.gradle.kotlin.dsl.create
import org.jetbrains.kotlin.gradle.disableLegacyWarning
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.plugin.*
import kotlin.test.*
import kotlin.test.Test
import kotlin.test.assertEquals
private fun Project.kotlinToolingMetadataOfModule(moduleName: String): KotlinToolingMetadata {
val module = kpmModules.getByName(moduleName)
val module = pm20Extension.modules.getByName(moduleName)
return module.buildKotlinToolingMetadataTask!!.get().kotlinToolingMetadata
}
@@ -72,158 +62,3 @@ class BuildKotlinToolingMetadataTest : AbstractKpmExtensionTest() {
)
}
}
class KotlinToolingMetadataWithModelMappingTest {
private val project = ProjectBuilder.builder().build().also { addBuildEventsListenerRegistryMock(it) } as ProjectInternal
private val multiplatformExtension get() = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
private fun getKotlinToolingMetadata() = project.kotlinToolingMetadataOfMainModule
@BeforeTest
fun setup() {
project.enableKpmModelMapping()
}
@Test
fun `multiplatform empty setup`() {
project.plugins.apply("kotlin-multiplatform")
val metadata = getKotlinToolingMetadata()
assertEquals("Gradle", metadata.buildSystem)
assertEquals(project.gradle.gradleVersion, metadata.buildSystemVersion)
assertEquals(KotlinMultiplatformPluginWrapper::class.java.canonicalName, metadata.buildPlugin)
assertEquals(project.getKotlinPluginVersion(), metadata.buildPluginVersion)
assertEquals(0, metadata.projectTargets.size, "Expected no targets in KPM")
assertTrue(metadata.toJsonString().isNotBlank(), "Expected non blank json representation")
}
@Test
fun `multiplatform JS JVM Android linuxX64 setup`() {
project.plugins.apply("com.android.application")
project.plugins.apply("kotlin-multiplatform")
disableLegacyWarning(project)
val android = project.extensions.getByType(ApplicationExtension::class.java)
val kotlin = multiplatformExtension
android.compileSdk = 31
kotlin.android()
kotlin.jvm()
kotlin.js {
nodejs()
browser()
}
kotlin.linuxX64()
project.evaluate()
val metadata = getKotlinToolingMetadata()
assertEquals(KotlinMultiplatformPluginWrapper::class.java.canonicalName, metadata.buildPlugin)
assertFalse("Kotlin Tooling Metadata generated from KPM should not contain target of 'common' platform") {
metadata.projectTargets.any { it.platformType == common.name }
}
val expectedTargets = mapOf(
androidJvm to GradleKpmLegacyMappedVariantWithRuntime::class,
jvm to GradleKpmJvmVariant::class,
js to GradleKpmLegacyMappedVariantWithRuntime::class,
native to GradleKpmLinuxX64Variant::class
)
assertEquals(
expectedTargets.keys.map { it.name }.sorted(),
metadata.projectTargets.map { it.platformType }.sorted()
)
expectedTargets.forEach { (platformType, targetClass) ->
assertEquals(
targetClass.decoratedClassCanonicalName,
metadata.projectTargets.single { it.platformType == platformType.name }.target,
"Platform '$platformType' has different target class"
)
}
assertTrue(metadata.projectSettings.isKPMEnabled, "projectSettings.isKPMEnabled must be set")
}
@Test
fun `multiplatform Android target with different source and target compatibility`() {
project.plugins.apply("kotlin-multiplatform")
project.plugins.apply("com.android.application")
val android = project.extensions.getByType(BaseExtension::class.java)
val kotlin = multiplatformExtension
android.compileSdkVersion(28)
kotlin.android()
android.compileOptions.sourceCompatibility = JavaVersion.VERSION_1_6
android.compileOptions.targetCompatibility = JavaVersion.VERSION_1_8
project.evaluate()
val androidTargetMetadata = getKotlinToolingMetadata()
.projectTargets.single { it.platformType == androidJvm.name }
assertEquals("1.6", androidTargetMetadata.extras.android?.sourceCompatibility)
assertEquals("1.8", androidTargetMetadata.extras.android?.targetCompatibility)
}
@Test
fun `multiplatform JVM with different targets`() {
project.plugins.apply("kotlin-multiplatform")
val kotlin = multiplatformExtension
val jvm = kotlin.jvm()
jvm.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME).compilerOptions.options.jvmTarget.set(JvmTarget.JVM_12)
jvm.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME).compilerOptions.options.jvmTarget.set(JvmTarget.JVM_10)
assertEquals(
"12", getKotlinToolingMetadata().projectTargets
.single { it.platformType == KotlinPlatformType.jvm.name }.extras.jvm?.jvmTarget,
"Expected jvmTarget of main compilation"
)
}
@Test
fun `multiplatform with native target`() {
project.plugins.apply("kotlin-multiplatform")
val kotlin = multiplatformExtension
kotlin.linuxX64()
val metadata = getKotlinToolingMetadata()
val linuxTarget = metadata.projectTargets.single { it.platformType == native.name }
assertEquals(KonanTarget.LINUX_X64.name, linuxTarget.extras.native?.konanTarget)
assertEquals(project.konanVersion.toString(), linuxTarget.extras.native?.konanVersion)
assertEquals(KotlinAbiVersion.CURRENT.toString(), linuxTarget.extras.native?.konanAbiVersion)
}
@Test
fun `multiple native targets`() {
project.plugins.apply("kotlin-multiplatform")
val kotlin = multiplatformExtension
kotlin.linuxX64()
kotlin.linuxArm64()
val metadata = getKotlinToolingMetadata()
val nativeTargets = metadata.projectTargets.filter { it.platformType == native.name }.sortedBy { it.extras.native?.konanTarget }
assertEquals(2, nativeTargets.size, "Expected only two native targets")
val (linuxArm64, linuxX64) = nativeTargets
assertEquals(
"linux_arm64",
linuxArm64.extras.native?.konanTarget
)
assertEquals(
"linux_x64",
linuxX64.extras.native?.konanTarget
)
assertEquals(
GradleKpmLinuxArm64Variant::class.decoratedClassCanonicalName,
linuxArm64.target
)
assertEquals(
GradleKpmLinuxX64Variant::class.decoratedClassCanonicalName,
linuxX64.target
)
}
}
@@ -1,106 +0,0 @@
/*
* 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.
*/
/* Associate compilations are not yet supported by the IDE. KT-34102 */
@file:Suppress("invisible_reference", "invisible_member", "FunctionName", "DuplicatedCode")
package org.jetbrains.kotlin.gradle.sources.kpm
import org.jetbrains.kotlin.gradle.MultiplatformExtensionTest
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
import org.jetbrains.kotlin.gradle.plugin.sources.kpm.MultiplatformSourceSetMappedFragmentLocator
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmModule
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.kpmModules
import org.jetbrains.kotlin.gradle.plugin.sources.kpm.SourceSetMappedFragmentLocator
internal open class MultiplatformSourceSetMappedFragmentLocatorTest : MultiplatformExtensionTest() {
protected val locator = MultiplatformSourceSetMappedFragmentLocator()
@BeforeTest
override fun setup() {
project.extensions.extraProperties.set(PropertiesProvider.PropertyNames.KOTLIN_KPM_EXPERIMENTAL_MODEL_MAPPING, "true")
super.setup()
}
protected fun doTest(sourceSetName: String, checkResult: SourceSetMappedFragmentLocator.FragmentLocation.() -> Unit) {
val result = checkNotNull(locator.locateFragmentForSourceSet(project, sourceSetName))
checkResult(result)
}
protected fun doTest(sourceSetName: String, fragmentName: String, moduleName: String) {
doTest(sourceSetName) {
assertEquals(fragmentName, this.fragmentName)
assertEquals(moduleName, this.moduleName)
}
}
@Test
fun `name with one part is returned as fragment name with main module`() {
doTest("foo", "foo", GradleKpmModule.MAIN_MODULE_NAME)
}
@Test
fun `main is truncated from name`() {
doTest("fooBarMain", "fooBar", GradleKpmModule.MAIN_MODULE_NAME)
}
@Test
fun `module chosen for test fragment`() {
doTest("abcDefGhiTest", "abcDefGhi", GradleKpmModule.TEST_MODULE_NAME)
}
@Test
fun `digits accepted`() {
val nameWithDigits = "testDigits123Accepted123"
project.kpmModules.create(nameWithDigits)
doTest("foo${nameWithDigits.capitalize()}", "foo", nameWithDigits)
doTest("${nameWithDigits}Main", nameWithDigits, GradleKpmModule.MAIN_MODULE_NAME)
}
@Test
fun `capitalized name handling`() {
doTest("IAmTheMain", "IAmThe", GradleKpmModule.MAIN_MODULE_NAME)
}
@Test
fun `live module logic update`() {
val nameForTest = "someNewTest"
doTest(nameForTest, "someNew", "test")
project.kpmModules.create("newTest")
doTest(nameForTest, "some", "newTest")
// also check for the same logic in fragments that go to main if no suffix matched:
val nameForMain = "fooBarBaz"
doTest(nameForMain, nameForMain, GradleKpmModule.MAIN_MODULE_NAME)
val moduleSuffixName = "barBaz"
project.kpmModules.create(moduleSuffixName)
doTest(nameForMain, "foo", moduleSuffixName)
}
}
internal class MultiplatformSourceSetMappedFragmentLocatorTestWithAndroid : MultiplatformSourceSetMappedFragmentLocatorTest() {
override fun setup() {
super.setup()
project.plugins.apply("android-library")
kotlin.android()
}
@Test
fun `android source set names`() {
doTest("androidMain", "android", GradleKpmModule.MAIN_MODULE_NAME)
doTest("androidTest", "android", GradleKpmModule.TEST_MODULE_NAME)
doTest("androidAndroidTest", "androidAndroid", GradleKpmModule.TEST_MODULE_NAME)
doTest("androidDebug", "androidDebug", GradleKpmModule.MAIN_MODULE_NAME)
doTest("androidDebugTest", "androidDebug", GradleKpmModule.TEST_MODULE_NAME)
doTest("androidDebugAndroidTest", "androidDebugAndroid", GradleKpmModule.TEST_MODULE_NAME)
}
}