Open-Source Wikis

/

Kotlin

/

Compiler

/

Native backend

JetBrains/kotlin

Native backend

Active contributors: Alexander Shabalin, Igor Chevdar, Svyatoslav Scherbina

Kotlin/Native compiles Kotlin to native binaries through LLVM. Unlike the JVM/JS/Wasm backends, the Native backend does not live entirely under compiler/ir/. It is split between kotlin-native/ (the LLVM-driven backend, the C/C++ runtime, and Native-specific build tooling) and native/ (cross-cutting Native infrastructure: commonizer, Swift export, tests). It also has its own build configuration and its own hacking guide.

Purpose

Take lowered Kotlin IR, run Native-specific lowerings, emit LLVM IR via the LLVM C API, link against the C/C++ runtime, and produce an executable or library for one of the supported Native targets (macOS, iOS, Linux, Windows, Android, watchOS, tvOS — currently around a dozen).

Directory layout

kotlin-native/ (the backend itself)

kotlin-native/
├── backend.native/           IR lowerings + LLVM emission (Kotlin code)
├── runtime/                  C/C++ runtime: GC, exceptions, ObjC interop
├── llvmDebugInfoC/           Debug-info bridges to LLVM
├── llvmInterop/              Kotlin interop with libLLVM
├── libllvmext/               Patched LLVM utilities
├── libclangInterop/          Bindings to libclang (used for header parsing)
├── libclangext/              Patched libclang utilities
├── platformLibs/             Pre-built klibs for platform APIs (UIKit, ...)
├── endorsedLibraries/        Bundled additional libraries
├── Interop/                  C interop (cinterop) tooling
├── cmd/                      kotlinc-native command-line driver
├── tools/                    Native dev tools (klib inspect, ...)
├── utilities/                Build utilities
├── samples/                  Native sample projects
├── HACKING.md                Onboarding for the Native backend
└── README.md                 High-level overview

native/ (cross-cutting Native code)

native/
├── commonizer/               Tool that merges per-platform klibs into a "common" klib
├── commonizer-api/, commonizer-embeddable/
├── swift/                    Swift export: produce a Swift API from a Kotlin module
├── objcexport-header-generator/  Objective-C header generator
├── frontend/                 Native-specific FE bits
├── cli-native/               kotlinc-native frontend → Native backend glue
├── native.config/            Native-specific compiler config
├── native.tests/             Native end-to-end tests
├── kotlin-test-native-xctest/  Bridge from kotlin-test to XCTest (iOS)
├── unsafe-mem/               Unsafe memory APIs for Native
├── binary-options/           Native-specific binary options
├── analysis-api-based-export-common/  Analysis API based exports
├── analysis-api-based-test-utils/     Analysis API based test utilities
├── external-projects-test-utils/      Test utils for external projects
├── base/, executors/, utils/ Shared utilities
└── analysis-api-based-test-utils/

Key abstractions

Type Where Role
KonanBackendContext kotlin-native/backend.native/... Native backend state. (Konan is the historical Native project name; you'll see "konan" throughout.)
LLVMValueRef, LLVMTypeRef, ... kotlin-native/llvmInterop/ Bindings to the LLVM C API.
RuntimeAware kotlin-native/runtime/... C/C++ runtime entry points (alloc, GC, exceptions).
Commonizer native/commonizer/... Produces "common" klibs by merging per-platform variants.

How Native compilation works

graph LR
    IR["Lowered Kotlin IR"] --> NativeLower["Native lowerings<br/>kotlin-native/backend.native"]
    NativeLower --> LLVMIR["LLVM IR"]
    LLVMIR --> LLVM["LLVM optimizer + codegen"]
    LLVM --> Obj["Object files"]
    Obj --> Link["Native linker (ld/lld/...)"]
    Runtime["Kotlin/Native runtime<br/>(kotlin-native/runtime)"] --> Link
    Link --> Bin["Native binary / .framework"]

Each compilation unit becomes a klib (Kotlin Library) — same format as JS/Wasm, just with different runtime. Klibs are linked into a final binary by the Native linker, with the Kotlin/Native runtime statically linked in.

The runtime

kotlin-native/runtime/ is a substantial body of C++ code implementing:

  • The garbage collector (mostly a concurrent mark-and-sweep with a young generation).
  • Exception handling.
  • Workers (the Kotlin/Native concurrency primitive).
  • Memory model machinery (atomic ops, freeze/thaw — the latter for the legacy memory model).
  • Objective-C interop (the bridge that lets Kotlin classes implement ObjC protocols, and vice versa).

This is one of the few large C++ pieces in the repo (~37,000 LOC of .cpp, plus ~70,000 LOC of .h).

C interop (cinterop)

kotlin-native/Interop/ and kotlin-native/libclangInterop/ together implement cinterop, the tool that converts a C/Objective-C header into a Kotlin klib. This is how Kotlin/Native binds to UIKit, AppKit, the C standard library, third-party C libraries, etc. It uses libclang to parse the headers and emits a klib with external Kotlin declarations.

Commonizer

native/commonizer/ solves a Multiplatform problem: when you target several platforms (e.g., iosX64, iosArm64, iosSimulatorArm64), each ships a slightly different platform klib (different signatures for pthread_*, different sizes of types). The commonizer compares the per-platform klibs and produces a single "common" klib whose declarations match those that are identical across all platforms. User Multiplatform code can then expect/actual against the common klib.

Swift export

native/swift/ and native/objcexport-header-generator/ produce Swift/Objective-C headers from a Kotlin module so iOS/macOS apps can call Kotlin code natively. This is the path Kotlin Multiplatform Mobile (KMM) uses on Apple platforms.

Build environment

kotlin-native/ builds with Groovy Gradle, not the Kotlin DSL — see kotlin-native/build.gradle. It pulls in a vendored LLVM (under kotlin-native/dependencies/) and requires platform-specific toolchains (Xcode, Visual Studio, glibc/musl) to produce binaries for each supported target. Read kotlin-native/HACKING.md and kotlin-native/BUILDING_LLVM.md before your first build.

Integration points

  • Input: lowered Kotlin IR + Kotlin/Native frontend additions.
  • Output: Native binaries (.kexe), .framework bundles, .dylib/.so/.dll libraries, klibs.
  • Used by: compiler/cli/cli-native-klib/, kotlin-native/cmd/kotlinc-native, KGP's kotlin("multiplatform") Native targets.
  • Tested by: native/native.tests/ and kotlin-native/backend.native/tests/.

Where to start

For a Kotlin-side change, kotlin-native/backend.native/ (under its compiler/ subdirectory) is the analog of compiler/ir/backend.jvm/. For a runtime-level concern (GC, exception handling), kotlin-native/runtime/. For C interop, kotlin-native/Interop/. The HACKING.md file is required reading.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Native backend – Kotlin wiki | Factory