Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sschuberth/60b14dfc7d4d821af1464efb618c6b51 to your computer and use it in GitHub Desktop.
Save sschuberth/60b14dfc7d4d821af1464efb618c6b51 to your computer and use it in GitHub Desktop.
Kotlin Usages of Gradle Variant-Aware Dependency Management

Kotlin Usages of Gradle Variant-Aware Dependency Management

This document is up-to-date for Kotlin release: 1.3.30.

Here is the list of all attributes used by the Kotlin Gradle plugin. The details, configuration and possible values will be listed below.

Name Type
org.gradle.usage (owned by Gradle) org.gradle.api.attributes.Usage
org.jetbrains.kotlin.platform.type org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
org.jetbrains.kotlin.native.target String
org.jetbrains.kotlin.localToProject String

Note: there's a plan to add at least one more attribute for Kotlin metadata dependencies resolution between Multiplatform projects.

This document does not cover how these attributes are set in old 1.2.x MPP to ensure compatibility with 1.3.x projects, as 1.2.x MPP will be deprecated soon.

Short history

Before Kotlin 1.3, Kotlin didn't actively use variant-aware dependency management and did not set any attributes of its own.

In Kotlin 1.3, we revamped the Multiplatform projects feature, which now allows having a single Gradle project build multiple Kotlin targets (most often, for multiple platforms). For that, we leveraged variant-aware dependency management that allowed us to set up dependency resolution between multiplatform projects and publish multiplatform libraries.

See also: Building Multiplatform Projects with Gradle

Attributes

Notation

Below, (C) is used to denote a consumable configuration, (R) for resolvable configurations.

org.gradle.usage (owned by Gradle)

The Kotlin plugin uses this attribute to ensure that a project that applies the Java plugin can consume a depedency on an MPP (i.e. can choose the JVM variant), and also to ensure that Kotlin MPP's JVM targets can properly consume JVM dependencies. We use the Java plugin's values on variants that are meant to be Java-compatible, and Kotlin-specific values for variants that the Java plugin is not supposed to care about.

See: org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages

