What is a ConfigurableFileCollection in Gradle, and how do you create one in a plugin or task?
answer
- objects.fileCollection()
- lazy / live set of files
- from(...) accepts almost anything
- resolved on query, not declaration
- implements Iterable<File>
basics
~10 sA ConfigurableFileCollection is a mutable, lazily-evaluated set of files. You create one with project.objects.fileCollection() and populate it with from(...), so the actual files are resolved later, not at configuration time.
solid answer
~30 sA `ConfigurableFileCollection` is Gradle's mutable, lazy container for a set of files. Unlike a plain `FileCollection` you build eagerly with `project.files(...)`, you create a `ConfigurableFileCollection` via `project.objects.fileCollection()` (the `ObjectFactory`). You add sources with `from(...)`, which accepts almost anything resolvable to files — `File`, `String` paths, `Provider`s, other `FileCollection`s, even closures — and Gradle only resolves them when the collection is actually queried. This laziness lets a task wire up inputs whose locations aren't known yet at configuration time and keeps you compatible with the configuration cache. It implements `Iterable<File>`, so you can iterate it like a normal collection once resolved.
code
kotlin · 5 linesval sources: ConfigurableFileCollection = project.objects.fileCollection()
sources.from("src/main/resources")
sources.from(layout.buildDirectory.dir("generated"))
// resolution happens here, lazily:
sources.files.forEach { println(it) }go deeper
Know it's a lazy, mutable file set created via objects.fileCollection() and filled with from(...).
Explain the laziness — files resolved on query — and why objects.fileCollection() is preferred over project.files().
Tie it to configuration-cache safety and to using it as a managed @InputFiles property instead of an eager FileCollection.
Frame conventions for plugin authors: standardize on ObjectFactory-created collections so plugins stay decoupled from Project and cache-compatible across a codebase.
## What it is A **`FileCollection`** in Gradle is a lazily-evaluated, *live* set of files — "live" meaning the actual `File` instances are computed only when you query the collection, not when you declare it. A **`ConfigurableFileCollection`** is the *mutable* subtype: you can keep adding sources to it after creation. ## Eager vs lazy creation - `project.files(...)` returns a `ConfigurableFileCollection` too, but you typically use it ad-hoc and it's tied to the `Project`. - `project.objects.fileCollection()` — via the **`ObjectFactory`** — is the preferred way inside plugins/tasks because it doesn't need a `Project` reference and plays well with managed types and the configuration cache. ## Populating it The key method is **`from(Object...)`**. It is extremely permissive about what you pass: - `File`, `Path`, `String` (relative to project dir) - a `Provider<T>` (e.g. `layout.buildDirectory.file("out.txt")`) - another `FileCollection` or `FileTree` - a `Callable`/closure that returns any of the above — this is how you defer resolution Because everything is resolved on query, you can call `from(someProvider)` before the provider has a value. ## Why laziness matters If you resolved file paths at configuration time (e.g. by calling `.get()` early), you'd break the **configuration cache** and force work even when the task won't run. A `ConfigurableFileCollection` defers all of that to execution time. ```kotlin val sources = project.objects.fileCollection() sources.from("src/main/resources") sources.from(layout.buildDirectory.dir("generated")) // nothing resolved yet — only when sources.files or iteration happens sources.forEach { println(it) } ``` ## It is iterable `ConfigurableFileCollection : FileCollection : Iterable<File>`, so once queried you can iterate, call `.files` (a `Set<File>`), `.singleFile`, `.isEmpty`, `.filter { }`, or combine with `+` / `-`.
- What is the difference between project.files(...) and project.objects.fileCollection()?Both return a ConfigurableFileCollection, but objects.fileCollection() comes from the ObjectFactory, needs no Project reference, and is the recommended form inside managed types and configuration-cache-compatible plugins. project.files() is convenient but couples you to the Project.
- When are the files actually resolved?Only when the collection is queried — iterated, .files / .singleFile read, or used as a task input during execution — not when from(...) is called.
saying these in an interview costs you the question
- Calling it an immutable or eagerly-resolved snapshot of files.
- Saying you must pass only File objects to from(...) (it accepts providers, strings, callables, etc.).