Get an overview of all the various components that are needed to build a project using the Bazel build system.
Episode 3 - Understand Bazel Build Process
When setting up a build project with Bazel, there are a few fundamental concepts that you need to understand. These are moving parts that go into a Bazel build.
The first concept is a workspace. This is a simple text file that sits at the top level directory of project. The workspace allows us to incorporate custom rules into our project as well as declare any dependencies that any build within the Workspace may use. Don’t worry about rules yet. We’ll get to those soon.
The important thing to note about Workspaces is that they don’t have to contain anything. They can simply be an empty file labeled WORKSPACE. In the case where you may have a conflict - for instance, you may have a subdirectory called WORKSPACE, you rename your WORKSPACE file to WORKSPACE.bazel and it will work the same.
Bazel views this workspace root as a repository. If you have a another workspace in a subdirectory, then Bazel will just ignore it. You can also reference external repositories. These are other directories that also contain a WORKSPACE file.
The next critical piece is the BUILD file. The build file is what we use to write our actual build instructions. This build file instructs Bazel to build a collection of assets. This collection is known as a target and we can create many of them. For example, we can have one target that will build the unit tests of a project. Another will build the actual app. And so on. Targets can depend on other targets and you’ll see this a lot. For instance, I may define a target for the unit tests that will compile just the tests, but I’ll add a dependency to my app code which is just another target.
When we instruct Bazel to commence a build operation, we must indicate the target that we want to build. If a target isn’t located in the build file, then Bazel will report an error.
Like the WORKSPACE file, if you run into a conflict with an existing file or directory, you can simply rename it BUILD.bazel. 1
As you can see, we have to do a little bit of coding to communicate our targets. We write our code in a language called Starlark. This is just a simplified version of Python. If you are coming from Gradle, this is the equivalent of Groovy.
When fire off a build in Bazel, you must indicate the actual package name. The package is any directory that contains a BUILD file. This package will include any subdirectories unless that subdirectory has its own BUILD file. So in summation, a Bazel repository contains one WORKSPACE file and one or more BUILD files that represents a package.
When you actually run your build, the Bazel will sandbox your build process from the rest of the file system. This ensures we are always working with the correct files and thus will produce repeatable builds. Bazel create a few new directories which are just symlinks to another part of your drive. This is where it saves your dependencies, build code, your binaries and all the various bits necessary to create your build. When you run the bazel clean command, this directories are simply wiped.
So as you can see, Bazel has a lot of moving parts. But really, the best way to really learn this is to see everything in action. And for that, we’ll tell a few jokes.