Set on configurations

  • In projects based on the Java plugin (kotlin and kotlin2js plugins, and experimental Java support for MPP):

    • (C) apiElements
    • (C) runtimeElements
    • (R) *compileClasspath
    • (R) *runtimeClasspath
  • In MPP (here foo is a target name, bar is a compilation name or empty for the main compilation):

    • (C) fooApiElements
    • (C) fooRuntimeElements
    • (R) fooBarCompileClasspath
    • (R) fooBarRuntimeClasspath
    • (R) fooBarCompileKLibraries (Kotlin/Native-only replacement for compile classpath)
  • In Kotlin/Native targets of an MPP (baz is a framework's name, qux is a CInterop library name)

    • (R) fooBazExport for an Objective-C framework's exported dependencies
    • (R) fooBarQuxCInterop for a CInterop library's dependencies, similar to compile classpath

Possible values that Kotlin sets

  • java-api

    For single-platform JVM projects (kotlin, kotlin-android plugins) and JVM targets of MPP.

    Starting with Gradle 5.3 & Kotlin 1.3.30, this value is set only on the resolvable compile-scoped JVM configurations.

  • java-api-jars

    Set only with Gradle 5.3+ & Kotlin 1.3.30+ on the consumable JVM API configurations in single- and multi-platform projects.

  • java-runtime

    For single-platform JVM projects and JVM targets of MPP, set only on the resolvable configurations.

  • java-runtime-jars

    For single-platform JVM projects and JVM targets of MPP, set only on the consumable configurations.

  • kotlin-api

    For kotlin2js projects, JS and Native targets of MPP. Set on both the consumable and resolvable API configurations.

  • kotlin-runtime

    For kotlin2js projects, JS targets of MPP (not Native). Set on both the consumable and resolvable runtime configurations.

Compatibility rules

  • A kotlin-api consumer is also compatible with java-api and java-api-jars producers.
  • A kotlin-runtime consumer is also compatible with java-runtime and java-runtime-jars.

These two rules ensure that a Kotlin consumer can depend on a plain library published to a Maven repository with Gradle Improved POM support enabled, when the library has no Kotlin-specific metadata.

Disambiguation rules

  • If the candidate values are just kotlin-api and kotlin-runtime, then choose kotlin-runtime; this is only possible when the consumer does not specify a usage but the compatible variants are limited to the Kotlin ones, either by the other attributes or just because the library doesn't have any non-Kotlin variants.

  • If all candidate values are the Java plugin's values mentioned above, then for a kotlin-api consumer choose any of the Java API values, for a kotlin-runtime consumer or a consumer that did not request a value choose any of the Java runtime usages.

  • Corner case: for a set of candidate values of java-runtime-classes, java-runtime-resources, and kotlin-runtime, choose kotlin-runtime.

org.jetbrains.kotlin.platform.type

This is one of the two attributes used to distinguish Kotlin platforms in dependency resolution between MPP and single-target projects alike. A special case of a platform type is the Kotlin metadata built from common code, which contains serialized Kotlin declarations.

See: org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType

Set on configurations

  • In projects based on the Java plugin (kotlin and kotlin2js plugins, and experimental Java support for MPP):

    • (C) apiElements
    • (C) runtimeElements
    • (R) *compileClasspath
    • (R) *runtimeClasspath
    • the deprecated source set configurations: (RC) *compile, (RC) *runtime, see also org.jetbrains.kotlin.localToProject
  • In MPP

    Here, foo is a target name, bar is a compilation name or empty for the main compilation, baz is a source set name:

    • (C) fooApiElements
    • (C) fooRuntimeElements
    • (R) fooBarCompileClasspath
    • (R) fooBarRuntimeClasspath
    • (R) fooBarCompileOnly (needed for IDE import)
    • (R) fooBarCompileKLibraries (Kotlin/Native-only replacement for compile classpath)
    • (R) bazApiDependenciesMetadata, (R) bazImplementationDependencyMetadata, (R) bazCompileOnlyDependencyMetadata, (R) bazRuntimeOnlyDependenciesMetadata – the configurations that are resolved for a source set to get its MPP dependencies Kotlin metadata
    • (RC) fooDefault (deprecated, see also org.jetbrains.kotlin.localToProject)
    • the deprecated configurations created for compilations: (RC) fooBarCompile, (RC) fooBarRuntime, see also org.jetbrains.kotlin.localToProject

Possible values

  • common for Kotlin metadata, set on the (C) metadataApiElements configuration in MPP and the source set dependencies metadata configurations
  • jvm for Kotlin/JVM configurations in both MPP JVM targets and kotlin single-target projects
  • androidJvm for MPP Android targets and kotlin-android single-target projects
  • js for Kotlin/JS configurations in both MPP JS targets and kotlin2js single-target projects
  • native for MPP Kotlin/Native targets for any Native platform (see also org.jetbrains.kotlin.native.target)

Compatibility rules

  • An androidJvm consumer can also use jvm variants.
  • A common consumer is compatible with any other platform type. This is done to allow the metadata configurations to consume platform-specific variants of the dependencies that have no metadata variants (these are single-platform libraries or MPP libraries that are published with no Gradle metadata).

Disambiguation rules

  • If the candidates set is just jvm and androidJvm, prefer androidJvm.
  • If common is in the candidates set, choose common. This can only happen if the consumer requested common or requested no specific platform.

org.jetbrains.kotlin.native.target

This is an additional attribute for Kotlin/Native variants that is used to distinguish them by the Native platform.

Set on configurations

The same as org.jetbrains.kotlin.platform.type, but only in MPP and only for Kotlin/Native targets.

Possible values

  • android_arm32
  • android_arm64
  • ios_arm32
  • ios_arm64
  • ios_x64
  • linux_x64
  • mingw_x64
  • mingw_x86
  • macos_x64
  • linux_arm32_hfp
  • linux_mips32
  • linux_mipsel32
  • wasm32

This attribute has no compatibility or disambiguation rules.

org.jetbrains.kotlin.localToProject

This attribute is used as a workaround to achieve the following goals at the same time:

  • The deprecated configurations *compile, *runtime, default should be able to resolve Kotlin MPP dependencies to the right platform-specific variant (which requires them to have proper attributes described above).
  • The deprecated configurations should not get chosen during variant-aware dependency resolution or otherwise interfere with the *Elements configurations that are intended to be consumed.
  • A user should still be able to specify a project dependency with explicit configuration, specifying one of the deprecated configurations, e.g. project(path: ':foo', configuration: 'compile').

We set this attribute on both configurations that should not be consumed and the ones that are intended for consumption.

Note: this attribute is excluded from published Gradle module metadata (all published variants should anyway have the 'public' value, but we don't want to expose it in published metadata, as it may complicate our future changes in the attributes schema).

See: org.jetbrains.kotlin.gradle.plugin.ProjectLocalConfigurations

Set on configurations

  • In projects based on the Java plugin (kotlin and kotlin2js plugins, and experimental Java support for MPP):

    • (RC) default gets a 'local' value
    • the deprecated source set configurations: (RC) *compile, (RC) *runtime get a 'local' value
    • (C) apiElements, (C) runtimeElements get the 'public' value
  • In MPP:

    • (RC) fooDefault gets a 'local' value
    • the deprecated configurations created for compilations: (RC) fooBarCompile, (RC) fooBarRuntime get a 'local' value
    • (C) fooApiElements (C) fooRuntimeElements get the 'public' value

Possible values

  • public – a single value that we set on any configuration meant for consumption
  • local to :foo where foo is the project path, so that different projects have different values set on their configurations

Compatibility rules

  • All values are compatible – this is needed for the requirement that a user should still be able to specify a project dependency with explicit configuration, specifying one of the deprecated configurations.

Disambiguation rules

  • If the candidate values set contains public, then choose public.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment