· 4 min read

A closer look at the Kotlin Multiplatform Artifacts

.pom vs .module files and a real-life exemple.

.pom vs .module files and a real-life exemple.

Disclaimer: the below was tested with Gradle 6.2.2, I’m not sure how much support for module files is in Gradle < 6.0

If you’re coming from the JVM ecosystem, chances are you are familiar with the Maven ecosystem, which I covered in another article.

Maven works well and is based on pom files. Pom files describe a project, its license, repository, authors and, importantly, dependencies. You can take a look at the okhttp pom file if haven’t seen a pom file before.

With the advent of Kotlin Multiplatform, the same project can target multiple platforms (js, JVM, native) and the pom file format became too limited. Depending the platform you’re building, the build system will have to lookup a different artifact file (.jar for JVM, .klib for native) and dependencies. Luckily, around the same time as KMP was developed, Gradle introduced Gradle Metadata in the form of .module files that are much more flexible that pom files.

The Gradle Metadata and the .modules file structure are described in details in the gradle blog so I won’t go over it here. Instead, we’ll take a look at a real-life exemple: Clikt

Clikt

Clikt is a multiplatform library for writing command-line applications. It’s awesome but even if you’re not writing command-line applications, bear with me as we’ll just be looking at publication today.

If you browse the maven repository for Clikt on MavenCentral, you’ll find this: The Clikt artifacts

Here you’ll find:

  • clikt : the JVM project, as expected in the JVM world. This should actually be named clikt-jvm but the author kept thecliktnamefor backward compatibility.
  • clikt-js , clikt-linxux64 , clikt-macosx64 , clikt-mingwx64 : the other platforms. mingw64 is for building apps for windows. Note that there is no iOS or ARM platform so you won’t be able to compile your command line app for mobile devices just yet
  • clikt-metadata : contains metadata about functions and types that cannot always be represented inside the individual platforms artifacts. Think of nullability, variance, etc… This is used by the IDE and by kotlin.reflect to have more information about the types.
  • clikt-multiplatform : the main entry point of the multiplatform lib. Multiplatform users of Clikt can just add this project to their dependencies instead of having to include each individual platform project.

Using a multiplatform library

Using Clikt in your projects with Gradle 6.0 is as easy as adding clikt-multiplatform to the list of dependencies:

kotlin {
  sourceSets {
        get("commonMain").apply {
            dependencies {
                implementation("com.github.ajalt:clikt-multiplatform:2.6.0")
            }
        }
    }
}

An look at the clickt-multiplatformmodule file gives the following:

{
  "formatVersion": "1.1",
  "component": { [SKIPPED] },
  "createdBy": { [SKIPPED] },
  "variants": [
    {
      "name": "js-api",
      "attributes": {
        "org.gradle.usage": "kotlin-api",
        "org.jetbrains.kotlin.platform.type": "js"
      },
      "available-at": {
        "url": "../../clikt-js/2.6.0/clikt-js-2.6.0.module",
        "group": "com.github.ajalt",
        "module": "clikt-js",
        "version": "2.6.0"
      }
    },
    [jvm, macOS, mingw, etc...],
    {
      "name": "metadata-api",
      "attributes": {
        "org.gradle.usage": "kotlin-api",
        "org.jetbrains.kotlin.platform.type": "common"
      },
      "available-at": {
        "url": "../../clikt-metadata/2.6.0/clikt-metadata-2.6.0.module",
        "group": "com.github.ajalt",
        "module": "clikt-metadata",
        "version": "2.6.0"
      }
    }
  ]
}

Instead of a files:{ ... } section, this module file contains a available-at:{ ... } to make Gradle point to the appropriate artifacts, including the Kotlin metadata.

Gradle Metadata vs Kotlin Metadata

Despite sharing the Metadata name, Gradle and Kotlin Metadata are quite different.

Gradle Metadata was introduced in Gradle 5.3. It refers to the ability of Gradle to write and read .module files that are more flexible than the .pom files.

Kotlin Metadata has been there for some time and allows to information about the Kotlin code in a single place, even if some of it is lost in the respective platforms.

It just happens that Gradle Metadata is a convenient way to distribute Kotlin Metadata but they shouldn’t be mistaken.

Conclusion

Using Multiplatform libraries could historically be a bit complex but as the ecosystem matures it’s becoming easier and easier. If you’re a library author, publishing has also greatly improved, especially using the maven-publish plugin.

I’m looking forward to see the KMP ecosystem grow!

By Martin Bonnin on March 21, 2020.

Photo: “parallel lines” by theilr

Canonical link

Exported from Medium on November 9, 2024.

    Share:
    Back to Blog