Show how to build and execute a binary, how to build a library, and how to build and run a test.
In this example we have declared 3 targets. A library, an executable and a test. The binary and the test depends on the library.
-
//:my_lib
: A library with a public header and a single cpp file. It can be defined in Bazel as follows:cc_library( name = "my_lib", srcs = ["my_lib.cpp"], hdrs = ["my_lib.h"], )
name
is the name for the target, it will also be used to create the library file in the form oflib<name>.a
orlib<name>.so
depending on whether is a dynamic or a static library.hdrs
is the list of public headers of the library, your interface to the rest of the world.srcs
is the list of source files needed to generate the library, including private headers and cpp files. The public header files should not be present in this parameter, they are defined inhdrs
. -
//:hello_world
: A binary that depends on the library mentioned above. It can be defined in Bazel as follows:cc_binary( name = "hello_world", srcs = ["hello_world.cpp"], deps = [":my_lib"], )
name
is the name for the target, it will also be used to create the executable file in the form of<name>
in Unix systems or<name>.exe
in Windows systems.srcs
is the list of source files needed to generate the executable.deps
is the list of libraries that your binary depends on. In this case we specify the target:my_lib
that is the library that we want to use in this binary. -
//:my_test
: A test formy_lib
target. In the end it is an executable also but Bazel will treat it different in several aspects. It can be defined in Bazel as follows:cc_test( name = "my_test", srcs = ["test.cpp"], deps = [":my_lib"], )
name
is the name for the target, it will also be used to create the executable file for the test in the form of<name>
in Unix systems or<name>.exe
in Windows systems.srcs
is the list of source files needed to generate the test executable. The requirement like a binary is that it has to contain amain
function that returns anint
. If it returns an 0 it is considered like the test passed, otherwise is considered as failure.deps
like for the binary, is the list of libraries that your test depends on.
To run the executable you call:
bazel run //:hello_world
It will run the executable and display the output on the terminal.
To run the test you call:
bazel test //:my_test
It will run the test without showing any output from the test but a Bazel output indicating if the test succeeded or failed.
//:my_test PASSED in 0.0s
A test, compared to a binary executed with bazel run
will not be allways executed. If Bazel detects that nothing changed it will cache the result of th test and show it in the report.
//:my_test (cached) PASSED in 0.0s
If you want to build the executable without running it you call:
bazel build //:hello_world
And if you want to build only the library you can do the same with the target of the library:
bazel build //:my_lib
In this example we have one executable and one library. This brings us to two possibilities, to load the library during runtime (dynamic linking) or embed it into the executable (static linking).
The way to control it in Bazel is using --dynamic_mode
. It has three options: default
, fully
and off
. The most relevant for us are fully
and off
.
If we build the binary using off
it will do static linking in all the cases that it is possible. Using fully
it will do dynamic linking with all the targets.
How to pass it to the command line would be as follows:
bazel build //:hello_world --dynamic_mode=off
You can also pass it when calling directly bazel run
.