diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTarget.kt b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTarget.kt index 2ba2a6f4039..295104c4fce 100644 --- a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTarget.kt +++ b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTarget.kt @@ -34,6 +34,7 @@ interface KotlinTarget : Named, HasAttributes { val defaultConfigurationName: String val apiElementsConfigurationName: String val runtimeElementsConfigurationName: String + val sourcesElementsConfigurationName: String val publishable: Boolean diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetComponent.kt b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetComponent.kt index 54e4e5b090a..1a52ba5d4ce 100644 --- a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetComponent.kt +++ b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetComponent.kt @@ -13,5 +13,11 @@ interface KotlinTargetComponent : SoftwareComponent { val publishable: Boolean val publishableOnCurrentHost: Boolean val defaultArtifactId: String + + @Deprecated( + message = "Sources artifacts are now published as separate variant " + + "use target.sourcesElementsConfigurationName to obtain necessary information", + replaceWith = ReplaceWith("target.sourcesElementsConfigurationName") + ) val sourcesArtifacts: Set } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt index 2f03dcb688d..1a4d18e9614 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt @@ -13,9 +13,7 @@ import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.Dependency import org.gradle.api.artifacts.PublishArtifact import org.gradle.api.artifacts.type.ArtifactTypeDefinition -import org.gradle.api.attributes.Attribute -import org.gradle.api.attributes.Category -import org.gradle.api.attributes.Usage +import org.gradle.api.attributes.* import org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE import org.gradle.api.file.FileCollection import org.gradle.api.internal.artifacts.ArtifactAttributes @@ -200,6 +198,14 @@ abstract class AbstractKotlinTargetConfigurator } } + configurations.maybeCreate(target.sourcesElementsConfigurationName).apply { + description = "Source files of main compilation of ${target.name}." + isVisible = false + isCanBeResolved = false + isCanBeConsumed = true + configureSourcesPublicationAttributes(target) + } + if (createTestCompilation) { val testCompilation = target.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME) val compileTestsConfiguration = testCompilation.internal.configurations.deprecatedCompileConfiguration @@ -390,6 +396,9 @@ internal fun Project.usageByName(usageName: String): Usage = internal fun Project.categoryByName(categoryName: String): Category = objects.named(Category::class.java, categoryName) +internal inline fun Project.attributeValueByName(attributeValueName: String): T = + objects.named(T::class.java, attributeValueName) + fun Configuration.usesPlatformOf(target: KotlinTarget): Configuration { attributes.attribute(KotlinPlatformType.attribute, target.platformType) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/AbstractKotlinTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/AbstractKotlinTarget.kt index 5582eeb63d1..bafcd9ec090 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/AbstractKotlinTarget.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/AbstractKotlinTarget.kt @@ -50,6 +50,9 @@ abstract class AbstractKotlinTarget( override val runtimeElementsConfigurationName: String get() = disambiguateName("runtimeElements") + override val sourcesElementsConfigurationName: String + get() = disambiguateName("sourcesElements") + override val artifactsTaskName: String get() = disambiguateName("jar") @@ -61,18 +64,24 @@ abstract class AbstractKotlinTarget( @InternalKotlinGradlePluginApi override val kotlinComponents: Set by lazy { val mainCompilation = compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME) - val usageContexts = createUsageContexts(mainCompilation) + val usageContexts = createUsageContexts(mainCompilation).toMutableSet() val componentName = if (project.kotlinExtension is KotlinMultiplatformExtension) targetName else PRIMARY_SINGLE_COMPONENT_NAME - val result = createKotlinVariant(componentName, mainCompilation, usageContexts) + val sourcesArtifact = configureSourcesJarArtifact(mainCompilation, componentName, dashSeparatedName(targetName.toLowerCase())) + if (sourcesArtifact != null) { + usageContexts += DefaultKotlinUsageContext( + compilation = mainCompilation, + dependencyConfigurationName = sourcesElementsConfigurationName, + includeIntoProjectStructureMetadata = false, + includeDependenciesToMavenPublication = false, + ) + } - result.sourcesArtifacts = setOf( - sourcesJarArtifact(mainCompilation, componentName, dashSeparatedName(targetName.toLowerCase())) - ) + val result = createKotlinVariant(componentName, mainCompilation, usageContexts) setOf(result) } @@ -117,28 +126,21 @@ abstract class AbstractKotlinTarget( } } - protected fun sourcesJarArtifact( + protected fun configureSourcesJarArtifact( producingCompilation: KotlinCompilation<*>, componentName: String, artifactNameAppendix: String, - classifierPrefix: String? = null - ): PublishArtifact { - val sourcesJarTask = sourcesJarTask(producingCompilation, componentName, artifactNameAppendix) - val sourceArtifactConfigurationName = producingCompilation.disambiguateName("sourceArtifacts") + classifierPrefix: String? = null, + sourcesElementsConfigurationName: String = this.sourcesElementsConfigurationName, + ): PublishArtifact? { + // If sourcesElements configuration not found, don't create artifact. + // This can happen in pure JVM plugin where source publication is delegated to Java Gradle Plugin + project.configurations.findByName(sourcesElementsConfigurationName) ?: return null - return with(producingCompilation.target.project) { - (configurations.findByName(sourceArtifactConfigurationName) ?: run { - val configuration = configurations.create(sourceArtifactConfigurationName) { - it.isCanBeResolved = false - it.isCanBeConsumed = false - } - artifacts.add(sourceArtifactConfigurationName, sourcesJarTask) - configuration - }).artifacts.single().apply { - this as ConfigurablePublishArtifact - classifier = dashSeparatedName(classifierPrefix, "sources") - } - } + val sourcesJarTask = sourcesJarTask(producingCompilation, componentName, artifactNameAppendix) + val artifact = project.artifacts.add(sourcesElementsConfigurationName, sourcesJarTask) as ConfigurablePublishArtifact + artifact.classifier = dashSeparatedName(classifierPrefix, "sources") + return artifact } @Suppress("UNCHECKED_CAST") diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt index 18655b3c4ef..e70c89f5db8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt @@ -7,9 +7,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp import org.gradle.api.Project import org.gradle.api.artifacts.* -import org.gradle.api.attributes.Attribute -import org.gradle.api.attributes.AttributeContainer -import org.gradle.api.attributes.Usage +import org.gradle.api.attributes.* import org.gradle.api.capabilities.Capability import org.gradle.api.component.ComponentWithCoordinates import org.gradle.api.component.ComponentWithVariants @@ -19,12 +17,12 @@ import org.gradle.api.internal.component.UsageContext import org.gradle.api.provider.SetProperty import org.gradle.api.publish.maven.MavenPublication import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension -import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation +import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME -import org.jetbrains.kotlin.gradle.plugin.KotlinTarget -import org.jetbrains.kotlin.gradle.plugin.ProjectLocalConfigurations -import org.jetbrains.kotlin.gradle.plugin.usageByName import org.jetbrains.kotlin.gradle.targets.metadata.* +import org.jetbrains.kotlin.gradle.targets.metadata.COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME +import org.jetbrains.kotlin.gradle.targets.metadata.isCompatibilityMetadataVariantEnabled +import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled import org.jetbrains.kotlin.gradle.utils.setProperty abstract class KotlinSoftwareComponent( @@ -35,6 +33,8 @@ abstract class KotlinSoftwareComponent( override fun getName(): String = name + private val metadataTarget get() = project.multiplatformExtension.metadata() + override fun getVariants(): Set = kotlinTargets .filter { target -> target !is KotlinMetadataTarget } .flatMap { target -> @@ -47,8 +47,6 @@ abstract class KotlinSoftwareComponent( }.toSet() private val _usages: Set by lazy { - val metadataTarget = project.multiplatformExtension.metadata() - if (!project.isKotlinGranularMetadataEnabled) { val metadataCompilation = metadataTarget.compilations.getByName(MAIN_COMPILATION_NAME) return@lazy metadataTarget.createUsageContexts(metadataCompilation) @@ -80,6 +78,14 @@ abstract class KotlinSoftwareComponent( ) } } + + configureSourcesJarArtifact() + this += DefaultKotlinUsageContext( + compilation = metadataTarget.compilations.getByName(MAIN_COMPILATION_NAME), + dependencyConfigurationName = metadataTarget.sourcesElementsConfigurationName, + includeIntoProjectStructureMetadata = false, + includeDependenciesToMavenPublication = false + ) } } @@ -87,7 +93,7 @@ abstract class KotlinSoftwareComponent( return _usages } - val sourcesArtifacts: Set by lazy { + private fun configureSourcesJarArtifact(): PublishArtifact { fun allPublishableCommonSourceSets() = getCommonSourceSetsForMetadataCompilation(project) + getHostSpecificMainSharedSourceSets(project) @@ -98,10 +104,10 @@ abstract class KotlinSoftwareComponent( lazy { allPublishableCommonSourceSets().associate { it.name to it.kotlin } }, name.toLowerCase() ) - val sourcesJarArtifact = project.artifacts.add(Dependency.ARCHIVES_CONFIGURATION, sourcesJarTask) { sourcesJarArtifact -> + + return project.artifacts.add(metadataTarget.sourcesElementsConfigurationName, sourcesJarTask) { sourcesJarArtifact -> sourcesJarArtifact.classifier = "sources" } - setOf(sourcesJarArtifact) } // This property is declared in the parent type to allow the usages to reference it without forcing the subtypes to load, @@ -214,4 +220,4 @@ class DefaultKotlinUsageContext( */ it.name != "org.gradle.jvm.environment" } -} +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt index 67ab6dae560..a4de2c6f430 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt @@ -61,6 +61,8 @@ object KotlinUsages { internal fun producerRuntimeUsage(project: Project, platformType: KotlinPlatformType) = project.usageByName( when (platformType) { + // This attribute is deprecated in Gradle and additionally to Usage attribute + // it implicitly adds `org.gradle.libraryelements=jar` in jvmPlatformTypes -> "java-runtime-jars" else -> KOTLIN_RUNTIME } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/Publishing.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/Publishing.kt index b713e338e73..3613a2cb66f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/Publishing.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/Publishing.kt @@ -6,6 +6,11 @@ package org.jetbrains.kotlin.gradle.plugin.mpp import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration +import org.gradle.api.attributes.Bundling +import org.gradle.api.attributes.Category +import org.gradle.api.attributes.DocsType +import org.gradle.api.attributes.Usage import org.gradle.api.provider.Provider import org.gradle.api.publish.PublicationContainer import org.gradle.api.publish.PublishingExtension @@ -14,7 +19,7 @@ import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension -import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope @@ -41,9 +46,6 @@ private fun createRootPublication(project: Project, publishing: PublishingExtens from(kotlinSoftwareComponent) (this as MavenPublicationInternal).publishWithOriginalFileName() kotlinSoftwareComponent.publicationDelegate = this@apply - kotlinSoftwareComponent.sourcesArtifacts.forEach { sourceArtifact -> - artifact(sourceArtifact) - } addKotlinToolingMetadataArtifactIfNeeded(project) } @@ -82,9 +84,6 @@ private fun InternalKotlinTarget.createMavenPublications(publications: Publicati // do this in whenEvaluated since older Gradle versions seem to check the files in the variant eagerly: project.whenEvaluated { from(gradleComponent) - kotlinComponent.sourcesArtifacts.forEach { sourceArtifact -> - artifact(sourceArtifact) - } } (this as MavenPublicationInternal).publishWithOriginalFileName() artifactId = kotlinComponent.defaultArtifactId @@ -144,3 +143,20 @@ private fun dependenciesForPomRewriting(target: InternalKotlinTarget): Provider< commonMainDependencies.map { ModuleCoordinates(it.group, it.name, it.version) }.toSet() } } + +internal fun Configuration.configureSourcesPublicationAttributes(target: KotlinTarget) { + val project = target.project + + // In order to be consistent with Java Gradle Plugin, set usage attribute for sources variant + // to be either JAVA_RUNTIME (for jvm) or KOTLIN_RUNTIME (for other targets) + // the latter isn't a strong requirement since there is no tooling that consume kotlin sources through gradle variants at the moment + // so consistency with Java Gradle Plugin seemed most desirable choice. + attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerRuntimeUsage(target)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.attributeValueByName(Category.DOCUMENTATION)) + attributes.attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.attributeValueByName(DocsType.SOURCES)) + // Bundling attribute is about component dependencies, external means that they are provided as separate components + // source variants doesn't have any dependencies (at least at the moment) so there is not much sense to use this attribute + // however for Java Gradle Plugin compatibility and in order to prevent weird Variant Resolution errors we include this attribute + attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, project.attributeValueByName(Bundling.EXTERNAL)) + usesPlatformOf(target) +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt index 67c832e37db..ca627009f22 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt @@ -74,8 +74,16 @@ open class KotlinVariant( override val publishableOnCurrentHost: Boolean get() = publishable && target.publishable - override var sourcesArtifacts: Set = emptySet() - internal set + @Deprecated( + message = "Sources artifacts are now published as separate variant " + + "use target.sourcesElementsConfigurationName to obtain necessary information", + replaceWith = ReplaceWith("target.sourcesElementsConfigurationName") ) + override val sourcesArtifacts: Set get() = target + .project + .configurations + .findByName(target.sourcesElementsConfigurationName) + ?.artifacts + ?: emptySet() internal var defaultArtifactIdSuffix: String? = null @@ -102,8 +110,7 @@ class KotlinVariantWithMetadataVariant( class JointAndroidKotlinTargetComponent( override val target: KotlinAndroidTarget, private val nestedVariants: Set, - val flavorNames: List, - override val sourcesArtifacts: Set + val flavorNames: List ) : KotlinTargetComponentWithCoordinatesAndPublication, SoftwareComponentInternal { override fun getUsages(): Set = nestedVariants.filter { it.publishable }.flatMap { it.usages }.toSet() @@ -124,4 +131,11 @@ class JointAndroidKotlinTargetComponent( ) override var publicationDelegate: MavenPublication? = null + + @Deprecated( + message = "Sources artifacts are now published as separate variant " + + "use target.sourcesElementsConfigurationName to obtain necessary information", + replaceWith = ReplaceWith("target.sourcesElementsConfigurationName") + ) + override val sourcesArtifacts: Set = emptySet() } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidTarget.kt index e174900854f..07da5012d00 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidTarget.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidTarget.kt @@ -11,9 +11,10 @@ import org.gradle.api.InvalidUserDataException import org.gradle.api.Named import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project -import org.gradle.api.attributes.Attribute -import org.gradle.api.attributes.Usage.JAVA_RUNTIME_JARS +import org.gradle.api.artifacts.Configuration +import org.gradle.api.attributes.* import org.jetbrains.kotlin.gradle.plugin.* +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.copyAttributes import org.jetbrains.kotlin.gradle.utils.dashSeparatedName import org.jetbrains.kotlin.gradle.utils.forAllAndroidVariants import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName @@ -120,33 +121,18 @@ abstract class KotlinAndroidTarget @Inject constructor( val androidVariantName = getVariantName(androidVariant) val compilation = compilations.getByName(androidVariantName) - val flavorNames = getFlavorNames(androidVariant) - val buildTypeName = getBuildTypeName(androidVariant) - - val artifactClassifier = buildTypeName.takeIf { it != "release" && publishLibraryVariantsGroupedByFlavor } + val usageContexts = createAndroidUsageContexts( + variant = androidVariant, + compilation = compilation, + isSingleBuildType = publishableVariants.filter(::isVariantPublished).map(::getBuildTypeName).distinct().size == 1, + ) createKotlinVariant( lowerCamelCaseName(compilation.target.name, *flavorGroupNameParts.toTypedArray()), compilation, - createAndroidUsageContexts( - androidVariant, - compilation, - artifactClassifier, - publishableVariants.filter(::isVariantPublished).map(::getBuildTypeName).distinct().size == 1 - ) + usageContexts, ).apply { publishable = isVariantPublished(androidVariant) - sourcesArtifacts = setOf( - sourcesJarArtifact( - compilation, compilation.disambiguateName(""), - dashSeparatedName( - compilation.target.name.toLowerCase(), - *flavorNames.map { it.toLowerCase() }.toTypedArray(), - buildTypeName.takeIf { it != "release" }?.toLowerCase() - ), - classifierPrefix = artifactClassifier - ) - ) if (!publishLibraryVariantsGroupedByFlavor) { defaultArtifactIdSuffix = @@ -163,7 +149,6 @@ abstract class KotlinAndroidTarget @Inject constructor( target = this@KotlinAndroidTarget, nestedVariants = nestedVariants, flavorNames = flavorGroupNameParts, - sourcesArtifacts = nestedVariants.filter { it.publishable }.flatMap { it.sourcesArtifacts }.toSet() ) } else { nestedVariants.single() @@ -174,9 +159,12 @@ abstract class KotlinAndroidTarget @Inject constructor( private fun AndroidProjectHandler.createAndroidUsageContexts( variant: BaseVariant, compilation: KotlinCompilation<*>, - artifactClassifier: String?, - isSingleBuildType: Boolean + isSingleBuildType: Boolean, ): Set { + val flavorNames = getFlavorNames(variant) + val buildTypeName = getBuildTypeName(variant) + val artifactClassifier = buildTypeName.takeIf { it != "release" && publishLibraryVariantsGroupedByFlavor } + val variantName = getVariantName(variant) val outputTaskOrProvider = getLibraryOutputTask(variant) ?: return emptySet() val artifact = run { @@ -193,9 +181,46 @@ abstract class KotlinAndroidTarget @Inject constructor( val apiElementsConfigurationName = lowerCamelCaseName(variantName, "apiElements") val runtimeElementsConfigurationName = lowerCamelCaseName(variantName, "runtimeElements") + val sourcesElementsConfigurationName = lowerCamelCaseName(variantName, "sourcesElements") + val sourcesElementsConfiguration = createSourcesElementsIfNeeded( + variantName, + apiElementsConfigurationName, + sourcesElementsConfigurationName + ) + configureSourcesJarArtifact( + compilation, + compilation.disambiguateName(""), + dashSeparatedName( + compilation.target.name.toLowerCase(), + *flavorNames.map { it.toLowerCase() }.toTypedArray(), + buildTypeName.takeIf { it != "release" }?.toLowerCase() + ), + classifierPrefix = artifactClassifier, + sourcesElementsConfigurationName = sourcesElementsConfigurationName + ) + + fun AttributeContainer.filterOutAndroidVariantAttributes(): AttributeContainer = + HierarchyAttributeContainer(this) { + val valueString = run { + val value = getAttribute(it) + (value as? Named)?.name ?: value.toString() + } + filterOutAndroidVariantAttribute(it) && + filterOutAndroidBuildTypeAttribute(it, valueString, isSingleBuildType) && + filterOutAndroidAgpVersionAttribute(it) + } + + val sourcesUsageContext = DefaultKotlinUsageContext( + compilation = compilation, + dependencyConfigurationName = sourcesElementsConfigurationName, + overrideConfigurationAttributes = sourcesElementsConfiguration.attributes.filterOutAndroidVariantAttributes(), + includeDependenciesToMavenPublication = false, + includeIntoProjectStructureMetadata = false + ) + return listOf( apiElementsConfigurationName to KotlinUsageContext.UsageScope.COMPILE, - runtimeElementsConfigurationName to KotlinUsageContext.UsageScope.RUNTIME + runtimeElementsConfigurationName to KotlinUsageContext.UsageScope.RUNTIME, ).mapTo(mutableSetOf()) { (dependencyConfigurationName, mavenScope) -> val configuration = project.configurations.getByName(dependencyConfigurationName) DefaultKotlinUsageContext( @@ -203,16 +228,32 @@ abstract class KotlinAndroidTarget @Inject constructor( mavenScope, dependencyConfigurationName, overrideConfigurationArtifacts = project.setProperty { listOf(artifact) }, - overrideConfigurationAttributes = HierarchyAttributeContainer(configuration.attributes) { - val valueString = run { - val value = configuration.attributes.getAttribute(it) - (value as? Named)?.name ?: value.toString() - } - filterOutAndroidVariantAttribute(it) && - filterOutAndroidBuildTypeAttribute(it, valueString, isSingleBuildType) && - filterOutAndroidAgpVersionAttribute(it) - } + overrideConfigurationAttributes = configuration.attributes.filterOutAndroidVariantAttributes() ) + } + sourcesUsageContext + } + + /** + * TODO: Ask Google about providing such configuration where they could set their attributes and control them. + * Just like as they do with apiElements or runtimeElements + */ + private fun createSourcesElementsIfNeeded( + variantName: String, + apiElementsConfigurationName: String, + sourcesElementsConfigurationName: String + ): Configuration { + val existingConfiguration = project.configurations.findByName(sourcesElementsConfigurationName) + if (existingConfiguration != null) return existingConfiguration + + val apiElementsConfiguration = project.configurations.getByName(apiElementsConfigurationName) + return project.configurations.create(sourcesElementsConfigurationName).apply { + description = "Source files of Android ${variantName}." + isVisible = false + isCanBeResolved = false + isCanBeConsumed = true + + copyAttributes(apiElementsConfiguration.attributes, attributes) + configureSourcesPublicationAttributes(this@KotlinAndroidTarget) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTarget.kt index 82310dd494e..9eb4118a8f8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTarget.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTarget.kt @@ -71,20 +71,26 @@ constructor( super.kotlinComponents else { val mainCompilation = compilations.getByName(MAIN_COMPILATION_NAME) - val usageContexts = createUsageContexts(mainCompilation) + - irTarget!!.createUsageContexts(irTarget!!.compilations.getByName(MAIN_COMPILATION_NAME)) + val usageContexts = createUsageContexts(mainCompilation).toMutableSet() + + usageContexts += irTarget!!.createUsageContexts(irTarget!!.compilations.getByName(MAIN_COMPILATION_NAME)) val componentName = if (project.kotlinExtension is KotlinMultiplatformExtension) irTarget?.let { targetName.removeJsCompilerSuffix(LEGACY) } ?: targetName else PRIMARY_SINGLE_COMPONENT_NAME - val result = createKotlinVariant(componentName, mainCompilation, usageContexts) - - result.sourcesArtifacts = setOf( - sourcesJarArtifact(mainCompilation, componentName, dashSeparatedName(targetName.toLowerCase())) + configureSourcesJarArtifact(mainCompilation, componentName, dashSeparatedName(targetName.toLowerCase())) + usageContexts += DefaultKotlinUsageContext( + compilation = mainCompilation, + usageScope = KotlinUsageContext.UsageScope.RUNTIME, + dependencyConfigurationName = sourcesElementsConfigurationName, + includeIntoProjectStructureMetadata = false, + includeDependenciesToMavenPublication = false, ) + val result = createKotlinVariant(componentName, mainCompilation, usageContexts) + setOf(result) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTarget.kt index adbdefc8912..fa92661c80c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTarget.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTarget.kt @@ -101,11 +101,16 @@ abstract class KotlinNativeTarget @Inject constructor( } } - val result = createKotlinVariant(targetName, mainCompilation, mutableUsageContexts) - - result.sourcesArtifacts = setOf( - sourcesJarArtifact(mainCompilation, targetName, dashSeparatedName(targetName.toLowerCase())) + configureSourcesJarArtifact(mainCompilation, targetName, dashSeparatedName(targetName.toLowerCase())) + val sourcesUsage = DefaultKotlinUsageContext( + compilation = mainCompilation, + dependencyConfigurationName = sourcesElementsConfigurationName, + includeIntoProjectStructureMetadata = false, + includeDependenciesToMavenPublication = false, ) + mutableUsageContexts += sourcesUsage + + val result = createKotlinVariant(targetName, mainCompilation, mutableUsageContexts) setOf(result) }