In the previous post, I described the motivation for switching the mjmech build system to bazel. For that to be useful with Super Mega Microbot, I first had to get a toolchain configured for bazel such that it could produce binaries that would run on the raspberry pi.
All the work in this post is publicly available on github: https://github.com/mjbots/rpi_bazel
Compiler and sysroot
First, I needed to pick the compiler I would be using and how to get the target system libraries available for cross compilation. In the past I’ve always done the gcc/binutils/gnu everything cross toolchain dance, however here I thought I would try something a bit more reproducible and see if I could make clang work. Amazingly, a single clang binary supports all possible target types! clang-6, which can be had through a PPA on Ubuntu 16.04 and natively on Ubuntu 18.04 supports it out of the box.
For the target system libraries, I wrote a small script: make_sysroot.py which when aimed at a live raspberry pi, will extract the Linux kernel headers and glibc headers and binaries. These are stored in a single tar.xz file, with the latest version checked into the tree: 2018-06-10-sysroot.tar.xz.
Bazel configuration
bazel has a legacy mechanism for configuring toolchains, called the CROSSTOOL file. It is not exactly pretty, is moderately underdocumented, but at least there are a few write ups online for how to create one. The CROSSTOOL I created here is minimally functional, with options for both host/clang and rpi/clang with a few caveats:
- It isn’t hermetic, it relies on the system installation of clang
- It includes hard coded paths to micro releases of clang
- The C++ main function isn’t handled correctly yet, and you have to ‘extern “C”‘ it to link applications
With a functioning CROSSTOOL, the next step is to declare the “cc_toolchain_suite” and “cc_toolchain” definitions. Those are defined in the tools/cc_toolchain/BUILD file and don’t have anything particularly complex in them.
Finally, I created a repository.bzl which is intended to be imported in client projects. This provides a relatively simple API for a client project to import the toolchain, and gets the sysroot extracted properly.
Using it in a bazel project
The top level README gives the steps to use the toolchain, which while not too bad, still requires touching 4 non-empty files (and 2 possibly empty files). Once that is done, you can use:
bazel test --config=pi //...
To build your entire project with binaries targeted to run on the raspberry pi!