Hierarchy¶
The plugin replaces KGP's default hierarchy template with a minimal one: only the intermediate source sets the registered targets need. Why: Design.
Minimal template¶
| Active targets | Intermediate source sets |
|---|---|
| one iOS leaf | none (target attaches to commonMain) |
| iOS (≥2 leaves) | iosMain only — no appleMain, no nativeMain |
| iOS + macOS | appleMain over iosMain + macosMain — no nativeMain |
| iOS + Linux | nativeMain over iosMain + linuxMain — no appleMain |
The collapse rule: a group materializes a source set only when it merges ≥2 present children; a single-child group collapses away. If that drops a source dir your code needs, see Keeping intermediates.
On by default, applied automatically.
Opting out¶
Opt out when a module supplies its own applyHierarchyTemplate { … } — KGP's default applies again:
# kmp-targets.properties — global default (also accepted via -P, env, gradle.properties,
# local.properties — same precedence chain as kmptargets.targets)
kmptargets.hierarchyTemplate=false
Precedence: project DSL > global key > built-in default (true).
Keeping intermediates¶
Codebases with actual implementations in intermediate source dirs (src/iosMain) break under the collapse: narrowing to a single iOS leaf (-Pkmptargets.targets=iosArm64) drops iosMain from the model and expect declarations stop resolving. No-collapse mode materializes a group whenever it has ≥1 present child, so iosMain survives:
# kmp-targets.properties — global default (same precedence chain as the other keys)
kmptargets.hierarchyCollapse=false
// any module's build.gradle.kts — per-project override; set BEFORE supports { }
kmpTargets {
collapseHierarchy.set(false)
supports { appleMobile }
}
Precedence mirrors hierarchyTemplate: project DSL > global key > built-in default (true, collapse).
Semantics:
- Single-child chains materialize fully (
nativeMain → appleMain → iosMainfor one iOS leaf). The empty intermediates are harmless — no code, nothing to resolve. - Empty groups are still dropped; ungrouped leaves (jvm/android/web) still never form groups.
- The knob never changes what registers — only which intermediate source sets materialize. It is a no-op when
hierarchyTemplateresolves tofalse.
The pinned-intermediates sample is an appleMobile module with collapse off.
Renamed targets¶
KGP's hierarchy matchers (withJvm()) key off the platform type, not the target name — a renamed jvm target attaches to the minimal template exactly as a plain jvm would.