Here you can learn how to use Kotlin Symbol Processing (KSP) in a Kotlin Multiplatform project. For a quick start, see
an example of a multiplatform project with several targets using KSP in the
source repository. The processor in this example
generates a Foo class used by the project.
In the client module's build.gradle.kts file, assign a processor to each target that needs symbol processing in the
dependencies {} block:
add("ksp<Target>", <processor>)
<Target> is one of the targets used in your multiplatform project. For a full list of targets, see
Multiplatform Gradle DSL reference
and Kotlin/Native supported targets.
<processor> is a Gradle project path. It can be:
-
a specific directory in your project that contains the logic for your symbol processor:
add("kspJvm", project(":local-processor")) -
an external processor such as Room:
add("kspJvm", "androidx.room:room-compiler:2.6.1")
A single target can have multiple processors:
add("kspAndroid", project(":test-processor"))
add("kspAndroid", "androidx.room:room-compiler:2.6.1")add('kspAndroid', project(':test-processor'))
add('kspAndroid', 'androidx.room:room-compiler:2.6.1')The same processor can be used in multiple targets:
add("kspIosX64", project(":test-processor"))
add("kspIosArm64", project(":test-processor"))
add("kspIosSimulatorArm64", project(":test-processor"))add('kspIosX64', project(':test-processor'))
add('kspIosArm64', project(':test-processor'))
add('kspIosSimulatorArm64', project(':test-processor'))If you have many iOS targets, you can avoid repetition by looping:
kotlin.targets.filter { it.name.startsWith("ios") }.forEach { target ->
add(
"ksp${target.name.replaceFirstChar { it.uppercaseChar() }}",
project(":test-processor")
)
}kotlin.targets.filter { it.name.startsWith("ios") }.forEach { target ->
add(
"ksp${target.name.replaceFirstChar { it.uppercaseChar() }}",
project(":test-processor")
)
}You can also configure KSP for test compilations:
add("kspJvmTest", project(":test-processor"))
add("kspJsTest", project(":test-processor"))
add("kspIosX64Test", project(":test-processor"))add('kspJvmTest', project(':test-processor'))
add('kspJsTest', project(':test-processor'))
add('kspIosX64Test', project(':test-processor'))For Android host and device tests, KSP derives configuration names from the corresponding source set names:
add("kspAndroidHostTest", project(":test-processor"))
add("kspAndroidDeviceTest", project(":test-processor"))add('kspAndroidHostTest', project(':test-processor'))
add('kspAndroidDeviceTest', project(':test-processor'))KSP configuration names depend on the source set names generated by the Kotlin plugin. To view the complete list of KSP configurations for a module, run:
./gradlew :<your-module-name>:dependencies | grep kspLook for the configuration names that correspond to your target source sets.
Since KSP 2, the catch-all
ksp(...)configuration is deprecated. Configure each target explicitly to avoid running processors where they are not needed.
{style="note"}
In a multiplatform project, Kotlin creates a separate compilation
for each target and source set, such as main andtest. For every eligible Kotlin compilation task, KSP creates a
corresponding symbol processing task.
The example project defines six targets:
- JVM
- JS
- Linux X64
- Android Native X64
- Android Native Arm64
- Mingw X64
Each of these targets includes a main and a test compilation. As a result, the project creates at least 12 Kotlin
compilation tasks.
In the example's workload/build.gradle.kts file, KSP dependencies are declared for the following configurations:
kspJvmandkspJvmTestkspJsandkspJsTestkspAndroidNativeX64andkspAndroidNativeX64TestkspAndroidNativeArm64andkspAndroidNativeArm64TestkspLinuxX64kspMingwX64
KSP creates a symbol processing task for each configuration where a KSP dependency is declared. In this example, the project creates at least 12 Kotlin compilation tasks and 10 symbol processing tasks. The remaining compilations don't have corresponding KSP tasks because KSP isn't configured for them.