Kotlin Help

kapt compiler plugin

The kapt compiler plugin allows you to use existing Java annotation processors in Kotlin and works with both Maven and Gradle. It generates stub files from Kotlin source code and then runs the Java annotation processors on those stubs.

This enables Java-based annotation processing in your Kotlin projects for libraries like MapStruct and Data Binding.

Set up the plugin

You can configure the kapt plugin for Gradle, Maven, or use it from the command line.

Gradle

To use kapt in Gradle, follow these steps:

  1. Apply the kapt Gradle plugin in your build script file build.gradle(.kts):

    plugins { kotlin("kapt") version "2.4.10" }
    plugins { id "org.jetbrains.kotlin.kapt" version "2.4.10" }
  2. Add the respective dependencies using the kapt configuration in the dependencies {} block:

    dependencies { kapt("groupId:artifactId:version") }
    dependencies { kapt 'groupId:artifactId:version' }
  3. If you previously used the Android support for annotation processors, replace usages of the annotationProcessor configuration with kapt. If your project contains Java classes, the kapt plugin processes them as well.

    If you use annotation processors for your androidTest or test sources, the respective kapt configurations are named kaptAndroidTest and kaptTest. Note that kaptAndroidTest and kaptTest extend kapt, so you can provide the kapt dependency, and it will be available both for production sources and tests.

Maven

You can set up kapt using either the <extensions> option to simplify setup or manually to get full control over kapt's execution.

Automatic configuration

You can simplify kapt configuration by enabling the <extensions> option for the Kotlin Maven plugin. In this case, you don't need to manually set up kapt's <execution> section with goals or source directories.

To automatically configure kapt, set the <extensions> option to true for the kotlin-maven-plugin in your pom.xml build file:

<plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <version>${kotlin.version}</version> <extensions>true</extensions> <configuration> <annotationProcessorPaths> <!-- Specify your annotation processors here --> <annotationProcessorPath> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.6.3</version> </annotationProcessorPath> </annotationProcessorPaths> </configuration> </plugin>

For more information on the <extensions> option, see Automatic configuration.

Manual configuration

To manually set up kapt in your Kotlin Maven project, add an execution of the kapt goal from kotlin-maven-plugin before the compile execution:

<execution> <id>kapt</id> <goals> <goal>kapt</goal> </goals> <configuration> <sourceDirs> <sourceDir>src/main/kotlin</sourceDir> <sourceDir>src/main/java</sourceDir> </sourceDirs> <annotationProcessorPaths> <!-- Specify your annotation processors here --> <annotationProcessorPath> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.6.3</version> </annotationProcessorPath> </annotationProcessorPaths> </configuration> </execution>

To configure the annotation processing mode, set the aptMode option in the <configuration> block. For example:

<configuration> ... <aptMode>stubs</aptMode> </configuration>

CLI

kapt is available as a standalone CLI tool in the binary distribution of the Kotlin compiler.

To run kapt from the command line, use:

kapt <options> <source files>

For example:

kapt -Kapt-mode=stubsAndApt \ -Kapt-sources=build/kapt/sources \ -Kapt-classes=build/kapt/classes \ -Kapt-stubs=build/kapt/stubs \ -Kapt-classpath=lib/ap.jar \ -Kapt-classpath=lib/anotherAp.jar \ src/main/kotlin

Configure annotation processors

kapt provides options to control how annotation processors are discovered, organized, and executed, including managing the processor classpath, inheriting processors from shared configurations, and keeping javac-specific processors active.

For more configuration options, such as passing options to annotation processors and javac, see Annotation processor configuration.

Configure processor classpath and discovery

You can disable the discovery of annotation processors that aren't included in kapt's processor path. This excludes unnecessary annotation processors from the compile classpath.

Gradle

Gradle uses compile avoidance to skip annotation processing during project rebuild, improving incremental build times with kapt. Particularly, annotation processing is skipped when:

  • The project's source files are unchanged.

  • The changes in dependencies are ABI-compatible. For example, when only function bodies change.

