Multiplatform
Kotlin Multiplatform compiles shared Kotlin to JVM, Native, JS, and Wasm, using expect/actual and a source-set hierarchy to isolate what genuinely differs per platform. It comes up for mobile teams sharing logic between Android and iOS.
part ofKotlinoverview, primer and where to startread it →on this pageshowhide
explore
- How Kotlin Does Multiplatform5 questions
- expect / actual Declarations15 questions
- expect / actual Functions5 questions
- expect / actual Classes & Objects5 questions
- actual typealias5 questions
- Source Sets20 questions
- Source-Set Hierarchy5 questions
- commonMain & commonTest5 questions
- Intermediate Source Sets5 questions
- Per-Target Dependency Declaration5 questions
- Compilation Targets25 questions
- Kotlin/JVM Target5 questions
- Kotlin/Native Target5 questions
- Kotlin/JS (IR) Target5 questions
- Kotlin/Wasm Target5 questions
- Android & iOS Targets5 questions
- Kotlin/Native Mechanics20 questions
- New Memory Manager5 questions
- C / Objective-C / Swift Interop (cinterop)5 questions
- @Throws on Native5 questions
- Concurrency on Native5 questions
- Multiplatform Libraries16 questions
- Multiplatform stdlib Subset6 questions
- kotlinx Multiplatform Libraries5 questions
- Platform-Specific Implementations5 questions
- JavaScript Interop10 questions
- external & dynamic5 questions
- @JsExport & JS Module Systems5 questions
questions
111 · 7 sectionsWhat is Kotlin Multiplatform (KMP), and what does it let you share across platforms?
basics
~10 sKotlin Multiplatform lets you write code once and run it on many platforms. You put shared code in one place, and the compiler builds it into apps for Android, iOS, web, and the desktop.
How do expect/actual declarations work, and what are their rules and limits?
basics
~10 sexpect/actual is how common code says 'something with this shape exists' and each platform fills in the real version. Common code declares expect; every target must provide a matching actual.
Explain the KMP source-set hierarchy and how intermediate source sets like appleMain enable code sharing.
basics
~10 sSource sets form a tree. commonMain is the root every target uses. Intermediate sets like appleMain group related targets (iOS, macOS) so you can share code among them without duplicating it per target.
How do you decide what belongs in commonMain versus platform code, and what architectural patterns keep the boundary clean?
basics
~10 sPut logic that doesn't depend on a specific platform (rules, data, networking) in commonMain. Put things that touch a device API in platform code. Hide platform details behind interfaces so common code stays clean.
What compilation targets does KMP support, and what artifact does each produce?
basics
~10 sA target is a platform you build for. JVM produces bytecode, Native produces machine-code binaries (like an iOS framework), JS produces JavaScript, and Wasm produces WebAssembly. You declare targets in Gradle.
In a Kotlin Multiplatform project, what does `actual typealias UUID = java.util.UUID` do, and why would you use it instead of writing an `actual class`?
basics
~10 sIt says: on this platform, the shared expect class UUID is exactly the platform's own UUID type. You reuse an existing native type directly instead of writing a wrapper class around it.
In Kotlin Multiplatform, what does declaring `expect class Platform` in common code and `actual class Platform` in a platform source set mean? Give a minimal example.
basics
~20 sYou write a placeholder class in shared code that says 'this exists, here's its shape.' Each platform (Android, iOS) then provides the real version with the same name and members. Shared code uses it without knowing the platform.
What are `expect` and `actual` functions in Kotlin Multiplatform, and how do you use them to expose platform-specific behavior through a common API?
basics
~20 sIn shared code you write expect fun with no body, like a promise. Each platform (Android, iOS, JVM, JS) provides the real actual fun. Common code calls the function without knowing which platform fills it in.
What are the matching rules between an `expect class` and its `actual class`? Cover constructors, members, supertypes, and the case where the actual carries members the expect did not declare.
basics
~20 sThe actual must have the same name, package, and matching constructors and members the expect declared, each marked actual. The actual is allowed to add extra members and extra supertypes, but those extras are invisible from shared code.
What are the exact matching rules between an `expect fun` and its `actual fun`? Where do default parameter values and type parameters go?
basics
~20 sThe actual function must have the same name, the same parameters and return type, and at least the same visibility. Default values and type parameters are written only on the expect side, not repeated on actual.
In a Kotlin Multiplatform project, what is the `commonMain` source set and what kind of code belongs in it?
basics
~10 scommonMain holds shared code that compiles to every target (JVM, iOS, JS, etc.). Put platform-independent logic there. It can only use APIs available on all targets.
In a Kotlin Multiplatform project, what is an intermediate source set such as iosMain, and why would you create one?
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.
In a Kotlin Multiplatform Gradle build, where do you declare a dependency on a library that works on every target, and where do you declare one that only exists on the JVM?
basics
~10 sPut shared dependencies in commonMain, inside the kotlin sourceSets block. Put a JVM-only library in jvmMain. Each source set only sees the libraries declared for it or its parents.
In a Kotlin Multiplatform project, what does it mean that platform source sets `dependsOn` commonMain, and why is this relationship special compared to a regular library dependency?
basics
~10 sPlatform code like jvmMain depends on commonMain. This lets shared code declare a feature and each platform fill in the missing parts. It is a special link, not a normal library dependency.
How do you write shared tests for a KMP module, and what role does `commonTest` and the `kotlin.test` library play?
basics
~10 sPut shared tests in commonTest and use the kotlin.test library. Those tests run once per target, so a single test verifies behavior on JVM, iOS, JS, etc.
In a Kotlin Multiplatform module, what artifact does the androidTarget() produce versus the iosArm64()/iosSimulatorArm64() targets, and how does each get consumed?
basics
~10 sandroidTarget() builds an Android library (an AAR) that Android apps use. The iOS targets build a native framework that an Xcode/Swift app imports. Same Kotlin code, two different output packages.
What is the Kotlin/JS IR target, and how do you enable it in a Gradle build with browser() and nodejs() environments?
basics
~10 sKotlin/JS lets you compile Kotlin code into JavaScript. The IR target is the modern compiler backend. In Gradle you add js(IR) and pick browser() or nodejs() depending on where the code runs.
In a Kotlin Multiplatform build, what does declaring the jvm() target do, and what kind of artifacts does it produce?
basics
~10 sAdding jvm() tells the compiler to build a JVM version of your code. It produces Java bytecode (.class files, usually packaged in a .jar) that runs on any Java Virtual Machine.
What is the Kotlin/Native target, and how does running a Kotlin/Native binary differ from running Kotlin on the JVM?
basics
~10 sKotlin/Native compiles Kotlin straight to a native machine-code program. There is no Java Virtual Machine running it; you get a standalone executable or library that runs directly on the operating system.
What are the wasmJs() and wasmWasi() targets in a Kotlin Multiplatform project, and how do they differ?
basics
~10 sThey are two Kotlin Multiplatform targets that compile code to WebAssembly. wasmJs() runs in the browser and can talk to JavaScript; wasmWasi() runs in standalone runtimes outside the browser using the WASI system interface.
What is the cinterop tool in Kotlin/Native, and what role does a .def file play when binding to a C library?
basics
~10 scinterop is a Kotlin/Native tool that reads C header files and produces Kotlin code so you can call the C library from Kotlin. A .def file tells it which headers and library to use.
What is the 'new memory manager' in Kotlin/Native, and what old model did it replace?
basics
~10 sIt is Kotlin/Native's modern garbage collector. It replaced an old rule that froze objects and locked them to one thread. Now you can share regular mutable objects across threads, like on the JVM.
What does the @Throws annotation do when a Kotlin/Native function is called from Swift or Objective-C, and what happens to an exception that isn't listed?
basics
~10 s@Throws tells the Kotlin compiler which exceptions should be passed to Swift or Objective-C as errors instead of crashing. Any exception you don't list will crash the whole app.
Explain memScoped, CPointer, and how you pass a C struct or an out-parameter to a C function from Kotlin/Native.
basics
~20 smemScoped gives you a temporary native memory area that is freed when the block ends. Inside it you allocate C structs and get CPointers to them, which you can pass to C functions, including as out-parameters the C code fills in.
In a Kotlin Multiplatform project, what does it mean that the standard library is available in commonMain, and which kinds of APIs can you safely call there?
basics
~20 scommonMain is shared code that compiles to every target. There you can use the common part of Kotlin's standard library — lists, maps, math, random, strings, numbers — but not platform-only things like Java's File or full Java reflection.
Which core kotlinx libraries are commonly added to commonMain in a Kotlin Multiplatform project, and what does each provide?
basics
~10 sThe main ones are kotlinx-coroutines-core for async work, kotlinx-serialization for turning objects to/from JSON, kotlinx-datetime for dates and times, and kotlinx-io for reading and writing bytes. All work in shared code.
In Kotlin Multiplatform, what do the `expect` and `actual` keywords do, and why does a library use them to back one common API across targets?
basics
~10 sexpect declares a shared API in common code with no body; each platform (Android, iOS, JS) provides an actual implementation. So you call one function everywhere and the right platform version runs.
Explain Kotlin's read-only vs. mutable collection interfaces (List vs MutableList, etc.) and how the collection builders like buildList relate to them.
basics
~20 sList, Set and Map are read-only views — they have no add/remove. MutableList, MutableSet, MutableMap add modification methods. buildList gives you a mutable list to fill in a lambda and returns it as a read-only List.
How does kotlinx-serialization work in common code, and why is it suitable for multiplatform while reflection-based libraries are not?
basics
~20 sYou mark a class with @Serializable and a compiler plugin generates the conversion code at build time. Because it doesn't use runtime reflection, it works on platforms like iOS and JS where reflection isn't available.
What does the @JsExport annotation do in Kotlin/JS, and why do you need it before JavaScript or TypeScript code can call your Kotlin declaration?
basics
~20 sBy default Kotlin renames things when it compiles to JavaScript, so JS code can't find them. Adding @JsExport keeps the real names and generates TypeScript type info, so JS/TS can call your class or function.
In Kotlin/JS, what is the `external` keyword for, and why do `external` declarations have no body?
basics
~10 sexternal tells the Kotlin compiler that something already exists in JavaScript and is implemented there. You only write its type signature, no body, so Kotlin can type-check your calls without re-implementing it.
Which Kotlin types are 'exportable' across an @JsExport boundary, and what happens if you use a non-exportable type like Long or a Kotlin collection in an exported signature?
basics
~20 sOnly simple, JS-friendly types are allowed: numbers, String, Boolean, arrays, function types, and your own exported classes. Things like Long or Kotlin's List aren't exportable, so the compiler warns or errors and the .d.ts gets a fallback type.
What is the `dynamic` type in Kotlin/JS, and how does it change the compiler's behavior compared with a normal typed value?
basics
~20 sdynamic is a special Kotlin/JS type that turns off compile-time checks. You can read any property or call any method on it and the compiler won't complain — correctness is your responsibility, checked only at runtime by JavaScript.
Compare @JsName, @JsModule, and @JsExport. When would you reach for each, especially to import from an npm package?
basics
~10 s@JsExport sends Kotlin OUT to JS. @JsName renames a symbol so it matches a specific JS name (both directions). @JsModule says 'this Kotlin declaration actually lives in an npm package', importing JS INTO Kotlin.