5 exercises on build tooling terms — targets, tasks, and reproducible builds.
0 / 5 completed
1 / 5
In Bazel, what is a target?
In Bazel, a target is a named buildable unit defined by a rule invocation in a BUILD file — for example cc_library, java_binary, or py_test. Each target declares its sources and explicit dependencies, letting Bazel construct a precise dependency graph. Because dependencies are fully declared, Bazel can build only what changed and parallelize aggressively. Targets are addressed by labels like //path/to/pkg:name. This explicitness is what enables Bazel's reproducible, incremental, and remotely cacheable builds across very large monorepos.
2 / 5
In Gradle, what is a task?
A Gradle task is the fundamental unit of build work — compiling code, running tests, copying files, or assembling artifacts. Tasks declare inputs and outputs, which lets Gradle skip them when nothing relevant changed (the task is reported UP-TO-DATE) and reuse cached results. Tasks form a directed acyclic graph based on dependencies (dependsOn), so running one task automatically runs its prerequisites in the correct order. You can define custom tasks or use those contributed by plugins like the Java or Android plugin.
3 / 5
In a Makefile, what is a .PHONY target?
A phony target in Make is one that does not correspond to an actual file on disk — common examples are clean, all, and test. Normally Make decides whether to run a target by comparing file modification timestamps. By listing a target as a prerequisite of .PHONY, you tell Make to always execute its recipe and never skip it, even if a file of the same name happens to exist in the directory. This avoids the classic bug where a file named clean would cause make clean to silently do nothing.
4 / 5
What is an incremental build?
An incremental build rebuilds only the portions of a project affected by recent changes, reusing previously produced outputs for everything unchanged. The build system tracks dependencies and input fingerprints (timestamps or content hashes) to determine the minimal set of work needed. This dramatically reduces build time compared with a clean, from-scratch build. Correctness depends on accurate dependency tracking — if a dependency is missed, an incremental build can produce stale or inconsistent results, which is why precise input/output declarations matter.
5 / 5
What is a hermetic build?
A hermetic build is sealed off from the host environment: it depends solely on explicitly declared inputs — pinned toolchains, source files, and dependencies — and not on ambient state like installed system packages, environment variables, the current time, or network access. This isolation makes builds reproducible: the same inputs always yield bit-identical outputs on any machine, which enables reliable caching and trustworthy supply chains. Tools like Bazel and Nix enforce hermeticity by sandboxing build actions and hashing every input.