The Kotlin Multiplatform (KMP) technology facilitates the sharing of application code across several platforms.
- Architecture Overview
- Testing the Application
- Intermediate Source Sets
- Adapter
- Relevant Design Choices
The KMP architecture is composed of three main categories:
- Common: Code shared across all platforms (i.e.,
CommonMain
,CommonTest
); - Intermediary: Code that can be shared on a particular set of platforms. See Intermediate Source Sets;
- Specific: Platform-specific code (i.e.,
<Platform>Main
,<Platform>Test
).
The main goal is to maximize code reuse, meaning to aggregate as much code as possible in the Common category. However, sometimes it's necessary to create specific code for a target platform in the following situations:
-
A certain functionality cannot be implemented commonly because:
- It requires access to specific target APIs;
- The libraries available for common code (i.e., Standard Kotlin Library, Kotlinx) do not cover the desired functionalities, and there's no external KMP-compatible library available to be used as a dependency (or it is discouraged to use);
-
A certain target does not directly support KMP (e.g., Node.js), and thus an adapter is needed for the code to be callable from the target.
To create specific code for a target, the expect/actual
mechanism is used, which allows defining the code to be
implemented and its target or sub-target implementation, respectively.
Example:
// commonMain
expect fun platformName(): String
// jvmMain
actual fun platformName(): String = "JVM"
// jsMain
actual fun platformName(): String = "JS"
![]() |
---|
KMP Architecture Overview |
In the KMP template provided by Kotlin,
the example with the fibonacci
sequence was removed
and replaced by a few examples to practice the expect/actual
mechanism more thoroughly.
This addition follows the same principles:
- test common functionality in CommonTest;
- test platform-specific functionality in each platform's test source set (
<Platform>Test
)
To run the tests for all supported targets, use the command:
# from root or within a run configuration
./gradlew :kmp:lib:cleanAllTests :kmp:lib:allTests --rerun-tasks
Intermediate Source Sets enable sharing code across a subset of platforms, allowing for more flexibility in the code sharing strategy.
![]() |
---|
Intermediate Source Set Example |
In the corresponding build.gradle.kts
file, the dependencies between source sets can be configured manually
or by using applyDefaultHierarchyTemplate()
which builds the hierarchy of the provided targets automatically.
Important
Both iOS
and macOs
source sets were removed from this build,
because there is no macOS x86-64
host available for testing, as required by Apple.
The adapter is a module that allows code defined in a KMP project to be called from a target that does not directly support KMP and Kotlin in general.
For demonstration purposes,
a pure JS application was created
to call the adapter
defined in the JsMain
sorceset, essentially acting as a consumer.
To run the application:
- Execute the perl script to link local npm packages in this project.
- Run the server:
node kmp/apps/js-app/src/server.mjs # take a look at the express paths and PORT configured in the server # open an HTTP client and access http://localhost:PORT
For more information about Kotlin and JavaScript interop, see Kotlin-Js Interop section.
As mentioned in this issue, the expect/actual
pattern
should only be used for functions
and interfaces
.
An alternative for this pattern is to use expect fun
+ interface
in the common module.
![]() |
---|
KT-61573 |