aboutsummaryrefslogtreecommitdiffhomepage
path: root/site
diff options
context:
space:
mode:
authorGravatar kchodorow <kchodorow@google.com>2017-05-01 20:08:25 +0200
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2017-05-02 11:26:43 +0200
commit2214797488d6916f7c0d6eac62bfa2df3650a3de (patch)
tree19b945be6d9fd6d659340c868c0db74a25102c26 /site
parent3c484c1294a58ac4145104279532f970b95d89b2 (diff)
Add best practices doc
PiperOrigin-RevId: 154734540
Diffstat (limited to 'site')
-rw-r--r--site/_layouts/documentation.html1
-rw-r--r--site/docs/best-practices.md4
-rw-r--r--site/versions/master/docs/best-practices.md321
3 files changed, 326 insertions, 0 deletions
diff --git a/site/_layouts/documentation.html b/site/_layouts/documentation.html
index 676d6162b9..4f77d6130d 100644
--- a/site/_layouts/documentation.html
+++ b/site/_layouts/documentation.html
@@ -84,6 +84,7 @@ version_prefix: /versions/master
<li><a href="{{ page.version_prefix }}/docs/command-line-reference.html">Command-line Reference</a></li>
<li><a href="{{ page.version_prefix }}/docs/output_directories.html">Output Directories</a></li>
<li><a href="{{ page.version_prefix }}/docs/windows.html">Bazel on Windows</a></li>
+ <li><a href="{{ page.version_prefix }}/docs/best-practices.html">Best Practices</a></li>
</ul>
{% include be-nav.html %}
<h3>Extensions</h3>
diff --git a/site/docs/best-practices.md b/site/docs/best-practices.md
new file mode 100644
index 0000000000..e936d3112e
--- /dev/null
+++ b/site/docs/best-practices.md
@@ -0,0 +1,4 @@
+---
+layout: redirect
+redirect: docs/best-practices.html
+---
diff --git a/site/versions/master/docs/best-practices.md b/site/versions/master/docs/best-practices.md
new file mode 100644
index 0000000000..a1f84d7377
--- /dev/null
+++ b/site/versions/master/docs/best-practices.md
@@ -0,0 +1,321 @@
+---
+layout: documentation
+title: Best practices
+---
+
+# Best practices for Bazel
+
+This document assumes that you are familiar with Bazel and provides advice on structuring your
+projects to take full advantage of Bazel's features.
+
+The overall goals are:
+
+- To use fine-grained dependencies to allow parallelism and incrementality.
+- To keep dependencies well-encapsulated.
+- To make code well-structured and testable.
+- To create a build configuration that is easy to understand and maintain.
+
+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 document uses the requirement levels described in
+[this RFC](https://www.ietf.org/rfc/rfc2119.txt).
+
+## Contents
+
+- [General structure](#general-structure)
+ - [Running builds and tests](#running-builds-and-tests)
+ - [Third party dependencies](#third-party-dependencies)
+ - [Depending on binaries](#depending-on-binaries)
+ - [Versioning](#versioning)
+ - [.bazelrc](#bazelrc)
+ - [Packages](#packages)
+- [BUILD files](#build-files)
+ - [BUILD file style guide](#build-file-style-guide)
+ - [Formatting](#formatting)
+ - [References to targets in the current package](#references-to-targets-in-the-current-package)
+ - [Target naming](#target-naming)
+ - [Visibility](#visibility)
+ - [Dependencies](#dependencies)
+ - [Globs](#globs)
+- [Skylark](#skylark)
+ - [Skylark style guide](#skylark-style-guide)
+ - [Packaging rules](#packaging-rules)
+ - [Rule choice](#rule-choice)
+- [WORKSPACE files](#workspace-files)
+ - [Repository rules](#repository-rules)
+ - [Custom BUILD files](#custom-build-files)
+ - [Skylark repository rules](#skylark-repository-rules)
+- [Java](#java)
+ - [Directory structure](#directory-structure)
+ - [BUILD files](#build-files)
+- [C++](#c)
+ - [BUILD files](#build-files)
+ - [Include paths](#include-paths)
+- [Protos](#protos)
+ - [Recommended Code Organization](#recommended-code-organization)
+
+# General structure
+
+## Running builds and tests
+
+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 (e.g.,
+require specific build flags, do not build on a certain platform, require license agreements)
+should be tagged as specifically as possible (e.g., "`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.
+
+## Third party dependencies
+
+Prefer declaring third party dependencies as remote repositories in the WORKSPACE file. If it's
+necessary to check third party dependencies into your repository, put them in a directory called
+`third_party/` under your workspace directory. Note that all BUILD files in `third_party/` must
+include [license](https://bazel.build/versions/master/docs/be/functions.html#licenses)
+declarations.
+
+## Depending on binaries
+
+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.
+
+Building from source prevents a build from using an library that was build with incompatible flags
+or a different architecture. There are also some features like coverage, static analysis, or
+dynamic analysis that will only work on the source.
+
+## Versioning
+
+Prefer building all code from head whenever possible. When versions must be used, avoid including
+the version in the target name (e.g., `//guava`, not `//guava-20.0`). This naming makes the library
+easier to update (only one target needs to be updated). It is 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`
+
+For project-specific options, use the configuration file `_your-workspace_/tools/bazel.rc`.
+
+For options that you **do not** want to check into source control, create the configuration file
+`_your-workspace_/.bazelrc` and add `.bazelrc` to your `.gitignore`. Note that this file has a
+different name than the file above (`bazel.rc` vs `.bazelrc`).
+
+## Packages
+
+Every directory that contains buildable files should be a package. If a BUILD file refers to files
+in subdirectories (e.g., `srcs = ["a/b/C.java"]`) it is 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.
+
+# BUILD files
+
+## BUILD file style guide
+
+See the [BUILD file style
+guide](https://bazel.build/versions/master/docs/skylark/build-style.html).
+
+## Formatting
+
+[Buildifier](https://github.com/bazelbuild/buildifier) should be used to achieve the correct
+formatting for BUILD files. Editors should be configured to automatically format BUILD files on
+save. Humans should not try to format BUILD files themselves.
+
+If there is a question as to what the correct formatting is, the answer is "how buildifier formats
+it."
+
+## References to targets in the current package
+
+Files should be referred to by their paths relative to the package directory (without ever using
+up-references, such as `..`). Generated files should be prefixed with "`:`" to indicate that they
+are not sources. Source files should not be prefixed with `:`. Rules should be prefixed with `:`.
+For example, assuming `x.cc` is a source file:
+
+```python
+cc_library(
+ name = "lib",
+ srcs = ["x.cc"],
+ hdrs = [":gen-header"],
+)
+
+genrule(
+ name = "gen-header",
+ srcs = [],
+ outs = ["x.h"],
+ cmd = "echo 'int x();' > $@",
+)
+```
+
+## Target naming
+
+Target names should be descriptive. If a target contains one source file, the target should
+generally be named after that source (e.g., a `cc_library` for `chat.cc` should be named "`chat`").
+
+The eponymous target for a package (the target with the same name as the containing directory)
+should provide the functionality described by the directory name. If there is no such target, do
+not create an eponymous target.
+
+Prefer using the short name when referring to an eponymous target (`//x` instead of `//x:x`). If
+you are in the same package, prefer the local reference (`:x` instead of `//x`).
+
+## Visibility
+
+Do not set the default visibility of a package to `//visibility:public`. `//visibility:public`
+should be individually set for targets in the project's public API. These could be libraries which
+are designed to be depended on by external projects or binaries that could be used by an external
+project's build process.
+
+Otherwise, visibility should be scoped as tightly as possible, while still allowing access by tests
+and reverse dependencies. Prefer using `__pkg__` to `__subpackages__`.
+
+## Dependencies
+
+Dependencies should be restricted to direct dependencies (dependencies needed by the sources listed
+in the rule). Do not list transitive dependencies.
+
+Package-local dependencies should be listed first and referred to in a way compatible with the
+[References to targets in the current package](#references-to-targets-in-the-current-package)
+section above (not by their absolute package name).
+
+## Globs
+
+Do not use recursive globs (e.g., `glob(["**/*.java"])`). Recursive globs make BUILD files
+difficult to read, as they skip subdirectories containing BUILD files. Non-recursive globs are
+generally acceptable, see language-specific advice below for details.
+
+Indicate "no targets" with `[]`. Do not use a glob that matches nothing: it is more error-prone and
+less obvious than an empty list.
+
+# Skylark
+
+## Skylark style guide
+
+See the [Style guide for .bzl
+files](https://bazel.build/versions/master/docs/skylark/bzl-style.html) for Skylark rule guidelines.
+
+## Packaging rules
+
+See [Packaging rules](https://bazel.build/versions/master/docs/skylark/deploying.html) for advice
+on how to structure and where to put new Skylark rules.
+
+## Rule choice
+
+When using a language for which Bazel has built-in rules (e.g., C++), prefer using these rules to
+writing your own in Skylark. These rules are documented in the [build
+encyclopedia](https://bazel.build/versions/master/docs/be/overview.html).
+
+# WORKSPACE files
+
+## Repository rules
+
+Prefer `http_archive` and `new_http_archive` to `git_repository`, `new_git_repository`, and
+`maven_jar`.
+
+`git_repository` depends on jGit, which has several unpleasant bugs, and `maven_jar` uses Maven's
+internal API, which generally works but is less optimized for Bazel than `http_archive`'s
+downloader logic. Track the following issues filed to remediate these problems:
+
+- [Use `http_archive` as `git_repository`'s
+ backend.](https://github.com/bazelbuild/bazel/issues/2147)
+- [Improve `maven_jar`'s backend.](https://github.com/bazelbuild/bazel/issues/1752)
+
+Do not use `bind()`. See "[Consider removing
+bind](https://github.com/bazelbuild/bazel/issues/1952)" for a long discussion of its issues and
+alternatives.
+
+## Custom BUILD files
+
+When using a `new_` repository rule, prefer to specify `build_file_content`, not `build_file`.
+
+## Skylark repository rules
+
+A Skylark repository rule should generally be responsible for:
+
+- Detecting system settings and writing them to files.
+- Finding resources elsewhere on the system.
+- Downloading resources from URLs.
+- Generating or symlinking BUILD files into the external repository directory.
+
+Avoid using `repository_ctx.execute` when possible. For example, when using a non-Bazel C++
+library that has a build using Make, it is preferable to use `respository_ctx.download()` and then
+write a BUILD file that builds it, instead of running `ctx.execute(["make"])`.
+
+# Java
+
+## Directory structure
+
+Prefer Maven's standard directory layout (sources under `src/main/java`, tests under
+`src/test/java`).
+
+## BUILD files
+
+Use one BUILD file per package containing Java sources. Every BUILD file should contain one
+`java_library` rule that looks like this:
+
+```python
+java_library(
+ name = "directory-name",
+ srcs = glob(["*.java"]),
+ deps = [...],
+)
+```
+
+The name of the library should be the name of the directory containing the BUILD file. The sources
+should be a non-recursive glob of all Java files in the directory.
+
+Tests should be in a matching directory under `src/test` and depend on this library.
+
+# C++
+
+## BUILD files
+
+Each BUILD file should contain one `cc_library` rule target per compilation unit in the directory.
+C++ libraries should be as fine-grained as possible to provide as much incrementality as possible.
+
+If there is a single source file in `srcs`, the library should be named based on that C++ file's
+name. This library should contain a C++ file(s), any matching header file(s), and the library's
+direct dependencies. For example,
+
+```python
+cc_library(
+ name = "mylib",
+ srcs = ["mylib.cc"],
+ hdrs = ["mylib.h"],
+ deps = [":lower-level-lib"]
+)
+```
+
+There should be one `cc_test` rule target per `cc_library` target in the file. The `cc_test`'s
+source should be a file named `[libname]_test.cc`. For example, a test for the target above might
+look like:
+
+```
+cc_test(
+ name = "mylib_test",
+ srcs = ["mylib_test.cc"],
+ deps = [":mylib"]
+)
+```
+
+## Include paths
+
+All include paths should be relative to the workspace directory. Use `includes` only if a public
+header needs to be widely used at a non-workspace-relative path (for legacy or `third_party` code).
+Otherwise, prefer to use the `copts` attribute, not the `includes` attribute.
+
+Using `cc_inc_library` is discouraged, prefer `copts` or `includes`.
+See [the design document](https://docs.google.com/document/d/18qUWh0uUiJBv6ZOySvp6DEV0NjVnBoEy-r-ZHa9cmhU/edit#heading=h.kmep1cl5ym9k)
+on C++ include directories for reasoning.
+
+# Protos
+
+## Recommended Code Organization
+
+- One `proto_library` rule per `.proto` file.
+- A file named `foo.proto` will be in a rule named `foo_proto`, which is located in the same
+ package.
+- A `[language]_proto_library` that wraps a `proto_library` named `foo_proto` should be called
+ `foo_[language]_proto`, and be located in the same package.