However, compile avoidance can't be used for annotation processors discovered on the compile classpath, since changes in their internal implementation require running the annotation processing tasks, even if the processors' ABI remains unchanged.

That's why we don't recommend using annotation processors from the compile classpath. To exclude these processors from kapt processing, add the kapt.include.compile.classpath property to your gradle.properties file:

# gradle.properties kapt.include.compile.classpath=false

With the option set to false, annotation processor dependencies that aren't included in the processor path (the kapt* configurations) are excluded from kapt processing.

Maven

To exclude annotation processors that aren't included in the kapt's processor path, set the includeCompileClasspath option to false in the <execution> section of the kapt plugin:

<execution> <id>kapt</id> <goals> <goal>kapt</goal> </goals> <configuration> <includeCompileClasspath>false</includeCompileClasspath> <sourceDirs>...</sourceDirs> <annotationProcessorPaths>...</annotationProcessorPaths> </configuration> </execution>

Alternatively, you can use the kapt.include.compile.classpath property in the <properties> section of your pom.xml:

<properties> <kapt.include.compile.classpath>false</kapt.include.compile.classpath> </properties>

With the option set to false, annotation processors that aren't included in the <annotationProcessorPaths> section are excluded from kapt processing.

If the includeCompileClasspath option isn't set and kapt detects an annotation processor on the compile classpath that isn't explicitly defined in the processor path, you'll see a deprecation warning:

[WARNING] Annotation processors discovery from compile classpath is deprecated. Set 'kapt.include.compile.classpath=false' to disable discovery.

Inherit annotation processors from superconfigurations

You can define a common set of annotation processors in a separate Gradle configuration as a superconfiguration and extend it further in kapt-specific configurations for your subprojects.

As an example, for a subproject using MapStruct, in your build.gradle(.kts) file, use the following configuration:

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") }

In this example, the commonAnnotationProcessors Gradle configuration is the common superconfiguration for annotation processing that you want to be used for all your projects. You use the extendsFrom() method to add commonAnnotationProcessors as a superconfiguration. kapt sees that the commonAnnotationProcessors Gradle configuration has a dependency on the MapStruct annotation processor. Therefore, kapt includes the MapStruct annotation processor in its configuration for annotation processing.

Keep Java compiler's annotation processors

By default, kapt runs all annotation processors and disables annotation processing by javac. However, you may need javac to run some annotation processors, such as Lombok.

In the Gradle build file, use the option keepJavacAnnotationProcessors:

kapt { keepJavacAnnotationProcessors = true }

If you use Maven, configure the plugin explicitly. See this example of setting up the Lombok compiler plugin.

Optimize kapt builds

kapt offers several Gradle-specific strategies to reduce annotation processing time, including running tasks in parallel, leveraging the build cache, caching processor classloaders, and using incremental annotation processing.

For more options that affect build behavior, such as error type correction, stub metadata stripping, and compile classpath scanning, see Behavioral options.

Run kapt tasks in parallel

kapt uses the Gradle Worker API to run annotation processing tasks. Using the Worker API lets Gradle run independent annotation processing tasks from a single project in parallel, which in some cases significantly decreases the execution time.

If you set the custom JDK version in the Kotlin Gradle plugin, kapt task workers use only the processIsolation() mode.

If you want to provide additional JVM arguments for a kapt worker process, use the input kaptProcessJvmArgs of the KaptWithoutKotlincTask:

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') }

Use Gradle build cache safely

Gradle caches kapt annotation processing tasks by default. However, annotation processors can run arbitrary code. This may result in unnecessary transformations of task inputs into outputs, or accessing and modifying files that Gradle doesn't track.

When annotation processors used in the build can't be properly cached, you can disable caching to prevent false-positive hits for kapt tasks. To do this, use the useBuildCache property in the build script:

kapt { useBuildCache = false }

Cache annotation processors' classloaders

Caching for annotation processors' classloaders helps kapt perform faster if you run many Gradle tasks consecutively.

