Kotlin 1.2 brings with it experimental support for multi-platform projects and last week at KotlinConf we showed how you can now
use Kotlin to target the Jvm, the Web, Android and iOS. The source code for the actual KotlinConf is availabe on GitHub, and while it’s a great example
of multi-platform project, it’s got a lot of moving pieces and opening it for the first time can be overwhelming.

I’m currently preparing a two week road trip to Asia, and one of the things I’ll be talking about is precisely MPPs. So I’ve prepared a very simple sample project which is now available on GitHub, and in this
blog post I’ll walk you through the different parts.

Project Structure

The project consists of three modules:

common module for shared code

js module targeting JavaScript

jvm module targeting the JVM

Common module

This module contains all common shared code, and should be limited to Kotlin.

In the case of a data classes, usually the implementation is the same
whether targeting the JVM, JavaScript or other platforms. In our case, we have this as part of the package com.hadihariri.multiplatform.common.data.

expect and actual

There are times when we still need to share common code, but have different behaviours on different platforms, since the implementation touch
platform-specific calls and/or libraries.

That’s where the expect and actual keywords come in to play and this is the module where we need to define them. If you recall C/C++, think of them as headers and implementations. We can mark any class or functions with the keyword
expect to indicate that the code is present, but the actual implementation will be provided in each specific module. How we link these modules and make the compiler aware of it all, we’ll see in a bit.

In our case, we’re going to define a class called Date and a function called platformMessage, and place these in the com.hadihariri.multiplatform.common package.

actual implementations

As soon as we do this, IntelliJ IDEA will display an error, along with an Intention, indicating that the implementation for these declarations are missing

We need to now implement these in their corresponding modules. That’s where platform specific modules come in.

Platform specific modules

Since we’re targeting Jvm and JavaScript, we have two platform specific modules. In each of these we’ll have
Kotlin code that can talk and interop with platform libraries and languages. In addition we’ll have the actual implementations of our expect declarations declared in the common module.

In our case, this would be the implementations for the Data class and the platformMessage function

One important thing to note here: the code should be declared in the same package as it is defined in the common module. If we see our project structure
we can see how we have a common and a jvm package defined in the jvm module

Linking modules with Gradle

One piece missing in this picture is how we link the Gradle projects together so that they correctly identify the dependencies between modules. It’s similar to the compile directive in Gradle
which allows one project to be referenced by another

dependencies{compileproject(':common')

except in this case, instead of compile, we use expectedBy

dependencies{expectedByproject(':common')

Starting a new MP project in IntelliJ IDEA

Currently multi-platform projects are only supported using Gradle. In IntelliJ IDEA, we can create the necessary modules using the New Module wizard

We first start by creating a general Gradle module, and then add a module per target platform (which then defines the correct dependencies). Currently the expectedBy relationship needs to be set manually.