skip to content

What is the `dependencies {}` block in a Gradle build script, and how do you add a dependency to a specific configuration inside it?

level: juniorimportance: must knowfreq 70%

answer

  1. dependencies {} = where deps are declared
  2. line = configurationName(notation)
  3. config name chooses classpath
  4. plugins create the config methods
  5. Kotlin parens+quotes; Groovy terser

basics

~10 s

The dependencies {} block is where you declare a module's dependencies. Inside it you call a configuration name like implementation(...) with the dependency coordinates (group:name:version) to attach a dependency to that configuration.

solid answer

~40 s

The `dependencies {}` block in `build.gradle(.kts)` is the DSL where you declare which external modules (or projects) your module needs. Inside it, each line is a method call whose **name is the configuration** and whose **argument is the dependency notation**. So `implementation("com.google.guava:guava:33.0.0-jre")` adds Guava to the `implementation` configuration. The configuration determines *which classpath(s)* the dependency lands on — `implementation` (compile + runtime), `compileOnly`, `runtimeOnly`, `testImplementation`, etc. The plugins you apply create the available configurations: the `java` plugin adds `implementation`/`compileOnly`/`runtimeOnly`/`testImplementation`/`testRuntimeOnly`, and `java-library` additionally adds `api`. In Kotlin DSL the calls look like function invocations with parentheses; in Groovy DSL you can omit parentheses (`implementation 'group:name:version'`).

code

kotlin · 8 lines
kotlin
plugins { `java-library` }

dependencies {
    api("com.google.guava:guava:33.0.0-jre")
    implementation("org.slf4j:slf4j-api:2.0.13")
    runtimeOnly("ch.qos.logback:logback-classic:1.5.6")
    testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
}

go deeper

for a junior

Know it's the block where you list dependencies and that each line is configuration("group:name:version").

for a middle

Explain that plugins create the configurations and the name selects the target classpath; note Kotlin vs Groovy DSL differences.

for a senior

Discuss how the available configuration set derives from the plugin stack and the implications of choosing each.

for a principal

Frame conventions for consistent dependency declaration (DSL choice, configuration discipline) across a large build.

## What the block is Every Gradle module (subproject) has a `build.gradle` (Groovy) or `build.gradle.kts` (Kotlin) script. The `dependencies {}` block is the standard place to declare dependencies. It's a configuration block on the project; inside it, the receiver exposes a method per **configuration**. ## The shape of a declaration ``` <configurationName>(<dependency notation>) ``` - **configurationName** — e.g. `implementation`, `api`, `compileOnly`, `runtimeOnly`, `testImplementation`. This is literally a method created by the applied plugins. If you call a configuration that doesn't exist (e.g. `api` without `java-library`), the build fails with an unknown-method error. - **dependency notation** — most commonly the `group:name:version` string coordinate. (Other notations like `project(...)`, files, and maps exist but belong to neighboring topics.) ## Kotlin vs Groovy DSL ```kotlin // build.gradle.kts (Kotlin DSL) plugins { `java-library` } dependencies { api("com.google.guava:guava:33.0.0-jre") implementation("org.slf4j:slf4j-api:2.0.13") testImplementation("org.junit.jupiter:junit-jupiter:5.10.2") } ``` ```groovy // build.gradle (Groovy DSL) plugins { id 'java-library' } dependencies { api 'com.google.guava:guava:33.0.0-jre' implementation 'org.slf4j:slf4j-api:2.0.13' testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2' } ``` Kotlin DSL requires parentheses and double quotes and gives you type-safe accessors + IDE completion for configuration names. Groovy DSL allows the terser space-separated, single-quoted form. ## Plugins create configurations The block is empty of meaningful methods until a plugin contributes configurations: - `java` → `implementation`, `compileOnly`, `runtimeOnly`, `annotationProcessor`, `testImplementation`, `testCompileOnly`, `testRuntimeOnly`, … - `java-library` → all of the above **plus** `api`, `compileOnlyApi`. So the available configuration names are a function of your plugin set. Choosing the right configuration name is choosing which classpath(s) the dependency affects — that's the substance of declaring dependencies.

  • Why might calling `api(...)` in the dependencies block fail?
    Because `api` is only created by the `java-library` plugin. Without it applied, `api` is an unknown method and the build fails.
  • What does the configuration name in each line actually control?
    Which classpath(s) the dependency lands on — compile, runtime, test, etc. — and, for `api` vs `implementation`, whether it's exposed transitively to consumers.

saying these in an interview costs you the question

  • Thinking the configuration name is arbitrary — it must be a real configuration created by an applied plugin.
  • Assuming all configuration names exist by default (e.g. `api` without `java-library`).
  • Mixing up Kotlin DSL (parentheses required) and Groovy DSL syntax.

context