--- layout: documentation title: User Manual ---

A User's Guide to Bazel

Bazel overview

To run Bazel, go to your base workspace directory or any of its subdirectories and type bazel.

  % bazel help
                             [Bazel release bazel-<version>]
  Usage: bazel <command> <options> ...

  Available commands:
    analyze-profile     Analyzes build profile data.
    build               Builds the specified targets.

    canonicalize-flags  Canonicalize Bazel flags.
    clean               Removes output files and optionally stops the server.

    help                Prints help for commands, or the index.

    info                Displays runtime info about the bazel server.

    fetch                Fetches all external dependencies of a target.
    mobile-install      Installs apps on mobile devices.

    query               Executes a dependency graph query.

    run                 Runs the specified target.
    shutdown            Stops the Bazel server.
    test                Builds and runs the specified test targets.
    version             Prints version information for Bazel.

  Getting more help:
    bazel help <command>
                     Prints help and options for <command>.
    bazel help startup_options
                     Options for the JVM hosting Bazel.
    bazel help target-syntax
                     Explains the syntax for specifying targets.
    bazel help info-keys
                     Displays a list of keys used by the info command.

The bazel tool performs many functions, called commands; users of CVS and Subversion will be familiar with this "Swiss army knife" arrangement. The most commonly used one is of course bazel build. You can browse the online help messages using bazel help.

Client/server implementation

The Bazel system is implemented as a long-lived server process. This allows it to perform many optimizations not possible with a batch-oriented implementation, such as caching of BUILD files, dependency graphs, and other metadata from one build to the next. This improves the speed of incremental builds, and allows different commands, such as build and query to share the same cache of loaded packages, making queries very fast.

When you run bazel, you're running the client. The client finds the server based on the path of the base workspace directory and your userid, so if you build in multiple workspaces, you'll have multiple Bazel server processes. Multiple users on the same workstation can build concurrently in the same workspace. If the client cannot find a running server instance, it starts a new one. The server process will stop after a period of inactivity (3 hours, by default).

For the most part, the fact that there is a server running is invisible to the user, but sometimes it helps to bear this in mind. For example, if you're running scripts that perform a lot of automated builds in different directories, it's important to ensure that you don't accumulate a lot of idle servers; you can do this by explicitly shutting them down when you're finished with them, or by specifying a short timeout period.

The name of a Bazel server process appears in the output of ps x or ps -e f as bazel(dirname), where dirname is the basename of the directory enclosing the root your workspace directory. For example:

  % ps -e f
  16143 ?        Sl     3:00 bazel(src-jrluser2) -server -Djava.library.path=...

This makes it easier to find out which server process belongs to a given workspace. (Beware that with certain other options to ps, Bazel server processes may be named just java.) Bazel servers can be stopped using the shutdown command.

You can also run Bazel in batch mode using the --batch startup flag. This will immediately shut down the process after the command (build, test, etc.) has finished and not keep a server process around.

When running bazel, the client first checks that the server is the appropriate version; if not, the server is stopped and a new one started. This ensures that the use of a long-running server process doesn't interfere with proper versioning.

.bazelrc, the Bazel configuration file, the --bazelrc=file option, and the --config=value option

Bazel accepts many options. Typically, some of these are varied frequently (e.g. --subcommands) while others stay the same across several builds (e.g. --package_path). To avoid having to specify these constant options every time you do a build or run some other Bazel command, Bazel allows you to specify options in a configuration file.

Bazel looks for an optional configuration file in the location specified by the --bazelrc=file option. If this option is not specified then, by default, Bazel looks for the file called .bazelrc in one of two directories: first, in your base workspace directory, then in your home directory. If it finds a file in the first (workspace-specific) location, it will not look at the second (global) location.

The --bazelrc=file option must appear before the command name (e.g. build), and must use the = syntax—a space is not allowed.

The option --bazelrc=/dev/null effectively disables the use of a configuration file. We strongly recommend that you use this option when performing release builds, or automated tests that invoke Bazel.

Aside from the configuration file described above, Bazel also looks for a master configuration file next to the binary, in the workspace at tools/bazel.rc or system-wide at /etc/bazel.bazelrc. These files are here to support installation-wide options or options shared between users.

Like all UNIX "rc" files, the .bazelrc file is a text file with a line-based grammar. Lines starting # are considered comments and are ignored, as are blank lines. Each line contains a sequence of words, which are tokenized according to the same rules as the Bourne shell. The first word on each line is the name of a Bazel command, such as build or query. The remaining words are the default options that apply to that command. More than one line may be used for a command; the options are combined as if they had appeared on a single line. (Users of CVS, another tool with a "Swiss army knife" command-line interface, will find the syntax familiar to that of .cvsrc.)

Startup options may be specified in the .bazelrc file using the command startup. These options are described in the interactive help at bazel help startup_options.

Options specified in the command line always take precedence over those from a configuration file, and options in the user-specific configuration file always take precedence over the master one.

Options may include words other than flags, such as the names of build targets, etc; these are always prepended to the explicit argument list provided on the command-line, if any.

Common command options may be specified in the .bazelrc file using the command common.

In addition, commands may have :name suffixes. These options are ignored by default, but can be pulled in through the --config=name option, either on the command line or in a .bazelrc file. The intention is that these bundle command line options that are commonly used together, for example --config=memcheck.

