Common Bazel style guide and best practices

Overview

The following style and best practices apply to all Bazel files in Fuchsia.

This page is part of the Bazel style guide and best practices, which contains additional guidance for specific scenarios.

Local variables for lists of source files and dependencies

While the official guide discourages dependency variables, Fuchsia permits them for managing large, shared lists of source files or dependencies. Exercise by considering whether the lists are substantially similar or merely share a few common items.

No subtraction: Never remove an item from a list variable.

Visibility

The following are general guidelines that apply to both BUILD.bazel and .bzl files. More specific details are provided on the page for each.

Always specify visibility where possible in both BUILD.bazel and .bzl files

The only scenarios where the attribute is supported that it does not need to be specified is macros that are private to the package (directory).

Do not use public visibility

Do not use public visibility ("//visibility:public" or visibility("public")) outside bazel_sdk/ directories. This level of access is only appropriate if the code is used by external repositories, which is not applicable to non-SDK code in fuchsia.git.

Visibility should be scoped as tightly as possible, while still allowing access by tests and reverse dependencies

Visibility should be restricted to only those targets that need it and/or should be allowed to use it. Be conservative yet practical. For example, if a target is used within five immediate subdirectories of //src, consider using //src:__subpackages__ to avoid needing to modify the visibility when a new use is added. However, if, for example, the target should only be used by drivers, limit it to packages that implement drivers.

Use package groups for common non-trivial visibility definitions

If the visibility of multiple targets should be restricted to the same set of labels, consider representing that set with a package_group. package_group also supports negative visibility when used with targets but not with Load visibility.

Do not mix SDK and platform symbols and targets

Platform targets (i.e., everything that goes in an AIB or in the IDK) must not use symbols defined in the Fuchsia Bazel SDK, targets provided by it, or targets built using it.

The opposite is also true, targets built using the Fuchsia Bazel SDK should not depend on platform targets or load symbols from platform .bzl files.

Do not use Fuchsia Bazel SDK paths

Platform code should never access file paths containing bazel_sdk or Fuchsia Bazel SDK repository paths such as:

  • @fuchsia_sdk//

  • @internal_sdk//

  • @rules_fuchsia//fuchsia

The only such paths that are permitted begin with @fuchsia_rules_common/, though only the Build team should use these directly.

Platform code should also avoid bazel_sdk/ paths except in the case of specific build rules that share implementation with the Fuchsia Bazel SDK.

Labels for targets and .bzl files

Referencing targets

When referencing targets (e.g., in deps), labels beginning with any of the following are permitted as long as prohibited label patterns are not used:

Loading from .bzl files

Most general purpose macros and rules for the Fuchsia platform can be found within //build/bazel/rules/.

It is safe to load() from .bzl files whose labels begin with the following as long as prohibited label patterns are not used:

The following are also allowed, though only developers on the Build Team are likely to use them:

  • @fuchsia_build_config//:defs.bzl

  • @fuchsia_build_info//:args.bzl

  • @fuchsia_rules_common//

Prohibited label patterns

Do NOT use [SHAC error]:

  • Workspace root package labels (those starting with //:)

    • There are very specific and very rare circumstances where this is needed (see issue 560343570), but this should generally only be done by the Build team.
  • Labels that contain a slash (/) in the package name, which is the part of the label after the colon (:).

    • There are rare exceptions for integrating third-party libraries.

fuchsia_... files and symbols are in the Fuchsia Bazel SDK

Avoid defining files, macros, and rules with names that begin with fuchsia_. Existing instances of names beginning with fuchsia_ likely belong to the Fuchsia Bazel SDK (see Do not use Fuchsia Bazel SDK paths), and avoiding such names helps maintain that separation.

See Wrapping built-in and common rules, macros, and functions for one pattern used when needing to differentiate Fuchsia platform from general Bazel identifiers.

Use Fuchsia-specific wrappers

When Fuchsia-specific wrappers exist, use those rather than external repositories, macros, etc. This helps ensure that Fuchsia build configurations are applied consistently.

Specifically, there are wrappers for the following languages:

  • C/C++: Use fx_cc_...() from //build/bazel/rules/cc/... rather than cc_... from @rules_cc//.

  • Rust: Use rustc_...() from //build/bazel/rules/rust/... rather than rust_... from @rules_rust//.

Fuchsia does not have wrappers for the following languages. Load from the following paths for consistency:

  • Go: @io_bazel_rules_go//go...

  • Python: @rules_python//python...

Strings

Use double quotation marks for strings except to avoid escaping

By default, use double quotation marks for strings. However, if printing a double quotation would be more appropriate and doing so would involve escaping the double quotation marks (\"), use single quotation marks to avoid the escaping.