skip to content

Tooling & Build

How Kotlin projects are built: the Gradle Kotlin DSL, annotation processing with kapt and KSP, compiler options and plugins, opt-in for experimental APIs, and the linters that gate a build. Interviewers use this to gauge how much real project setup you have done.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

explore

questions

91 · 5 sections

What actually turns your Kotlin source into runnable artifacts, and what role does Gradle (or Maven) play in that process?

level: juniorimportance: must knowfreq 70%
basics
~20 s

The Kotlin compiler, kotlinc, turns your .kt files into class files. Gradle or Maven is the build tool that calls the compiler for you, downloads libraries, and packages the output. The build tool drives the compiler.

open as a page

Why does Kotlin recommend KSP over kapt for annotation processing, and how do they differ mechanically?

level: middleimportance: must knowfreq 65%
basics
~20 s

Both generate code at build time from annotations. kapt fakes Java stubs so old Java annotation processors work, which is slow. KSP reads Kotlin code directly through a lightweight API, so it is much faster and understands Kotlin features properly.

open as a page

What is Kotlin's opt-in mechanism for experimental APIs (e.g. @OptIn / @RequiresOptIn), and how do you satisfy it at call sites and project-wide?

level: middleimportance: should knowfreq 40%
basics
~20 s

Some Kotlin APIs are marked as experimental and may change. The compiler forces you to explicitly acknowledge that risk before using them — either by adding @OptIn at the call site or by enabling the opt-in for the whole module in the build file.

open as a page

Kotlin libraries often prefer compile-time codegen (KSP / compiler plugins) over runtime reflection. What are the engineering trade-offs of that choice?

level: seniorimportance: should knowfreq 35%
basics
~20 s

Generating code while building makes the program start faster, run faster, and catch mistakes early because everything is decided at compile time. Reflection is more flexible and needs no extra tooling, but is slower at runtime and harder to optimize, especially for native or small binaries.

open as a page

How do Kotlin compiler plugins differ from KSP/kapt symbol processors, and what can a compiler plugin do that a processor cannot? Give examples.

level: seniorimportance: should knowfreq 45%
basics
~20 s

Symbol processors can only read your code and generate new files. Compiler plugins hook inside the compiler and can change the actual bytecode of existing code — adding methods, rewriting bodies, or generating synthetic members. They are more powerful but more invasive.

open as a page

What is the difference between build.gradle and build.gradle.kts, and what do you gain by choosing the Kotlin DSL?

level: juniorimportance: must knowfreq 70%
basics
~10 s

build.gradle uses the Groovy language; build.gradle.kts uses Kotlin. The Kotlin version is type-checked, so the IDE gives autocompletion, error highlighting, and reliable refactoring before you run the build.

open as a page

How do you enable Kotlin/JVM compilation in a Gradle Kotlin DSL build, and what does applying the Kotlin Gradle Plugin actually give you?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Add the Kotlin JVM plugin in the plugins block of build.gradle.kts. That tells Gradle to compile your .kt files, sets up source folders, and adds the Kotlin standard library automatically.

open as a page

In a Kotlin Multiplatform build, how do you apply the plugin and declare which platforms (targets) your library should compile for?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Apply the kotlin("multiplatform") plugin, then inside the kotlin { } block call functions like jvm(), js(), and a native target such as linuxX64(). Each call adds a platform you compile for.

open as a page

What is the Gradle `plugins {}` block in a `build.gradle.kts` file, and how does it differ from the older `apply plugin` approach?

level: juniorimportance: must knowfreq 70%
basics
~20 s

The plugins {} block is where you list the build plugins a project uses, each by an id and optional version. It is the modern, recommended way and lets Gradle resolve and apply plugins efficiently.

open as a page

What are 'type-safe accessors' in the Gradle Kotlin DSL, where do they come from, and why might one suddenly be unavailable?

level: middleimportance: must knowfreq 55%
basics
~20 s

Type-safe accessors are generated, strongly typed shortcuts—like a java {} block or an implementation(...) configuration—that appear after a plugin is applied. They give autocompletion and compile checks. They disappear when Gradle cannot see the plugin at configuration time.

open as a page

You're adding Room to a Kotlin module. Which Gradle dependency configuration do you use to wire up Room's annotation processor, and what else must you add to the build?

level: juniorimportance: must knowfreq 70%
basics
~20 s

You add the Room library as a normal dependency, and put Room's compiler on the ksp configuration (the modern way) instead of a plain dependency. You also apply the KSP Gradle plugin so ksp(...) exists.

open as a page

What is kapt and what problem does the kotlin-kapt Gradle plugin solve for Kotlin projects?

