What does applyDefaultHierarchyTemplate() do, and when do you still need to define intermediate source sets manually?
answer
- Auto-creates standard intermediate sets + dependsOn
- Only materializes sets you have targets for
- Implicit when using standard targets only
- Manual for jvmAndAndroidMain custom groupings
- Don't half-mix template + manual on same set
basics
~20 sIt auto-creates the standard tree of intermediate source sets (like nativeMain, appleMain, iosMain) and wires them with dependsOn, based on the targets you declared. You only hand-write a set when you need a non-standard grouping the template does not provide.
solid answer
~40 s`applyDefaultHierarchyTemplate()` applies Kotlin's built-in **default hierarchy template**: given your declared targets it generates the conventional intermediate source sets — e.g. `nativeMain` for all native targets, `appleMain`, `iosMain`, `tvosMain`, etc. — and wires every `dependsOn` automatically. In recent Kotlin it is applied implicitly when you use only standard targets and don't define your own hierarchy, so calling it is often optional but explicit-is-clearer. You still wire sets manually for groupings the template doesn't model, the canonical case being `jvmAndAndroidMain` shared by JVM and Android (the template keeps those separate). If you call it and *also* manually create a set the template owns, you risk conflicting wiring, so customize via the template DSL or accept the manual route consistently. The template only materializes a set if at least one declared target uses it.
code
kotlin · 13 lineskotlin {
applyDefaultHierarchyTemplate()
jvm()
androidTarget()
iosArm64()
iosX64()
sourceSets {
// iosMain auto-created; we add a custom JVM+Android group manually
val jvmAndAndroidMain by creating { dependsOn(commonMain.get()) }
jvmMain.get().dependsOn(jvmAndAndroidMain)
androidMain.get().dependsOn(jvmAndAndroidMain)
}
}go deeper
Knows the template saves manual dependsOn boilerplate.
Explains which sets it creates, the implicit-application rule, and the jvmAndAndroidMain exception.
Discusses conflict pitfalls and customizing via the template DSL lambda.
Weighs declarative template customization vs. fully manual hierarchies for large multi-target codebases.
## The problem it solves Before the template, every project hand-wrote `dependsOn` chains: `iosArm64Main.dependsOn(iosMain)`, `iosMain.dependsOn(nativeMain)`, and so on — verbose and error-prone. ## What `applyDefaultHierarchyTemplate()` does It applies Kotlin's **default hierarchy template**, a predefined tree of intermediate source sets. Based on the targets you declared, it: - **Creates** the conventional intermediate sets that apply, e.g. `nativeMain`, `appleMain`, `iosMain`, `tvosMain`, `watchosMain`, `macosMain`, `linuxMain`, `mingwMain` — and their `*Test` counterparts. - **Wires** all `dependsOn` edges (leaf → group → … → `commonMain`). - Only **materializes a set when relevant**: `iosMain` appears only if you declared at least one iOS target. ```kotlin kotlin { applyDefaultHierarchyTemplate() iosArm64(); iosX64(); macosArm64() // auto: iosMain, appleMain, nativeMain created & wired sourceSets { appleMain.dependencies { /* shared by iOS + macOS */ } } } ``` ## Implicit application With recent Kotlin Gradle plugin versions, the template is **applied automatically** when you use only standard targets and have **not** declared your own hierarchy or manually called `dependsOn`. Calling it explicitly is still recommended for clarity and to silence warnings when mixing. ## When you still go manual The template models *platform-family* groupings, not arbitrary ones. You wire `dependsOn` by hand for non-standard sets: - **`jvmAndAndroidMain`** — the classic: share `java.*`-based code across JVM and Android (the template keeps `jvmMain` and `androidMain` separate). - Any bespoke subset like 'all targets that have a filesystem'. ## Conflict pitfall If you call the template **and** manually create/own a set it already manages, you can get duplicate `dependsOn` edges or compiler warnings. Either customize through the template DSL (`applyDefaultHierarchyTemplate { ... }`) or define a fully custom hierarchy — don't half-mix. ## Customizing the template You can pass a lambda to extend it (e.g. add a `jvmAndAndroidMain` group) rather than wiring raw `dependsOn`, keeping everything declarative.
- Will applyDefaultHierarchyTemplate() create iosMain if you declared no iOS targets?No. It materializes only the sets relevant to your declared targets, so iosMain appears only when an iOS target exists.
- Why is jvmAndAndroidMain not created automatically?The template models platform-family groupings; JVM and Android stay separate, so a shared java.* set is a custom grouping you must wire or add via the template lambda.
saying these in an interview costs you the question
- Thinking it creates every possible set regardless of targets
- Manually re-creating a set the template already owns
- Believing it can produce jvmAndAndroidMain out of the box
- Not knowing it can be applied implicitly