To start with, let’s get the simplest possible program to execute.
We’ll largely follow along with https://bazel.build/start/cpp in this lesson.
Lets create a simple hello world application that prints “hello” to the standard out. Put this content in src/hello.c
:
#include <stdio.h>
int main(int argc, char const *argv[])
{
printf("hello world!");
return 0;
}
The natural next step here is to invoke a compiler like gcc
or clang
to get a executable binary by invoking it with something like gcc main.c -o main
and run the ./main
. Under other build tools, you’d write something that performs these steps directly.
For example in a Makefile
, it would look like this and in order build it, one would have to invoke make main
:
main:
gcc hello.c -o hello
Bazel is similar to make in this regard, however in Bazel there is not direct invocation of the compiler. Instead we use plugins (called “rules”) to describe the compilation units. For C and C++, cc_binary
is the rule for turning .c
code into executable binaries. Put this content in src/BUILD
:
cc_binary(
name = "main",
srcs = ["hello.c"]
)
Running this main.c is similar to make, running bazel run src:main
will compile and run hello.c
.
This build will depend on a hermetic LLVM toolchain, which you’ll observe downloaded and extracted the first time you run a build.
Bazel builds should ideally be completely reproducible across machines, regardless of OS distro, installed system libraries, and so on. Every file or tool needed for the build is managed by Bazel. This property is called “hermeticity”.
If there is an existing Makefile in your repository, there’s no reason to remove it. Instead, adjust it so that it runs bazel. This avoids re-training engineers and triggering their aversion to change.
main:
bazel build //:main