Adding Custom Packages to Buildroot

3 minute read

This is a quick tutorial on adding a custom package into buildroot for creating your own Linux distribution for embedded and emulation targets. You can find detailed instructions in the buildroot documentation

Buildroot allows you to quickly generate full-fledged cross-compiled Linux systems. It comes with a tonne of packages that you can select while configuring. They are then cross-compiled into the final root file system generated by Buildroot. But, how do you add a new package into Buildroot? It might be a proprietary tool or a package not yet upstreamed into Buildroot. This article covers the basics of how this can be done.

There are two main methods to add a custom package into buildroot. The first method includes adding a package directly into the source tree and is described here. The second involves the use of an external package tree. A reference to using the second method is provided at the end of this article.

Let us consider that you have a custom package (embeddedinn) that you would like to include in your Root FS created with buildroot. This package will consist of a source file and a makefile in the most straightforward case.

Source (package/embeddedinn/src/embeddedinn.c):

#include <stdio.h>

int main(void) {
printf("EMBEDDEDINN\r\n");
}

package/embeddedinn/src/Makefile


.PHONY: clean
.PHONY: embeddedinn

embeddedinn: embeddedinn.c
    $(CC) -o '$@' '$<'

clean:
    -rm embeddedinn

Note: Makefile requires a tab character for indentation. Spaces will not work.

Now, let us create a package definition for this package in the buildroot source tree. In this case, we are assuming that the package is located in the /package/ directory and is locally available. Buildroot also lets you pull package contents from git, svn, wget, tar.gz etc.

Within the Buildroot source tree, you can create an embeddedinn directory under the package directory and create two files: embeddedinn.mk and Config.in within the embeddedinn directory.

package/embeddedinn/Config.in

config BR2_PACKAGE_EMBEDDEDINN
    bool "embeddedinn"
    help
        embeddedinn package.

        https://embeddedinn.xyz

package/embeddedinn/embeddedinn.mk

################################################################################
#
# embeddedinn package
#
################################################################################

EMBEDDEDINN_VERSION = 1.0
EMBEDDEDINN_SITE = package/embeddedinn/src
EMBEDDEDINN_SITE_METHOD = local# Other methods like git,wget,scp,file etc. are also available.

define EMBEDDEDINN_BUILD_CMDS
    $(MAKE) CC="$(TARGET_CC)" LD="$(TARGET_LD)" -C $(@D)
endef

define EMBEDDEDINN_INSTALL_TARGET_CMDS
    $(INSTALL) -D -m 0755 $(@D)/embeddedinn  $(TARGET_DIR)/usr/bin
endef

$(eval $(generic-package))

Note: In the latest version of buildroot that I tested (2022.11.1), a trailing space after local in the EMBEDDEDINN_SITE_METHOD variable causes buildroot to fail since it then tries to download the package over the network.

Now create a link to the Config.in file by making an entry in the package/Config.in file of Buildroot.

package/Config.in:

menu "EMBEDDEDINN Packages"
    source "package/embeddedinn/Config.in"
endmenu

At this stage, the package will become visible in the menu and can be enabled to make an entry in the .config file.

Menu for EMBEDDEDINN packages

Menu for EMBEDDEDINN packages

EMBEDDEDINN package details

EMBEDDEDINN package details

To configure the package, I did make qemu_riscv64_virt_defconfig and then make menuconfig. The new package will be available under Target Packages

Issuing a make command will build the package and include it into the generated root file system.

In this case, I am executing the generated RFS on a RISCV QEMU virt machine using the start-qemu script generated by buildroot. The embeddedinn command is now available in the generated RFS.

EMBEDDEDINN command in RFS

EMBEDDEDINN command in RFS

BR2_EXTERNAL

If you want to maintain the project-specific source code outside the buildroot tree, you can use the BR2_EXTERNAL mechanism detailed in the Buildroot documentation. The path to BR2_EXTERNAL is passed to make invocation, and from that point onwards, buildroot considers the external tree as a part of the buildroot build process. A .br2-external.mk file is also generated in the output directory to avoid entering the BR2_EXTERNAL paths for every make invocation.

Some useful commands when working with packages

The following commands are for the embeddedinn package we added here. But it works for any package in buildroot. Just replace embeddedinn with the package name.

command description
make embeddedinn Build the package and install it on target
make embeddedinn-dirclean Remove the build directory for the package
make embeddedinn-rebuild restart the compilation and installation of the package

Stages are tracked by buildroot by creating the following stamp files in the output/build/<package>-<version> directory.

 .stamp_built
 .stamp_configured
 .stamp_installed
 .stamp_rsynced
 .stamp_target_installed

You can restart the build process at any stage by deleting the corresponding stamp file. For example, if you want to restart the build process after the package has been built, you can delete the .stamp_built file.

Leave a comment