Documentation

Edit

Functions

load

load(label, symbols...)

load() is a statement that imports definitions from a Skylark module (.bzl file). For example:

load("//tools/build_rules:build_test.bzl", "build_test")

build_test(name = ...)

This will execute the Skylark module tools/build_rules/build_test.bzl and import the symbol build_test in the local environment. This is useful for using macros or for sharing values between multiple BUILD files. By using more arguments, you can load more symbols at once.

load("//tools/build_rules:build_defs.bzl", "COMPILER_FLAGS", "LINKER_FLAGS")

In load() statement, keyword arguments have special meaning. They can be used to import a value from a .bzl file under a new name. For example:

load(""//tools/build_rules:build_defs.bzl", BUILD_DEF_COMPILER_FLAGS="COMPILER_FLAGS", "LINKER_FLAGS")

This will make COMPILER_FLAGS exported from build_defs.bzl available under the name BUILD_DEF_COMPILER_FLAGS in the current file.

The label must refer to an existing package. For example, for the above statement to work, tools/build_rules/BUILD must exist (an empty file is sufficient) The name of the file must have the suffix .bzl. If the specified label is in the relative label syntax (:a/b.bzl), it will be resolved relative to the package of the file the load statement is in. load statements don't respect visibility: there is no need to use exports_files to make the .bzl file visible.

Note: The load statement still supports the legacy syntax that refers to Skylark modules by their paths and not by their labels. This statement is equivalent to the first example:

load("/tools/build_rules/build_test", "build_test")

However, this syntax is deprecated and will be removed soon.

package

package(default_deprecation, default_testonly, default_visibility, features)

This function declares metadata that applies to every subsequent rule in the package. It is used at most once within a package (BUILD file).

The package() function should be called right after all the load() statements at the top of the file, before any rule.

Arguments

Attribute Description
default_visibility

List of labels; optional

The default visibility of the rules in this package.

Every rule in this package has the visibility specified in this attribute, unless otherwise specified in the visibility attribute of the rule. For detailed information about the syntax of this attribute, see the documentation of the visibility attribute. The package default visibility does not apply to exports_files, which is public by default.

default_deprecation

String; optional

Sets the default deprecation message for all rules in this package.

default_testonly

Boolean; optional; default is 0 except as noted

Sets the default testonly property for all rules in this package.

In packages under javatests the default value is 1.

features

List strings; optional

Sets various flags that affect the semantics of this BUILD file.

This feature is mainly used by the people working on the build system to tag packages that need some kind of special handling. Do not use this unless explicitly requested by someone working on the build system.

Examples

The declaration below declares that the rules in this package are visible only to members of package group //foo:target. Individual visibility declarations on a rule, if present, override this specification.
package(default_visibility = ["//foo:target"])

package_group

package_group(name, packages, includes)

This function defines a set of packages and assigns a label to the group. The label can be referenced in visibility attributes.

Package groups are used for visibility control. You can grant access to a rule to one or more package groups, every rule in the entire source tree, or only to rules declared in the same package. For more detailed description of the visibility system, see the visibility attribute.

Arguments

Attribute Description
name

Name; required

A unique name for this rule.

packages

List of Package; optional

A complete enumeration of packages in this group.

Packages should be referred to using their full names, starting with a double slash. For example, //foo/bar/main is a valid element of this list.

You can also specify wildcards: the specification //foo/... specifies every package under //foo, including //foo itself.

If this attribute is missing, the package group itself will contain no packages (but it can still include other package groups).

includes

List of labels; optional

Other package groups that are included in this one.

The labels in this attribute must refer to other package groups. Packages in referenced package groups are taken to be part of this package group. This is transitive, that is, if package group a contains package group b, and b contains package group c, every package in c will also be a member of a.

Examples

The following package_group declaration specifies a package group called "tropical" that contains tropical fruits.

package_group(
    name = "tropical",
    packages = [
        "//fruits/mango",
        "//fruits/orange",
        "//fruits/papaya/...",
    ],
)

The following declarations specify the package groups of a fictional application:

package_group(
    name = "fooapp",
    includes = [
        ":controller",
        ":model",
        ":view",
    ],
)

package_group(
    name = "model",
    packages = ["//fooapp/database"],
)

package_group(
    name = "view",
    packages = [
        "//fooapp/swingui",
        "//fooapp/webui",
    ],
)

package_group(
    name = "controller",
    packages = ["//fooapp/algorithm"],
)

licenses

licenses(license_types)

licenses() specifies the default license type (or types) of the build rules in a BUILD file. The licenses() directive should appear close to the beginning of the BUILD file, before any build rules, as it sets the BUILD-file scope default for build rule license types.

Arguments

The argument, license_types, is a list of license-type strings.

Legal license types include:

restricted
Requires mandatory source distribution.
reciprocal
Allows usage of software freely in unmodified form. Any modifications must be made freely available.
notice
Original or modified third-party software may be shipped without danger nor encumbering other sources. All of the licenses in this category do, however, have an "original Copyright notice" or "advertising clause", wherein any external distributions must include the notice or clause specified in the license.
permissive
Code that is under a license but does not require a notice.
unencumbered
Public domain, free for any use.
licenses(["notice"]) # MIT license exports_files(["jquery-2.1.1.js"])

exports_files

exports_files([label, ...], visibility, licenses)

exports_files() specifies a list of files belonging to this package that are exported to other packages but not otherwise mentioned in the BUILD file.

The BUILD file for a package may only refer to files belonging to another package if they are mentioned somewhere in the other packages's BUILD file, whether as an input to a rule or an explicit or implicit output from a rule. The remaining files are not associated with a specific rule but are just "data", and for these, exports_files ensures that they may be referenced by other packages. (One kind of data for which this is particularly useful are shell scripts.)

Arguments

The argument is a list of names of files within the current package. A visibility declaration can also be specified; in this case, the files will be visible to the targets specified. If no visibility is specified, the files will be visible to every package, even if a package default visibility was specified in the package function. The licenses can also be specified.

Example

The following example exports golden.txt, a text file from the test_data package, so that other packages may use it, for example, in the data attribute of tests.

# from //test_data/BUILD

exports_files(["golden.txt"])

glob

glob(include, exclude=[], exclude_directories=1)

Glob is a helper function that can be used anywhere a list of filenames is expected. It takes one or two lists of filename patterns containing the * wildcard: as per the Unix shell, this wildcard matches any string excluding the directory separator /. In addition filename patterns can contain the recursive ** wildcard. This wildcard will match zero or more complete path segments separated by the directory separator /. This wildcard can only be used as a complete path segment. For example, "x/**/*.java" is legal, but "test**/testdata.xml" and "**.java" are both illegal. No other wildcards are supported.

Glob returns a sorted list of every file in the current package that:

  • Matches at least one pattern in include.
  • Does not match any of the patterns in exclude (default []).

If the exclude_directories argument is enabled (set to 1), files of type directory will be omitted from the results (default 1).

There are several important limitations and caveats:

  1. Since glob() runs during BUILD file evaluation, glob() matches files only in your source tree, never generated files. If you are building a target that requires both source and generated files, create a list of generated files. This list can be specified by using the labels for the generated files or using the label for the target that produces the generated files. Use + to add the list of generated files to the result of the glob() call as shown in the example below with the target :gen_java_srcs.
  2. Globs may match files in subdirectories. And subdirectory names may be wildcarded. However...
  3. Labels are not allowed to cross the package boundary and glob does not match files in subpackages. For example, the glob expression **/*.cc in package x does not include x/y/z.cc if x/y exists as a package (either as x/y/BUILD, or somewhere else on the package-path). This means that the result of the glob expression actually depends on the existence of BUILD files — that is, the same glob expression would include x/y/z.cc if there was no package called x/y or it was marked as deleted using the --deleted_packages flag.
  4. The restriction above applies to all glob expressions, no matter which wildcards they use.
  5. A hidden file with filename starting with . is matched by both the ** and the * wildcards.
  6. If a rule and a source file with the same name both exist in the package, the glob will return the outputs of the rule instead of the source file.
  7. The "**" wildcard has one corner case: the pattern "**" doesn't match the package's directory path. That is to say, glob(["**"], exclude_directories = 0) matches all files and directories transitively strictly under the current package's directory (but of course not going into directories of subpackages - see the previous note about that).

In general, you should try to provide an appropriate extension (e.g. *.html) instead of using a bare '*' for a glob pattern. The more explicit name is both self documenting and ensures that you don't accidentally match backup files, or emacs/vi/... auto-save files.

When writing build rules you can enumerate the elements of the glob. This enables generating individual rules for every input, for example. See the expanded glob example section below.

Glob Examples

Create a Java library built from all java files in this directory, and all files generated by the :gen_java_srcs rule.

java_library(
    name = "mylib",
    srcs = glob(["*.java"]) + [":gen_java_srcs"],
    deps = "...",
)

genrule(
    name = "gen_java_srcs",
    outs = [
        "Foo.java",
        "Bar.java",
    ],
    ...
)

Include all txt files in directory testdata except experimental.txt. Note that files in subdirectories of testdata will not be included. If you want those files to be included, use a recursive glob (**).

sh_test(
    name = "mytest",
    srcs = ["mytest.sh"],
    data = glob(
        ["testdata/*.txt"],
        exclude = ["testdata/experimental.txt"],
    ),
)

Recursive Glob Examples

Create a library built from all java files in this directory and all subdirectories except those whose path includes a directory named testing. Subdirectories containing a BUILD file are ignored. This pattern should be avoided if possible, as it can reduce build incrementality and therefore increase build times.

java_library(
    name = "mylib",
    srcs = glob(
        ["**/*.java"],
        exclude = ["**/testing/**"],
    ),
)

