blob: 09daf780de8470de242b47ec41a3e251cb856190 [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
6# Best practices for Bazel
7
8This document assumes that you are familiar with Bazel and provides advice on structuring your
9projects to take full advantage of Bazel's features.
10
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
23This document uses the requirement levels described in
24[this RFC](https://www.ietf.org/rfc/rfc2119.txt).
25
26## Contents
27
28- [General structure](#general-structure)
29 - [Running builds and tests](#running-builds-and-tests)
30 - [Third party dependencies](#third-party-dependencies)
31 - [Depending on binaries](#depending-on-binaries)
32 - [Versioning](#versioning)
33 - [.bazelrc](#bazelrc)
34 - [Packages](#packages)
35- [BUILD files](#build-files)
36 - [BUILD file style guide](#build-file-style-guide)
37 - [Formatting](#formatting)
38 - [References to targets in the current package](#references-to-targets-in-the-current-package)
39 - [Target naming](#target-naming)
40 - [Visibility](#visibility)
41 - [Dependencies](#dependencies)
42 - [Globs](#globs)
laurentlb978780d2017-07-19 19:19:21 +020043- [.bzl files](#bzl-files)
44 - [.bzl files style guide](#bzl-files-style-guide)
dzc22b85a22017-05-31 20:37:50 +020045 - [Packaging rules](#packaging-rules)
46 - [Rule choice](#rule-choice)
47- [WORKSPACE files](#workspace-files)
48 - [Repository rules](#repository-rules)
49 - [Custom BUILD files](#custom-build-files)
50 - [Skylark repository rules](#skylark-repository-rules)
51- [Java](#java)
52 - [Directory structure](#directory-structure)
53 - [BUILD files](#build-files)
54- [C++](#c)
55 - [BUILD files](#build-files)
56 - [Include paths](#include-paths)
57- [Protos](#protos)
58 - [Recommended Code Organization](#recommended-code-organization)
59
60# General structure
61
62## Running builds and tests
63
64A project should always be able to run `bazel build //...` and `bazel test //...` successfully on
65its stable branch. Targets that are necessary but do not build under certain circumstances (e.g.,
66require specific build flags, do not build on a certain platform, require license agreements)
67should be tagged as specifically as possible (e.g., "`requires-osx`"). This tagging allows
68targets to be filtered at a more fine-grained level than the "manual" tag and allows someone
69inspecting the BUILD file to understand what a target's restrictions are.
70
71## Third party dependencies
72
73Prefer declaring third party dependencies as remote repositories in the WORKSPACE file. If it's
74necessary to check third party dependencies into your repository, put them in a directory called
75`third_party/` under your workspace directory. Note that all BUILD files in `third_party/` must
dzc5596d3b2017-06-07 21:51:52 -040076include [license](https://docs.bazel.build/be/functions.html#licenses)
dzc22b85a22017-05-31 20:37:50 +020077declarations.
78
79## Depending on binaries
80
81Everything should be built from source whenever possible. Generally this means that, instead of
82depending on a library `some-library.so`, you'd create a BUILD file and build `some-library.so`
83from its sources, then depend on that target.
84
85Building from source prevents a build from using a library that was built with incompatible flags
86or a different architecture. There are also some features like coverage, static analysis, or
87dynamic analysis that will only work on the source.
88
89## Versioning
90
91Prefer building all code from head whenever possible. When versions must be used, avoid including
92the version in the target name (e.g., `//guava`, not `//guava-20.0`). This naming makes the library
93easier to update (only one target needs to be updated). It is also more resilient to diamond
94dependency issues: if one library depends on `guava-19.0` and one depends on `guava-20.0`, you
95could end up with a library that tries to depend on two different versions. If you created a
96misleading alias to point both targets to one guava library, then the BUILD files are misleading.
97
98## `.bazelrc`
99
100For project-specific options, use the configuration file `_your-workspace_/tools/bazel.rc`.
101
102For options that you **do not** want to check into source control, create the configuration file
103`_your-workspace_/.bazelrc` and add `.bazelrc` to your `.gitignore`. Note that this file has a
104different name than the file above (`bazel.rc` vs `.bazelrc`).
105
106## Packages
107
108Every directory that contains buildable files should be a package. If a BUILD file refers to files
109in subdirectories (e.g., `srcs = ["a/b/C.java"]`) it is a sign that a BUILD file should be added to
110that subdirectory. The longer this structure exists, the more likely circular dependencies will be
111inadvertently created, a target's scope will creep, and an increasing number of reverse
112dependencies will have to be updated.
113
114# BUILD files
115
dzc22b85a22017-05-31 20:37:50 +0200116See the [BUILD file style
dzc5596d3b2017-06-07 21:51:52 -0400117guide](https://docs.bazel.build/skylark/build-style.html).
dzc22b85a22017-05-31 20:37:50 +0200118
laurentlb978780d2017-07-19 19:19:21 +0200119# .bzl files
dzc22b85a22017-05-31 20:37:50 +0200120
laurentlb978780d2017-07-19 19:19:21 +0200121## .bzl files style guide
dzc22b85a22017-05-31 20:37:50 +0200122
123See the [Style guide for .bzl
dzc5596d3b2017-06-07 21:51:52 -0400124files](https://docs.bazel.build/skylark/bzl-style.html) for Skylark rule guidelines.
dzc22b85a22017-05-31 20:37:50 +0200125
126## Packaging rules
127
dzc5596d3b2017-06-07 21:51:52 -0400128See [Packaging rules](https://docs.bazel.build/skylark/deploying.html) for advice
dzc22b85a22017-05-31 20:37:50 +0200129on how to structure and where to put new Skylark rules.
130
131## Rule choice
132
133When using a language for which Bazel has built-in rules (e.g., C++), prefer using these rules to
134writing your own in Skylark. These rules are documented in the [build
dzc5596d3b2017-06-07 21:51:52 -0400135encyclopedia](https://docs.bazel.build/be/overview.html).
dzc22b85a22017-05-31 20:37:50 +0200136
137# WORKSPACE files
138
139## Repository rules
140
141Prefer `http_archive` and `new_http_archive` to `git_repository`, `new_git_repository`, and
142`maven_jar`.
143
144`git_repository` depends on jGit, which has several unpleasant bugs, and `maven_jar` uses Maven's
145internal API, which generally works but is less optimized for Bazel than `http_archive`'s
146downloader logic. Track the following issues filed to remediate these problems:
147
148- [Use `http_archive` as `git_repository`'s
149 backend.](https://github.com/bazelbuild/bazel/issues/2147)
150- [Improve `maven_jar`'s backend.](https://github.com/bazelbuild/bazel/issues/1752)
151
152Do not use `bind()`. See "[Consider removing
153bind](https://github.com/bazelbuild/bazel/issues/1952)" for a long discussion of its issues and
154alternatives.
155
156## Custom BUILD files
157
158When using a `new_` repository rule, prefer to specify `build_file_content`, not `build_file`.
159
160## Skylark repository rules
161
162A Skylark repository rule should generally be responsible for:
163
164- Detecting system settings and writing them to files.
165- Finding resources elsewhere on the system.
166- Downloading resources from URLs.
167- Generating or symlinking BUILD files into the external repository directory.
168
169Avoid using `repository_ctx.execute` when possible. For example, when using a non-Bazel C++
170library that has a build using Make, it is preferable to use `respository_ctx.download()` and then
171write a BUILD file that builds it, instead of running `ctx.execute(["make"])`.
172
173# Java
174
175## Directory structure
176
177Prefer Maven's standard directory layout (sources under `src/main/java`, tests under
178`src/test/java`).
179
180## BUILD files
181
182Use one BUILD file per package containing Java sources. Every BUILD file should contain one
183`java_library` rule that looks like this:
184
185```python
186java_library(
187 name = "directory-name",
188 srcs = glob(["*.java"]),
189 deps = [...],
190)
191```
192
193The name of the library should be the name of the directory containing the BUILD file. The sources
194should be a non-recursive glob of all Java files in the directory.
195
196Tests should be in a matching directory under `src/test` and depend on this library.
197
198# C++
199
200## BUILD files
201
202Each BUILD file should contain one `cc_library` rule target per compilation unit in the directory.
203C++ libraries should be as fine-grained as possible to provide as much incrementality as possible.
204
205If there is a single source file in `srcs`, the library should be named based on that C++ file's
206name. This library should contain a C++ file(s), any matching header file(s), and the library's
207direct dependencies. For example,
208
209```python
210cc_library(
211 name = "mylib",
212 srcs = ["mylib.cc"],
213 hdrs = ["mylib.h"],
214 deps = [":lower-level-lib"]
215)
216```
217
218There should be one `cc_test` rule target per `cc_library` target in the file. The `cc_test`'s
219source should be a file named `[libname]_test.cc`. For example, a test for the target above might
220look like:
221
222```
223cc_test(
224 name = "mylib_test",
225 srcs = ["mylib_test.cc"],
226 deps = [":mylib"]
227)
228```
229
230## Include paths
231
232All include paths should be relative to the workspace directory. Use `includes` only if a public
233header needs to be widely used at a non-workspace-relative path (for legacy or `third_party` code).
234Otherwise, prefer to use the `copts` attribute, not the `includes` attribute.
235
236Using `cc_inc_library` is discouraged, prefer `copts` or `includes`.
237See [the design document](https://docs.google.com/document/d/18qUWh0uUiJBv6ZOySvp6DEV0NjVnBoEy-r-ZHa9cmhU/edit#heading=h.kmep1cl5ym9k)
238on C++ include directories for reasoning.
239
240# Protos
241
242## Recommended Code Organization
243
244- One `proto_library` rule per `.proto` file.
245- A file named `foo.proto` will be in a rule named `foo_proto`, which is located in the same
246 package.
247- A `[language]_proto_library` that wraps a `proto_library` named `foo_proto` should be called
248 `foo_[language]_proto`, and be located in the same package.