level: juniorimportance: must knowfreq 60%
basics
~20 s

kapt is a Kotlin plugin that lets old Java annotation-processing tools (like Dagger or Room) work on Kotlin code. It does this by first turning Kotlin into simple Java placeholder files those tools can read.

open as a page

Why is KSP generally faster than kapt for annotation processing in a Kotlin project?

level: juniorimportance: must knowfreq 70%
basics
~10 s

kapt first turns your Kotlin into fake Java code so old Java tools can read it, which is slow. KSP reads your Kotlin code directly, skipping that extra step, so the build is faster.

open as a page

What is KSP (Kotlin Symbol Processing), and what are the two entry-point types a processor author must implement?

level: juniorimportance: must knowfreq 55%
basics
~10 s

KSP is Kotlin's tool for reading code at compile time and generating new source files. You write a SymbolProcessor that does the work, and a SymbolProcessorProvider that creates it.

open as a page

Walk through configuring kapt for a Java annotation processor in a Gradle Kotlin DSL build, including how processor arguments are passed.

level: middleimportance: must knowfreq 50%
basics
~10 s

Apply the kotlin-kapt plugin, then add the processor with the kapt(...) line instead of implementation(...). If the processor needs options, pass them in a kapt { arguments { arg(...) } } block.

open as a page

What does the Kotlin compiler's jvmTarget option control, and what happens if you target a higher bytecode version than the JDK that actually runs your app?

level: juniorimportance: must knowfreq 70%
basics
~10 s

jvmTarget sets which Java bytecode version the compiler produces, like 17 or 21. If you produce bytecode newer than the JVM running it, the app fails to start with an UnsupportedClassVersionError.

open as a page

Kotlin classes are final by default. Why does that break Spring and JPA, and what compiler plugins solve it?

level: juniorimportance: must knowfreq 75%
basics
~20 s

Kotlin classes can't be subclassed unless you write 'open'. Spring and Hibernate need to subclass your classes to add behavior. The all-open and no-arg plugins make the needed classes open and give them an empty constructor automatically.

open as a page

What is the K2 compiler in Kotlin, and since which version is it the stable default?

level: juniorimportance: must knowfreq 55%
basics
~10 s

K2 is a rewritten Kotlin compiler frontend. It understands your code faster and more consistently. It became the stable default starting with Kotlin 2.0.

open as a page

What is the opt-in mechanism in Kotlin, and how do you consume an experimental API like ExperimentalCoroutinesApi?

level: juniorimportance: must knowfreq 55%
basics
~10 s

Some Kotlin APIs are marked experimental and may change. The compiler warns or errors when you use them. To say 'I accept the risk', you add @OptIn(TheMarker::class) above your function or class.

open as a page

How do you enable kotlinx.serialization in a Kotlin Gradle project, and what two pieces do you need besides the @Serializable annotation?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Add the serialization compiler plugin in the Gradle plugins block and add the runtime library as a dependency. Then mark classes with @Serializable.

open as a page

What is detekt and what does running the `detekt` Gradle task do for a Kotlin project?

level: juniorimportance: must knowfreq 62%
basics
~10 s

detekt is a static analysis tool for Kotlin. It scans your source code without running it and reports code smells, overly complex functions, and style problems so you can fix them.

open as a page

What is ktlint, and what is the difference between the ktlintCheck and ktlintFormat Gradle tasks?

level: juniorimportance: must knowfreq 70%
basics
~10 s

ktlint is a tool that checks and fixes Kotlin code style. ktlintCheck only reports problems and fails the build; ktlintFormat automatically rewrites your files to fix the fixable ones.

open as a page

Explain the relationship between the apiDump and apiCheck tasks and the typical developer workflow when you intentionally change a public API.

level: middleimportance: must knowfreq 40%
basics
~20 s

apiCheck compares your current public API to the saved file and fails if they differ. apiDump regenerates that saved file. When you intentionally change the API, you run apiDump and commit the updated file so the check passes again.

open as a page

How does `detekt.yml` work, and what do `buildUponDefaultConfig` and `--build-upon-default-config` mean when configuring rules?

level: middleimportance: must knowfreq 55%
basics
~10 s

detekt.yml is a YAML file where you turn rules on or off and set their thresholds. With buildUponDefaultConfig, your file only overrides the defaults instead of replacing them entirely.

open as a page

How do you enable Explicit API mode in a Kotlin Gradle build, and what is the difference between strict and warning levels?

level: middleimportance: must knowfreq 40%
basics
~10 s

In your Gradle build script's kotlin block, call explicitApi() for strict mode (build fails) or explicitApiWarning() for warnings only. Under the hood it passes a -Xexplicit-api compiler flag.

open as a page