skip to content

What is the Kotlin Multiplatform Gradle plugin, and how do you declare the platforms a module should compile for?

level: juniorimportance: must knowfreq 60%

answer

  1. plugin id org.jetbrains.kotlin.multiplatform
  2. kotlin { } extension
  3. target functions: jvm(), js(), iosX64()
  4. commonMain is the shared root
  5. per-target source sets dependsOn common

basics

~10 s

Apply the org.jetbrains.kotlin.multiplatform plugin, then open a kotlin { } block and call target functions like jvm(), js(), and iosX64(). Each call adds a platform the module compiles for.

solid answer

~40 s

The Kotlin Multiplatform Gradle plugin (KMP, plugin id `org.jetbrains.kotlin.multiplatform`, often called KGP-MP) lets one Gradle module produce artifacts for several platforms from shared Kotlin code. You apply it in the `plugins { }` block, then configure a `kotlin { }` extension where each *target* is declared by calling a function: `jvm()`, `js()`, `iosX64()`, `iosArm64()`, `linuxX64()`, and so on. Each target gets its own compilations and source sets. Code that all targets share lives in `commonMain`; platform-specific code lives in target source sets like `jvmMain` or `iosMain`. The plugin wires the compilers, dependency resolution, and per-target tasks (e.g. `jvmJar`, `compileKotlinJvm`) automatically. Declaring a target is the trigger that makes the module actually build for that platform.

code

kotlin · 19 lines
kotlin
plugins {
    kotlin("multiplatform") version "2.0.0"
}

kotlin {
    jvm()
    js(IR) { browser() }
    iosArm64()
    iosSimulatorArm64()

    sourceSets {
        commonMain.dependencies {
            implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.0")
        }
        commonTest.dependencies {
            implementation(kotlin("test"))
        }
    }
}

go deeper

for a junior

Name the plugin id, the kotlin { } block, and that you call jvm(), js(), iosX64() to add targets, with shared code in commonMain.

for a middle

Explain that each target creates its own compilations/source sets/tasks and that source sets form a hierarchy with commonMain at the root; show per-source-set dependencies.

for a senior

Discuss variant-aware publishing/resolution of multiplatform libraries and the boundary between Gradle wiring and the Kotlin-language expect/actual mechanism.

for a principal

Frame KMP as a strategy for sharing logic across mobile/server/web, the build-graph cost of many native targets, CI matrix implications, and when a multi-module vs single-module shared layer is warranted.

## What the plugin is Kotlin Multiplatform (KMP) is a Kotlin feature for sharing code across platforms — JVM, JavaScript, and native targets like iOS, Linux, and Windows. On Gradle it is delivered by the **Kotlin Multiplatform Gradle plugin**, whose id is `org.jetbrains.kotlin.multiplatform`. It is a *sibling* of the single-platform `org.jetbrains.kotlin.jvm` plugin: you apply one or the other in a module, not both. Applying the plugin adds a `kotlin { }` extension (the DSL entry point) to the project and registers the Kotlin compiler tooling, dependency variants, and the per-platform task graph. ## Declaring targets Inside `kotlin { }` you call **target functions**. Each call registers one platform: ```kotlin kotlin { jvm() // JVM bytecode js(IR) // JavaScript via the IR backend iosX64() // iOS simulator on Intel macs iosArm64() // real iOS devices linuxX64() } ``` Calling `jvm()` does several things: it creates the JVM **compilation**, the `jvmMain`/`jvmTest` source sets, and tasks such as `compileKotlinJvm` and `jvmJar`. A target you never declare is simply not built — there is no implicit "all platforms" mode. Targets come in families: `jvm()`, `js()`/`wasmJs()`, and the *native* targets (`iosX64`, `iosArm64`, `iosSimulatorArm64`, `macosArm64`, `linuxX64`, `mingwX64`, …). For Apple platforms there are convenience aggregators; KMP also offers `androidTarget()` when combined with the Android Gradle Plugin (that combination is its own topic). ## Source sets The whole point is shared code. Every target has a *main* and *test* source set, and they all depend on the **common** source sets: - `commonMain` — code compiled for *every* declared target; may only use the Kotlin common stdlib and multiplatform libraries. - `commonTest` — shared tests, typically using `kotlin.test`. - `jvmMain`, `iosMain`, `jsMain`, … — platform-specific code that can use that platform's APIs. The plugin builds a **source-set hierarchy**: `commonMain` is the root, platform source sets `dependsOn` it. Code in `commonMain` cannot reference JVM or iOS APIs because it must compile for all targets; that is exactly what `expect`/`actual` declarations are for (a Kotlin-language mechanism — bridge out to the Kotlin topic for the details). ## Dependencies Dependencies are added per source set: ```kotlin kotlin { sourceSets { commonMain.dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0") } jvmMain.dependencies { implementation("com.squareup.okhttp3:okhttp:4.12.0") } } } ``` A multiplatform library publishes a *root* (metadata) module plus one variant per target; Gradle's variant-aware resolution picks the right artifact for each target automatically. ## Why it matters From a build-tool perspective, KMP is the canonical example of one Gradle module producing many outputs with a shared source tree. Understanding that *targets are declared by function calls* and *source sets form a hierarchy rooted at `commonMain`* is the overview every JVM/Gradle engineer is expected to have, even if the deep `expect`/`actual` semantics belong to Kotlin proper.

  • What is the difference between applying `kotlin("multiplatform")` and `kotlin("jvm")`?
    `kotlin("jvm")` is the single-platform plugin: one target (JVM), the standard `main`/`test` source sets, and a plain `kotlin { }` with no target functions. `kotlin("multiplatform")` registers the multi-target DSL, the `commonMain` hierarchy, and per-target compilations. You apply one or the other, never both.
  • If I call `jvm()` but never call `iosX64()`, does the module still build for iOS?
    No. A target is only built if you declare it. There is no implicit set of targets; the function calls are what register the compilations and tasks.

Think of commonMain as a master blueprint and each target as a factory: every factory builds from the master blueprint plus its own local adaptations (jvmMain, iosMain).

saying these in an interview costs you the question

  • Saying you apply both `kotlin("jvm")` and `kotlin("multiplatform")` in the same module.
  • Claiming `commonMain` can call JVM/Android APIs directly — it can only use common/multiplatform APIs.
  • Thinking targets are auto-detected; they are explicit function calls.

context