My 6 tips for working with Buildroot

Buildroot VAB820 header

Buildroot is a great tool to generate embedded Linux systems, and I’ve been using it at VIA for both software development and projects for a while now. Now Buildroot also includes some basic support and information for using it with our VAB-820 and AMOS-820. The changes were added in a commit recently, and if you use the cutting edge Buildroot from git then you already have everything to get started, otherwise it will be included in the next, 2015.08 release.

“Get started” in this context means that you can get to a bootable file system for your board or system in just a couple of simple steps, starting from scratch:

[bash] $ git clone git://git.busybox.net/buildroot
$ cd buildroot
$ make via_imx6_vab820_defconfig
… # setting up default values
$ make menuconfig
… # modify default settings for your use case
$ make
… # have a cup of coffee and wait for result: u-boot, kernel, rootfs
[/bash]

You can then check out the “readme.txt” in “board/via/imx6_vab820/” for the steps to create a bootable SD card and so on. I don’t think there ever was an easier way to create an embedded system.

To celebrate the first VIA device included with Buildroot, I thought it would be great to share what have I learned using Buildroot for the last half a year, what are the most useful features I’ve come across.

6 tips for working with Buildroot

1) Use compiler cache

Development always involves a lot of trial and error, which is in this case means a lot of compilation. When changing settings in Buildroot, oftentimes the best is to clean everything and start over.

[bash]$ make clean
… # do your modifications
$ make
[/bash]

To speed this process up, the first option I always enable in any Buildroot configuration I work with is the compiler cache.

[code gutter=”false”]Build options —> [*] Enable compiler cache[/code]

That setting has a couple of options as well, probably the only really important consideration is, that you can get even more out of this cache by putting it on an in-memory file system (e.g. /tmp on most recent Linux distros). You can expect a lot of time saved after the first compilation.

2) Easily modify the kernel configuration

If you use Buildroot to generate a kernel for your device, you might want to quickly change some configuration value for the kernel (e.g. enabling or disabling devices, or changing debug options). Buildroot has a shortcut for that:

[bash]$ make linux-menuconfig[/bash]

After this you’ll have the new configuration file available in the Linux build directory, make sure you copy it somewhere to else (e.g. your board’s config directory) so it won’t be removed the next time you run “make clean”, and update your Buildroot settings to use that config.

You can also use this trick for a couple of other software within Buildroot too, but I’ve found I only needed this for the kernel. See other options in the manual, or by running:

[bash]$ make help[/bash]

3) Build on defconfigs

You can adapt the Buildroot config to pretty much any kind of embedded board by starting a new configuration from scratch. To make things easier, they also include a collection of “defconfigs” in the “configs/” directory. They contain the minimal amount of customization one needs end up with a usable system for a particular board. For example in the case of the VAB-820, you can just run this:

[bash]$ make via_imx6_vab820_defconfig && make[/bash]

Of course most of the time you want to customize your final result, and then you’d add one more step in between:

[bash]$ make via_imx6_vab820_defconfig && make menuconfig && make[/bash]

Defconfigs provide a great basis for customization for projects using the particular hardware, so I’d very much recommend adding a defconfig for the board or system of your interest, if it doesn’t exist yet!

To create a new defconfig, the easiest is to go through the steps something like this:

[bash]$ make distclean && make menuconfig
… # add your configuration settings, including:
….# Build options —> (configs/myboard_defconfig) Location to save buildroot config
$ make
… # test the result
$ make savedefconfig
… # this will create or overwrite "configs/myboard_defconfig"
[/bash]

The contents of the defconfig are just the settings that are not at their default value. Within that file you can re-arrange the options and add comments to it for clarity, as many other defconfigs do, check them out!

4) Customize the file system with overlays

For many real-world projects you don’t just want the bare system, but it has to be customized in many ways. For example these things came up for me during development

  • Network configuration, for example “/etc/network/interfaces“, “/etc/resolv.conf
  • SSH credentials, for the server (dropbear host key) or the client “authorized_keys” for the users of ths system
  • NTP client settings (“/etc/chrony.conf“)
  • User scripts

These can be included by creating a directory that will act your “root”, and place files in there as they would “overlay” on the default root file system, then add that directory to the Buildroot config:

[code gutter=”false”]System configuration —> ( ) Root filesystem overlay directories[/code]

It is very handy for both development and deployment!

5) Add your own patches

It’s quite common that some of the software needs to be patched to work correctly with the hardware in question, whether it’s the kernel, the bootloader, or any other userspace tools.

The handiest way I’ve found is using a global patch directory, that is enabled in the menu:

[code gutter=”false”]Build options —> ( ) global patch directories[/code]

Here I can add a path, usually relative to the buildroot root directory, e.g. in a “board/vendor/myboard/patches” pattern. Buildroot will look within that directory before every package for a folder bearing the package’s name, and will apply all patches found within there. If for example you want to patch the upstream u-boot, create a “uboot” folder within the global patch directory, and copy your patches there. You can find the package name you have to use in the “package/” directory which lists everything that’s supported.

There are options for the more important packages in the Buildroot config to use specific patch directories, but I’ve found a lot more convenient having a global patch directory and configuring with the paths instead of the “config”.

6) Be part of the community!

The best way I’ve found learning about Buildroot is to actually contribute to it. There’s a mailing list & IRC channel where you can discuss issues with other (usually more experienced) developers. Buildroot has a patch management system and an autobuilder to automatically test changes: these are really good places to poke around, test patches, fix up problems that you can…

As the Buildroot community is very much a do-ocracy, I’ve also found that I got a lot more feedback and support adding VIA-related code as I’ve been submitting patches and “tested-by” confirmations to the mailing list already, compared to those who just arrive and do a “code drop”.

Also, Buildroot has a policy of upstreaming any patch that applied to the projects they add to the builde. This makes it possible to also learn about and contribute to a big variety of open source software.


Our contribution to Buildroot will not stop here of course. Looking forward to the future development and even more lessons!

VIA Technologies, Inc.