Where does the Kotlin Gradle Plugin add Kotlin compilation into the Gradle build, and what kind of task is compileKotlin?
answer
- compileKotlin / compileTestKotlin per source set
- type org.jetbrains.kotlin.gradle.tasks.KotlinCompile
- classes depends on compileKotlin
- @CacheableTask + incremental
- mixed Java+Kotlin feed same output
basics
~10 sKGP registers a KotlinCompile task named compileKotlin per source set (plus compileTestKotlin), wired into the classes lifecycle. It's an incremental, cacheable task whose output joins the same classpath as Java compilation.
solid answer
~40 sFor each source set KGP registers a `org.jetbrains.kotlin.gradle.tasks.KotlinCompile` task: `compileKotlin` for `main`, `compileTestKotlin` for `test`. These hang off the existing JVM lifecycle — `classes` depends on `compileKotlin`, so `build`/`jar`/`test` transitively trigger Kotlin compilation. The tasks are **incremental** (KGP tracks changed sources and dependencies to recompile a subset) and **build-cache enabled** (`@CacheableTask`), so unchanged inputs reuse outputs locally or from a remote cache. In a mixed Java+Kotlin module, KGP coordinates ordering so Kotlin and Java that reference each other compile correctly, and both feed the source set's classes output directory. You configure these tasks either project-wide through `kotlin { compilerOptions { … } }` or per task via `tasks.withType<KotlinCompile>().configureEach { compilerOptions { … } }`.
code
kotlin · 7 linesimport org.jetbrains.kotlin.gradle.tasks.KotlinCompile
tasks.withType<KotlinCompile>().configureEach {
compilerOptions {
freeCompilerArgs.add("-Xjsr305=strict")
}
}go deeper
Know that applying KGP gives you a compileKotlin task that build/test triggers automatically.
Name the per-source-set tasks, their type, and the classes-depends-on-compileKotlin wiring.
Explain @CacheableTask, incremental compilation, mixed Java+Kotlin ordering, and configureEach configuration.
Reason about cache hit-rates and build performance across modules and CI (remote build cache, input normalization).
## Plugging into existing machinery The key idea behind KGP is that it does **not** invent a parallel build — it inserts Kotlin compilation into the source-set/lifecycle structure the JVM plugin already provides. ### Per-source-set compile tasks For every source set, KGP registers a Kotlin compile task: - `compileKotlin` → compiles `src/main/kotlin` - `compileTestKotlin` → compiles `src/test/kotlin` Each is an instance of `org.jetbrains.kotlin.gradle.tasks.KotlinCompile`. They are registered lazily with `tasks.register`, so they're only configured if actually needed. ### Lifecycle wiring KGP wires these into the standard graph: the `classes` task depends on `compileKotlin`, and the Kotlin output directory is added to the source set's output. As a result, running `jar`, `test`, or `build` pulls in Kotlin compilation automatically — you never invoke `compileKotlin` directly. ### Incremental + cacheable `KotlinCompile` is annotated `@CacheableTask` and declares its inputs (sources, classpath, compiler options) and outputs precisely. That gives two performance properties: - **Up-to-date / build cache**: if inputs are unchanged, Gradle skips the task or pulls outputs from the local or a remote build cache. - **Incremental compilation**: when only some sources change, KGP recompiles the affected subset rather than everything, using its own dependency tracking on top of Gradle's incremental task support. ### Mixed Java + Kotlin When a module has both languages, KGP coordinates the two compilers so cross-references resolve and both write into the same `classes` output. This is why adding KGP to a Java module and dropping in `.kt` files just works. ### Configuring the tasks ```kotlin import org.jetbrains.kotlin.gradle.tasks.KotlinCompile // Per-task configuration (lazy) tasks.withType<KotlinCompile>().configureEach { compilerOptions { freeCompilerArgs.add("-Xjsr305=strict") } } ``` Use the project-level `kotlin { compilerOptions { … } }` for the common case; drop to `tasks.withType<KotlinCompile>()` when you need per-task differences (e.g. extra args only on test compilation).
- Why don't you usually run compileKotlin directly?Because it's wired into the lifecycle — classes depends on it, so build/jar/test trigger it transitively. You invoke the lifecycle task and Kotlin compilation happens as a dependency.
- What makes KotlinCompile build-cache friendly?It's annotated @CacheableTask and declares its inputs (sources, classpath, compiler options) and outputs precisely, so Gradle can fingerprint inputs and reuse outputs from the local or remote cache when they're unchanged.
saying these in an interview costs you the question
- Claiming Kotlin compilation runs as a separate build outside Gradle's task graph.
- Saying KotlinCompile isn't cacheable or incremental — it is both.