skip to content

In a Kotlin Multiplatform build, how do you apply the plugin and declare which platforms (targets) your library should compile for?

level: juniorimportance: must knowfreq 70%

answer

  1. plugins { kotlin("multiplatform") }
  2. kotlin { } extension block
  3. jvm() / js(IR) / native targets
  4. each target -> XMain / XTest source sets
  5. name JVM variants: jvm("desktop")

basics

~10 s

Apply the kotlin("multiplatform") plugin, then inside the kotlin { } block call functions like jvm(), js(), and a native target such as linuxX64(). Each call adds a platform you compile for.

solid answer

~30 s

In build.gradle.kts you apply the plugin with `kotlin("multiplatform")` in the plugins { } block. Inside the `kotlin { }` extension you declare targets by calling functions: `jvm()` for the JVM, `js(IR) { browser(); nodejs() }` for JavaScript, and native targets like `linuxX64()`, `macosArm64()`, `iosArm64()`. Each target function registers compilations and creates source sets (e.g. jvmMain, jsMain). Some helpers expand to several targets — `iosArm64() + iosSimulatorArm64()` cover device and simulator; the convenience `iosX64/iosArm64` are declared individually. You can name targets, e.g. `jvm("desktop")`, when you need two JVM variants. The set of declared targets defines exactly which platform artifacts Gradle produces.

code

kotlin · 13 lines
kotlin
plugins {
    kotlin("multiplatform") version "2.1.0"
}

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

go deeper

for a junior

Can apply kotlin("multiplatform") and call jvm()/js() to declare targets, and knows source sets appear per target.

for a middle

Explains native targets, js(IR) environments, and naming a JVM target to create variants.

for a senior

Reasons about the target set as a shipping contract and how adding a target forces new actual implementations.

for a principal

Weighs target matrix breadth vs. CI cost and the API-surface commitment of supporting each platform long-term.

## What a "target" is A **target** in Kotlin Multiplatform (KMP) is one platform you compile your code for — the JVM, JavaScript, or a Kotlin/Native platform (iOS, Linux, macOS, Windows, etc.). Declaring a target tells the Kotlin Gradle plugin to set up compilations, source sets, and produce an artifact for that platform. ## Applying the plugin KMP is driven by the `org.jetbrains.kotlin.multiplatform` Gradle plugin. In the Kotlin DSL you usually write the accessor form: ```kotlin plugins { kotlin("multiplatform") version "2.1.0" } ``` Applying it adds the `kotlin { }` extension block where all multiplatform configuration lives. ## Declaring targets Inside `kotlin { }` you call a function per platform: ```kotlin kotlin { jvm() // JVM target -> jvmMain / jvmTest js(IR) { // JavaScript (IR backend) browser() nodejs() } linuxX64() // Kotlin/Native Linux macosArm64() // Kotlin/Native macOS Apple Silicon iosArm64() // iOS device iosSimulatorArm64() // iOS simulator on Apple Silicon } ``` - `jvm()` — compiles to JVM bytecode. You can pass a **name** like `jvm("desktop")` to declare more than one JVM variant. - `js(IR)` — JavaScript via the **IR** compiler backend (the legacy backend is removed in current Kotlin). The `browser()` / `nodejs()` sub-blocks pick the run/test environment. - **Native targets** (`linuxX64`, `mingwX64`, `macosArm64`, `iosArm64`, …) compile through Kotlin/Native to native binaries via LLVM. ## What each target call creates For a target `X`, the plugin creates a default `main` and `test` compilation, and corresponding source sets named `XMain` and `XTest` (for `jvm()` that's `jvmMain`/`jvmTest`). These are wired beneath the shared `commonMain`/`commonTest` source sets. ## Why it matters The set of declared targets is the contract for which platforms your library ships. Adding `iosArm64()` later, for example, forces you to provide `actual` implementations for any `expect` declarations on that platform.

  • What happens to source sets when you call jvm()?
    It creates jvmMain and jvmTest source sets (plus the jvm compilations), automatically depending on commonMain/commonTest.
  • Why might you write jvm("desktop")?
    To declare two distinct JVM targets in the same module; the name disambiguates their source sets (desktopMain) and configurations.

Declaring targets is like choosing which countries to print a passport edition for — each one you add means a separate, valid document you must produce.

saying these in an interview costs you the question

  • Thinking targets are applied with separate plugins instead of function calls in kotlin { }
  • Using the removed legacy JS backend instead of js(IR)
  • Believing one jvm() call can produce iOS or JS output
  • Not knowing each target generates its own source sets

context