Note that some config sections are defined in the master bazelrc file. To avoid conflicts, user-defined sections should start with the '_' (underscore) character.

The command named import is special: if Bazel encounters such a line in a .bazelrc file, it parses the contents of the file referenced by the import statement, too. Options specified in an imported file take precedence over ones specified before the import statement, options specified after the import statement take precedence over the ones in the imported file, and options in files imported later take precedence over files imported earlier.

Here's an example ~/.bazelrc file:

  # Bob's Bazel option defaults

  startup --batch --host_jvm_args=-XX:-UseParallelGC
  import /home/bobs_project/bazelrc
  build --show_timestamps --keep_going --jobs 600
  build --color=yes
  query --keep_going

  build:memcheck --strip=never --test_timeout=3600

Building programs with Bazel

The build command

The most important function of Bazel is, of course, building code. Type bazel build followed by the name of the target you wish to build. Here's a typical session:

  % bazel build //foo
  ____Loading package: foo
  ____Loading package: bar
  ____Loading package: baz
  ____Loading complete.  Analyzing...
  ____Building 1 target...
  ____[0 / 3] Executing Genrule //bar:helper_rule
  ____[1 / 3] Executing Genrule //baz:another_helper_rule
  ____[2 / 3] Building foo/foo.bin
  Target //foo:foo up-to-date:
    bazel-bin/foo/foo.bin
    bazel-bin/foo/foo
  ____Elapsed time: 9.905s

Bazel prints the progress messages as it loads all the packages in the transitive closure of dependencies of the requested target, then analyzes them for correctness and to create the build actions, finally executing the compilers and other tools of the build.

Bazel prints progress messages during the execution phase of the build, showing the current build step (compiler, linker, etc.) that is being started, and the number of completed over total number of build actions. As the build starts the number of total actions will often increase as Bazel discovers the entire action graph, but the number will usually stabilize within a few seconds.

At the end of the build Bazel prints which targets were requested, whether or not they were successfully built, and if so, where the output files can be found. Scripts that run builds can reliably parse this output; see --show_result for more details.

Typing the same command again:

  % bazel build //foo
  ____Loading...
  ____Found 1 target...
  ____Building complete.
  Target //foo:foo up-to-date:
    bazel-bin/foo/foo.bin
    bazel-bin/foo/foo
  ____Elapsed time: 0.280s

we see a "null" build: in this case, there are no packages to re-load, since nothing has changed, and no build steps to execute. (If something had changed in "foo" or some of its dependencies, resulting in the reexecution of some build actions, we would call it an "incremental" build, not a "null" build.)

Before you can start a build, you will need a Bazel workspace. This is simply a directory tree that contains all the source files needed to build your application. Bazel allows you to perform a build from a completely read-only volume.

Setting up a --package_path

Bazel finds its packages by searching the package path. This is a colon separated ordered list of bazel directories, each being the root of a partial source tree.

To specify a custom package path using the --package_path option:

  % bazel build --package_path %workspace%:/some/other/root

Package path elements may be specified in three formats:

  1. If the first character is /, the path is absolute.
  2. If the path starts with %workspace%, the path is taken relative to the nearest enclosing bazel directory.
    For instance, if your working directory is /home/bob/clients/bob_client/bazel/foo, then the string %workspace% in the package-path is expanded to /home/bob/clients/bob_client/bazel.
  3. Anything else is taken relative to the working directory.
    This is usually not what you mean to do, and may behave unexpectedly if you use Bazel from directories below the bazel workspace. For instance, if you use the package-path element ., and then cd into the directory /home/bob/clients/bob_client/bazel/foo, packages will be resolved from the /home/bob/clients/bob_client/bazel/foo directory.

If you use a non-default package path, we recommend that you specify it in your Bazel configuration file for convenience.

Bazel doesn't require any packages to be in the current directory, so you can do a build from an empty bazel workspace if all the necessary packages can be found somewhere else on the package path.

Example: Building from an empty client

  % mkdir -p foo/bazel
  % cd foo/bazel
  % bazel build --package_path /some/other/path //foo

Specifying targets to build

Bazel allows a number of ways to specify the targets to be built. Collectively, these are known as target patterns. The on-line help displays a summary of supported patterns:

% bazel help target-syntax

Target pattern syntax
=====================

The BUILD file label syntax is used to specify a single target. Target
patterns generalize this syntax to sets of targets, and also support
working-directory-relative forms, recursion, subtraction and filtering.
Examples:

Specifying a single target:

  //foo/bar:wiz     The single target '//foo/bar:wiz'.
  foo/bar/wiz       Equivalent to:
                      '//foo/bar/wiz:wiz' if foo/bar/wiz is a package,
                      '//foo/bar:wiz' if foo/bar is a package,
                      '//foo:bar/wiz' otherwise.
  //foo/bar         Equivalent to '//foo/bar:bar'.

Specifying all rules in a package:

  //foo/bar:all       Matches all rules in package 'foo/bar'.

Specifying all rules recursively beneath a package:

  //foo/...:all     Matches all rules in all packages beneath directory 'foo'.
  //foo/...           (ditto)

  By default, directory symlinks are followed when performing this recursive traversal, except
  those that point to under the output base (for example, the convenience symlinks that are created
  in the root directory of the workspace) But we understand that your workspace may intentionally
  contain directories with unusual symlink structures that you don't want consumed. As such, if a
  directory has a file named
  'DONT_FOLLOW_SYMLINKS_WHEN_TRAVERSING_THIS_DIRECTORY_VIA_A_RECURSIVE_TARGET_PATTERN' then symlinks
  in that directory won't be followed when evaluating recursive target patterns.

