In a Kotlin Multiplatform project, what is an intermediate source set such as iosMain, and why would you create one?
answer
- Shared by SOME targets, not all
- Sits between commonMain and leaf sets
- iosMain over iosArm64/iosX64
- Reaches subset-common APIs (POSIX)
- Wired with dependsOn
basics
~20 sIt is a source set shared by some targets but not all. For example iosMain is shared by iosArm64 and iosX64, so you write code once for both iOS targets instead of copying it into each.
solid answer
~40 sAn intermediate source set sits between commonMain (shared by every target) and the leaf target source sets (like iosArm64Main). It groups a subset of targets so they can share code and APIs available only to that subset. A classic example is iosMain, shared by the iosArm64 and iosX64 (and iosSimulatorArm64) targets. You create one to avoid duplicating logic across closely related targets and to reach platform APIs common to that subset (e.g. POSIX on native targets, or java.* across jvm+android). It is wired with dependsOn so the leaf source sets inherit from it, and it can see APIs from all the targets that depend on it. Modern Kotlin can also generate the standard hierarchy automatically via the default hierarchy template.
code
kotlin · 12 lineskotlin {
applyDefaultHierarchyTemplate()
iosArm64()
iosX64()
iosSimulatorArm64()
sourceSets {
// iosMain is auto-created and shared by all three iOS targets
iosMain.dependencies {
// dependencies only the iOS family needs
}
}
}go deeper
Can define intermediate source set as shared-by-some and give iosMain as an example.
Explains it reaches subset-common APIs and is wired via dependsOn / default hierarchy.
Discusses the hierarchy tree, visibility rules, and when a custom intermediate set is warranted.
Frames source-set hierarchy as an architecture lever for code-sharing strategy across a multi-target codebase.
## What a source set is In Kotlin Multiplatform (KMP) a **source set** is a named bucket of Kotlin source files plus its own dependencies. Each compilation target (JVM, Android, iOS, etc.) gets a *target* source set like `jvmMain` or `iosArm64Main`, and there is a universal `commonMain` whose code compiles for **every** target. ## What an intermediate source set is An **intermediate source set** sits *between* `commonMain` and the per-target leaf source sets. It is shared by **some but not all** targets. Examples: - `iosMain` — shared by `iosArm64`, `iosX64`, `iosSimulatorArm64`. - `nativeMain` — shared by all Kotlin/Native targets. - `jvmAndAndroidMain` — shared by the JVM and Android targets. ## Why create one - **No duplication**: write logic once for a family of related targets instead of copy-pasting into each leaf. - **Reach a subset's common APIs**: code in `iosMain` can call APIs available to *all* iOS targets (e.g. POSIX via `platform.posix`, or Apple Foundation types). Code in `commonMain` cannot, because not every target has them. ## How it is wired Leaf source sets connect to the intermediate set with **`dependsOn`**. With the **default hierarchy template** (enabled by `applyDefaultHierarchyTemplate()` or implied when you only use standard targets), Kotlin creates `iosMain`, `nativeMain`, etc. for you. ```kotlin kotlin { iosArm64() iosX64() // default hierarchy auto-creates iosMain shared by both } ``` ## Mental model Think of a tree: `commonMain` at the root, intermediate sets in the middle, leaf target sets at the bottom. Each node sees only the APIs common to everything below it.
- Can commonMain call POSIX functions?No. POSIX exists only on native targets, not on JVM/JS, so it is not visible from commonMain. It is visible from a native-or-iOS intermediate set.
- Name another common intermediate set besides iosMain.nativeMain (all native targets), appleMain, or a custom jvmAndAndroidMain shared by the JVM and Android targets.
Like a family folder: documents in 'Smith family' apply to all Smiths but not to strangers, while the household-wide folder applies to everyone.
saying these in an interview costs you the question
- Saying it is shared by all targets (that is commonMain)
- Claiming commonMain can access platform APIs like POSIX
- Confusing it with a Gradle module or a build flavor
- Thinking each target needs its own copy of the shared code