Crafting and publishing Kotlin Multiplatform library to Bintray

Yev Kanivets
Jun 9, 2020 · 5 min read

Kotlin Multiplatform is a great technology in the maturing period, which means that it's not always possible to find what you need for your project and you must craft it yourself. Are you ready for a challenge?

Image for post
Image for post

In this article, I'll share a step-by-step guide of creating and publishing of KMP library for JVM, Android and iOS targets. Target, if simply put, is just a type of device where you want your library to work.

Prerequisites

Codeforces WatchR is an open-source mobile client for Codeforces platform, where thousands of programmers compete in weekly algorithmic challenges. There are both, iOS and Android apps, which are available in stores.

Image for post
Image for post

Recently we've migrated both apps to Kotlin Multiplatform. In the process, we've just copy/pasted ReKotlin source code (doesn't support KMP at the moment) to KMP common module, which was the short-term solution.

But then we needed ReKotlin in another KMP project, so we decided to publish it as KMP library to Bintray. Now it can be included as a dependency in build.gradle file. Other developers can also benefit from our work.

Source code

All source code can be found in the official ReKamp (this is how we called the library) repo on GitHub. As you can see, all classes are located under src/commonMain folder, which means ReKotlin was 99% ready for KMP.

There is no platform dependent code and our changes are limited to a few tiny tweaks related to how Kotlin/Native compiler transforms Kotlin into Obj-C:

  • For some reason === didn't work as expected within Kotlin/Native, even though printed addressed were the same. Changed them to ==.

Compilation

Configuration of your build happens in kotlin block where you specify your source sets and targets. jvm corresponds to any JVM-powered target and gives you an access to different Java-related APIs. android is subset of jvm, but allows you access Android-specific APIs.

It’s much more complicated for ios target. In many libraries listed in https://github.com/AAkira/Kotlin-Multiplatform-Libraries I've seen a shortcut for ios() preset of targets, which works good until you try to archive the iOS app, which uses the library, in XCode.

Architectures

If you inspect the default Valid Architectures field in your XCode project, you will see that it contains both arm32 (armv7, armv7s) and arm64 (arm64, arm64e) architectures.

But for some reason shortcut for ios() in KMP contains only x64 (simulator) and arm64 (devices) architectures. And when you try to archive the project, you will see following errors:

Image for post
Image for post

One of the solutions is getting rid of arm32 architectures in both your common KMP module and XCode project, but I'm not sure about implications of this choice. Comment if it's safe, please.

We've chosen another, more robust solution and decided to support iosArm32 in ReKamp. It can be done by explicitly including iosArm32, iosArm64 and iosX64 targets in the build.gradle. Just make sure that their corresponding source sets depends on nativeMain.

Metadata

When you do ./gradlew build, outputs for each target are created. These are jar files for JVM targets and klib for Native ones. So far, so good.

The problem is that there is no target for common source set, so no outputs are generated. But Android Studio needs jar file, which is named your-library.jar to support highlighting in your common KMP module.

The solution is simple, you need to rename your-library-metadata.jar (and other metadata outputs) to your-library.jar. Here is the code, which makes exactly that + makes sure that other outputs are named properly.

Publishing

We've used com.jfrog.bintray plugin, which provides convenient methods for uploading your outputs and metadata to Bintray repository. To make sure that all outputs are correctly uploaded, we've added them to publications:

publish.gradle provides the most important information to publishing plugin: repository url, group, artifact and version.

pom.gradle is just another Gradle script, which is used to provide additional information about library' license, developer, etc in POM format.

All the values you see in Gradle files are gathered in gradle.properties:

Another 2 values are located in local.properties, which are private: bintrayUser and bintrayApiKey, which you can get by registering at https://bintray.com/ for free.

At this moment, you should be able to publish your library with ./gradlew bintrayUpload. You should see about 20 lines of Uploaded to ...

Image for post
Image for post

Usage

First of all, check that you have all outputs successfully uploaded to Bintray: Repository -> Package -> Files. You should see a few folders (common, mavenProject + one per target).

Image for post
Image for post

Now you can include these dependencies for targets you need like this:

Gradle cache

Half of the time I've spent fighting with Gradle cache, which was super persistent about keeping old versions of my library after changes without changing the version.

Here are a few advices on how to overcome caching mechanism:

  • update version of your library after every single change
Image for post
Image for post

Bottom line

Creating and publishing Kotlin Multiplatform library was super challenging for the first time. It took me almost 2 weeks to get all things right in several rounds and a few broken projects.

I hope that this kind of step-by-step guide with working examples will help other developers to get their library published and working much faster.

Good luck!

Sources

xorum.io

Engaging #EdTech solutions for Mobile (iOS | Android | KMP) and Web (Kotlin | Ktor)

Yev Kanivets

Written by

Professional Mobile Engineer since 2014, passionated by #EdTech, learning and teaching. Competitive programming enthusiast. Marathon Finisher.

xorum.io

xorum.io

Engaging #EdTech solutions for Mobile (iOS | Android | Kotlin Multiplatform) and Web (Kotlin | Ktor | Vue.js)

Yev Kanivets

Written by

Professional Mobile Engineer since 2014, passionated by #EdTech, learning and teaching. Competitive programming enthusiast. Marathon Finisher.

xorum.io

xorum.io

Engaging #EdTech solutions for Mobile (iOS | Android | Kotlin Multiplatform) and Web (Kotlin | Ktor | Vue.js)

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store