Bazel builds software from source code organized in a directory tree called a
workspace. Source files in the workspace are organized in a nested hierarchy of
packages, where each package is a directory that contains a set of related
source files and one BUILD
file. The BUILD
file specifies what software
outputs can be built from the source.
Workspace
A workspace is a directory tree on your filesystem that contains the source
files for the software you want to build. Each workspace has a text file named
WORKSPACE
which may be empty, or may contain references to external
dependencies required to build the outputs.
Directories containing a file called WORKSPACE
are considered the root of a
workspace. Therefore, Bazel ignores any directory trees in a workspace rooted at
a subdirectory containing a WORKSPACE
file, as they form another workspace.
Bazel also supports WORKSPACE.bazel
file as an alias of WORKSPACE
file. If
both files exist, WORKSPACE.bazel
is used.
Repositories
Code is organized in repositories. The directory containing the WORKSPACE
file is the root of the main repository, also called @
. Other, (external)
repositories are defined in the WORKSPACE
file using workspace rules, or
generated from modules and extensions in the Bzlmod system. See external
dependencies overview for more information.
The workspace rules bundled with Bazel are documented in the Workspace Rules section in the Build Encyclopedia and the documentation on embedded Starlark repository rules.
As external repositories are repositories themselves, they often contain a
WORKSPACE
file as well. However, these additional WORKSPACE
files are
ignored by Bazel. In particular, repositories depended upon transitively are not
added automatically.
Packages
The primary unit of code organization in a repository is the package. A package is a collection of related files and a specification of how they can be used to produce output artifacts.
A package is defined as a directory containing a
BUILD
file named either BUILD
or BUILD.bazel
. A
package includes all files in its directory, plus all subdirectories beneath it,
except those which themselves contain a BUILD
file. From this definition, no
file or directory may be a part of two different packages.
For example, in the following directory tree there are two packages, my/app
,
and the subpackage my/app/tests
. Note that my/app/data
is not a package, but
a directory belonging to package my/app
.
src/my/app/BUILD
src/my/app/app.cc
src/my/app/data/input.txt
src/my/app/tests/BUILD
src/my/app/tests/test.cc
Targets
A package is a container of targets, which are defined in the package's
BUILD
file. Most targets are one of two principal kinds, files and rules.
Files are further divided into two kinds. Source files are usually written by the efforts of people, and checked in to the repository. Generated files, sometimes called derived files or output files, are not checked in, but are generated from source files.
The second kind of target is declared with a rule. Each rule instance specifies the relationship between a set of input and a set of output files. The inputs to a rule may be source files, but they also may be the outputs of other rules.
Whether the input to a rule is a source file or a generated file is in most cases immaterial; what matters is only the contents of that file. This fact makes it easy to replace a complex source file with a generated file produced by a rule, such as happens when the burden of manually maintaining a highly structured file becomes too tiresome, and someone writes a program to derive it. No change is required to the consumers of that file. Conversely, a generated file may easily be replaced by a source file with only local changes.
The inputs to a rule may also include other rules. The precise meaning of such relationships is often quite complex and language- or rule-dependent, but intuitively it is simple: a C++ library rule A might have another C++ library rule B for an input. The effect of this dependency is that B's header files are available to A during compilation, B's symbols are available to A during linking, and B's runtime data is available to A during execution.
An invariant of all rules is that the files generated by a rule always belong to the same package as the rule itself; it is not possible to generate files into another package. It is not uncommon for a rule's inputs to come from another package, though.
Package groups are sets of packages whose purpose is to limit accessibility of
certain rules. Package groups are defined by the package_group
function. They
have three properties: the list of packages they contain, their name, and other
package groups they include. The only allowed ways to refer to them are from the
visibility
attribute of rules or from the default_visibility
attribute of
the package
function; they do not generate or consume files. For more
information, refer to the package_group
documentation.