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
- Read this
vagrant ssh
git clone https://github.com/valkyrierobotics/mass
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.
cc_binary
is a particular rule, which tells Bazel that we will be building an executable C or C++ program.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.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.