Working-directory relative forms:  (assume cwd = 'workspace/foo')

  Target patterns which do not begin with '//' are taken relative to
  the working directory.  Patterns which begin with '//' are always
  absolute.

  ...:all           Equivalent to  '//foo/...:all'.
  ...                 (ditto)

  bar/...:all       Equivalent to  '//foo/bar/...:all'.
  bar/...             (ditto)

  bar:wiz           Equivalent to '//foo/bar:wiz'.
  :foo              Equivalent to '//foo:foo'.

  bar               Equivalent to '//foo/bar:bar'.
  foo/bar           Equivalent to '//foo/foo/bar:bar'.

  bar:all           Equivalent to '//foo/bar:all'.
  :all              Equivalent to '//foo:all'.

Summary of target wildcards:

  :all,             Match all rules in the specified packages.
  :*, :all-targets  Match all targets (rules and files) in the specified
                      packages, including ones not built by default, such
                      as _deploy.jar files.

Subtractive patterns:

  Target patterns may be preceded by '-', meaning they should be
  subtracted from the set of targets accumulated by preceding
  patterns. (Note that this means order matters.) For example:

    % bazel build -- foo/... -foo/contrib/...

  builds everything in 'foo', except 'contrib'.  In case a target not
  under 'contrib' depends on something under 'contrib' though, in order to
  build the former bazel has to build the latter too. As usual, the '--' is
  required to prevent '-f' from being interpreted as an option.

Whereas labels are used to specify individual targets, e.g. for declaring dependencies in BUILD files, Bazel's target patterns are a syntax for specifying multiple targets: they are a generalization of the label syntax for sets of targets, using wildcards. In the simplest case, any valid label is also a valid target pattern, identifying a set of exactly one target.

foo/... is a wildcard over packages, indicating all packages recursively beneath directory foo (for all roots of the package path). :all is a wildcard over targets, matching all rules within a package. These two may be combined, as in foo/...:all, and when both wildcards are used, this may be abbreviated to foo/....

In addition, :* (or :all-targets) is a wildcard that matches every target in the matched packages, including files that aren't normally built by any rule, such as _deploy.jar files associated with java_binary rules.

This implies that :* denotes a superset of :all; while potentially confusing, this syntax does allow the familiar :all wildcard to be used for typical builds, where building targets like the _deploy.jar is not desired.

In addition, Bazel allows a slash to be used instead of the colon required by the label syntax; this is often convenient when using Bash filename expansion. For example, foo/bar/wiz is equivalent to //foo/bar:wiz (if there is a package foo/bar) or to //foo:bar/wiz (if there is a package foo).

