Bazel Overview
Reference docs.bazel.build and take some notes
What is Bazel?
- Bazel is an open-source build and test tool similar to Make, Maven, and Gradle. It uses a human-readable, high-level build language. Bazel supports projects in multiple languages and builds outputs for multiple platforms. Bazel supports large codebases across multiple repositories, and large numbers of users.
Concepts and terminology
Workspace
- A workspace is a directory on your filesystem that contains the source files for the software you want to build, as well as symbolic links to directories that contain the build outputs.
Packages
- A package is a container. The elements of a package are called targets.
- A package is defined as a directory containing a file named
BUILD
orBUILD.bazel
Labels (//package-name:target-name)
- Each label has two parts, a package name (my/app/main) and a target name (app_binary). Every label uniquely identifies a target.
- Labels start with //
//my/app/main:app_binary
Within a BUILD file, the package-name part of label may be omitted, and optionally the colon(:) too. The following “relative” labels are all equivalent:
//my/app:app
//my/app
:app
app
But from other packages, or from the command-line, these file targets must always be referred to by their complete label.
Types of build rule
- Difference languages have different prefix(*). For example, cc for c++, java for java.
- *_binary rules build executable programs in a given language.
- *_test rules are a specialization of a *_binary rule, used for automated testing. Tests are simply programs that return zero on success.
- *_library rules specify separately-compiled modules in the given programming language. Libraries can depend on other libraries, and binaries and tests can depend on libraries, with the expected separate-compilation behavior.
Native rules
- alias: The
alias
rule creates another name a rule can be referred to as. In particular,package_group
andtest_suite
cannot be aliased.
filegroup(
name = “data”,
srcs = [“data.txt”],
)alias(
name = “other”,
actual = “:data”,
)
- filegroup: Using
filegroup
is encouraged instead of referencing directories directly. When combined with glob,filegroup
can ensure that all files are explicitly known to the build system.
filegroup(
name = "exported_testdata",
srcs = glob([
"testdata/*.dat",
"testdata/logs/**/*.log",
]),
)cc_library(
name = "my_library",
srcs = ["foo.cc"],
data = [
"//my_package:exported_testdata",
"//my_package:mygroup",
],
)
- test_suite: A
test_suite
defines a set of tests that are considered "useful" to humans.
test_suite(
name = "smoke_tests",
tests = [
"system_unittest",
"public_api_unittest",
],
)
- config_setting: The following matches any Bazel invocation that specifies
--compilation_mode=opt
or-c opt
(either explicitly at the command line or implicitly from .bazelrc files).select()
is the helper function that makes a rule attribute configurable.
config_setting(
name = "simple",
values = {"compilation_mode": "opt"}
)sh_binary(
name = "mytarget",
srcs = select({
":simple": ["mytarget_a.sh"],
":conditionB": ["mytarget_b.sh"],
"//conditions:default": ["mytarget_default.sh"]
})
)
- genrule: A
genrule
generates one or more files using a user-defined Bash command. Do use$(location)
extensively, for outputs, tools and sources. Due to the segregation of output files for different configurations, genrules cannot rely on hard-coded and/or absolute paths.
genrule(
name = "foo",
srcs = [],
outs = ["foo.h"],
cmd = "./$(location create_foo.pl) > \"$@\"",
tools = ["create_foo.pl"],
)
OUTS
: Thegenrule
'souts
list. If you have only one output file, you can also use$@
SRCS
: Thegenrule
'ssrcs
list (or more precisely: the path names of the files corresponding to labels in thesrcs
list). If you have only one source file, you can also use$<
RULEDIR
: The output directory of the rule@D
: The output directory.
Types of dependencies
- srcs: Files consumed directly by the rule or rules that output source files.
- deps: Rule pointing to separately-compiled modules providing header files, symbols, libraries, data, etc.
- data: A build target might need some data files to run correctly. These data files aren’t source code: they don’t affect how the target is built. For example, a unit test might compare a function’s output to the contents of a file.
Bazel extensions
Bazel extensions are files ending in .bzl
Macros
- A macro is a function called from the BUILD file that can instantiate rules. Macros are mainly used for encapsulation and code reuse of existing rules and other macros.
generator.bzl
def file_generator(name, arg, visibility=None):
native.genrule(
name = name,
outs = [name + ".txt"],
cmd = "$(location //:generator) %s > $@" % arg,
tools = ["//:generator"],
visibility = visibility,
)Build
load("//path:generator.bzl", "file_generator")
file_generator(
name = "file",
arg = "some_arg",
)
file_generator(
name = "file-two",
arg = "some_arg_two",
)
Rule (Tutorial)
- A rule is more powerful than a macro. A rule defines a series of actions that Bazel performs on inputs to produce a set of outputs.
- when you call the
rule
function, you must define a callback function. Thectx
argument provides information about the target.
foo.bzl
def _foo_binary_impl(ctx):
print("analyzing", ctx.label)
foo_binary = rule(
implementation = _foo_binary_impl,
)BUILD
load(":foo.bzl", "foo_binary")
foo_binary(name = "bin1")
foo_binary(name = "bin2")