This page covers how to define repository rules and provides examples for more details.
An external repository is a directory tree,
containing source files usable in a Bazel build, which is generated on demand by
running its corresponding repo rule. Repos can be defined in a multitude of
ways, but ultimately, each repo is defined by invoking a repo rule, just as
build targets are defined by invoking build rules. They can be used to depend on
third-party libraries (such as Maven packaged libraries) but also to generate
BUILD files specific to the host Bazel is running on.
Repository rule definition
.bzl file, use the
repository_rule function to define a
new repo rule and store it in a global variable. After a repo rule is defined,
it can be invoked as a function to define repos. This invocation is usually
performed from inside a module extension implementation
The two major components of a repo rule definition are its attribute schema and implementation function. The attribute schema determines the names and types of attributes passed to a repo rule invocation, and the implementation function is run when the repo needs to be fetched.
Attributes are arguments passed to the repo rule invocation. The schema of
attributes accepted by a repo rule is specified using the
attrs argument when
the repo rule is defined with a call to
repository_rule. An example defining
sha256 attributes as strings:
http_archive = repository_rule(
To access an attribute within the implementation function, use
url = repository_ctx.attr.url
checksum = repository_ctx.attr.sha256
repository_rules have the implicitly defined attribute
name. This is a
string attribute that behaves somewhat magically: when specified as an input to
a repo rule invocation, it takes an apparent repo name; but when read from the
repo rule's implementation function using
repository_ctx.attr.name, it returns
the canonical repo name.
Every repo rule requires an
implementation function. It contains the
actual logic of the rule and is executed strictly in the Loading Phase.
The function has exactly one input parameter,
repository_ctx. The function
None to signify that the rule is reproducible given the
specified parameters, or a dict with a set of parameters for that rule that
would turn that rule into a reproducible one generating the same repo. For
example, for a rule tracking a git repository that would mean returning a
specific commit identifier instead of a floating branch that was originally
The input parameter
repository_ctx can be used to
access attribute values, and non-hermetic functions (finding a binary,
executing a binary, creating a file in the repository or downloading a file
from the Internet). See the API docs for
more context. Example:
local_repository = repository_rule(
When is the implementation function executed?
The implementation function of a repo rule is executed when Bazel needs a target from that repository, for example when another target (in another repo) depends on it or if it is mentioned on the command line. The implementation function is then expected to create the repo in the file system. This is called "fetching" the repo.
In contrast to regular targets, repos are not necessarily re-fetched when something changes that would cause the repo to be different. This is because there are things that Bazel either cannot detect changes to or it would cause too much overhead on every build (for example, things that are fetched from the network). Therefore, repos are re-fetched only if one of the following things changes:
- The attributes passed to the repo rule invocation.
- The Starlark code comprising the implementation of the repo rule.
- The value of any environment variable passed to
getenv()method or declared with the
environattribute of the
repository_rule. The values of these environment variables can be hard-wired on the command line with the
- The content of any file passed to the
execute()and similar methods of
repository_ctxwhich is referred to by a label (for example,
bazel fetch --forceis executed.
There are two parameters of
repository_rule that control when the repositories
- If the
configureflag is set, the repository is only re-fetched on
bazel fetchwhen the
--configureparameter is passed to it (if the attribute is unset, this command will not cause a re-fetch)
- If the
localflag is set, in addition to the above cases, the repo is also re-fetched when the Bazel server restarts.
Restarting the implementation function
The implementation function can be restarted while a repo is being fetched if a dependency it requests is missing. In that case, the execution of the implementation function will stop, the missing dependency is resolved and the function will be re-executed after the dependency has been resolved. To avoid unnecessary restarts (which are expensive, as network access might have to be repeated), label arguments are prefetched, provided all label arguments can be resolved to an existing file. Note that resolving a path from a string or a label that was constructed only during execution of the function might still cause a restart.
Forcing refetch of external repos
Sometimes, an external repo can become outdated without any change to its
definition or dependencies. For example, a repo fetching sources might
follow a particular branch of a third-party repository, and new commits are
available on that branch. In this case, you can ask bazel to refetch all
external repos unconditionally by calling
bazel fetch --force --all.
Moreover, some repo rules inspect the local machine and might become
outdated if the local machine was upgraded. Here you can ask Bazel to
only refetch those external repos where the
definition has the
configure attribute set, use
bazel fetch --all --configure.
C++ auto-configured toolchain: it uses a repo rule to automatically create the C++ configuration files for Bazel by looking for the local C++ compiler, the environment and the flags the C++ compiler supports.
Go repositories uses several
repository_ruleto defines the list of dependencies needed to use the Go rules.
rules_jvm_external creates an external repository called
@mavenby default that generates build targets for every Maven artifact in the transitive dependency tree.