Make the test depend on all txt files in the testdata directory, its subdirectories

sh_test(
    name = "mytest",
    srcs = ["mytest.sh"],
    data = glob(["testdata/**/*.txt"]),
)

Expanded Glob Examples

Create an individual genrule for *_test.cc in the current directory that counts the number of lines in the file.

# Conveniently, the build language supports list comprehensions.
[genrule(
    name = "count_lines_" + f[:-3],  # strip ".cc"
    srcs = [f],
    outs = ["%s-linecount.txt" % f[:-3]],
    cmd = "wc -l $< >$@",
 ) for f in glob(["*_test.cc"])]

If the BUILD file above is in package //foo and the package contains three matching files, a_test.cc, b_test.cc and c_test.cc then running bazel query '//foo:all' will list all rules that were generated:

$ bazel query '//foo:all' | sort
//foo:count_lines_a_test
//foo:count_lines_b_test
//foo:count_lines_c_test

select

select(
    {conditionA: valuesA, conditionB: valuesB, ...},
    no_match_error = "custom message"
)

select() is the helper function that makes a rule attribute configurable. It can replace the right-hand side of almost any attribute assignment so its value depends on command-line Bazel flags. This can be used, for example, to define platform-specific dependencies or to embed different resources depending on whether a rule is built in "developer" vs. "release" mode.

