Search code examples
mobiledesktopkotlin-multiplatform

How to add Desktop Support to Kotlin Multiplatform Mobile Project


Using Android Studio with the Kotlin Multiplatform Mobile plugin, I have created a KMM project, which provides support for Android and iOS.

However, I would also like to be able to use the same code base and UI to deploy to create a desktop app. Is that possible? And if yes, how?


Solution

  • Yes, it is possible. In fact, this tutorial details how to do it, albeit in a quite roundabout way that took me several days to complete:

    https://www.kodeco.com/books/kotlin-multiplatform-by-tutorials/v1.0/chapters/1-introduction

    Because of that, I have taken the liberty to creating a short summary for how you can create a basic project setup for a Desktop/Android/iOS app:

    1. Install the Kotlin Multiplatform Mobile and Compose Multiplatform IDE Support plugins in Android Studio

    2. Create a new Kotlin Multiplatform App project (under Phone and Tablet)

      • For the following points, I am going to assume the project name is "My Project" and the package name is com.domain.project
    3. In the shared/build.gradle.kts, in the kotlin block, after android(), add:

      • jvm("desktop"){
            compilations.all {
                kotlinOptions.jvmTarget = "11"
            }
        }
        
    4. Add a new desktop folder at the top level of the app

    5. Add a new file build.gradle.kts into the desktop folder, and fill it with this content:

      • import org.jetbrains.compose.compose
        import org.jetbrains.compose.desktop.application.dsl.TargetFormat
        
        plugins {
            kotlin("multiplatform")
            id("org.jetbrains.compose") version "1.2.2"
        }
        
        group = "com.domain.project"
        version = "1.0.0"
        
        kotlin {
            jvm {
                withJava()
                compilations.all {
                    kotlinOptions.jvmTarget = "11"
                }
            }
            sourceSets {
                val jvmMain by getting {
                    kotlin.srcDirs("src/jvmMain/kotlin")
                    dependencies {
                        implementation(compose.desktop.currentOs)
                        api(compose.runtime)
                        api(compose.foundation)
                        api(compose.material)
                        api(compose.ui)
                        api(compose.materialIconsExtended)
        
                        implementation(project(":shared"))
                    }
                }
            }
        }
        
        compose.desktop {
            application {
                mainClass = "MainKt"
                nativeDistributions {
                    targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
                    packageName = "MyProject"
                    macOS {
                        bundleID = "com.domain.project"
                    }
                }
            }
        }
        
    6. On the top level, in the settings.gradle.kts add include(":desktop") at the very end

    7. Click on "sync now" (Or File > Sync project with gradle files)

      • After the sync, the desktop folder should now be recognized as a module, indicated by a little square at the bottom right of the folder icon
    8. In the desktop module, create the folder chain src/jvmMain/kotlin

    9. In the just created kotlin folder create the Kotlin file Main, and fill it as follows:

      • import androidx.compose.foundation.layout.fillMaxSize
        import androidx.compose.material.Surface
        import androidx.compose.ui.Modifier
        import androidx.compose.ui.window.Window
        import androidx.compose.ui.window.application
        import androidx.compose.ui.window.rememberWindowState
        import androidx.compose.material.*
        
        fun main() {
            application {
                val windowState = rememberWindowState()
        
                Window(
                    onCloseRequest = ::exitApplication,
                    state = windowState,
                    title = "My Project"
                ) {
                    Surface(modifier = Modifier.fillMaxSize()) {
                        Text(text = "Welcome to my Project")
                    }
                }
            }
        }
        
    10. Add a run configuration of type Gradle with the following settings:

      • Name: "Desktop"
      • Run: "run"
      • Gradle Project: "project:desktop"
    11. Create the file shared/src/desktopMain/kotiln/com.domain.project/Platform.kt, and fill it with this:

      • package com.domain.project
        
        class DesktopPlatform : Platform {
            override val name: String = "Desktop"
        }
        
        actual fun getPlatform(): Platform = DesktopPlatform()
        
    12. You should now be able to run the desktop app

    After that, you can then create shared Compose views that will work on both android and desktop. Chapter 5 of aforementioned tutorial covers that:

    https://www.kodeco.com/books/kotlin-multiplatform-by-tutorials/v1.0/chapters/5-developing-ui-compose-multiplatform

    In addition, here's a bare-bones version of a project that I created using the above steps:

    https://github.com/KiraResari/ceal-chronicler/releases/tag/basic-android-and-desktop-app