Experimentations on Bazel: intro
Tags: bazel
Published: 2021-03-14 13:49:01

[Bazel](https://bazel.build) is a build tool with a growing popularity, maybe the one I'm looking for (I tried to create my own few years ago). So I read part of its documentation, viewed some talks from introduction to more advanced subjects (BazelCon, Bazel Days,...). I also played a little with it and tried to use it on a "real" project.
This serie of articles collects my notes (present and future), my fights, my fails, and I hope my success during my exploration and learn of Bazel.

## Unusual way

If you are looking for a tutorial about how to use Bazel the right way, you're at the wrong place. Because I'm new to Bazel and I want to use it the wrong or at least the unusual way.
The full power of Bazel comes when you embrace it at a whole with all its requirements for actions (reproducible, hermetic, ...). Those requirements are not compatible with lot of ecosystem (eg downloading dependencies on fly, or caching artifacts under `$HOME/.cache`), meaning that actions should be recreated to follow bazel's spirit. That takes times, requires some skills, so it's not an immediate job. Lots of company, who migrate to Bazel, had to create tools and bazel's rules (in name for plugin / toolset like in bazel ecosystem). Also IDE and Editors do not provided a friendly experience for non-first citizen build system (eg incremental build, code completion, find reference, import dependencies, ...).

> Can I cheat some requirements and being able to use Bazel as a "better" Make (at the cost/sacrifice of which advantages) ?
That is the purpose of my quest and of the following articles.

## So why Bazel?

IMHO, Bazel becomes interesting when you want:

- to coordinate actions by input & output, instead of a list of action names. Declaring this output of action "A" is an input of action "B" is better than declaring action "B" depends of action "A"
- to coordinate a multi-language project
- to share an input/output cache between build run, developers,...

The unusual way (hybrid way) can also become a transitive phase to the right way.

## What is planned ?

The roadmap / order is not fully defined, but I would like to experiment and to share my notes about:

- create basic custom action: generate `version.txt`
- bazel & github-action
- bazel & rust (w/o cargo)
- bazel & flutter
- bazel & ml project

## Get started

To not have zero line of code in this introduction, let's go by creating an empty Bazel [`workspace`](https://docs.bazel.build/versions/master/build-ref.html#workspace) (~ top level project in Bazel's terminology), where we'll add [`package`](https://docs.bazel.build/versions/master/build-ref.html#packages) (~ sub-modules in the Bazel's terminology).

```sh
mkdir sandbox_bazel
cd sandbox_bazel
touch WORKSPACE.bazel
```
The file `WORKSPACE.bazel` is used to mark the root folder of the workspace, and to include some setup, but we'll ignore this aspect now.

The file `WORKSPACE.bazel` can also be named `WORKSPACE`. The short name is used in the literature (and on lot of projects), the main advantage of the longer is to be explicit about which build tool is targeted because other build tool also used `WORKSPACE` name, legacy from a common father `Blaze`.

```sh
touch BUILD.bazel
```
The file [`BUILD.bazel`](https://docs.bazel.build/versions/master/build-ref.html#BUILD_files) marks the folder as a package. It is used to host [rule](https://docs.bazel.build/versions/master/build-ref.html#rules) that defined how to build outputs.

The file `BUILD.bazel` can also be named `BUILD`. The short name is used in the literature (and on lot of projects), the main advantage of the longer is to be explicit about which build tool is targeted because other build tool also used `BUILD` name, legacy from a common father `Blaze`. And to avoid conflict/issue with existing system that generates `build` folder, and `.gitignore` file that ignores it, especially on file system that are not really case sensitive (Windows & Mac OS X). Using or not the `.bazel` extension as default is a old discussion in the Bazel's community ;-).

Now we have the minimum to build "nothing" with Bazel. So you need to install Bazel'cli. But I recommend you to install [bazelisk](https://github.com/bazelbuild/bazelisk), it will take care of installing the latest (or the project specific) version of Bazel. In the following articles, codes when you'll see `bazel ...` it could also be replaced by `bazelisk ...` (in fact some packaging of Bazel installs bazelisk and create an alias). For this step use your favorite way (distribution package system, download from github, homebrew,...).

To document (also used to configure (optional) bazelisk), add a file `.bazelversion` with the version of bazel to use.

```sh
echo "4.0.0" >.bazelversion
```

Time to build everything in the workspace, so nothing currently:

```sh
❯ bazel build //...
INFO: Analyzed 0 targets (0 packages loaded, 0 targets configured).
INFO: Found 0 targets...
INFO: Elapsed time: 0.047s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
```

The `...` is not something to replace, it's like a wildcard to say `everything`.

We have to use the sub-command `build` because bazel cli can do more stuff that `build`, as we'll see later.

```sh
❯ ls -a1                                                                                      11:31:07
./
../
bazel-bin@
bazel-out@
bazel-sandbox_bazel@
bazel-testlogs@
.bazelversion
BUILD.bazel
WORKSPACE.bazel
```

We'll discover what is `bazel-bin`, `bazel-out`, `bazel-testlogs`, `bazel-<workspace_name>` in the coming articles (I hope).

Now to store the workspace on git:

```sh
curl -o .gitignore https://www.toptal.com/developers/gitignore/api/bazel
git init
git add .
git commit -m ":tada: let's go"
```

## Conclusion of intro :thinking:

That's all for this serie's introduction. Thanks for reading until the end, sorry for this first non-technical post. The sandbox_bazel is hosted on github, use tag to have the expected view at end of article: [`article/0_intro`](https://github.com/davidB/sandbox_bazel/tree/article/0_intro)

{% github davidB/sandbox_bazel no-readme %}

I'm learning Bazel, so I'll do mistake, please share your corrections and suggestions, other readers/learners (and I) will "Thank you" in advance.