Basic usage is as follows:

sh_binary(
    name = "myrule",
    srcs = select({
        ":conditionA": ["myrule_a.sh"],
        ":conditionB": ["myrule_b.sh"],
        "//conditions:default": ["myrule_default.sh"]
    })
)

This makes the srcs attribute of a sh_binary configurable by replacing its normal label list assignment with a select call that maps configuration conditions to matching values. Each condition is a label reference to a config_setting instance, which "matches" if the rule's configuration matches an expected set of values. The value of myrule#srcs then becomes whichever label list matches the current invocation.

Further notes:

  • Exactly one condition is selected on any invocation.
  • If multiple conditions match and one is a specialization of the others (i.e. it matches on the same flags as any of the others plus additional ones), the specialization takes precedence.
  • If multiple conditions match and one is not a specialization of all the others, Bazel fails with an error.
  • The special pseudo-label //conditions:default is considered to match if no other condition matches. If this condition is left out, some other rule must match to avoid an error.
  • select can be embedded inside a larger attribute assignment. So srcs = ["common.sh"] + select({ ":conditionA": ["myrule_a.sh"], ...}) and srcs = select({ ":conditionA": ["a.sh"]}) + select({ ":conditionB": ["b.sh"]}) are valid expressions.
  • select works with most, but not all, attributes. Incompatible attributes are marked nonconfigurable in their documentation.
By default, Bazel produces the following error when no conditions match:
Configurable attribute "foo" doesn't match this configuration (would a default
condition help?).
Conditions checked:
 //pkg:conditionA.
 //pkg:conditionB.
no_match_error can be used to signal more precise errors.

Examples

config_setting(
    name = "windows",
    values = {
        "crosstool_top": "//crosstools/windows",
    },
)

cc_binary(
    name = "multiplatform_app",
    ...
    linkopts = select({
        ":windows": [
            "-Wl,windows_support1.lib",
            "-Wl,windows_support2.lib",
        ],
        "//conditions:default": [],
    ...
)

In the above example, multiplatform_app links with additional options when invoked with bazel build //pkg:multiplatform_app --crosstool_top=//crosstools/windows .

workspace

workspace(name = "com_example_project")

This can only be used in a WORKSPACE file.

Each repository's WORKSPACE file should have a workspace(name = "...") line, which sets a global name for the repository.

This name is used for the directory that the repository's runfiles are stored in. For example, if there is a runfile foo/bar in the local repository and the WORKSPACE file contains workspace(name = "baz"), then the runfile will be available under mytarget.runfiles/baz/foo/bar. If no workspace name is specified, then the runfile will be symlinked to bar.runfiles/foo/bar.

A workspace name must start with a letter and can contain letters, numbers, and underscores (this is to maximize the number of languages for which this string can be a legal package/module name). It should describe the project in reverse-DNS form, with elements separated by underscores. For example, if a project is hosted at example.com/some-project, you might use com_example_some_project as the workspace name.

Remote repository rule names must be valid workspace names. For example, you could have maven_jar(name = "foo"), but not maven_jar(name = "foo.bar"), as Bazel would attempt to write a WORKSPACE file for the maven_jar containing workspace(name = "foo.bar").