This is a small Bazel example that uses third party dependencies (also called external dependencies) but is well structured following the principles of software development. The main goal is that the principles and guidelines shown here they should scale big. Bazel consultants with access to over 40 codebases have seen this pattern deployed successfully at scale.
Because of this, we want to keep the following requirements:
- Works with bzlmod both enabled and disabled, as a repository may need during a migration.
- We don't want all dependencies listed in the
WORKSPACE
file. It mixes order-dependent and order-independent code, and makes the file harder to manage. Thus we forbidhttp_archive
and other "fetch" functions from being loaded inWORKSPACE
- The principles mentioned here should be applicable to any programming language.
The MODULE.bazel
file lists the dependencies. When bzlmod is enabled, the WORKSPACE.bzlmod
file
takes priority over the WORKSPACE
file. Since WORKSPACE.bzlmod
is empty, it means this
workspace has been fully converted to work with bzlmod.
All dependencies need to be loaded in the workspace file but this does not prevent us on splitting this in several files. The first split comes on the WORKSPACE
, first we load the source code of all declared dependencies by calling fetch_deps
, and then we finish what is left to have a fully loaded dependency.
Because WORKSPACE doesn't have the transitive dependency semantics of bzlmod, it requires us as the user to repeat the transitive dependencies. After declaring our external deps to fetch, we must load and then call the transitive dependency fetching function from each direct dependency, and then any initializers such as toolchain registration. The rules should indicate what WORKSPACE incantation is required in their README or release notes.
In cases where the versions of some transitive dependency are skewed, it can be hard to tell how this
relates to the order of the WORKSPACE calls. In this case, you can add transitive dependencies to
the fetch_deps
macro as a workaround. Since bzlmod will be the only way to specify dependencies
in some future version of Bazel, you can treat this as a short-term problem.
In this example you can find a C++ binary, a C++ library and two C++ tests, one using Catch2 and the other one using Google Test.
You can run the C++ binary with the following command:
bazel run //:hello_world
You can run the tests with the following command:
bazel test //:all --test_output=streamed
For the Catch2 test, you can add additinal parameters for a nicer output:
bazel test //:catch2_test --test_arg "--reporter compact" --test_arg --success --test_output=streamed
If you want to know more about the parameters of the bazel command, you can check here
To try with bzlmod, add the --enable_bzlmod
flag to any of the bazel commands above.