To stay on top of bazel development, and to prepare for some future improvements, I’ve gone ahead and upgraded the moteus firmware build system, rules_mbed to use the new bazel “platforms” toolchain resolution mechanism.
Previously, rules_mbed used the “crosstool_top” bazel mechanism for toolchain configuration. This allowed a single package to contribute a set of C++ toolchains which would be selected based on CPU and compiler. One of the downsides from the rules_mbed perspective, is that it made it difficult to make a build that included both mbed targets and host targets (or anything else non-mbed). rules_mbed worked around this by including a functioning clang host toolchain within it.
With the new toolchain resolution support, at the command line you specify to bazel what “platform” you want to be the final target. The updated rules_mbed specifies a “platform” for each of the STM32 processors that are supported. So for instance you could use:
bazel build --platforms=@rules_mbed//:stm32g4 //:target
It then uses that platform to find a toolchain with a compatible operating system and CPU, which for rules_mbed is the arm-gcc compiler for the correct chip.
Because of this, the command lines necessary to compile the moteus firmware and host side tools have changed. Rather than expose the raw bazel options, it now just uses a bazel config to abstract away whatever mechanisms are required. So, the two necessary new command lines are:
tools/bazel test --config=target //:target # build firmware
tools/bazel test --config=host //:host # build host tools
Soon, we’ll use this capability to add some useful new features to the moteus tools, such as support for non-linux operating systems.
While working on the next revision of the moteus controller, I started by bringing up a software toolchain on a NUCLEO-G474RE board. Unfortunately, even the most recent mbed 5.14 doesn’t yet support that processor. Thus, I have a half-baked solution which pulls in the ST CUBE sources for that controller into the mbed tree as a patch.
The patch only implements wrappers for the things I care about, so it isn’t a complete solution. Since I am not really using any mbed libraries anymore in any project, that isn’t a whole lot. Right now I’m just using it for the one function that sets up the board, a linker script, and the pin mappings. I will probably eventually just make a rules_stm32 and ditch mbed entirely but for now that is more work than it is worth.
When working on the firmware for Super Mega Microbot’s improved actuators, I decided to try using mbed-os from ARM for the STM32 libraries instead of the HAL libraries. I always found that the HAL libraries had a terrible API, and yet they still required that any non-trivial usage of the hardware devolve into register twiddling to be effective. mbed presents a pretty nice C++ API for the features they do support, which is only a little less capable than HAL, but still makes it trivial to drop down to register twiddling when necessary (and includes all of the HAL by reference).
Most people probably use mbed through their online IDE. While this is a remarkable convenience, I am a big fan of reproducibility of builds and also of host based testing. mbed provides mbed-cli which gets part of the way there by letting you build offline. Unfortunately, it still doesn’t provide great support for projects that both deploy to a target and have automated unit tests. It actually has zero support for unit tests that can run on the host.
As many have guessed, I’m a big fan of bazel https://bazel.build, for building software projects. Despite being raw around the edges, it does a lot of things right. Its philosophy is to be fast, correct, and reproducible. While it doesn’t support flagless multi-platform builds yet (#6519), it does provide some minimal multi-platform support. It also has robust capabilities for pulling in external projects, including entire toolchains and build environments. Finally, it has excellent support for host based unit tests.
To make it work, you do have to configure a toolchain though. That I’ve now done for at least STM32F4 based mbed targets. It is published under an Apache 2.0 license at: https://github.com/mjbots/rules_mbed
- Seamless toolchain provisioning: It configures bazel to automatically download a recent GNU gcc toolchain from ARM (2018q2).
- Processor support: Currently all STM32F4 processors are supported, although others could be added with minimal effort.
- Host based testing: Common modules that rely only on the standard library can have unit tests run on the host using any C/C++ testing tools such as boost::test.
- Simultaneous multi-target configuration: Multiple targets (currently limited to the same CPU family) can be built with a single bazel command. Multiple families can be configured within the same source tree.
Once you have it installed in a project, building all host based tests is as simple as:
tools/bazel test //...
and building all binary output files is as simple as:
tools/bazel test -c opt --cpu=stm32f4 //...