To enable this feature, use the following properties in your gradle.properties file:

# gradle.properties # # Any positive value enables caching # Use the same value as the number of modules that use kapt kapt.classloaders.cache.size=5 # Disable for caching to work kapt.include.compile.classpath=false

If you run into any problems with caching for annotation processors, disable caching for them:

# Specify annotation processors' full names to disable caching for them kapt.classloaders.cache.disableForProcessors=[annotation processors full names]

Use incremental annotation processing

With Gradle, kapt supports incremental annotation processing by default so that only the changed files are re-processed.

Currently, incremental annotation processing works only if:

To disable incremental annotation processing, add this line to your gradle.properties file:

kapt.incremental.apt=false

Analyze performance

kapt provides built-in diagnostics to help you understand annotation processing performance, including per-processor execution time reports and generated file counts to identify unused processors.

For more diagnostic options, such as file read history for debugging incremental processing and memory leak detection, see Diagnostics and statistics options.

Measure the performance of annotation processors

To get performance statistics on the annotation processors execution, use the showProcessorStats option. An example output:

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

You can dump this report to a file with the dumpProcessorStats option. For example, the following CLI command runs kapt and dumps the statistics to the ap-perf-report.file file:

kapt -Kapt-mode=stubsAndApt \ -Kapt-classpath=processor/build/libs/processor.jar \ -Kapt-dump-processor-stats=ap-perf-report.file \ sample/src/main/

Track the number of generated files

The kapt plugin can report statistics on the number of generated files for each annotation processor.

This helps track whether any unused annotation processors are included in the build. You can use the generated report to find modules that trigger unnecessary annotation processors and update the modules to avoid that.

To enable statistics reporting:

  1. In your Gradle build file, set the showProcessorStats option to true:

    // build.gradle(.kts) kapt { showProcessorStats = true }
  2. In your gradle.properties file, set the verbose compiler option to true:

    # gradle.properties kapt.verbose=true

The statistics appear in the logs with the info level. You can see the Annotation processor stats: line followed by statistics on the execution time of each annotation processor. After these lines, there is the Generated files report: line followed by statistics on the number of generated files for each annotation processor. For example:

