What makes Bazel a good choice? You'll start learning about Bazel by describing goals at a high level, and point out what's required of developers to get Bazel's guarantees.
Here are the desirable properties of a general-purpose build and test system:
Incremental
The time to perform a re-build or re-test should be proportional to what was changed.
For example, comment-only source changes should be nearly instant, but changing the version of an SDK might require re-building the whole application.
Requires: breaking up a monolithic app into modules/libraries without cyclic dependencies.
Correct
Developers should not get in the habit of running a "clean" build when they distrust a build or test result, as that slows down development with a slow retry when your code isn't working.
Instead they should trust that the system will rebuild anything required, so the outputs are up-to-date.
Requires: care from the beginning. Correctness is very difficult to retrofit onto an existing build tool! For example, Gradle struggles because the dependency graph is usually heuristic and not trustworthy.
Cached
Can re-use outputs of previous builds, even those performed on a different computer. The build should be a "pure function" from inputs to outputs.
Requires: determinism, which means “given the same inputs, tools write identical output” regardless of where they run. For example, the compiler should not write an absolute file path into the output.
Without determinism, later build steps will always get a cache miss due to changed inputs.
As a side-effect, it's also isolated. Tool run-times are in ephemeral sub-processes, defending against resource leaks and statefulness bugs.
"Persistent Workers" are a notable exception, however.
Parallel and Fast
Schedule as much work concurrently as possible, given multiple local or remote CPUs.
Bazel can't be faster than the underlying tool it calls. The goal is to add minimal overhead, and avoid calling those tools at all.
Requires: hermeticity. All dependencies are known to the build system, including tools, environment variables, and third-party libraries.
Some execution strategies have stricter hermeticity requirements than others.
Reproducible
Thanks to hermeticity and determinism, all the build inputs and are guaranteed to get identical outputs.
This allows you to demonstrate that your binaries were built from the sources you claim, providing a strong “supply chain security” guarantee. It also means you can safely cherry-pick a hot-fix onto a months-old release and be assured it still builds, and the program behavior won’t have surprising differences.
Composable
Allows reuse of existing build rules and creating new ones by combining them. Bazel follows the Unix Philosophy which says to:
- Write programs that do one thing and do it well.
- Write programs to work together.
- Write programs to handle text streams, because that is a universal interface.
Bazel models your build and test the same way, except that instead of "text streams", the universal interface is files.
Universal
Through plugins called “rules”, Bazel supports the build and test of nearly every language and framework.
Industrial
Googlers have beat on this thing in every way at large scale. As of 2015, "google3" was 2 billion source lines of code (SLOC)!