Skip to main content
This section defines various terms and concepts that are common to many functions or build rules.

Contents

Bourne shell tokenization

Certain string attributes of some rules are split into multiple words according to the tokenization rules of the Bourne shell: unquoted spaces delimit separate words, and single- and double-quotes characters and backslashes are used to prevent tokenization. Those attributes that are subject to this tokenization are explicitly indicated as such in their definitions in this document. Attributes subject to “Make” variable expansion and Bourne shell tokenization are typically used for passing arbitrary options to compilers and other tools. Examples of such attributes are cc_library.copts and java_library.javacopts. Together these substitutions allow a single string variable to expand into a configuration-specific list of option words.

Label expansion

Some string attributes of a very few rules are subject to label expansion: if those strings contain a valid label as a substring, such as //mypkg:target, and that label is a declared prerequisite of the current rule, it is expanded into the pathname of the file represented by the target //mypkg:target. Example attributes include genrule.cmd and cc_binary.linkopts. The details may vary significantly in each case, over such issues as: whether relative labels are expanded; how labels that expand to multiple files are treated, etc. Consult the rule attribute documentation for specifics.

Typical attributes defined by most build rules

This section describes attributes that are defined by many build rules, but not all.

Attributes common to all build rules

This section describes attributes that are implicitly added to all build rules.

Attributes common to all test rules (*_test)

This section describes attributes that are common to all test rules.

Attributes common to all binary rules (*_binary)

This section describes attributes that are common to all binary rules.

Configurable attributes

Most attributes are “configurable”, meaning that their values may change when the target is built in different ways. Specifically, configurable attributes may vary based on the flags passed to the Bazel command line, or what downstream dependency is requesting the target. This can be used, for instance, to customize the target for multiple platforms or compilation modes. The following example declares different sources for different target architectures. Running bazel build :multiplatform_lib --cpu x86 will build the target using x86_impl.cc, while substituting --cpu arm will instead cause it to use arm_impl.cc.
The select() function chooses among different alternative values for a configurable attribute based on which config_setting or constraint_value criteria the target’s configuration satisfies. Bazel evaluates configurable attributes after processing macros and before processing rules (technically, between the loading and analysis phases). Any processing before select() evaluation doesn’t know which branch the select() chooses. Macros, for example, can’t change their behavior based on the chosen branch, and bazel query can only make conservative guesses about a target’s configurable dependencies. See this FAQ for more on using select() with rules and macros. Attributes marked nonconfigurable in their documentation cannot use this feature. Usually an attribute is nonconfigurable because Bazel internally needs to know its value before it can determine how to resolve a select(). See Configurable Build Attributes for a detailed overview.

Implicit output targets

Implicit outputs in C++ are deprecated. Please refrain from using it in other languages where possible. We don’t have a deprecation path yet but they will eventually be deprecated too. When you define a build rule in a BUILD file, you are explicitly declaring a new, named rule target in a package. Many build rule functions also implicitly entail one or more output file targets, whose contents and meaning are rule-specific. For example, when you explicitly declare a java_binary(name='foo', ...) rule, you are also implicitly declaring an output file target foo_deploy.jar as a member of the same package. (This particular target is a self-contained Java archive suitable for deployment.) Implicit output targets are first-class members of the global target graph. Just like other targets, they are built on demand, either when specified in the top-level built command, or when they are necessary prerequisites for other build targets. They can be referenced as dependencies in BUILD files, and can be observed in the output of analysis tools such as bazel query. For each kind of build rule, the rule’s documentation contains a special section detailing the names and contents of any implicit outputs entailed by a declaration of that kind of rule. An important but somewhat subtle distinction between the two namespaces used by the build system: labels identify targets, which may be rules or files, and file targets may be divided into either source (or input) file targets and derived (or output) file targets. These are the things you can mention in BUILD files, build from the command-line, or examine using bazel query; this is the target namespace. Each file target corresponds to one actual file on disk (the “file system namespace”); each rule target may correspond to zero, one or more actual files on disk. There may be files on disk that have no corresponding target; for example, .o object files produced during C++ compilation cannot be referenced from within BUILD files or from the command line. In this way, the build tool may hide certain implementation details of how it does its job. This is explained more fully in the BUILD Concept Reference.