[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, 0

Generate Kotlin sources

kapt can generate Kotlin sources. To do that, write the generated Kotlin source files to the specified directory using processingEnv.options["kapt.kotlin.generated"]. Kotlin source files are then compiled together with the main sources.

Compiler options

Annotation processor configuration

Option

Description

How to set up

aptMode

Controls the execution of kapt workflow stages:

  • stubsAndApt generates stubs and runs annotation processing (default)

  • stubs only generates Java stubs from Kotlin

  • apt only runs annotation processors (assumes stubs already exist)

Gradle: not directly available; Gradle runs stubs and apt as separate tasks

Maven:

<aptMode>stubsAndApt</aptMode>

CLI: -Kapt-mode=stubsAndApt

classpath

Classpath entries where annotation processors are discovered.

Gradle:

dependencies { kapt("com.example:processor:1.0") }

Maven:

<annotationProcessorPaths> <annotationProcessorPath>...</annotationProcessorPath> </annotationProcessorPaths>

CLI: -Kapt-classpath=lib/my-processor.jar

processors

Comma-separated fully qualified class names of processors to run, bypassing discovery.

Gradle:

kapt { annotationProcessor("com.example.MyProcessor") }

Maven:

<annotationProcessors> <annotationProcessor>com.example.MyProcessor</annotationProcessor> </annotationProcessors>

CLI: -Kapt-processors=com.example.MyProcessor

apOption

Key-value options passed to annotation processors.

Gradle:

kapt { arguments { arg("room.schemaLocation", "$projectDir/schemas") } }

Maven:

<annotationProcessorArgs> <annotationProcessorArg>room.schemaLocation=/schemas</annotationProcessorArg> </annotationProcessorArgs>

CLI: -Kapt-options:room.schemaLocation=/schemas

javacOption

Key-value options passed to the Java compiler.

Gradle:

kapt { javacOptions { option("-source", "11") } }

Maven:

<javacOptions> <javacOption>-source=11</javacOption> </javacOptions>

CLI: -Kapt-javac-option:-source=11

processIncrementally

Enables incremental annotation processing; only reprocesses files affected by changes.

Gradle:

# gradle.properties kapt.incremental.apt=true

Maven: currently not supported

CLI: currently not supported

Output directory options

Option

Description

How to set up

sources

Directory where annotation processors generate .java source files.

Gradle: set automatically to build/generated/source/kapt/main

Maven: set automatically to target/generated-sources/kapt/

CLI: -Kapt-sources=build/kapt/sources

classes

Directory for .class files compiled from generated sources.

Gradle: managed automatically

Maven: managed automatically

CLI: -Kapt-classes=build/kapt/classes

stubs

Directory for Java stub files generated from Kotlin sources, used as input to annotation processors.

Gradle: managed automatically

Maven: managed automatically

CLI: -Kapt-stubs=build/kapt/stubs

incrementalData

Stores state for incremental builds.

Gradle: managed automatically

Maven: currently not supported

CLI: currently not supported

Behavioral options

Option

Description

How to set up

correctErrorTypes

By default, kapt replaces every unknown type (including types for the generated classes) with NonExistentClass. You can enable error type interference in stubs to replace unresolved error types with types from generated sources.

false by default

Gradle:

kapt { correctErrorTypes = true }

Maven:

<correctErrorTypes>true</correctErrorTypes>

CLI: -Kapt-correct-error-types=true

dumpDefaultParameterValues

Includes default parameter initializers as field values in generated stubs.

false by default

Gradle:

kapt { dumpDefaultParameterValues = true }

Maven: not available

CLI: -Kapt-dump-default-parameter-values=true

mapDiagnosticLocations

Maps error messages from stub files back to their original Kotlin source locations.

false by default

Gradle:

kapt { mapDiagnosticLocations = true }

Maven:

<mapDiagnosticLocations>true</mapDiagnosticLocations>

CLI: -Kapt-map-diagnostic-locations=true

strict

Turns stub generation incompatibilities into errors instead of warnings.

false by default

Gradle:

kapt { strictMode = true }

Maven: not available

CLI: -Kapt-strict=true

stripMetadata

Removes @kotlin.Metadata annotations from generated stubs, reducing stub size and hiding Kotlin-specific info from processors.

false by default

Gradle:

kapt { stripMetadata = true }

Maven: not available

CLI: -Kapt-strip-metadata=true

verbose

Enables verbose kapt logging.

false by default

Gradle:

# gradle.properties kapt.verbose=true

Maven: currently not supported

CLI: currently not supported

infoAsWarnings

Promotes info-level kapt messages to warnings.

false by default

Gradle: not directly available

Maven: currently not supported

CLI: currently not supported

includeCompileClasspath

Scans the compile classpath for annotation processors. Set to false for reproducibility.

true by default

Gradle:

kapt { includeCompileClasspath = false }

Maven:

<includeCompileClasspath>false</includeCompileClasspath>

CLI: currently not supported

Diagnostics and statistics options

Option

Description

How to set up

showProcessorStats

Prints per-processor execution time to stdout.

Gradle:

kapt { showProcessorStats = true }

Maven: not available

CLI: -Kapt-show-processor-stats=true

dumpProcessorStats

Writes processor timing stats to a file.

Gradle: not available

Maven: not available

CLI: -Kapt-dump-processor-stats=build/kapt-stats.txt

dumpFileReadHistory

Writes a list of files read by processors to a file, useful for incremental annotation processor debugging.

Gradle: not available

Maven: not available

CLI: -Kapt-dump-file-read-history=build/kapt-reads.txt

detectMemoryLeaks

Memory leak detection mode: none, default, or paranoid.

Gradle:

kapt { detectMemoryLeaks = "paranoid" }

Maven: currently not supported

CLI: currently not supported

What's next

24 July 2026