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 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

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/, etc. I haven’t investigated why this happens.

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


  1. Have you found a workaround for when the host and target differ in bits (32-bit target, 64-bit host)?

    Some part of the cmake configure step of gnuradio calls some helper code in pybind11 which checks the wrong version of python (the host, instead of the target) and you end up getting this:
    “Python config failure: Python is 64-bit, chosen compiler is 32-bit”

    If you disable that test then you’ll later get an error related to the definition of LONG_BITS, which, IIRC, is another issue related to mismatching host and target.

    1. Hi! I didn’t have this problem. I was building for an arm32 target from an x86_64 host. I don’t recall if I did something to avoid this problem or if simply my set up was somewhat different to yours. In any case, the gr39 branch has all the modifications I needed to do.

  2. You shouldn’t override CMAKE_CXX_FLAGS in like that.

    At the very least, if you do, you should prepend ${TARGET_CXXFLAGS} which is a buildroot variable used in the cmake toolchain file.

    1. Thanks for the tip! I’m aware that this solution is not very good, and arrived at it in a kind of “I don’t want to spend too much time and get this working now”. I thought it was more helpful sharing it than not. I’ll keep this advice in mind for next time.

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.