Kotlin Multiplatform Library Publishing: Overcoming the CommonMain Conundrum
Image by Chesea - hkhazo.biz.id

Kotlin Multiplatform Library Publishing: Overcoming the CommonMain Conundrum

Posted on

As a Kotlin developer, you’re eager to share your brilliant library with the world. You’ve invested countless hours crafting a masterpiece, and now it’s time to publish it for others to use. However, you’ve hit a snag: you can’t use classes in commonMain. Don’t worry, friend, you’re not alone! In this article, we’ll embark on a journey to conquer the challenges of Kotlin multiplatform library publishing, sans commonMain classes.

Understanding the Problem

The Kotlin Multiplatform (MPP) framework allows you to share code between different platforms, such as Android, iOS, and JavaScript. The commonMain module is where you typically place platform-agnostic code, which can be used across all platforms. However, when it comes to publishing your library, you might encounter issues when trying to use classes from commonMain.

The reason for this limitation lies in the way MPP compiles and packages your code. When you publish a library, the compiler generates platform-specific artifacts, such as JAR files for Android and frameworks for iOS. Unfortunately, the commonMain module is not intended for direct consumption by the platforms, which makes it difficult to use its classes in your published library.

Designing a Workaround

To overcome this hurdle, we’ll employ a clever strategy: we’ll create a separate module for our platform-agnostic code, which will be used as a dependency by our library. This approach allows us to decouple our common logic from the MPP framework’s restrictions.

Create a new module in your project, let’s call it `common-logic`. This module will contain the platform-agnostic code that was previously in commonMain.

// common-logic/build.gradle
plugins {
    id 'org.jetbrains.kotlin.multiplatform' version '1.6.20'
}

repositories {
    mavenCentral()
}

kotlin {
    jvm()
    js(IR) {
        browser()
        nodejs()
    }

    // Define the common-logic module
    sourceSets {
        commonMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
            }
        }
    }
}

Publishing the Common-Logic Module

Now that we have our `common-logic` module, we need to publish it as a separate artifact. This artifact will be used as a dependency by our library.

Create a new Gradle publication for the `common-logic` module:

// common-logic/build.gradle
publishing {
    publications {
        commonLogic(MavenPublication) {
            groupId = 'com.example'
            artifactId = 'common-logic'
            version = '1.0.0'

            artifact file('build/libs/common-logic-1.0.0.jar')
        }
    }
}

Publish the `common-logic` artifact to your desired repository, such as Maven Central or a local artifact repository.

Consuming the Common-Logic Module

Now that the `common-logic` module is published, we can use it as a dependency in our library.

In your library’s `build.gradle` file, add the following dependency:

// library/build.gradle
dependencies {
    implementation 'com.example:common-logic:1.0.0'
}

This will allow you to use the classes from the `common-logic` module in your library.

Using the Library in a Multiplatform Project

Let’s create a new Kotlin multiplatform project to demonstrate how to use our published library.

Create a new project with the following structure:

.
MultiplatformProject
commonMain
...
androidMain
...
iosMain
...
jsMain
...
build.gradle
settings.gradle

In the `build.gradle` file, add the following dependencies:

// build.gradle
dependencies {
    implementation 'com.example:library:1.0.0'
}

Now, you can use the classes from your published library in your multiplatform project.

Working Around commonMain Limitations

When using the library in a multiplatform project, you might encounter issues with the commonMain module. To overcome these limitations, consider the following strategies:

  • Use interfaces instead of classes: When possible, define interfaces in commonMain and provide platform-specific implementations in the respective modules (e.g., androidMain, iosMain, etc.). This approach allows you to keep the common logic separate from the platform-specific code.

  • Use abstract classes: If you need to share some implementation details between platforms, consider using abstract classes in commonMain. These classes can be extended by platform-specific classes in the respective modules.

  • Use platform-specific modules: If you have platform-specific code that can’t be shared, create separate modules for each platform. This approach allows you to keep the platform-specific code separate from the common logic.

Conclusion

Kotlin multiplatform library publishing can be a daunting task, especially when dealing with the limitations of the commonMain module. By employing a separate module for platform-agnostic code and publishing it as a separate artifact, we can overcome these challenges. With the strategies outlined in this article, you’re now equipped to share your Kotlin library with the world, sans commonMain class restrictions.

Remember to:

  • Create a separate module for platform-agnostic code
  • Publish the module as a separate artifact
  • Consume the published artifact in your library
  • Use interfaces, abstract classes, and platform-specific modules to work around commonMain limitations

Happy publishing, and may your Kotlin library bring joy to developers everywhere!

Module Description
common-logic Platform-agnostic code module
library Kotlin multiplatform library module
MultiplatformProject Kotlin multiplatform project using the published library

Don’t forget to checkout the GitHub repository for this article, which includes a working example of the concepts discussed.

By following these steps and considering the strategies outlined in this article, you’ll be well on your way to publishing a successful Kotlin multiplatform library that can be used by developers across various platforms.

Stay tuned for more articles on Kotlin development, and don’t hesitate to reach out if you have any questions or need further guidance.

Happy coding!

Frequently Asked Question

Get the answers to the most frequently asked questions about Kotlin multiplatform library publishing and using classes in commonMain!

Why can’t I use classes from commonMain in my platform-specific modules?

When you create a Kotlin multiplatform library, the commonMain module is meant to be platform-agnostic. This means that any classes you define in commonMain should be compatible with all platforms (e.g., JVM, JS, Native). However, when you try to use these classes in your platform-specific modules (e.g., jvmMain, jsMain), the compiler will complain because it can’t ensure that the classes will work correctly on that specific platform.

How do I make my commonMain classes accessible from my platform-specific modules?

To make your commonMain classes accessible, you need to declare them as interfaces or abstract classes. This way, you can provide platform-specific implementations for these interfaces or abstract classes in your platform-specific modules. For example, you can define an interface in commonMain and provide a JVM-specific implementation in jvmMain.

What’s the purpose of the expect and actual keywords in Kotlin multiplatform?

In Kotlin multiplatform, the expect and actual keywords are used to define platform-specific implementations of commonMain declarations. The expect keyword is used in commonMain to declare a function or class that will be implemented differently on each platform, while the actual keyword is used in platform-specific modules to provide the implementation for that function or class.

Can I use Kotlin multiplatform library publishing for Android apps?

Yes, you can use Kotlin multiplatform library publishing for Android apps. In fact, this is one of the main use cases for Kotlin multiplatform. By creating a multiplatform library, you can share common code between your Android and iOS apps, and then use platform-specific modules to handle the platform-specific logic.

How do I publish my Kotlin multiplatform library to Maven or Gradle?

To publish your Kotlin multiplatform library to Maven or Gradle, you need to configure your build script to generate platform-specific artifacts for each module. Then, you can upload these artifacts to your repository of choice, such as Maven Central or a private repository. You’ll need to use the maven-publish or(gradle) plugin to configure the publishing process.