skip to content

KGP Multiplatform Targets

The Kotlin Multiplatform plugin's target declarations and common source sets, at an orientation level. Asked to see whether you can describe how one build serves several platforms.

on this pageshow

questions

5

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

open as a page

Explain the source-set hierarchy in a Kotlin Multiplatform module and how an intermediate source set like `iosMain` fits in.

level: middleimportance: should knowfreq 45%

basics

~20 s

Source sets form a tree: commonMain is the root, and each platform source set dependsOn it. Intermediate sets like iosMain group several related native targets (iosArm64, iosSimulatorArm64) so they can share code above common but below the individual targets.

open as a page

When you declare multiple targets in a KMP module, what tasks does the plugin generate and how do you build or test a single platform?

level: middleimportance: should knowfreq 40%

basics

~10 s

Each target gets its own tasks — e.g. compileKotlinJvm, jvmJar, jvmTest, compileKotlinIosArm64, iosX64Test. To build or test just one platform you run the target-prefixed task, like ./gradlew jvmTest instead of ./gradlew check.

open as a page

How is a Kotlin Multiplatform library published and consumed, and what role does Gradle variant-aware resolution play?

level: seniorimportance: should knowfreq 30%

basics

~20 s

A KMP library publishes a root metadata module plus one Gradle module per target (jvm, iosArm64, js…), each with attributes. When a consumer adds the library, Gradle's variant-aware resolution matches each target's attributes to pick the correct per-platform artifact automatically.

open as a page

A team has a single JVM library. When would you reach for the Kotlin Multiplatform plugin instead of the plain `kotlin("jvm")` plugin, and what does adopting it cost?

level: seniorimportance: nice to knowfreq 22%

basics

~20 s

Use kotlin("jvm") if you only ever need the JVM — it's simpler. Reach for kotlin("multiplatform") when you genuinely need to share code with other platforms (iOS, JS, native). KMP adds build complexity, slower builds, and host constraints, so don't adopt it for a JVM-only library.

open as a page