Bazel & Introductions: Part Five – Building Stuff with Bazel

At last, the long waited moment has arrived. I’m going to write about the actual use of Bazel, albeit with no external dependencies and no cross compilation. That’ll be next post.

Let’s Build Hello World

Alright. For the moment, we’ll step away from the complexities of cross-compilation, and third party libraries, and look at only the simplest use of Bazel – compiling “Hello, World.”

At this point, I’d really like to assume that everyone knows the source to the “Hello, World” program in C++, but then again, you may also not.

Without explanation, then:

#include <iostream>

int main() {
    std::cout << "Hello, World\n"

    return 0;
}

Note that I use \n instead of std::endl because std::endl both adds a newline and flushes the buffer. If you have a lot of printing in a row, stuff gets very slow.

I picked this example for the same reason everyone else in the modern world chooses “Hello, World.” It’s really frickin’ simple. Hell, even the assembly is just a few lines:

                .Ltext0:
                    .section    .rodata
                .LC0:
0000 48656C6C       .string "Hello, World"
     6F2C2057 
     6F726C64 
     00
                    .text
                    .globl  main
                main:
                .LFB0:
                    .cfi_startproc
0000 55             pushq   %rbp
                    .cfi_def_cfa_offset 16
                    .cfi_offset 6, -16
0001 4889E5         movq    %rsp, %rbp
                    .cfi_def_cfa_register 6
0004 BF000000       movl    $.LC0, %edi
     00
0009 E8000000       call    puts
     00
000e B8000000       movl    $0, %eax
     00
0013 5D             popq    %rbp
                    .cfi_def_cfa 7, 8
0014 C3             ret
                    .cfi_endproc
                .LFE0:
                .Letext0:               .Ltext0:
                    .section    .rodata
                .LC0:
0000 48656C6C       .string "Hello, World"
     6F2C2057 
     6F726C64 
     00
                    .text
                    .globl  main
                main:
                .LFB0:
                    .cfi_startproc
0000 55             pushq   %rbp
                    .cfi_def_cfa_offset 16
                    .cfi_offset 6, -16
0001 4889E5         movq    %rsp, %rbp
                    .cfi_def_cfa_register 6
0004 BF000000       movl    $.LC0, %edi
     00
0009 E8000000       call    puts
     00
000e B8000000       movl    $0, %eax
     00
0013 5D             popq    %rbp
                    .cfi_def_cfa 7, 8
0014 C3             ret
                    .cfi_endproc
                .LFE0:
                .Letext0:

Or not quite a few. I really need to stop trying to verify stuff like this. Anyway, at this point, we could build this project with a simple

g++ main.cpp -o main ; ./main

But, based on all the previous posts on I’ve made, you can probably guess that we aren’t going to do that. We’re going to use Bazel!

Actually Using Bazel

Okay. Fun times are over – now we’re building with Bazel.

I’ll be honestly – this is going to seem ridiculously overcomplicated. It’s not, however, when you have a massive project. Trust me.

Quick Guide to Valkyrie Dev Environments
  1. Read this
  2. vagrant ssh
  3. git clone https://github.com/valkyrierobotics/mass
  4. cd mass

Now, you’ll need to (if it’s a blank Bazel install) create a blank file named ‘WORKSPACE’ in the top level of your folder (the folder with main.cpp). This establishes that we are working in a Bazel environment.

Finally, our environment is all set up. Let’s build code!

In order to build this project, and run it, we will have to write a BUILD file, and in it we have to put a particular message to Bazel – what’s called a ‘rule.’ Note that a full list of build can be found on their website under ‘Rules’

So now, create a new file named ‘BUILD’ in the same directory as main.cpp and fill type in the following:

cc_binary(
    name = 'hello',
    srcs = [ 'main.cpp' ],
)

Now, you can run the file using bazel run :hello or if you’re in mass, tools/bazel run :hello. Honestly, I cannot teach you Bazel through blogposts, but their website has pretty good documentation, and reading mass might help a lot. Now that everything is working, let’s look at this BUILD file line by line.

  1. cc_binary is a particular rule, which tells Bazel that we will be building an executable C or C++ program.
  2. name = 'hello', tells Bazel that this project will be named “hello,” which allows us to access it using //:hello, which means “the target called hello at the root of the workspace.” These sort of paths are also documented on their website.
  3. srcs = [ 'main.cpp' ] defines the list of src files, which in this case is only main.cpp. Note that this is similar to Python list notation.

That’s all the blogging I can do today, but I’ll write another NumPy post soon, and probably another Bazel one eventually.