kotlin-tooling-native-build-performance

von kotlin

Diagnoses and fixes slow Kotlin/Native compilation and linking in Kotlin Multiplatform projects that target iOS. Use when the user reports slow iOS or…

npx skills add https://github.com/kotlin/kotlin-agent-skills --skill kotlin-tooling-native-build-performance

Kotlin/Native Build Performance

Turn "the iOS build is slow" into a measured diagnosis and a small set of safe fixes. Two rules apply throughout:

  1. Never trade away required release behavior. A faster local loop must not change what CI publishes.
  2. Measure before and after with the same command and the same build state. An unmeasured fix is a guess.

Step 0: Classify the Slow Scenario

Establish four facts before editing anything: where (local or CI), what (debug feedback loop or release/distribution artifact), state (first build, clean, warm, or no-op), and phase (which tasks dominate the log). Then match the dominant symptom:

Symptom in the build logLikely causeRead
linkRelease* or *ReleaseXCFramework tasks in a local development loopBuilding distribution artifacts for developmentartifacts-and-targets
Kotlin/Native compiler distribution downloaded on every CI run~/.konan not preserved between runscaching-and-gradle
Long pause before the first task startsConfiguration phase, no configuration cachecaching-and-gradle
All iOS targets build when only one simulator is neededBroad task (build, assemble, assemble*XCFramework) or unused targetsartifacts-and-targets
ksp* tasks ahead of compileKotlinIos*Generated-code work on the native pathexports-and-generated-code
Small source edit recompiles and relinks everythingCompiler caches disabled, or missing incrementalitycaching-and-gradle, experimental
Machine overloaded while several link* tasks run at onceParallel native linkingcaching-and-gradle, worker-limit caveat

Step 1: Audit and Measure

  1. Run the static audit from the project root:

    scripts/audit-native-build.sh /path/to/project
    

    It is read-only and prints file:line findings (disabled caches, broad local tasks, transitiveExport, broad KSP configuration, missing CI .konan cache), each pointing at the reference file with the fix. Findings are leads, not verdicts — confirm each against project policy.

  2. Find the command the user actually waits for: a script, a CI step, or the Gradle invocation inside an Xcode build phase. Optimize that command, not a task you picked yourself.

  3. Run it twice when practical. The first build downloads Kotlin/Native components and fills caches; only the second and later runs are representative. Attribute time per task before blaming the compiler:

    kotlin.build.report.output=file   # writes build/reports/kotlin-build/
    

    Gradle's --scan or --profile work too.

  4. If you cannot run the build (no macOS host, no Xcode), analyze logs, build scans, or checked-in metrics instead — and state explicitly that the conclusion is static.

Step 2: Fix in Safe Order

Apply fixes one at a time, re-measuring as you go:

  1. Restore healthy defaults — remove cache/daemon workarounds, enable Gradle build and configuration caches, keep ~/.konan warm in CI, update Kotlin: references/caching-and-gradle.md
  2. Build only what the feedback loop needs — one specific task per loop, correct integration method, justified target matrix: references/artifacts-and-targets.md
  3. Cut export and generated-code cost — drop transitiveExport, narrow export(...), scope KSP work to the native compilations that need it: references/exports-and-generated-code.md
  4. Experimental switches last, with the user's agreement: references/experimental.md

Worked Example

A developer on an Apple Silicon Mac complains that "every shared-module change costs 12 minutes". Their loop runs ./gradlew :shared:assembleXCFramework. A build scan of the second (warm) run shows:

:shared:linkReleaseFrameworkIosArm64             348s
:shared:linkReleaseFrameworkIosX64               341s
:shared:compileKotlinIosX64                       96s
:shared:linkDebugFrameworkIosSimulatorArm64       41s
:shared:compileKotlinIosSimulatorArm64            38s
configuration phase                               64s

