kapt 编译器插件
Kotlin 使用 kapt 编译器插件来支持注解处理器(参见 JSR 269). 译注: kapt 是 "Kotlin annotation processing tool" 的缩写
简单地说, 你可以在 Kotlin 项目中使用 Dagger 或 Data Binding 之类的库.
关于如何在你的 Gradle/Maven 编译脚本中使用 kapt 插件, 请阅读下文.
在 Gradle 中使用
执行以下步骤:
应用
kotlin-kapt
Gradle plugin:plugins { kotlin("kapt") version "2.0.21" }plugins { id "org.jetbrains.kotlin.kapt" version "2.0.21" }在你的
dependencies
块中使用kapt
配置来添加对应的依赖:dependencies { kapt("groupId:artifactId:version") }dependencies { kapt 'groupId:artifactId:version' }如果你以前对注解处理器使用过 Android support, 请将使用
annotationProcessor
配置的地方替换为kapt
. 如果你的工程中包含 Java 类,kapt
也会正确地处理这些 Java 类.如果你需要对
androidTest
或test
源代码使用注解处理器, 那么与kapt
配置相对应的名称应该是kaptAndroidTest
和kaptTest
. 注意,kaptAndroidTest
和kaptTest
从kapt
继承而来, 因此你只需要提供kapt
的依赖项, 它可以同时用于产品代码和测试代码.
试用 Kotlin K2 编译器
从 Kotlin 1.9.20 开始, 你可以对 K2 编译器 试用 kapt 编译器插件, K2 编译器带来了性能改进和很多其它优点. 要在你的项目中使用 K2 编译器, 请在你的 gradle.properties
文件中添加以下选项:
如果你在对 K2 编译器使用 kapt 插件时遇到任何问题, 请报告到我们的 问题追踪系统.
注解处理器的参数
可以使用 arguments {}
代码段来传递参数给注解处理器:
支持 Gradle 编译缓存
kapt 注解处理任务默认情况下不会 被 Gradle 缓存. 因为注解处理器可以运行任意代码, 并不一定只是将编译任务的输入文件转换为输出文件, 它还可能访问并修改未被 Gradle 追踪的其他文件. 如果确实需要为 kapt 启用 Gradle 编译缓存, 请将以下代码加入到你的编译脚本中:
改进使用 kapt 时的构建速度
并行运行多个 KAPT 任务
为了改进使用 kapt 时的构建速度, 你可以对 kapt 任务启用 Gradle Worker API. 使用 Worker API 可以让 Gradle 并行运行单个项目中的多个独立的注解处理任务, 某些情况下能够显著缩短运行时间.
如果在 Kotlin Gradle 插件中使用了 自定义 JDK home 功能, kapt 任务执行器只会使用 进程隔离模式. 注意, kapt.workers.isolation
属性会被忽略.
如果你想要对 kapt worker 进程指定额外的 JVM 参数, 请使用 KaptWithoutKotlincTask
的输入参数 kaptProcessJvmArgs
:
注解处理器的 classloader 缓存
如果连续执行很多 Gradle 任务, 注解处理器的 classloader 缓存功能可以帮助 kapt 提高运行速度.
要启用这个功能, 可以在你的 gradle.properties
文件中使用以下属性:
如果你遇到与注解处理器缓存相关的问题, 可以对这些处理器关闭缓存:
测量注解处理器的性能
可以使用 -Kapt-show-processor-timings
plugin 选项得到注解处理器执行时的性能统计. 输出示例:
你可以使用 plugin 选项 -Kapt-dump-processor-timings
(org.jetbrains.kotlin.kapt3:dumpProcessorTimings
), 将这个报告输出到一个文件. 以下命令将会运行 kapt, 并将统计报告输出到 ap-perf-report.file
文件:
测量注解处理器生成的文件数量
kotlin-kapt
Gradle plugin 可以对每个注解处理器统计生成的文件数量.
这个功能可以用于追踪构建过程中是否存在未使用的注解处理器. 你可以使用生成的报告来寻找哪些模块触发了不必要的注解处理器, 然后更新这些模块, 不再触发这些注解处理器.
使用以下步骤启用这个统计功能:
在你的
build.gradle(.kts)
文件中, 将showProcessorStats
flag 设置为true
:kapt { showProcessorStats = true }在你的
gradle.properties
文件中, 将kapt.verbose
Gradle 属性设置为true
:kapt.verbose=true
统计结果将出现在日志中, 级别为 info
. 你将会看到 Annotation processor stats:
行, 之后是每个注解处理器的执行时间统计. 再后面, 将是 Generated files report:
行, 之后是每个注解处理器生成的文件数量统计. 比如:
对 KAPT 使用编译回避功能
为了改进使用 kapt 时的增量构建次数, 可以使用 Gradle 的 编译回避(compile avoidance) 功能. 启用编译回避时, Gradle 可以在重新构建项目时跳过注解处理任务. 具体来说, 在以下情况下会跳过注解处理任务:
项目的源代码文件没有变化.
依赖项目中的变更满足 ABI 兼容. 比如说, 变更只发生在方法体之内, 而方法接口没有变更.
但是, 编译回避不能用于编译类路径中发现的注解处理器, 因为它们的 任何变更 都需要运行注解处理任务.
要使用编译回避模式运行 kapt, 你需要:
对
kapt*
配置手工添加注解处理器依赖项目, 具体方法参见 上文.不要在编译类路径中查找注解处理器, 方法是在你的
gradle.properties
文件中添加以下代码:
增量式(Incremental)注解处理
kapt 支持增量式(Incremental)注解处理, 这个功能默认启用. 目前, 只有当所有注解处理器都以增量模式使用时, 注解处理才可以增量式运行.
要关闭增量式注解处理, 请在你的 gradle.properties
文件添加以下代码:
注意, 增量式注解处理同时还需要启用 增量式编译(Incremental Compilation).
从父配置(superconfiguration)继承注解处理器
你可以在一个单独的 Gradle 配置中, 定义注解处理器的一组共通设置, 作为父配置(superconfiguration), 然后对你的子项目扩展这些父配置, 进行更多的 kapt 相关的配置.
例如, 对一个使用 Dagger 的子项目, 在你的 build.gradle(.kts)
文件中, 使用下面的配置:
在这个示例中, commonAnnotationProcessors
Gradle 配置, 是你想要在所有的项目中使用的, 关于注解处理的共通父配置. 你使用 extendsFrom()
方法, 将 commonAnnotationProcessors
添加为一个父配置. kapt 看到 commonAnnotationProcessors
Gradle 配置存在对 Dagger 注解处理器的依赖项. 因此, kapt 会在它关于注解处理的配置中包含 Dagger 注解处理器.
Java 编译器选项
kapt 使用 Java 编译器来运行注解处理器. 下面的例子是, 如何向 javac 传递任意的参数:
对不存在的类型进行纠正
有些注解处理库(比如 AutoFactory
), 依赖于类型声明签名中的明确的数据类型. 默认情况下, kapt 会将所有的未知类型替换为 NonExistentClass
, 包括编译产生的类的类型信息, 但是你可以修改这种行为. 在 build.gradle(.kts)
文件中添加一个选项, 就可以对桩代码中推断错误的数据类型进行修正:
在 Maven 中使用
在 compile
之前, 执行 kotlin-maven-plugin 中的 kapt
目标:
要配置注解处理的级别(level), 请在 <configuration>
代码段中将 aptMode
设置为下面的值之一:
stubs
– 只生成注解处理所需要的桩代码.apt
– 只允许注解处理.stubsAndApt
– (默认值) 生成桩代码, 并运行注解处理.
例如:
在 IntelliJ 构建系统中使用
IntelliJ IDEA 自有的构建系统不支持 kapt. 如果你想要重新运行注解处理过程, 请通过 "Maven Projects" 工具栏启动编译过程.
在命令行中使用
kapt 编译器插件随 Kotlin 编译器的二进制发布版一同发布.
编译时, 你可以添加这个插件, 方法是使用 kotlinc 的 Xplugin
编译选项, 指定它的 JAR 文件路径:
以下是这个插件的命令行选项列表:
sources
(必须): 指定生成的源代码文件的输出路径.classes
(必须): 指定生成的 class 文件和资源文件的输出路径.stubs
(必须): 指定生成的桩(stub)源代码文件的输出路径. 也可以理解为, 某种临时目录.incrementalData
: 指定生成的桩二进制文件的输出路径.apclasspath
(可多次指定): 指定注解处理器的 JAR 文件路径. 你需要多少个 JAR 文件, 就要指定多少个apclasspath
选项.apoptions
: 传递给注解处理器的选项列表, 使用 base64 编码. 详情请参见 AP/javac 选项编码.javacArguments
: 传递给 javac 编译器的选项列表, 使用 base64 编码. 详情请参见 AP/javac 选项编码.processors
: 注解处理器的全限定类名列表, 多个类名之间以逗号分隔. 如果指定了这个选项, kapt 不会在apclasspath
中查找注解处理器.verbose
: 启用详细输出.aptMode
(必须)stubs
– 只生成注解处理所需要的桩代码.apt
– 只进行注解处理.stubsAndApt
– 生成桩代码, 并且进行注解处理.
correctErrorTypes
: 详情请参见 对不存在的类型进行纠正. 默认关闭.dumpFileReadHistory
: 输出路径, 用于输出每个文件的注解处理过程中使用的类的列表.
plugin 的命令行选项格式是: -P plugin:<plugin id>:<key>=<value>
. 命令行选项可以重复.
示例:
生成 Kotlin 源代码
kapt 可以生成 Kotlin 源代码. 它会将生成的 Kotlin 源代码文件写入到 processingEnv.options["kapt.kotlin.generated"]
指定的目录, 这些文件会和主源代码文件一起编译.
注意, 对于生成的 Kotlin 文件, kapt 不支持多轮处理.
AP/Javac 选项编码
apoptions
和 javacArguments
命令行选项可以接受一个编码的参数 map. 对参数 map 编码的方法如下:
保留 Java 编译器的注解处理器
kapt 默认会运行所有的注解处理器, 并关闭 javac 编译器的注解处理. 但是, 你有可能会需要 javac 的某些注解处理器继续运行 (比如, Lombok).
在 Gradle 构建脚本文件中, 可以使用 keepJavacAnnotationProcessors
选项:
如果使用 Maven, 需要指定具体的 plugin 设置. 详情请参见 Lombok 编译器插件的设置示例.