kchodorow | 2214797 | 2017-05-01 20:08:25 +0200 | [diff] [blame] | 1 | --- |
dzc | 22b85a2 | 2017-05-31 20:37:50 +0200 | [diff] [blame] | 2 | layout: documentation |
| 3 | title: Best practices |
kchodorow | 2214797 | 2017-05-01 20:08:25 +0200 | [diff] [blame] | 4 | --- |
dzc | 22b85a2 | 2017-05-31 20:37:50 +0200 | [diff] [blame] | 5 | |
Googler | 817e220 | 2020-11-20 19:14:47 -0800 | [diff] [blame] | 6 | # Best Practices |
dzc | 22b85a2 | 2017-05-31 20:37:50 +0200 | [diff] [blame] | 7 | |
Googler | cb395cb | 2020-12-21 10:33:20 -0800 | [diff] [blame] | 8 | This page assumes you are familiar with Bazel and provides guidelines and |
| 9 | advice on structuring your projects to take full advantage of Bazel's features. |
dzc | 22b85a2 | 2017-05-31 20:37:50 +0200 | [diff] [blame] | 10 | |
| 11 | The 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 | |
| 18 | These guidelines are not requirements: few projects will be able to adhere to all of them. As the |
| 19 | man page for lint says, "A special reward will be presented to the first person to produce a real |
| 20 | program that produces no errors with strict checking." However, incorporating as many of these |
| 21 | principles as possible should make a project more readable, less error-prone, and faster to build. |
| 22 | |
Googler | 47849d4 | 2021-01-15 17:43:25 -0800 | [diff] [blame] | 23 | This page uses the requirement levels described in |
dzc | 22b85a2 | 2017-05-31 20:37:50 +0200 | [diff] [blame] | 24 | [this RFC](https://www.ietf.org/rfc/rfc2119.txt). |
| 25 | |
dzc | 22b85a2 | 2017-05-31 20:37:50 +0200 | [diff] [blame] | 26 | ## Running builds and tests |
| 27 | |
| 28 | A project should always be able to run `bazel build //...` and `bazel test //...` successfully on |
| 29 | its stable branch. Targets that are necessary but do not build under certain circumstances (e.g., |
| 30 | require specific build flags, do not build on a certain platform, require license agreements) |
| 31 | should be tagged as specifically as possible (e.g., "`requires-osx`"). This tagging allows |
| 32 | targets to be filtered at a more fine-grained level than the "manual" tag and allows someone |
| 33 | inspecting the BUILD file to understand what a target's restrictions are. |
| 34 | |
Googler | 817e220 | 2020-11-20 19:14:47 -0800 | [diff] [blame] | 35 | ## Third-party dependencies |
dzc | 22b85a2 | 2017-05-31 20:37:50 +0200 | [diff] [blame] | 36 | |
Googler | 817e220 | 2020-11-20 19:14:47 -0800 | [diff] [blame] | 37 | You may declare third-party dependencies: |
laurentlb | 86d97d2 | 2018-10-23 10:45:05 -0700 | [diff] [blame] | 38 | |
| 39 | * Either declare them as remote repositories in the WORKSPACE file. |
Greg | 4fa60d7 | 2019-05-01 11:28:58 -0700 | [diff] [blame] | 40 | * Or put them in a directory called `third_party/` under your workspace directory. |
dzc | 22b85a2 | 2017-05-31 20:37:50 +0200 | [diff] [blame] | 41 | |
| 42 | ## Depending on binaries |
| 43 | |
| 44 | Everything should be built from source whenever possible. Generally this means that, instead of |
| 45 | depending on a library `some-library.so`, you'd create a BUILD file and build `some-library.so` |
| 46 | from its sources, then depend on that target. |
| 47 | |
buchgr | 2384b98 | 2017-12-21 08:09:21 -0800 | [diff] [blame] | 48 | Always building from source ensures that a build is not using a library that was built with |
| 49 | incompatible flags or a different architecture. There are also some features like coverage, |
| 50 | static analysis, or dynamic analysis that will only work on the source. |
dzc | 22b85a2 | 2017-05-31 20:37:50 +0200 | [diff] [blame] | 51 | |
| 52 | ## Versioning |
| 53 | |
| 54 | Prefer building all code from head whenever possible. When versions must be used, avoid including |
| 55 | the version in the target name (e.g., `//guava`, not `//guava-20.0`). This naming makes the library |
| 56 | easier to update (only one target needs to be updated). It is also more resilient to diamond |
| 57 | dependency issues: if one library depends on `guava-19.0` and one depends on `guava-20.0`, you |
| 58 | could end up with a library that tries to depend on two different versions. If you created a |
| 59 | misleading alias to point both targets to one guava library, then the BUILD files are misleading. |
| 60 | |
Googler | 817e220 | 2020-11-20 19:14:47 -0800 | [diff] [blame] | 61 | ## Using the `.bazelrc` file |
dzc | 22b85a2 | 2017-05-31 20:37:50 +0200 | [diff] [blame] | 62 | |
laszlocsomor | 31fb25d | 2019-08-20 23:55:55 -0700 | [diff] [blame] | 63 | For project-specific options, use the configuration file your |
wyv | 3a634fa | 2020-05-15 06:47:26 -0700 | [diff] [blame] | 64 | `<workspace>/.bazelrc` (see [bazelrc format](guide.html#bazelrc)). |
dzc | 22b85a2 | 2017-05-31 20:37:50 +0200 | [diff] [blame] | 65 | |
Dmitry Lomov | b5dfe58 | 2018-10-09 14:11:30 -0700 | [diff] [blame] | 66 | If you want to support per-user options for your project that you **do not** want to check |
| 67 | into source control, include the line |
| 68 | ``` |
Kerrick Staley | 39ac64a | 2020-07-20 22:58:52 -0700 | [diff] [blame] | 69 | try-import %workspace%/user.bazelrc |
Dmitry Lomov | b5dfe58 | 2018-10-09 14:11:30 -0700 | [diff] [blame] | 70 | ``` |
laszlocsomor | 31fb25d | 2019-08-20 23:55:55 -0700 | [diff] [blame] | 71 | (or any other file name) in your `<workspace>/.bazelrc` and |
Dmitry Lomov | b5dfe58 | 2018-10-09 14:11:30 -0700 | [diff] [blame] | 72 | add `user.bazelrc` to your `.gitignore`. |
dzc | 22b85a2 | 2017-05-31 20:37:50 +0200 | [diff] [blame] | 73 | |
| 74 | ## Packages |
| 75 | |
| 76 | Every directory that contains buildable files should be a package. If a BUILD file refers to files |
| 77 | in subdirectories (e.g., `srcs = ["a/b/C.java"]`) it is a sign that a BUILD file should be added to |
| 78 | that subdirectory. The longer this structure exists, the more likely circular dependencies will be |
| 79 | inadvertently created, a target's scope will creep, and an increasing number of reverse |
| 80 | dependencies will have to be updated. |