kapt 编译器插件
kapt 编译器插件允许你在 Kotlin 中使用现有的 Java 注解处理器,并同时支持 Maven 和 Gradle。 它从 Kotlin 源代码生成存根文件,然后在这些存根上运行 Java 注解处理器。
这使得在你的 Kotlin 项目中可以为 MapStruct 和 数据绑定 等库启用基于 Java 的注解处理。
在 Gradle 中使用
要在 Gradle 中使用 kapt,请按照以下步骤操作:
在你的构建脚本文件
build.gradle(.kts)中应用kaptGradle 插件:kotlinplugins { kotlin("kapt") version "2.3.0" }groovyplugins { id "org.jetbrains.kotlin.kapt" version "2.3.0" }在
dependencies {}代码块中使用kapt配置添加相应的依赖项:kotlindependencies { kapt("groupId:artifactId:version") }groovydependencies { kapt 'groupId:artifactId:version' }如果你之前使用 Android 支持 来处理注解处理器,请将
annotationProcessor配置的用法替换为kapt。如果你的项目包含 Java 类,kapt也会负责处理它们。如果你为
androidTest或test源码使用注解处理器,相应的kapt配置分别命名为kaptAndroidTest和kaptTest。注意kaptAndroidTest和kaptTest继承自kapt,因此你可以提供kapt依赖项,它将同时用于生产源码和测试。
注解处理器参数
在你的构建脚本文件 build.gradle(.kts) 中使用 arguments {} 代码块向注解处理器传递参数:
kapt {
arguments {
arg("key", "value")
}
}Gradle 构建缓存支持
kapt 注解处理任务默认在 Gradle 中缓存。 然而,注解处理器可以运行任意代码,这些代码可能无法可靠地将任务输入转换为输出,或者可能会访问和修改 Gradle 无法跟踪的文件。 如果构建中使用的注解处理器无法被正确缓存,你可以通过在构建脚本中指定 useBuildCache 属性来完全禁用 kapt 的缓存。 这有助于防止 kapt 任务出现误报的缓存命中:
kapt {
useBuildCache = false
}提高使用 kapt 的构建速度
并行运行 kapt 任务
为了提高使用 kapt 的构建速度,你可以为 kapt 任务启用 Gradle Worker API。使用 Worker API 让 Gradle 能够并行运行来自单个项目的独立注解处理任务,在某些情况下,这会显著减少执行时间。
当你在 Kotlin Gradle 插件中使用 自定义 JDK 路径 功能时,kapt 任务工作程序仅使用 进程隔离模式。请注意,kapt.workers.isolation 属性会被忽略。
如果你想为 kapt 工作进程提供额外的 JVM 参数,请使用 KaptWithoutKotlincTask 的输入 kaptProcessJvmArgs:
tasks.withType<org.jetbrains.kotlin.gradle.internal.KaptWithoutKotlincTask>()
.configureEach {
kaptProcessJvmArgs.add("-Xmx512m")
}tasks.withType(org.jetbrains.kotlin.gradle.internal.KaptWithoutKotlincTask.class)
.configureEach {
kaptProcessJvmArgs.add('-Xmx512m')
}为注解处理器的类加载器启用缓存
如果你连续运行多个 Gradle 任务,为注解处理器的类加载器启用缓存有助于 kapt 运行得更快。
要启用此功能,请在你的 gradle.properties 文件中使用以下属性:
# gradle.properties
#
# 任何正值都会启用缓存
# 使用与使用 kapt 的模块数量相同的值
kapt.classloaders.cache.size=5
# 禁用此项以使缓存工作
kapt.include.compile.classpath=false如果你在注解处理器的缓存方面遇到任何问题,请为它们禁用缓存:
# 指定注解处理器的全名以禁用它们的缓存
kapt.classloaders.cache.disableForProcessors=[annotation processors full names]如果你遇到该功能的任何问题,我们非常感谢你在 YouTrack 中提供反馈。
衡量注解处理器的性能
要获取有关注解处理器执行情况的性能统计信息,请使用 -Kapt-show-processor-timings 插件选项。示例输出如下:
Kapt Annotation Processing performance report:
com.example.processor.TestingProcessor: total: 133 ms, init: 36 ms, 2 round(s): 97 ms, 0 ms
com.example.processor.AnotherProcessor: total: 100 ms, init: 6 ms, 1 round(s): 93 ms你可以使用插件选项 -Kapt-dump-processor-timings (org.jetbrains.kotlin.kapt3:dumpProcessorTimings) 将此报告转储到文件中。以下命令将运行 kapt 并将统计信息转储到 ap-perf-report.file 文件中:
kotlinc -cp $MY_CLASSPATH \
-Xplugin=kotlin-annotation-processing-SNAPSHOT.jar -P \
plugin:org.jetbrains.kotlin.kapt3:aptMode=stubsAndApt,\
plugin:org.jetbrains.kotlin.kapt3:apclasspath=processor/build/libs/processor.jar,\
plugin:org.jetbrains.kotlin.kapt3:dumpProcessorTimings=ap-perf-report.file \
-Xplugin=$JAVA_HOME/lib/tools.jar \
-d cli-tests/out \
-no-jdk -no-reflect -no-stdlib -verbose \
sample/src/main/统计使用注解处理器生成的文件数量
kapt Gradle 插件可以报告每个注解处理器生成文件数量的统计信息。
这有助于跟踪构建中是否包含任何未使用的注解处理器。你可以使用生成的报告找到触发不必要注解处理器的模块,并更新这些模块以避免这种情况。
要启用统计报告:
在你的
build.gradle(.kts)中将showProcessorStats属性值设置为true:kotlin// build.gradle.kts kapt { showProcessorStats = true }在你的
gradle.properties中将kapt.verboseGradle 属性设置为true:none# gradle.properties kapt.verbose=true
你也可以通过 命令行选项
verbose来启用详细输出。
统计信息以 info 级别出现在日志中。你可以看到 Annotation processor stats: 行,随后是每个注解处理器执行时间的统计信息。在这些行之后是 Generated files report: 行,随后是每个注解处理器生成文件数量的统计信息。例如:
[INFO] Annotation processor stats:
[INFO] org.mapstruct.ap.MappingProcessor: total: 290 ms, init: 1 ms, 3 round(s): 289 ms, 0 ms, 0 ms
[INFO] Generated files report:
[INFO] org.mapstruct.ap.MappingProcessor: total sources: 2, sources per round: 2, 0, 0kapt 的编译回避
为了缩短使用 kapt 的增量构建时间,它可以利用 Gradle 编译回避。启用编译回避后,Gradle 在重新构建项目时可以跳过注解处理。特别是,在以下情况下会跳过注解处理:
- 项目的源文件未更改。
- 依赖项中的更改是 ABI 兼容的。例如,唯一的更改是在方法体中。
然而,对于在编译类路径中发现的注解处理器,无法使用编译回避,因为其中的 任何更改 都需要运行注解处理任务。
要结合编译回避运行 kapt:
在
gradle.properties文件中关闭编译类路径中注解处理器的发现功能:none# gradle.properties kapt.include.compile.classpath=false
增量注解处理
kapt 默认支持增量注解处理。目前,只有在使用中的所有注解处理器都是增量的情况下,注解处理才能是增量的。
要禁用增量注解处理,请在你的 gradle.properties 文件中添加这一行:
kapt.incremental.apt=false请注意,增量注解处理还要求同时启用 增量编译。
从超配置中继承注解处理器
你可以在一个单独的 Gradle 配置中定义一组通用的注解处理器作为超配置,并在子项目中专门针对 kapt 的配置进一步扩展它。
例如,对于使用 MapStruct 的子项目,在你的 build.gradle(.kts) 文件中使用以下配置:
val commonAnnotationProcessors by configurations.creating
configurations.named("kapt") { extendsFrom(commonAnnotationProcessors) }
dependencies {
implementation("org.mapstruct:mapstruct:1.6.3")
commonAnnotationProcessors("org.mapstruct:mapstruct-processor:1.6.3")
}在此示例中,commonAnnotationProcessors Gradle 配置是你希望在所有项目中使用的通用注解处理超配置。你使用 extendsFrom() 方法将 commonAnnotationProcessors 添加为超配置。kapt 识别到 commonAnnotationProcessors Gradle 配置对 MapStruct 注解处理器有依赖。因此,kapt 在其注解处理配置中包含了 MapStruct 注解处理器。
Java 编译器选项
kapt 使用 Java 编译器来运行注解处理器。 以下是向 javac 传递任意选项的方法:
kapt {
javacOptions {
// 增加来自注解处理器的最大错误计数。
// 默认为 100。
option("-Xmaxerrs", 500)
}
}不存在的类型修正
某些注解处理器(如 AutoFactory)依赖于声明签名中的精确类型。 默认情况下,kapt 会将每个未知类型(包括生成的类的类型)替换为 NonExistentClass,但你可以更改此行为。在 build.gradle(.kts) 文件中添加该选项,以启用在存根中的错误类型推断:
kapt {
correctErrorTypes = true
}在 Maven 中使用
在 compile 之前添加 kotlin-maven-plugin 中 kapt 目标的执行:
<execution>
<id>kapt</id>
<goals>
<goal>kapt</goal> <!-- 如果你为该插件启用了扩展,
可以跳过 <goals> 元素 -->
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/main/kotlin</sourceDir>
<sourceDir>src/main/java</sourceDir>
</sourceDirs>
<annotationProcessorPaths>
<!-- 在此处指定你的注解处理器 -->
<annotationProcessorPath>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.6.3</version>
</annotationProcessorPath>
</annotationProcessorPaths>
</configuration>
</execution>要配置注解处理的级别,请在 <configuration> 代码块中将以下内容之一设置为 aptMode:
stubs– 仅生成注解处理所需的存根。apt– 仅运行注解处理。stubsAndApt– (默认)生成存根并运行注解处理。
例如:
<configuration>
...
<aptMode>stubs</aptMode>
</configuration>在 IntelliJ 构建系统中使用
IntelliJ IDEA 的自有构建系统不支持 kapt。每当你想要重新运行注解处理时,请从“Maven Projects”工具栏启动构建。
在命令行中使用
kapt 编译器插件在 Kotlin 编译器的二进制分发版中可用。
你可以通过使用 kotlinc 选项 Xplugin 提供其 JAR 文件的路径来附加该插件:
-Xplugin=$KOTLIN_HOME/lib/kotlin-annotation-processing.jar以下是可用选项的列表:
sources(必填):生成文件的输出路径。classes(必填):生成的类文件和资源的输出路径。stubs(必填):存根文件的输出路径。换句话说,是一些临时目录。incrementalData:二进制存根的输出路径。apclasspath(可重复):注解处理器 JAR 的路径。根据你拥有的 JAR 数量传递相应数量的apclasspath选项。apoptions:Base64 编码的注解处理器选项列表。有关更多信息,请参阅 AP/javac 选项编码。javacArguments:Base64 编码的传递给 javac 的选项列表。有关更多信息,请参阅 AP/javac 选项编码。processors:逗号分隔的注解处理器完全限定类名列表。如果指定了此项,kapt 将不会尝试在apclasspath中查找注解处理器。verbose:启用详细输出。aptMode(必填)stubs– 仅生成注解处理所需的存根。apt– 仅运行注解处理。stubsAndApt– 生成存根并运行注解处理。
correctErrorTypes:有关更多信息,请参阅 不存在的类型修正。默认禁用。dumpFileReadHistory:转储每个文件在注解处理期间使用的类列表的输出路径。
插件选项格式为:-P plugin:<plugin id>:<key>=<value>。选项可以重复。
示例:
-P plugin:org.jetbrains.kotlin.kapt3:sources=build/kapt/sources
-P plugin:org.jetbrains.kotlin.kapt3:classes=build/kapt/classes
-P plugin:org.jetbrains.kotlin.kapt3:stubs=build/kapt/stubs
-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=lib/ap.jar
-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=lib/anotherAp.jar
-P plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true生成 Kotlin 源码
kapt 可以生成 Kotlin 源码。只需将生成的 Kotlin 源码文件写入 processingEnv.options["kapt.kotlin.generated"] 指定的目录,这些文件将与主源码一起编译。
请注意,kapt 不支持对生成的 Kotlin 文件进行多轮处理。
AP/Javac 选项编码
apoptions 和 javacArguments 命令行选项接受一个编码后的选项映射。 以下是你可以自行编码选项的方法:
fun encodeList(options: Map<String, String>): String {
val os = ByteArrayOutputStream()
val oos = ObjectOutputStream(os)
oos.writeInt(options.size)
for ((key, value) in options.entries) {
oos.writeUTF(key)
oos.writeUTF(value)
}
oos.flush()
return Base64.getEncoder().encodeToString(os.toByteArray())
}保留 Java 编译器的注解处理器
默认情况下,kapt 运行所有注解处理器并禁用 javac 的注解处理。 然而,你可能需要一些 javac 的注解处理器正常工作(例如 Lombok)。
在 Gradle 构建文件中,使用选项 keepJavacAnnotationProcessors:
kapt {
keepJavacAnnotationProcessors = true
}如果你使用 Maven,则需要显式配置该插件。 参见这个 Lombok 编译器插件设置示例。
