Labels

Report an issue View source Nightly · 8.0 · 7.4 · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

A label is an identifier for a target. A typical label in its full canonical form looks like:

@@myrepo//my/app/main:app_binary

The first part of the label is the repository name, @@myrepo. The double-@ syntax signifies that this is a canonical repo name, which is unique within the workspace. Labels with canonical repo names unambiguously identify a target no matter which context they appear in.

Often the canonical repo name is an arcane string that looks like @@rules_java++toolchains+local_jdk. What is much more commonly seen is labels with an apparent repo name, which looks like:

@myrepo//my/app/main:app_binary

The only difference is the repo name being prefixed with one @ instead of two. This refers to a repo with the apparent name myrepo, which could be different based on the context this label appears in.

In the typical case that a label refers to the same repository from which it is used, the repo name part may be omitted. So, inside @@myrepo the first label is usually written as

//my/app/main:app_binary

The second part of the label is the un-qualified package name my/app/main, the path to the package relative to the repository root. Together, the repository name and the un-qualified package name form the fully-qualified package name @@myrepo//my/app/main. When the label refers to the same package it is used in, the package name (and optionally, the colon) may be omitted. So, inside @@myrepo//my/app/main, this label may be written either of the following ways:

app_binary
:app_binary

It is a matter of convention that the colon is omitted for files, but retained for rules, but it is not otherwise significant.

The part of the label after the colon, app_binary is the un-qualified target name. When it matches the last component of the package path, it, and the colon, may be omitted. So, these two labels are equivalent:

//my/app/lib
//my/app/lib:lib

The name of a file target in a subdirectory of the package is the file's path relative to the package root (the directory containing the BUILD file). So, this file is in the my/app/main/testdata subdirectory of the repository:

//my/app/main:testdata/input.txt

Strings like //my/app and @@some_repo//my/app have two meanings depending on the context in which they are used: when Bazel expects a label, they mean //my/app:app and @@some_repo//my/app:app, respectively. But, when Bazel expects a package (e.g. in package_group specifications), they reference the package that contains that label.

A common mistake in BUILD files is using //my/app to refer to a package, or to all targets in a package--it does not. Remember, it is equivalent to //my/app:app, so it names the app target in the my/app package of the current repository.

However, the use of //my/app to refer to a package is encouraged in the specification of a package_group or in .bzl files, because it clearly communicates that the package name is absolute and rooted in the top-level directory of the workspace.

Relative labels cannot be used to refer to targets in other packages; the repository identifier and package name must always be specified in this case. For example, if the source tree contains both the package my/app and the package my/app/testdata (each of these two directories has its own BUILD file), the latter package contains a file named testdepot.zip. Here are two ways (one wrong, one correct) to refer to this file within //my/app:BUILD:

Wrongtestdata is a different package, so you can't use a relative path

testdata/testdepot.zip

Correct — refer to testdata with its full path

//my/app/testdata:testdepot.zip

Labels starting with @@// are references to the main repository, which will still work even from external repositories. Therefore @@//a/b/c is different from //a/b/c when referenced from an external repository. The former refers back to the main repository, while the latter looks for //a/b/c in the external repository itself. This is especially relevant when writing rules in the main repository that refer to targets in the main repository, and will be used from external repositories.

For information about the different ways you can refer to targets, see target patterns.

Lexical specification of a label

Label syntax discourages use of metacharacters that have special meaning to the shell. This helps to avoid inadvertent quoting problems, and makes it easier to construct tools and scripts that manipulate labels, such as the Bazel Query Language.

The precise details of allowed target names are below.

Target names — package-name:target-name

target-name is the name of the target within the package. The name of a rule is the value of the name attribute in the rule's declaration in a BUILD file; the name of a file is its pathname relative to the directory containing the BUILD file.

Target names must be composed entirely of characters drawn from the set az, AZ, 09, and the punctuation symbols !%-@^_"#$&'()*-+,;<=>?[]{|}~/..

Filenames must be relative pathnames in normal form, which means they must neither start nor end with a slash (for example, /foo and foo/ are forbidden) nor contain multiple consecutive slashes as path separators (for example, foo//bar). Similarly, up-level references (..) and current-directory references (./) are forbidden.

Wrong — Do not use .. to refer to files in other packages

Correct — Use //package-name:filename

While it is common to use / in the name of a file target, avoid the use of / in the names of rules. Especially when the shorthand form of a label is used, it may confuse the reader. The label //foo/bar/wiz is always a shorthand for //foo/bar/wiz:wiz, even if there is no such package foo/bar/wiz; it never refers to //foo:bar/wiz, even if that target exists.

However, there are some situations where use of a slash is convenient, or sometimes even necessary. For example, the name of certain rules must match their principal source file, which may reside in a subdirectory of the package.

Package names — //package-name:target-name

The name of a package is the name of the directory containing its BUILD file, relative to the top-level directory of the containing repository. For example: my/app.

On a technical level, Bazel enforces the following:

  • Allowed characters in package names are the lowercase letters a through z, the uppercase letters A through Z, the digits 0 through 9, the characters ! \"#$%&'()*+,-.;<=>?@[]^_`{|} (yes, there's a space character in there!), and of course forward slash / (since it's the directory separator).
  • Package names may not start or end with a forward slash character /.
  • Package names may not contain the substring //. This wouldn't make sense---what would the corresponding directory path be?
  • Package names may not contain the substring /./ or /../ or /.../ etc. This enforcement is done to avoid confusion when translating between a logical package name and a physical directory name, given the semantic meaning of the dot character in path strings.

On a practical level:

  • For a language with a directory structure that is significant to its module system (for example, Java), it's important to choose directory names that are valid identifiers in the language. For example, don't start with a leading digit and avoid special characters, especially underscores and hyphens.
  • Although Bazel supports targets in the workspace's root package (for example, //:foo), it's best to leave that package empty so all meaningful packages have descriptive names.

Rules

A rule specifies the relationship between inputs and outputs, and the steps to build the outputs. Rules can be of one of many different kinds (sometimes called the rule class), which produce compiled executables and libraries, test executables and other supported outputs as described in the Build Encyclopedia.

BUILD files declare targets by invoking rules.

In the example below, we see the declaration of the target my_app using the cc_binary rule.

cc_binary(
    name = "my_app",
    srcs = ["my_app.cc"],
    deps = [
        "//absl/base",
        "//absl/strings",
    ],
)

Every rule invocation has a name attribute (which must be a valid target name), that declares a target within the package of the BUILD file.

Every rule has a set of attributes; the applicable attributes for a given rule, and the significance and semantics of each attribute are a function of the rule's kind; see the Build Encyclopedia for a list of rules and their corresponding attributes. Each attribute has a name and a type. Some of the common types an attribute can have are integer, label, list of labels, string, list of strings, output label, list of output labels. Not all attributes need to be specified in every rule. Attributes thus form a dictionary from keys (names) to optional, typed values.

The srcs attribute present in many rules has type "list of labels"; its value, if present, is a list of labels, each being the name of a target that is an input to this rule.

In some cases, the name of the rule kind is somewhat arbitrary, and more interesting are the names of the files generated by the rule, and this is true of genrules. For more information, see General Rules: genrule.

In other cases, the name is significant: for *_binary and *_test rules, for example, the rule name determines the name of the executable produced by the build.

This directed acyclic graph over targets is called the target graph or build dependency graph, and is the domain over which the Bazel Query tool operates.

Targets BUILD files