GNU Radio 3.9 in Buildroot

Recently I’ve had to cross-compile GNU Radio for an ARM embedded system. I have decided to use Buildroot to build GNU Radio and its dependencies, since I’m fairly familiar with using Buildroot to generate embedded Linux images. Earlier this year, Jean-Michel Friedt and
Gwenhaël Goavec-Merou
presented in FOSDEM their work about adding a GNU Radio package in buildroot. They gave a talk called “Never compile on the target!“.

Unfortunately, the version they used was GNU Radio 3.8, and the package hasn’t been updated to GNU Radio 3.9 yet. I wanted to use GNU Radio 3.9, so I decided to try to update the Buildroot package. After some assorted problems, I have managed to get GNU Radio 3.9 running on my ARM target. The fixes I’ve done are really horrible, so I’ve been quite tempted not to share my changes. I’ve finally decide to share this even though it’s far from perfect, because it might save someone from having to replicate this work, and because if anyone wants to do this properly and update the upstream package, this could be useful as a starting point.

The changes to the Buildroot tree are in the gr39 branch of my Github fork of Buildroot. This patch applies against the current stable release, which is the 2021.08 tag, but it could possibly apply cleanly to other versions.

These are the difficulties I’ve had to solve. First, the detection of NumPy with CMake didn’t work, even though NumPy was correctly installed to the STAGING and TARGET directories, and in fact it was possible to import numpy in the target. I am not totally sure how this works, but from glancing at GrPython.cmake, it seems to me that this runs the host Python and tries to import NumPy. This seems bound to give problems, because NumPy has been built for the target, and might not be present in the host. To get around this problem, I have simply modified the CMakeLists.txt so that not finding NumPy doesn’t cause a fatal error.

A related problem is that, during the build, some .h header files from NumPy could not be found, because the correct include path wasn’t passed to g++. I tried without success to use -DNUMPY_INCLUDE_DIR when running cmake (inspired by this). Finally, I’ve decided not to spend more time and set this by hand in -DCMAKE_CXX_FLAGS.

After getting GNU Radio to build, I found a real oddity. The library libgnuradio-digital.so had an undefined symbol: gr::digital::map_bb_impl::s_map_size. This is a static constexpr that is only used in a few places in map_bb_impl.h and map_bb_impl.cc.

Why g++ would create a symbol for this instead of just replacing the constant value in the generated code escapes me. I’ve tried to search for some clues and understand the subtleties of constexpr, but after finding some references to ODR-used and remembering this joke, I decided to replace the static constexpr by a #define macro.

Finally, the dynamic libraries generated by pybind11 are missing the .so extension in the target directory. This will give import errors in Python. They need to be renamed to add the .so extension. I haven’t included this in the patch in my gr39 branch, because I renamed them by hand. These libraries are found in usr/lib/python3.9/site-packages/gnuradio and usr/lib/python3.9/site-packages/pmt in the target directory and have names ending in _python, such as blocks/blocks_python. They should be renamed to blocks/blocks_python.so, etc. I haven’t investigated why this happens.

And this is it. Hopefully someone will find this post useful eventually.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.