What does a source set's `output` represent, and how is it used to wire one source set against another?
answer
- output = classesDirs + resourcesDir
- FileCollection carrying task dependencies
- add output, don't hardcode build/classes path
- classesDirs is a set (multi-language)
- output.dir registers extra outputs
basics
~10 sA source set's output is a FileCollection of its compiled classes (classesDirs) and processed resources (resourcesDir). You add it to another set's classpath to let that set see these compiled artifacts.
solid answer
~40 s`SourceSet.output` (a `SourceSetOutput`) is the set of directories produced by compiling and processing that source set: `output.classesDirs` (per-language compiled `.class` directories) and `output.resourcesDir` (processed resources). It is a `FileCollection` that carries built-in task dependencies on the compile and `processResources` tasks, so referencing it on another classpath also schedules the compilation. The canonical use is letting one source set depend on another's compiled output, e.g. `integrationTest.compileClasspath += sourceSets.main.get().output`. This is exactly how the `test` set is wired to `main` by default. Because `output` is a live `FileCollection` with task dependencies, you should add it rather than hardcoding `build/classes/...` paths — the latter would lose the implicit dependency and break ordering.
code
kotlin · 11 lines// Reuse main's compiled output on a custom set's classpath
val testFixtures by sourceSets.creating {
compileClasspath += sourceSets.main.get().output
runtimeClasspath += sourceSets.main.get().output
}
// Inspect output programmatically
tasks.register("printMainOutput") {
val dirs = sourceSets.main.get().output.classesDirs
doLast { dirs.forEach { println(it) } }
}go deeper
Know that a source set produces compiled classes under build/classes.
Use sourceSets.main.output to share compiled classes with another set's classpath.
Explain that output carries task dependencies and why hardcoded paths are wrong; know classesDirs is multi-language.
Standardize cross-source-set wiring patterns and reason about how generated outputs registered via output.dir propagate through a multi-module graph.
## SourceSetOutput When you compile a source set Gradle writes: - compiled classes into `build/classes/<lang>/<set>` (e.g. `build/classes/java/main`) - processed resources into `build/resources/<set>` `SourceSet.getOutput()` returns a `SourceSetOutput`, a `FileCollection` exposing: - **`classesDirs`** — a `FileCollection` of the per-language class output dirs (a set, because a set can mix Java, Kotlin, Groovy each writing their own dir). - **`resourcesDir`** — the single processed-resources dir. - **`dirs`** — extra registered output dirs (e.g. via `output.dir(...)` for generated outputs). ## The key property: built-in task dependencies The crucial feature is that `output` is a **task-dependency-carrying** `FileCollection`. When you place `sourceSets.main.output` on another configuration or task input, Gradle automatically knows that `compileJava`/`processResources` for `main` must run first. You get correct ordering without an explicit `dependsOn`. ```kotlin val integrationTest by sourceSets.creating { // Adding output gives both the files AND the dependency on main's compile tasks compileClasspath += sourceSets.main.get().output runtimeClasspath += sourceSets.main.get().output } ``` ## Why not hardcode the path Writing `files("build/classes/java/main")` would point at the same files but **lose** the implicit task dependency and be brittle to layout changes. Always go through `output`. ## Registering extra outputs `output.dir("build/generated-output", builtBy = someTask)` registers an additional directory as part of the source set's output, useful when a task generates non-class artifacts that downstream sets must see. ## Relationship to `test` The default `test` wiring is literally `testCompileClasspath` and `testRuntimeClasspath` including `main.output` — the same mechanism you reuse for custom sets.
- Why is `classesDirs` a collection rather than a single directory?A source set can host multiple JVM languages (Java, Kotlin, Groovy), and each compiler writes to its own output directory. `classesDirs` aggregates all of them so the full set of compiled classes is exposed.
- What do you lose by putting `files("build/classes/java/main")` on a classpath instead of `sourceSets.main.output`?You lose the implicit task dependency on `compileJava`/`processResources`, so the dependent task may run before the classes exist, and you couple yourself to a hardcoded path that breaks if the layout changes.
saying these in an interview costs you the question
- Hardcoding `build/classes/...` paths instead of using `output`, dropping the task dependency.
- Assuming `classesDirs` is a single directory — it's a FileCollection to support multiple languages.