12.4.9 在 Kotlin Multiplatform 中使用 KSP

原文链接: https://kotlinlang.org/docs/ksp-multiplatform.html

12.4.9 在 Kotlin Multiplatform 中使用 KSP

这里你将了解如何在 Kotlin Multiplatform 项目中使用 Kotlin Symbol Processing(KSP)。关于快速上手,请查看源代码仓库中一个包含多个目标并使用 KSP 的多平台项目示例。该示例中的处理器会生成项目所使用的 Foo 类。

把 KSP 添加到多平台项目

在客户端模块(即使用处理器的模块)的 build.gradle.kts 文件中,为每个需要符号处理的目标添加相应的 KSP 处理器依赖:

dependencies {
  add("ksp<Target>", <processor>)
}
  • <Target> 是你的多平台项目所使用的目标之一。

提示: 目标的完整列表请参阅 Multiplatform Gradle DSL 参考和 Kotlin/Native 支持的目标。

  • <processor> 是一个 Gradle 项目路径。它可以是:

  • 项目中包含符号处理器逻辑的某个特定目录:

      add("kspJvm", project(":local-processor"))
  • 外部处理器,例如 Room:
      add("kspJvm", "androidx.room:room-compiler:2.6.1")

警告: 从 KSP 2 开始,包罗万象的 ksp(...) 配置已被弃用。请显式配置每个目标,以避免在不需要的地方运行处理器。

在单个目标中使用多个处理器

你可以为一个目标添加多个处理器:

Kotlin

1
2
add("kspAndroid", project(":test-processor"))
add("kspAndroid", "androidx.room:room-compiler:2.6.1")

Groovy

1
2
add('kspAndroid', project(':test-processor'))
add('kspAndroid', 'androidx.room:room-compiler:2.6.1')

在多个目标中使用同一个处理器

你可以把同一个处理器添加到多个目标:

Kotlin

1
2
3
add("kspIosX64", project(":test-processor"))
add("kspIosArm64", project(":test-processor"))
add("kspIosSimulatorArm64", project(":test-processor"))

Groovy

1
2
3
add('kspIosX64', project(':test-processor'))
add('kspIosArm64', project(':test-processor'))
add('kspIosSimulatorArm64', project(':test-processor'))

如果你有很多 iOS 目标,可以通过循环来避免重复:

Kotlin

1
2
3
4
5
6
kotlin.targets.filter { it.name.startsWith("ios") }.forEach { target ->
    add(
        "ksp${target.name.replaceFirstChar { it.uppercaseChar() }}",
        project(":test-processor")
    )
}

Groovy

1
2
3
4
5
6
kotlin.targets.filter { it.name.startsWith("ios") }.forEach { target ->
    add(
        "ksp${target.name.replaceFirstChar { it.uppercaseChar() }}",
        project(":test-processor")
    )
}

为测试编译配置 KSP

要在测试编译期间运行 KSP,请把处理器添加到相应的测试配置中:

Kotlin

1
2
3
add("kspJvmTest", project(":test-processor"))
add("kspJsTest", project(":test-processor"))
add("kspIosX64Test", project(":test-processor"))

Groovy

1
2
3
add('kspJvmTest', project(':test-processor'))
add('kspJsTest', project(':test-processor'))
add('kspIosX64Test', project(':test-processor'))

对于 Android 的宿主端测试和设备端测试,KSP 会根据相应的源集名称推导配置名称:

Kotlin

1
2
add("kspAndroidHostTest", project(":test-processor"))
add("kspAndroidDeviceTest", project(":test-processor"))

Groovy

1
2
add('kspAndroidHostTest', project(':test-processor'))
add('kspAndroidDeviceTest', project(':test-processor'))

查找 KSP 配置名称

KSP 会根据 Kotlin Multiplatform 的源集推导配置名称。要查看某个模块的 KSP 配置完整列表,请运行:

1
./gradlew :<your-module-name>:dependencies | grep ksp

请查找与你的目标源集相对应的配置名称。

编译与处理

在多平台项目中,Kotlin 会为每个目标和源集(例如 main 和 test)创建单独的编译。对于每个配置了一个或多个 KSP 处理器的 Kotlin 编译任务,KSP 都会创建一个相应的符号处理任务。

该示例项目定义了六个目标。每个目标都有 main 和 test 编译,从而产生以下编译和符号处理任务:

  • JVM:jvmMain 和 jvmTest

  • JS:jsMain 和 jsTest

  • LinuxX64:linuxX64Main 和 linuxX64Test

  • AndroidNativeX64:androidNativeX64Main 和 androidNativeX64Test

  • AndroidNativeArm64:androidNativeArm64Main 和 androidNativeArm64Test

  • MingwX64:mingwX64Main 和 mingwX64Test

在示例的 workload/build.gradle.kts 文件中,KSP 依赖声明在以下配置中:

  • kspJvm 和 kspJvmTest
  • kspJs 和 kspJsTest
  • kspAndroidNativeX64 和 kspAndroidNativeX64Test
  • kspAndroidNativeArm64 和 kspAndroidNativeArm64Test
  • kspLinuxX64
  • kspMingwX64

KSP 会为每个声明了 KSP 依赖的配置创建一个符号处理任务。在这个例子中,项目至少创建 12 个 Kotlin 编译任务和 10 个符号处理任务。其余编译没有对应的 KSP 任务,因为没有为它们配置 KSP。