Reasoning chain:

  • The loop is local + debug + warm, but ~690s goes to linkRelease* — release linking is an order of magnitude slower than debug and only CI needs it. Replace the local command with :shared:linkDebugFrameworkIosSimulatorArm64 (or the Xcode embed task if Xcode drives the build). (artifacts-and-targets)
  • All iosX64 work serves Intel simulators; ask whether the team still supports them before removing the target. (artifacts-and-targets)
  • 64s of configuration on every run disappears behind org.gradle.configuration-cache=true once trialed. (caching-and-gradle)
  • Expected loop after the change: ~40s compile + ~40s link on warm builds — confirm by re-running the new command twice and comparing.
  • CI keeps assembleXCFramework untouched; note that explicitly in the report.

Verify

  • Re-run the exact baseline command; compare warm build against warm build, not warm against cold.
  • Second run with the configuration cache reports it is being reused.
  • The local development log no longer contains linkRelease*, *ReleaseXCFramework, or removed generator tasks.
  • CI still produces every required release artifact, unchanged.
  • Tests pass and the app still runs from Xcode.
  • scripts/audit-native-build.sh reports no findings you have not consciously accepted and documented.

Report Your Changes

Close with a short performance note:

  • The slow scenario (local/CI, debug/release, cold/warm) and the measured evidence — or a statement that the analysis was static.
  • Each change, and why it is safe for release behavior.
  • The before/after commands the user can run to confirm the win.
  • Remaining tradeoffs: experimental flags enabled, targets removed under a policy assumption, worker limits, or generated-code work deferred.
  • Links to the relevant official documentation below.

Official Documentation

TopicLink
Improving Kotlin/Native compilation timehttps://kotlinlang.org/docs/native-improving-compilation-time.html
Kotlin Gradle plugin compilation and cacheshttps://kotlinlang.org/docs/gradle-compilation-and-caches.html
iOS integration methodshttps://kotlinlang.org/docs/multiplatform-ios-integration-overview.html
Direct integration with Xcodehttps://kotlinlang.org/docs/multiplatform/multiplatform-direct-integration.html
Building final native binaries and XCFrameworkshttps://kotlinlang.org/docs/multiplatform/multiplatform-build-native-binaries.html
Kotlin/Native binary optionshttps://kotlinlang.org/docs/native-binary-options.html
KSP with Kotlin Multiplatformhttps://kotlinlang.org/docs/ksp-multiplatform.html

Mehr Skills von kotlin

ci-cd-containerization-advisor
kotlin
Entwerfen Sie reproduzierbare Build-, Image- und Deployment-Pipelines für Kotlin plus Spring-Anwendungen, einschließlich CI-Verifikation, geschichteten Containern, Rollout-Sicherheit,…
official
configuration-properties-profiles-kotlin-safe
kotlin
Design and diagnose Spring configuration, profiles, and `@ConfigurationProperties` binding for Kotlin applications. Use when property binding fails,…
official
dependency-conflict-resolver
kotlin
Diagnose and resolve Gradle and Spring classpath conflicts, version drift, and binary incompatibilities in Kotlin applications. Use when `NoSuchMethodError`,…
official
domain-decomposition-api-design-advisor
kotlin
Geschäftsbereich in begrenzte Kontexte, Modul- oder Servicegrenzen, Workflows und API-Verträge zerlegen, bevor die Implementierung beginnt. Verwenden Sie dies bei der Gestaltung eines neuen…
official
error-model-validation-architect
kotlin
Entwerfen und implementieren Sie konsistentes API-Validierungs- und Fehlerbehandlungsverhalten für Kotlin- und Spring-Dienste. Verwenden Sie es, wenn Sie Fehler-Payloads definieren, Framework-Mapping…
official
gradle-kotlin-dsl-doctor
kotlin
Generate, debug, and repair Kotlin + Spring Gradle builds with minimal, compatible changes. Use when `build.gradle.kts` or `settings.gradle.kts` is failing,…
official
integration-resilience-engineer
kotlin
Entwerfen Sie resiliente HTTP-, Messaging- und geplante Integrationen für Kotlin- und Spring-Dienste mit expliziten Timeout-Budgets, Wiederholungen, Idempotenz, Circuit…
official
jackson-kotlin-serialization-specialist
kotlin
Diagnostizieren und entwerfen Sie das JSON-Serialisierungs- und Deserialisierungsverhalten für Kotlin plus Jackson in Spring-Anwendungen. Verwenden Sie dies, wenn DTOs nicht deserialisiert werden, Standard…
official