diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ConfigurationsTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ConfigurationsTest.kt new file mode 100644 index 00000000000..d5972010f87 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ConfigurationsTest.kt @@ -0,0 +1,47 @@ +/* + * 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. + */ + +@file:Suppress("FunctionName") + +package org.jetbrains.kotlin.gradle + +import org.gradle.api.attributes.Category +import org.gradle.api.attributes.Usage +import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertNotNull + +class ConfigurationsTest : MultiplatformExtensionTest() { + + @Test + fun `consumable configurations with platform target are marked with Category LIBRARY`() { + kotlin.linuxX64() + kotlin.iosX64() + kotlin.iosArm64() + kotlin.jvm() + kotlin.js() + + val nativeMain = kotlin.sourceSets.create("nativeMain") + kotlin.targets.withType(KotlinNativeTarget::class.java).all { target -> + target.compilations.getByName("main").defaultSourceSet.dependsOn(nativeMain) + } + + project.evaluate() + + project.configurations + .filter { configuration -> + configuration.attributes.contains(KotlinPlatformType.attribute) || + configuration.attributes.getAttribute(Usage.USAGE_ATTRIBUTE)?.name in KotlinUsages.values + } + .forEach { configuration -> + val category = configuration.attributes.getAttribute(Category.CATEGORY_ATTRIBUTE) + assertNotNull(category, "Expected configuration ${configuration.name} to provide 'Category' attribute") + assertEquals(Category.LIBRARY, category.name, "Expected configuration $configuration to be 'LIBRARY' Category") + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index 59a02a9c19d..e478d81ecfb 100755 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -13,6 +13,7 @@ import com.android.build.gradle.api.SourceKind import org.gradle.api.* import org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer import org.gradle.api.artifacts.maven.MavenResolver +import org.gradle.api.attributes.Category import org.gradle.api.attributes.Usage import org.gradle.api.file.ConfigurableFileTree import org.gradle.api.file.Directory @@ -574,12 +575,14 @@ internal abstract class AbstractKotlinPlugin( if (kotlinTarget.platformType != KotlinPlatformType.common) { project.configurations.getByName(kotlinTarget.apiElementsConfigurationName).run { attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(kotlinTarget)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) setupAsPublicConfigurationIfSupported(kotlinTarget) usesPlatformOf(kotlinTarget) } project.configurations.getByName(kotlinTarget.runtimeElementsConfigurationName).run { attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerRuntimeUsage(kotlinTarget)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) setupAsPublicConfigurationIfSupported(kotlinTarget) usesPlatformOf(kotlinTarget) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt index e0f48c0df72..810c46e5ca3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt @@ -12,6 +12,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.Category import org.gradle.api.attributes.Usage import org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE import org.gradle.api.file.FileCollection @@ -181,6 +182,7 @@ abstract class AbstractKotlinTargetConfigurator isCanBeResolved = false isCanBeConsumed = true attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) extendsFrom(configurations.maybeCreate(mainCompilation.apiConfigurationName)) if (mainCompilation is KotlinCompilationToRunnableFiles) { val runtimeConfiguration = configurations.findByName(mainCompilation.deprecatedRuntimeConfigurationName) @@ -197,6 +199,7 @@ abstract class AbstractKotlinTargetConfigurator isCanBeConsumed = true isCanBeResolved = false attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.producerRuntimeUsage(target)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) val runtimeConfiguration = configurations.findByName(mainCompilation.deprecatedRuntimeConfigurationName) extendsFrom(implementationConfiguration) if (runtimeOnlyConfiguration != null) @@ -275,6 +278,7 @@ abstract class AbstractKotlinTargetConfigurator fun defineConfigurationsForCompilation( compilation: KotlinCompilation<*> ) { + val project = compilation.target.project val target = compilation.target val configurations = target.project.configurations @@ -319,6 +323,7 @@ abstract class AbstractKotlinTargetConfigurator val compileOnlyConfiguration = configurations.maybeCreate(compilation.compileOnlyConfigurationName).apply { isCanBeConsumed = false setupAsLocalTargetSpecificConfigurationIfSupported(target) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) isVisible = false isCanBeResolved = true // Needed for IDE import description = "Compile only dependencies for $compilation." @@ -330,6 +335,7 @@ abstract class AbstractKotlinTargetConfigurator isVisible = false isCanBeConsumed = false attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.consumerApiUsage(compilation.target)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) description = "Compile classpath for $compilation." } @@ -359,6 +365,7 @@ abstract class AbstractKotlinTargetConfigurator isCanBeConsumed = false isCanBeResolved = true attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.consumerRuntimeUsage(compilation.target)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) description = "Runtime classpath of $compilation." } } @@ -492,7 +499,10 @@ internal interface KotlinTargetWithTestsConfigurator, } internal fun Project.usageByName(usageName: String): Usage = - project.objects.named(Usage::class.java, usageName) + objects.named(Usage::class.java, usageName) + +internal fun Project.categoryByName(categoryName: String): Category = + objects.named(Category::class.java, categoryName) fun Configuration.usesPlatformOf(target: KotlinTarget): Configuration { attributes.attribute(KotlinPlatformType.attribute, target.platformType) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinSourceSetFactory.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinSourceSetFactory.kt index 5bc9ba1663a..661f98747b8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinSourceSetFactory.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinSourceSetFactory.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin.sources import org.gradle.api.NamedDomainObjectFactory import org.gradle.api.Project import org.gradle.api.artifacts.Configuration +import org.gradle.api.attributes.Category import org.gradle.api.attributes.Usage import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.plugin.* @@ -87,6 +88,7 @@ internal class DefaultKotlinSourceSetFactory( project.configurations.maybeCreate(metadataName).apply { attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.common) attributes.attribute(Usage.USAGE_ATTRIBUTE, project.usageByName(KotlinUsages.KOTLIN_API)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) isVisible = false isCanBeConsumed = false diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt index 8b1a3d3ded2..80881041e68 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt @@ -10,6 +10,7 @@ import org.gradle.api.artifacts.FileCollectionDependency import org.gradle.api.artifacts.ResolvedArtifact import org.gradle.api.artifacts.ResolvedDependency import org.gradle.api.artifacts.component.ProjectComponentIdentifier +import org.gradle.api.attributes.Category import org.gradle.api.attributes.Usage import org.gradle.api.initialization.IncludedBuild import org.gradle.api.internal.artifacts.DefaultProjectComponentIdentifier @@ -17,6 +18,7 @@ import org.gradle.api.tasks.* import org.gradle.api.tasks.bundling.Zip import org.gradle.configurationcache.extensions.serviceOf import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation +import org.jetbrains.kotlin.gradle.plugin.categoryByName import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages import org.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName @@ -166,6 +168,7 @@ internal class KotlinCompilationNpmResolver( all.usesPlatformOf(target) all.attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.consumerRuntimeUsage(target)) + all.attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) all.isVisible = false all.isCanBeConsumed = false all.isCanBeResolved = true diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt index fb26faaf198..f7406cc0b12 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt @@ -8,6 +8,8 @@ package org.jetbrains.kotlin.gradle.targets.metadata import org.gradle.api.Project import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.component.ComponentIdentifier +import org.gradle.api.attributes.Category +import org.gradle.api.attributes.Category.CATEGORY_ATTRIBUTE import org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE import org.gradle.api.file.FileCollection import org.gradle.api.internal.component.SoftwareComponentInternal @@ -16,8 +18,6 @@ import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.bundling.Jar import org.gradle.api.tasks.bundling.Zip import org.jetbrains.kotlin.gradle.dsl.* -import org.jetbrains.kotlin.gradle.dsl.kotlinExtension -import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.mpp.* import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationSourceSetUtil.compilationsBySourceSets @@ -97,6 +97,7 @@ class KotlinMetadataTargetConfigurator : target.project.configurations.getByName(target.apiElementsConfigurationName).run { attributes.attribute(USAGE_ATTRIBUTE, target.project.usageByName(KotlinUsages.KOTLIN_METADATA)) + attributes.attribute(CATEGORY_ATTRIBUTE, target.project.categoryByName(Category.LIBRARY)) /** Note: to add this artifact here is enough to avoid duplicate artifacts in this configuration: the default artifact * won't be added (later) if there's already an artifact in the configuration, see * [KotlinOnlyTargetConfigurator.configureArchivesAndComponent] */ @@ -271,6 +272,7 @@ class KotlinMetadataTargetConfigurator : usesPlatformOf(target) attributes.attribute(USAGE_ATTRIBUTE, project.usageByName(KotlinUsages.KOTLIN_METADATA)) + attributes.attribute(CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) } } } @@ -451,10 +453,8 @@ class KotlinMetadataTargetConfigurator : setupAsPublicConfigurationIfSupported(target) usesPlatformOf(target) - attributes.attribute( - USAGE_ATTRIBUTE, - KotlinUsages.producerApiUsage(target) - ) // 'kotlin-api' usage + attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target)) + attributes.attribute(CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) val commonMainApiConfiguration = project.sourceSetDependencyConfigurationByScope( project.kotlinExtension.sourceSets.getByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME), diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt index 6defa84d637..218668c0447 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt @@ -14,6 +14,7 @@ import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.Dependency import org.gradle.api.attributes.Attribute import org.gradle.api.attributes.AttributeContainer +import org.gradle.api.attributes.Category import org.gradle.api.attributes.Usage import org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE import org.gradle.api.internal.artifacts.ArtifactAttributes @@ -339,6 +340,7 @@ open class KotlinNativeTargetConfigurator : AbstractKotl isCanBeResolved = true usesPlatformOf(target) attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.consumerApiUsage(target)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) } } @@ -350,6 +352,7 @@ open class KotlinNativeTargetConfigurator : AbstractKotl isCanBeResolved = true usesPlatformOf(target) attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.consumerApiUsage(target)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) description = "Dependenceis to be exported in framework ${framework.name} for target ${target.targetName}" } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropConfigurations.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropConfigurations.kt index f36595787aa..47b192e6de7 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropConfigurations.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropConfigurations.kt @@ -10,14 +10,11 @@ import org.gradle.api.artifacts.Configuration import org.gradle.api.attributes.* import org.gradle.api.internal.artifacts.ArtifactAttributes import org.gradle.api.tasks.TaskProvider -import org.jetbrains.kotlin.gradle.plugin.CInteropSettings +import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.KotlinNativeTargetConfigurator.NativeArtifactFormat -import org.jetbrains.kotlin.gradle.plugin.KotlinTarget import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultCInteropSettings import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages -import org.jetbrains.kotlin.gradle.plugin.setupAsPublicConfigurationIfSupported -import org.jetbrains.kotlin.gradle.plugin.usesPlatformOf import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropKlibLibraryElements.cinteropKlibLibraryElements import org.jetbrains.kotlin.gradle.tasks.CInteropProcess @@ -53,6 +50,7 @@ internal fun Project.locateOrCreateCInteropDependencyConfiguration( usesPlatformOf(target) attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, cinteropKlibLibraryElements()) attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage::class.java, KotlinUsages.KOTLIN_API)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) description = "Dependencies for cinterop '${cinterop.name}' (compilation '${compilation.name}')." } } @@ -69,6 +67,7 @@ internal fun Project.locateOrCreateCInteropApiElementsConfiguration(target: Kotl usesPlatformOf(target) attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, cinteropKlibLibraryElements()) attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage::class.java, KotlinUsages.KOTLIN_API)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) attributes.attribute(ArtifactAttributes.ARTIFACT_FORMAT, NativeArtifactFormat.KLIB) } }