This set of exercises is a practical introduction to building polyglot projects with Bazel, supported by Nix for reproducible, hermetic build environments. It is self-contained and works on Linux and macOS.
Please open an issue if you have questions or encounter problems running the examples.
Please make a pull request if you found and fixed an issue.
This codelab is based on Google's Bazel Codelab. It has been adapted to
buildifier
or using BUILD.bazel
files instead of BUILD
files.rules_nixpkgs
to import Nix provided toolchains from nixpkgs
.direnv
used to automatically set up shell environment, see .envrc
.shell.nix
nix/
.MODULE.bazel
defines root of Bazel project and defines external module dependenciesbazel_dep
to import Bazel dependencies from the Bazel Central Registry (BCR)register_toolchains
to register toolchains from nixpkgsuse_repo
to bring repositories into scopenon_module_dependencies.bzl
contains legacy WORKSPACE rules that are not available as native module extensionsnixpkgs_*_configure
to create toolchainshttp_archive
to import Bazel dependenciesnixpkgs_package
to import Nix dependencies into Bazel.bazelrc
configures BazelBUILD.bazel
files define Bazel packages and targets in that packageThe repository contains bazel build files that are known to work, they are shipped in the solutions
subdirectory of the project.
A script named lab
is added to your environment with nix-shell
, it helps using the solutions files.
lab
can be used in multiple ways:
lab help
to get help and examples of uselab compare $file
to view a difference between your file and the solution if existslab display $file
to view its solution if anylab install $file
to copy the solution if any (this will replace your work!)lab install_all
install all solutions file, the project should compile fine after running this commandRead up on Bazel Concepts and Terminology.
nix-shell
Install the Nix package manager with
sh <(curl -L https://nixos.org/nix/install) --daemon
All commands from the instructions are expected to run in the environment created by entering
nix-shell
If you want to use your favorite shell (e.g. fish
) installed on your system:
nix-shell --run fish
Use direnv
to automatically set up the environment when changing to this project's directory.
This project contains missing pieces that you will have to write, with some guidance, to make it compile again.
In the files that require editing, you will find comments such as # section 1 code to add here
helping you ensure that you are looking at the right place for the current exercise.
The lab
script can be used if you need to compare your changes with the solution.
Feel free to open an issue to ask questions, or if you think something is wrong in the codelab.
Build an example Java application that prints
Welcome to the Bootcamp! Let's get going :)
to the console.
java/src/main/java/bazel/bootcamp/BUILD.bazel
HelloBazelBootcamp.java
java_binary()
HelloBazelBootcamp
bazel run //java/src/main/java/bazel/bootcamp:HelloBazelBootcamp
Build a Go server that receives log messages in the format defined in proto/logger/logger.proto
.
proto/logger/BUILD.bazel
proto_library()
logger_proto
protobuf
library based on logger.proto
go_proto_library()
logger_go_proto
importpath
server.go
compilers
["@rules_go//proto:go_grpc"]
builds functions implementing the Logger
service for gRPC
go/cmd/server/BUILD.bazel
go_library
target server_lib
is already written for youserver.go
go_binary()
go-server
server_lib
bazel run //go/cmd/server:go-server
run
implies the build
stephttp://localhost:8081
"No log messages received yet."
Build a Java client which sends log messages to the server, in the format defined in proto/logger/logger.proto
.
Edit proto/logger/BUILD.bazel
logger.proto
java_proto_library()
logger_java_proto
gRPC
service Logger
defined in logger.proto
java_grpc_library()
logger_java_grpc
Edit java/src/main/java/bazel/bootcamp/BUILD.bazel
java_library()
JavaLoggingClientLibrary
JavaLoggingClientLibrary.java
as source*_proto
and *_grpc
targets created in previous stepsJavaLoggingClientLibrary
uses the io.grpc
package, you will also need to declare a dependency on @grpc-java//core
, as well as a transport impementation such as @grpc-java//netty
.java_binary()
JavaLoggingClient
JavaLoggingClient.java
as sourceJavaLoggingClientLibrary
Run the Java binary with
bazel run //java/src/main/java/bazel/bootcamp:JavaLoggingClient
nixpkgs
issue on macOS
env CC=gcc bazel run //java/src/main/java/bazel/bootcamp:JavaLoggingClient
Note that it will not work by fixing CC
to either clang
or clang++
, as both C
and C++
dependencies are present!
Run the Go binary from Section 2 from another nix-shell
Type messages to send from the client to the server and view them on http://localhost:8081
java/src/main/java/bazel/bootcamp/BUILD.bazel
JavaLoggingClientLibrary
java_test()
JavaLoggingClientLibraryTest
JavaLoggingClientLibraryTest.java
as sourceJavaLoggingClientLibrary
target from Section 3 as dependencyJavaLoggingClient
lab install go/cmd/server/BUILD.bazel
to get the solution of this exercise and bazel run //go/cmd/server:go-server
to run it.nix-shell
, as in Section 2bazel test //java/src/main/java/bazel/bootcamp:JavaLoggingClientLibraryTest
--cache_test_results=no
in the command line.JavaLoggingClient
proto/logger/BUILD.bazel
protobuf
library implementing logger.proto
ts_proto_library()
logger_ts_proto
typescript/BUILD.bazel
app.ts
ts_project()
logger_ts_proto
as a dependencytranspiler = "tsc"
bundle
.js
)js_run_devserver()
devserver
esbuild
target and index.html
as data
dependenciesargs = ["typescript"]
to serve files from the typescript
directorytool = ":http_server"
to make it work correctlybazel run //typescript:devserver
http://localhost:5432
tests/BUILD.bazel
integrationtest.sh
sh_test
data
dependenciesbazel test <target>
and make sure that it passes
bazel test <target> --runs_per_test=10
tags
documentation may prove useful.BUILD.bazel
load
instruction to import the rule buildifier
.
buildifier-print
which warns about lint error and only prints the changes buildifier
would make.
mode = "diff"
is deprecated,
and suggesting to use a buildifier_test
rule instead.
There is a known issue preventing a buildifier_test
from being run on every folders of a project, hence, for now, let's simply ignore this deprecation warning.buildifier-fix
which fixes all the formatting errors (including linting ones).