blob: 9828143680993ae77f7dbf433824bb57b5effe85 [file] [log] [blame] [view]
kchodorow22147972017-05-01 20:08:25 +02001---
dzc22b85a22017-05-31 20:37:50 +02002layout: documentation
3title: Best practices
kchodorow22147972017-05-01 20:08:25 +02004---
dzc22b85a22017-05-31 20:37:50 +02005
Googler817e2202020-11-20 19:14:47 -08006# Best Practices
dzc22b85a22017-05-31 20:37:50 +02007
Googlercb395cb2020-12-21 10:33:20 -08008This page assumes you are familiar with Bazel and provides guidelines and
9advice on structuring your projects to take full advantage of Bazel's features.
dzc22b85a22017-05-31 20:37:50 +020010
11The overall goals are:
12
13- To use fine-grained dependencies to allow parallelism and incrementality.
14- To keep dependencies well-encapsulated.
15- To make code well-structured and testable.
16- To create a build configuration that is easy to understand and maintain.
17
18These guidelines are not requirements: few projects will be able to adhere to all of them. As the
19man page for lint says, "A special reward will be presented to the first person to produce a real
20program that produces no errors with strict checking." However, incorporating as many of these
21principles as possible should make a project more readable, less error-prone, and faster to build.
22
Googler47849d42021-01-15 17:43:25 -080023This page uses the requirement levels described in
dzc22b85a22017-05-31 20:37:50 +020024[this RFC](https://www.ietf.org/rfc/rfc2119.txt).
25
dzc22b85a22017-05-31 20:37:50 +020026## Running builds and tests
27
28A project should always be able to run `bazel build //...` and `bazel test //...` successfully on
29its stable branch. Targets that are necessary but do not build under certain circumstances (e.g.,
30require specific build flags, do not build on a certain platform, require license agreements)
31should be tagged as specifically as possible (e.g., "`requires-osx`"). This tagging allows
32targets to be filtered at a more fine-grained level than the "manual" tag and allows someone
33inspecting the BUILD file to understand what a target's restrictions are.
34
Googler817e2202020-11-20 19:14:47 -080035## Third-party dependencies
dzc22b85a22017-05-31 20:37:50 +020036
Googler817e2202020-11-20 19:14:47 -080037You may declare third-party dependencies:
laurentlb86d97d22018-10-23 10:45:05 -070038
39* Either declare them as remote repositories in the WORKSPACE file.
Greg4fa60d72019-05-01 11:28:58 -070040* Or put them in a directory called `third_party/` under your workspace directory.
dzc22b85a22017-05-31 20:37:50 +020041
42## Depending on binaries
43
44Everything should be built from source whenever possible. Generally this means that, instead of
45depending on a library `some-library.so`, you'd create a BUILD file and build `some-library.so`
46from its sources, then depend on that target.
47
buchgr2384b982017-12-21 08:09:21 -080048Always building from source ensures that a build is not using a library that was built with
49incompatible flags or a different architecture. There are also some features like coverage,
50static analysis, or dynamic analysis that will only work on the source.
dzc22b85a22017-05-31 20:37:50 +020051
52## Versioning
53
54Prefer building all code from head whenever possible. When versions must be used, avoid including
55the version in the target name (e.g., `//guava`, not `//guava-20.0`). This naming makes the library
56easier to update (only one target needs to be updated). It is also more resilient to diamond
57dependency issues: if one library depends on `guava-19.0` and one depends on `guava-20.0`, you
58could end up with a library that tries to depend on two different versions. If you created a
59misleading alias to point both targets to one guava library, then the BUILD files are misleading.
60
Googler817e2202020-11-20 19:14:47 -080061## Using the `.bazelrc` file
dzc22b85a22017-05-31 20:37:50 +020062
laszlocsomor31fb25d2019-08-20 23:55:55 -070063For project-specific options, use the configuration file your
wyv3a634fa2020-05-15 06:47:26 -070064`<workspace>/.bazelrc` (see [bazelrc format](guide.html#bazelrc)).
dzc22b85a22017-05-31 20:37:50 +020065
Dmitry Lomovb5dfe582018-10-09 14:11:30 -070066If you want to support per-user options for your project that you **do not** want to check
67into source control, include the line
68```
Kerrick Staley39ac64a2020-07-20 22:58:52 -070069try-import %workspace%/user.bazelrc
Dmitry Lomovb5dfe582018-10-09 14:11:30 -070070```
laszlocsomor31fb25d2019-08-20 23:55:55 -070071(or any other file name) in your `<workspace>/.bazelrc` and
Dmitry Lomovb5dfe582018-10-09 14:11:30 -070072add `user.bazelrc` to your `.gitignore`.
dzc22b85a22017-05-31 20:37:50 +020073
74## Packages
75
76Every directory that contains buildable files should be a package. If a BUILD file refers to files
77in subdirectories (e.g., `srcs = ["a/b/C.java"]`) it is a sign that a BUILD file should be added to
78that subdirectory. The longer this structure exists, the more likely circular dependencies will be
79inadvertently created, a target's scope will creep, and an increasing number of reverse
80dependencies will have to be updated.