Many Bazel commands accept a list of target patterns as arguments, and they all honor the prefix negation operator `-'. This can be used to subtract a set of targets from the set specified by the preceding arguments. (Note that this means order matters.) For example,

  bazel build foo/... bar/...

means "build all targets beneath foo and all targets beneath bar", whereas

  bazel build -- foo/... -foo/bar/...

means "build all targets beneath foo except those beneath foo/bar". (The -- argument is required to prevent the subsequent arguments starting with - from being interpreted as additional options.)

It's important to point out though that subtracting targets this way will not guarantee that they are not built, since they may be dependencies of targets that weren't subtracted. For example, if there were a target //foo:all-apis that among others depended on //foo/bar:api, then the latter would be built as part of building the former.

Targets with tags=["manual"] will not be included in wildcard target patterns (..., :*, :all, etc). You should specify such test targets with explicit target patterns on the command line if you want Bazel to build/test them.

Fetching external dependencies

By default, Bazel will download and symlink external dependencies during the build. However, this can be undesirable, either because you'd like to know when new external dependendencies are added or because you'd like to "prefetch" dependencies (say, before a flight where you'll be offline). If you would like to prevent new dependencies from being added during builds, you can specify the --fetch=false flag. Note that this flag only applies to repository rules that do not point to a directory in the local file system. Changes, for example, to local_repository, new_local_repository and Android SDK and NDK repository rules will always take effect regardless of the value --fetch .

If you disallow fetching during builds and Bazel finds new external dependencies, your build will fail.

You can manually fetch dependencies by running bazel fetch. If you disallow during-build fetching, you'll need to run bazel fetch:

  1. Before you build for the first time.
  2. After you add a new external dependency.
Once it has been run, you should not need to run it again until the WORKSPACE file changes.

fetch takes a list of targets to fetch dependencies for. For example, this would fetch dependencies needed to build //foo:bar and //bar:baz:

$ bazel fetch //foo:bar //bar:baz

To fetch all external dependencies for a workspace, run:

$ bazel fetch //...

You do not need to run bazel fetch at all if you have all of the tools you are using (from library jars to the JDK itself) under your workspace root. However, if you're using anything outside of the workspace directory then you will need to run bazel fetch before running bazel build.

Build configurations and cross-compilation

All the inputs that specify the behavior and result of a given build can be divided into two distinct categories. The first kind is the intrinsic information stored in the BUILD files of your project: the build rule, the values of its attributes, and the complete set of its transitive dependencies. The second kind is the external or environmental data, supplied by the user or by the build tool: the choice of target architecture, compilation and linking options, and other toolchain configuration options. We refer to a complete set of environmental data as a configuration.

In any given build, there may be more than one configuration. Consider a cross-compile, in which you build a //foo:bin executable for a 64-bit architecture, but your workstation is a 32-bit machine. Clearly, the build will require building //foo:bin using a toolchain capable of creating 64-bit executables, but the build system must also build various tools used during the build itself—for example tools that are built from source, then subsequently used in, say, a genrule—and these must be built to run on your workstation. Thus we can identify two configurations: the host configuration, which is used for building tools that run during the build, and the target configuration (or request configuration, but we say "target configuration" more often even though that word already has many meanings), which is used for building the binary you ultimately requested.

Typically, there are many libraries that are prerequisites of both the requested build target (//foo:bin) and one or more of the host tools, for example some base libraries. Such libraries must be built twice, once for the host configuration, and once for the target configuration.
Bazel takes care of ensuring that both variants are built, and that the derived files are kept separate to avoid interference; usually such targets can be built concurrently, since they are independent of each other. If you see progress messages indicating that a given target is being built twice, this is most likely the explanation.

Bazel uses one of two ways to select the host configuration, based on the --distinct_host_configuration option. This boolean option is somewhat subtle, and the setting may improve (or worsen) the speed of your builds.

--distinct_host_configuration=false

When this option is false, the host and request configurations are identical: all tools required during the build will be built in exactly the same way as target programs. This setting means that no libraries need to be built twice during a single build, so it keeps builds short. However, it does mean that any change to your request configuration also affects your host configuration, causing all the tools to be rebuilt, and then anything that depends on the tool output to be rebuilt too. Thus, for example, simply changing a linker option between builds might cause all tools to be re-linked, and then all actions using them reexecuted, and so on, resulting in a very large rebuild. Also, please note: if your host architecture is not capable of running your target binaries, your build will not work.

If you frequently make changes to your request configuration, such as alternating between -c opt and -c dbg builds, or between simple- and cross-compilation, we do not recommend this option, as you will typically rebuild the majority of your codebase each time you switch.

--distinct_host_configuration=true (default)

If this option is true, then instead of using the same configuration for the host and request, a completely distinct host configuration is used. The host configuration is derived from the target configuration as follows:

There are many reasons why it might be preferable to select a distinct host configuration from the request configuration. Some are too esoteric to mention here, but two of them are worth pointing out.

Firstly, by using stripped, optimized binaries, you reduce the time spent linking and executing the tools, the disk space occupied by the tools, and the network I/O time in distributed builds.

Secondly, by decoupling the host and request configurations in all builds, you avoid very expensive rebuilds that would result from minor changes to the request configuration (such as changing a linker options does), as described earlier.

That said, for certain builds, this option may be a hindrance. In particular, builds in which changes of configuration are infrequent (especially certain Java builds), and builds where the amount of code that must be built in both host and target configurations is large, may not benefit.

Correct incremental rebuilds

One of the primary goals of the Bazel project is to ensure correct incremental rebuilds. Previous build tools, especially those based on Make, make several unsound assumptions in their implementation of incremental builds.

Firstly, that timestamps of files increase monotonically. While this is the typical case, it is very easy to fall afoul of this assumption; syncing to an earlier revision of a file causes that file's modification time to decrease; Make-based systems will not rebuild.

More generally, while Make detects changes to files, it does not detect changes to commands. If you alter the options passed to the compiler in a given build step, Make will not re-run the compiler, and it is necessary to manually discard the invalid outputs of the previous build using make clean.

Also, Make is not robust against the unsuccessful termination of one of its subprocesses after that subprocess has started writing to its output file. While the current execution of Make will fail, the subsequent invocation of Make will blindly assume that the truncated output file is valid (because it is newer than its inputs), and it will not be rebuilt. Similarly, if the Make process is killed, a similar situation can occur.

Bazel avoids these assumptions, and others. Bazel maintains a database of all work previously done, and will only omit a build step if it finds that the set of input files (and their timestamps) to that build step, and the compilation command for that build step, exactly match one in the database, and, that the set of output files (and their timestamps) for the database entry exactly match the timestamps of the files on disk. Any change to the input files or output files, or to the command itself, will cause re-execution of the build step.

The benefit to users of correct incremental builds is: less time wasted due to confusion. (Also, less time spent waiting for rebuilds caused by use of make clean, whether necessary or pre-emptive.)

Build consistency and incremental builds

Formally, we define the state of a build as consistent when all the expected output files exist, and their contents are correct, as specified by the steps or rules required to create them. When you edit a source file, the state of the build is said to be inconsistent, and remains inconsistent until you next run the build tool to successful completion. We describe this situation as unstable inconsistency, because it is only temporary, and consistency is restored by running the build tool.

There is another kind of inconsistency that is pernicious: stable inconsistency. If the build reaches a stable inconsistent state, then repeated successful invocation of the build tool does not restore consistency: the build has gotten "stuck", and the outputs remain incorrect. Stable inconsistent states are the main reason why users of Make (and other build tools) type make clean. Discovering that the build tool has failed in this manner (and then recovering from it) can be time consuming and very frustrating.

Conceptually, the simplest way to achieve a consistent build is to throw away all the previous build outputs and start again: make every build a clean build. This approach is obviously too time-consuming to be practical (except perhaps for release engineers), and therefore to be useful, the build tool must be able to perform incremental builds without compromising consistency.

Correct incremental dependency analysis is hard, and as described above, many other build tools do a poor job of avoiding stable inconsistent states during incremental builds. In contrast, Bazel offers the following guarantee: after a successful invocation of the build tool during which you made no edits, the build will be in a consistent state. (If you edit your source files during a build, Bazel makes no guarantee about the consistency of the result of the current build. But it does guarantee that the results of the next build will restore consistency.)

As with all guarantees, there comes some fine print: there are some known ways of getting into a stable inconsistent state with Bazel. We won't guarantee to investigate such problems arising from deliberate attempts to find bugs in the incremental dependency analysis, but we will investigate and do our best to fix all stable inconsistent states arising from normal or "reasonable" use of the build tool.

If you ever detect a stable inconsistent state with Bazel, please report a bug.

Sandboxed execution

Bazel uses sandboxes to guarantee that actions run hermetically1 and correctly. Bazel runs Spawns (loosely speaking: actions) in sandboxes that only contain the minimal set of files the tool requires to do its job. Currently sandboxing works on Linux 3.12 or newer with the CONFIG_USER_NS option enabled.

Bazel will print a warning if your system does not support sandboxing to alert you to the fact that builds are not guaranteed to be hermetic and might affect the host system in unknown ways. To disable this warning you can pass the --ignore_unsupported_sandboxing flag to Bazel.

On some platforms such as Google Container Engine cluster nodes or Debian, user namespaces are deactivated by default due to security concerns. This can be checked by looking at the file /proc/sys/kernel/unprivileged_userns_clone: if it exists and contains a 0, then user namespaces can be activated with sudo sysctl kernel.unprivileged_userns_clone=1.

In some cases, the Bazel sandbox fails to execute rules because of the system setup. The symptom is generally a failure that output a message similar to namespace-sandbox.c:633: execvp(argv[0], argv): No such file or directory. In that case, try to deactivate the sandbox for genrules with --genrule_strategy=standalone and for other rules with --spawn_strategy=standalone. Also please report a bug on our issue tracker and mention which Linux distribution you're using so that we can investigate and provide a fix in a subsequent release.

1: Hermeticity means that the action only uses its declared input files and no other files in the filesystem, and it only produces its declared output files.

Deleting the outputs of a build

The clean command

Bazel has a clean command, analogous to that of Make. It deletes the output directories for all build configurations performed by this Bazel instance, or the entire working tree created by this Bazel instance, and resets internal caches. If executed without any command-line options, then the output directory for all configurations will be cleaned.

Recall that each Bazel instance is associated with a single workspace, thus the clean command will delete all outputs from all builds you've done with that Bazel instance in that workspace.

To completely remove the entire working tree created by a Bazel instance, you can specify the --expunge option. When executed with --expunge, the clean command simply removes the entire output base tree which, in addition to the build output, contains all temp files created by Bazel. It also stops the Bazel server after the clean, equivalent to the shutdown command. For example, to clean up all disk and memory traces of a Bazel instance, you could specify:

  % bazel clean --expunge

Alternatively, you can expunge in the background by using --expunge_async. It is safe to invoke a Bazel command in the same client while the asynchronous expunge continues to run. Note, however, that this may introduce IO contention.

The clean command is provided primarily as a means of reclaiming disk space for workspaces that are no longer needed. However, we recognize that Bazel's incremental rebuilds might not be perfect; clean may be used to recover a consistent state when problems arise.

Bazel's design is such that these problems are fixable; we consider such bugs a high priority, and will do our best fix them. If you ever find an incorrect incremental build, please file a bug report. We encourage developers to get out of the habit of using clean and into that of reporting bugs in the tools.

Phases of a build

In Bazel, a build occurs in three distinct phases; as a user, understanding the difference between them provides insight into the options which control a build (see below).

Loading phase

The first is loading during which all the necessary BUILD files for the initial targets, and their transitive closure of dependencies, are loaded, parsed, evaluated and cached.

For the first build after a Bazel server is started, the loading phase typically takes many seconds as many BUILD files are loaded from the file system. In subsequent builds, especially if no BUILD files have changed, loading occurs very quickly.

Errors reported during this phase include: package not found, target not found, lexical and grammatical errors in a BUILD file, and evaluation errors.

Analysis phase

The second phase, analysis, involves the semantic analysis and validation of each build rule, the construction of a build dependency graph, and the determination of exactly what work is to be done in each step of the build.

Like loading, analysis also takes several seconds when computed in its entirety. However, Bazel caches the dependency graph from one build to the next and only reanalyzes what it has to, which can make incremental builds extremely fast in the case where the packages haven't changed since the previous build.

Errors reported at this stage include: inappropriate dependencies, invalid inputs to a rule, and all rule-specific error messages.

The loading and analysis phases are fast because Bazel avoids unnecessary file I/O at this stage, reading only BUILD files in order to determine the work to be done. This is by design, and makes Bazel a good foundation for analysis tools, such as Bazel's query command, which is implemented atop the loading phase.

Execution phase

The third and final phase of the build is execution. This phase ensures that the outputs of each step in the build are consistent with its inputs, re-running compilation/linking/etc. tools as necessary. This step is where the build spends the majority of its time, ranging from a few seconds to over an hour for a large build. Errors reported during this phase include: missing source files, errors in a tool executed by some build action, or failure of a tool to produce the expected set of outputs.

Options

The following sections describe the options available during a build. When --long is used on a help command, the on-line help messages provide summary information about the meaning, type and default value for each option.

Most options can only be specified once. When specified multiple times, the last instance wins. Options that can be specified multiple times are identified in the on-line help with the text 'may be used multiple times'.

Options that affect how packages are located

See also the --show_package_location option.

--package_path

This option specifies the set of directories that are searched to find the BUILD file for a given package.

--deleted_packages

This option specifies a comma-separated list of packages which Bazel should consider deleted, and not attempt to load from any directory on the package path. This can be used to simulate the deletion of packages without actually deleting them.

Error checking options

These options control Bazel's error-checking and/or warnings.

--check_constraint constraint

This option takes an argument that specifies which constraint should be checked.

Bazel performs special checks on each rule that is annotated with the given constraint.

The supported constraints and their checks are as follows:

--[no]check_visibility

If this option is set to false, visibility checks are demoted to warnings. The default value of this option is true, so that by default, visibility checking is done.

--experimental_action_listener=label

The experimental_action_listener option instructs Bazel to use details from the action_listener rule specified by label to insert extra_actions into the build graph.

--experimental_extra_action_filter=regex

The experimental_extra_action_filter option instructs Bazel to filter the set of targets to schedule extra_actions for.

This flag is only applicable in combination with the --experimental_action_listener flag.

By default all extra_actions in the transitive closure of the requested targets-to-build get scheduled for execution. --experimental_extra_action_filter will restrict scheduling to extra_actions of which the owner's label matches the specified regular expression.

The following example will limit scheduling of extra_actions to only apply to actions of which the owner's label contains '/bar/':

% bazel build --experimental_action_listener=//test:al //foo/... \
  --experimental_extra_action_filter=.*/bar/.*

--output_filter regex

The --output_filter option will only show build and compilation warnings for targets that match the regular expression. If a target does not match the given regular expression and its execution succeeds, its standard output and standard error are thrown away. This option is intended to be used to help focus efforts on fixing warnings in packages under development. Here are some typical values for this option:

--output_filter= Show all output.
--output_filter='^//(first/project|second/project):' Show the output for the specified packages.
--output_filter='^//((?!(first/bad_project|second/bad_project):).)*$' Don't show output for the specified packages.
--output_filter=DONT_MATCH_ANYTHING Don't show output.

--[no]analysis_warnings_as_errors

When this option is enabled, visible analysis warnings (as specified by the output filter) are treated as errors, effectively preventing the build phase from starting. This feature can be used to enable strict builds that do not allow new warnings to creep into a project.

Flags options

These options control which options Bazel will pass to other tools.

--copt gcc-option

This option takes an argument which is to be passed to gcc. The argument will be passed to gcc whenever gcc is invoked for preprocessing, compiling, and/or assembling C, C++, or assembler code. It will not be passed when linking.

This option can be used multiple times. For example:

  % bazel build --copt="-g0" --copt="-fpic" //foo

will compile the foo library without debug tables, generating position-independent code.

Note that changing --copt settings will force a recompilation of all affected object files. Also note that copts values listed in specific cc_library or cc_binary build rules will be placed on the gcc command line after these options.

Warning: C++-specific options (such as -fno-implicit-templates) should be specified in --cxxopt, not in --copt. Likewise, C-specific options (such as -Wstrict-prototypes) should be specified in --conlyopt, not in copt. Similarly, gcc options that only have an effect at link time (such as -l) should be specified in --linkopt, not in --copt.

--host_copt gcc-option

This option takes an argument which is to be passed to gcc for source files that are compiled in the host configuration. This is analogous to the --copt option, but applies only to the host configuration.

--conlyopt gcc-option

This option takes an argument which is to be passed to gcc when compiling C source files.

This is similar to --copt, but only applies to C compilation, not to C++ compilation or linking. So you can pass C-specific options (such as -Wno-pointer-sign) using --conlyopt.

Note that copts parameters listed in specific cc_library or cc_binary build rules will be placed on the gcc command line after these options.

--cxxopt gcc-option

This option takes an argument which is to be passed to gcc when compiling C++ source files.

This is similar to --copt, but only applies to C++ compilation, not to C compilation or linking. So you can pass C++-specific options (such as -fpermissive or -fno-implicit-templates) using --cxxopt. For example:

  % bazel build --cxxopt="-fpermissive" --cxxopt="-Wno-error" //foo/cruddy_code

Note that copts parameters listed in specific cc_library or cc_binary build rules will be placed on the gcc command line after these options.

--cwarn gcc-warning

This option takes an argument which is a gcc warning to be enabled when compiling C or C++ source files. This warning enabling will override any other copt, cxxopt or copts that disable the given warning.

This is similar to --copt and --cxxopt, but can only be used to enable warnings. The arguments to this option are appended to the "-W" flag to gcc, and must not contain a leading "no-" prefix. For example:

  % bazel build --cwarn="unused-variable" --cwarn="unused-function" //foo/cruddy_code

--linkopt linker-option

This option takes an argument which is to be passed to gcc when linking.

This is similar to --copt, but only applies to linking, not to compilation. So you can pass gcc options that only make sense at link time (such as -lssp or -Wl,--wrap,abort) using --linkopt. For example:

  % bazel build --copt="-fmudflap" --linkopt="-lmudflap" //foo/buggy_code

Build rules can also specify link options in their attributes. This option's settings always take precedence. Also see cc_library.linkopts.

--strip (always|never|sometimes)

This option determines whether Bazel will strip debugging information from all binaries and shared libraries, by invoking the linker with the -Wl,--strip-debug option. --strip=always means always strip debugging information. --strip=never means never strip debugging information. The default value of --strip=sometimes means strip iff the --compilation_mode is fastbuild.

  % bazel build --strip=always //foo:bar

will compile the target while stripping debugging information from all generated binaries.

Note that if you want debugging information, it's not enough to disable stripping; you also need to make sure that the debugging information was generated by the compiler, which you can do by using either -c dbg or --copt -g.

Note also that Bazel's --strip option corresponds with ld's --strip-debug option: it only strips debugging information. If for some reason you want to strip all symbols, not just debug symbols, you would need to use ld's --strip-all option, which you can do by passing --linkopt=-Wl,--strip-all to Bazel.

--stripopt strip-option

An additional option to pass to the strip command when generating a *.stripped binary. The default is -S -p. This option can be used multiple times.

Note that --stripopt does not apply to the stripping of the main binary with --strip=(always|sometimes).

--fdo_instrument profile-output-dir

The --fdo_instrument option enables the generation of FDO (feedback directed optimization) profile output when the built C/C++ binary is executed. For GCC, the argument provided is used as a directory prefix for a per-object file directory tree of .gcda files containing profile information for each .o file.

Once the profile data tree has been generated, the profile tree should be zipped up, and provided to the --fdo_optimize=profile-zip Bazel option to enable the FDO optimized compilation.

For the LLVM compiler the argument instead is the path to the raw LLVM profile output file to generate, e.g. --fdo_instrument=/path/to/profile.profraw.

The options --fdo_instrument and --fdo_optimize cannot be used at the same time.

--fdo_optimize profile-zip

The --fdo_optimize option enables the use of the per-object file profile information to perform FDO (feedback directed optimization) optimizations when compiling. For GCC, the argument provided is the zip file containing the previously-generated file tree of .gcda files containing profile information for each .o file.

Alternatively, the argument provided can point to an auto profile identified by the extension .afdo.

Note that this option also accepts labels that resolve to source files. You may need to add an exports_files directive to the corresponding package to make the file visible to Bazel.

For the LLVM compiler the argument provided should point to the indexed LLVM profile output file prepared by the llvm-profdata tool, and should have a .profdata extension.

The options --fdo_instrument and --fdo_optimize cannot be used at the same time.

--lipo (off|binary)

The --lipo=binary option enables LIPO (Lightweight Inter-Procedural Optimization). LIPO is an extended C/C++ optimization technique that optimizes code across different object files. It involves compiling each C/C++ source file differently for every binary. This is in contrast to normal compilation where compilation outputs are reused. This means that LIPO is more expensive than normal compilation.

This option only has an effect when FDO is also enabled (see the --fdo_instrument and --fdo_options). Currently LIPO is only supported when building a single cc_binary rule.

Setting --lipo=binary implicitly sets --dynamic_mode=off.

--lipo_context context-binary

Specifies the label of a cc_binary rule that was used to generate the profile information for LIPO that was given to the --fdo_optimize option.

Specifying the context is mandatory when --lipo=binary is set. Using this option implicitly also sets --linkopt=-Wl,--warn-unresolved-symbols.

--[no]output_symbol_counts

If enabled, each gold-invoked link of a C++ executable binary will also output a symbol counts file (via the --print-symbol-counts gold option) that logs the number of symbols from each .o input that were used in the binary. This can be used to track unnecessary link dependencies. The symbol counts file is written to the binary's output path with the name [targetname].sc.

This option is disabled by default.

--jvmopt jvm-option

This option allows option arguments to be passed to the Java VM. It can be used with one big argument, or multiple times with individual arguments. For example:

  % bazel build --jvmopt="-server -Xms256m" java/com/example/common/foo:all

will use the server VM for launching all Java binaries and set the startup heap size for the VM to 256 MB.

--javacopt javac-option

This option allows option arguments to be passed to javac. It can be used with one big argument, or multiple times with individual arguments. For example:

  % bazel build --javacopt="-g:source,lines" //myprojects:prog

will rebuild a java_binary with the javac default debug info (instead of the bazel default).

The option is passed to javac after the Bazel built-in default options for javac and before the per-rule options. The last specification of any option to javac wins. The default options for javac are:

  -source 8 -target 8 -encoding UTF-8

Note that changing --javacopt settings will force a recompilation of all affected classes. Also note that javacopts parameters listed in specific java_library or java_binary build rules will be placed on the javac command line after these options.

-extra_checks[:(off|on)]

This javac option enables extra correctness checks. Any problems found will be presented as errors. Either -extra_checks or -extra_checks:on may be used to force the checks to be turned on. -extra_checks:off completely disables the analysis. When this option is not specified, the default behavior is used.

--strict_java_deps (default|strict|off|warn|error)

This option controls whether javac checks for missing direct dependencies. Java targets must explicitly declare all directly used targets as dependencies. This flag instructs javac to determine the jars actually used for type checking each java file, and warn/error if they are not the output of a direct dependency of the current target.

--javawarn (all|cast|deprecation|empty|unchecked|fallthrough|path|rawtypes|serial|finally|overrides)

This option is used to enable Java warnings across an entire build. It takes an argument which is a javac warning to be enabled, overriding any other Java options that disable the given warning. The arguments to this option are appended to the "-Xlint:" flag to javac, and must be exactly one of the listed warnings.

For example:

  % bazel build --javawarn="deprecation" --javawarn="unchecked" //java/...

Note that changing --javawarn settings will force a recompilation of all affected classes.

Semantics options

These options affect the build commands and/or the output file contents.

--compilation_mode (fastbuild|opt|dbg) (-c)

This option takes an argument of fastbuild, dbg or opt, and affects various C/C++ code-generation options, such as the level of optimization and the completeness of debug tables. Bazel uses a different output directory for each different compilation mode, so you can switch between modes without needing to do a full rebuild every time.

--cpu cpu

This option specifies the target CPU architecture to be used for the compilation of binaries during the build.

Note that a particular combination of crosstool version, compiler version, libc version, and target CPU is allowed only if it has been specified in the currently used CROSSTOOL file.

--host_cpu cpu

This option specifies the name of the CPU architecture that should be used to build host tools.

--experimental_skip_static_outputs

The --experimental_skip_static_outputs option causes all statically-linked C++ binaries to not be output in any meaningful way.

If you set this flag, you must also set --distinct_host_configuration. It is also inherently incompatible with running tests — don't use it for that. This option is experimental and may go away at any time.

--per_file_copt [+-]regex[,[+-]regex]...@option[,option]...

When present, any C++ file with a label or an execution path matching one of the inclusion regex expressions and not matching any of the exclusion expressions will be built with the given options. The label matching uses the canonical form of the label (i.e //package:label_name). The execution path is the relative path to your workspace directory including the base name (including extension) of the C++ file. It also includes any platform dependent prefixes. Note, that if only one of the label or the execution path matches the options will be used.

Notes: To match the generated files (e.g. genrule outputs) Bazel can only use the execution path. In this case the regexp shouldn't start with '//' since that doesn't match any execution paths. Package names can be used like this: --per_file_copt=base/.*\.pb\.cc@-g0. This will match every .pb.cc file under a directory called base.

This option can be used multiple times.

The option is applied regardless of the compilation mode used. I.e. it is possible to compile with --compilation_mode=opt and selectively compile some files with stronger optimization turned on, or with optimization disabled.

Caveat: If some files are selectively compiled with debug symbols the symbols might be stripped during linking. This can be prevented by setting --strip=never.

Syntax: [+-]regex[,[+-]regex]...@option[,option]... Where regex stands for a regular expression that can be prefixed with a + to identify include patterns and with - to identify exclude patterns. option stands for an arbitrary option that is passed to the C++ compiler. If an option contains a , it has to be quoted like so \,. Options can also contain @, since only the first @ is used to separate regular expressions from options.

Example: --per_file_copt=//foo:.*\.cc,-//foo:file\.cc@-O0,-fprofile-arcs adds the -O0 and the -fprofile-arcs options to the command line of the C++ compiler for all .cc files in //foo/ except file.cc.

--dynamic_mode mode

Determines whether C++ binaries will be linked dynamically, interacting with the linkstatic attribute on build rules.

Modes:

--fission (yes|no|[dbg][,opt][,fastbuild])

Enables Fission, which writes C++ debug information to dedicated .dwo files instead of .o files, where it would otherwise go. This substantially reduces the input size to links and can reduce link times.

When set to [dbg][,opt][,fastbuild] (example: --fission=dbg,fastbuild), Fission is enabled only for the specified set of compilation modes. This is useful for bazelrc settings. When set to yes, Fission is enabled universally. When set to no, Fission is disabled universally. Default is dbg.

--force_ignore_dash_static

If this flag is set, any -static options in linkopts of cc_* rules BUILD files are ignored. This is only intended as a workaround for C++ hardening builds.

--[no]force_pic

If enabled, all C++ compilations produce position-independent code ("-fPIC"), links prefer PIC pre-built libraries over non-PIC libraries, and links produce position-independent executables ("-pie"). Default is disabled.

Note that dynamically linked binaries (i.e. --dynamic_mode fully) generate PIC code regardless of this flag's setting. So this flag is for cases where users want PIC code explicitly generated for static links.

--custom_malloc malloc-library-target

When specified, always use the given malloc implementation, overriding all malloc="target" attributes, including in those targets that use the default (by not specifying any malloc).

--crosstool_top label

This option specifies the location of the crosstool compiler suite to be used for all C++ compilation during a build. Bazel will look in that location for a CROSSTOOL file and uses that to automatically determine settings for --compiler.

--host_crosstool_top label

If not specified, bazel uses the value of --crosstool_top to compile code in the host configuration, i.e., tools run during the build. The main purpose of this flag is to enable cross-compilation.

--compiler version

This option specifies the C/C++ compiler version (e.g. gcc-4.1.0) to be used for the compilation of binaries during the build. If you want to build with a custom crosstool, you should use a CROSSTOOL file instead of specifying this flag.

Note that only certain combinations of crosstool version, compiler version, libc version, and target CPU are allowed.

--glibc version

This option specifies the version of glibc that the target should be linked against. If you want to build with a custom crosstool, you should use a CROSSTOOL file instead of specifying this flag. In that case, Bazel will use the CROSSTOOL file and the following options where appropriate: