Differences Between Bazel and Gradle Builds
In parallel with the revolution of reproducible build environments led by Docker, there’s also been a revolution for multilingual programmers in build systems. Since the beginning of the century, one other challenge for software engineers has been developing applications that repeatedly and quickly compile to the correct result.
When working with a multilingual code base of several languages (C++, Java, Go, etc.), this challenge becomes especially hairy. For this reason, several open-source projects have sprung up in an attempt to boil the build step of large, multilingual projects down to a series of clear tasks. Two of the most popular build systems are Google’s Bazel and Gradle Inc.’s Gradle.
Bazel and Gradle both attack the repeatable build problem using project-level configuration files, but the configuration files have drastically different structures.
Bazel Build Files
Bazel operates off of two configuration files: BUILD and WORKSPACE.
The presence of a BUILD file tells Bazel that it is looking at a package of code — this package of code includes the current directory and any subdirectories within it, unless the subdirectory contains a build file.
// Diagram 1
A typical BUILD will have two things: Rules and Files. A Rule is similar to a function in that it can take in Files as an input and use that input to produce some new Files as an output. Files that have been written by someone with a text editor are source Files, while files that have been produced from a rule are generated Files.
The Bazel architecture allows for further expansion of a Rule: For instance, a rule can take in other rules, or multiple groups of files as an input. Additionally, Bazel is functional: Each rule is run within a sandbox, and therefore can only produce outputs without side effects.
In order to make BUILDs easy to reason about, a rule can only generate files inside of the package that it is currently running in. However, the generated files of other packages can be used as an input to a rule. In this way, each package can be thought to have limited, but modular scope.
The WORKSPACE file is written in the BUILD language, and, like BUILD files, there can only be one WORKSPACE in a package. The purpose of the WORKSPACE file is to track the external dependencies of a project. Each external dependency is added to the WORKSPACE using rules — the following is an example:

The repositories listed in this file are then built individually and made available to the package’s BUILD file as Files. Bazel includes a compatibility layer to compile dependencies if they are not Bazel projects.
Gradle Build Files
The Gradle build system uses several files: build.gradle, settings.gradle and gradlew. Rather than running each build step in scripted sequence as Bazel does, Gradle handles build step configuration using Groovy, an object-oriented language related to Java.
The build.gradle file defines the configuration and execution phases of a build, separating between the two using objects. Execution orders of the script are defined as such:
In this system, each task has access to the entire directory, and each task can perform actions depending on the plugins imported into the build. Stateful actions (such as retrieving items from a webserver) and manipulations outside of the project directory are permitted.
There are two different kinds of projects: Multi-project and single-project. The multi-project build must also contain the settings.gradle file, which determines the dependencies of the the application. Dependencies are included using an object oriented style:
include ‘project1’, ‘project2:child1’, ‘project3:child2’
Finally, the gradlew file identifies the version of gradle that the project should be built with.
Conclusion:
There is a similar level of functionality between these two build formats, and it becomes apparent that the two systems are made with different philosophies. Bazel provides a structured system that is easy to reason about and provides a strong, functional foundation for large and growing products. Gradle, on the other hand, offers a flexible, stateful, object-oriented interface that may feel familiar to those who don’t frequently use scripting languages.