Project: /_project.yaml Book: /_book.yaml
{% include “_buttons.html” %}
This page assumes you are familiar with Bazel and provides guidelines and advice on structuring your projects to take full advantage of Bazel's features.
The overall goals are:
These guidelines are not requirements: few projects will be able to adhere to all of them. As the man page for lint says, “A special reward will be presented to the first person to produce a real program that produces no errors with strict checking.” However, incorporating as many of these principles as possible should make a project more readable, less error-prone, and faster to build.
This page uses the requirement levels described in this RFC{: .external}.
A project should always be able to run bazel build //...
and bazel test //...
successfully on its stable branch. Targets that are necessary but do not build under certain circumstances (such as,require specific build flags, don‘t build on a certain platform, require license agreements) should be tagged as specifically as possible (for example, “requires-osx
”). This tagging allows targets to be filtered at a more fine-grained level than the “manual” tag and allows someone inspecting the BUILD
file to understand what a target’s restrictions are.
You may declare third-party dependencies:
WORKSPACE
file.third_party/
under your workspace directory.Everything should be built from source whenever possible. Generally this means that, instead of depending on a library some-library.so
, you'd create a BUILD
file and build some-library.so
from its sources, then depend on that target.
Always building from source ensures that a build is not using a library that was built with incompatible flags or a different architecture. There are also some features like coverage, static analysis, or dynamic analysis that only work on the source.
Prefer building all code from head whenever possible. When versions must be used, avoid including the version in the target name (for example, //guava
, not //guava-20.0
). This naming makes the library easier to update (only one target needs to be updated). It's also more resilient to diamond dependency issues: if one library depends on guava-19.0
and one depends on guava-20.0
, you could end up with a library that tries to depend on two different versions. If you created a misleading alias to point both targets to one guava
library, then the BUILD
files are misleading.
.bazelrc
file {:#bazelrc-file}For project-specific options, use the configuration file your {{ '<var>' }}workspace{{ '</var>' }}/.bazelrc
(see bazelrc format).
If you want to support per-user options for your project that you do not want to check into source control, include the line:
try-import %workspace%/user.bazelrc
(or any other file name) in your {{ '<var>' }}workspace{{ '</var>' }}/.bazelrc
and add user.bazelrc
to your .gitignore
.
Every directory that contains buildable files should be a package. If a BUILD
file refers to files in subdirectories (such as, srcs = ["a/b/C.java"]
) it‘s a sign that a BUILD
file should be added to that subdirectory. The longer this structure exists, the more likely circular dependencies will be inadvertently created, a target’s scope will creep, and an increasing number of reverse dependencies will have to be updated.