Search:

PmWiki

pmwiki.org

edit SideBar

Main / Buildroot

uClibc is a small C standard library for embedded Linux systems (vs. glibc, which is the full size library). It originated from the uClinux project, for processors without MMUs.

http://buildroot.uclibc.org/
Getting started: http://agentoss.wordpress.com/2011/02/27/how-to-create-a-very-small-linux-system-using-buildroot/
http://elinux.org/images/2/2a/Using-buildroot-real-project.pdf

"Buildroot is a set of Makefiles and patches that makes it easy to generate a complete embedded Linux system. Buildroot can generate any or all of a cross-compilation toolchain, a root filesystem, a kernel image and a bootloader image. Buildroot is useful mainly for people working with small or embedded systems, using various CPU architectures (x86, ARM, MIPS, PowerPC, etc.) : it automates the building process of your embedded system and eases the cross-compilation process."

It has a nice "terminal graphical" menu system for configuring builds (make menuconfig). You can actually choose other core libraries besides uclibc, such as eglibc.

A toolchain includes components needed for the building of the OS, such as the compiler, binutils, runtime library, debugger, etc.

The notes in here began with Buildroot 2014.08, but in some cases may apply only to later revisions.

What else is included?

This version does not have freeGLUT (freeGLUT support for OpenGL ES is questionable) but does include EGL and SDL.

Issue with package management

https://buildroot.org/downloads/manual/manual.html#faq-no-binary-packages

Getting Started in a Strange BR Project

Find out what targets are available with make list-defconfigs.

Restrict the menuconfig launch to one target only with make <target>-menuconfig. Otherwise, menuconfig will launch over and over, once for each possible target.

Compiling Unmasked

When you run make menuconfig you end up with edits to the .config file, which governs the build. The build auto-configure command is make ***_defconfig, which loads the .config. The "Defconfig" kernel option is for the arch/arm/configs/ config file selection in the kernel directory.

Remember that when doing a make <target>-clean you lose the menuconfig edits you've made, because the .config file that gets updated is placed in the outputs/ folder. If you want to set default settings that are maintained through a clean, put the flags in the defconfig file. To keep the settings when rebuilding, you can simply do a manual remove on the outputs/ folder to force BR to rebuild everything.

In the process of building a cross-compilation toolchain, the C library is being built. This library provides the interface between userspace applications and the Linux kernel. In order to know how to "talk" to the Linux kernel, the C library needs to have access to the Linux kernel headers (i.e. the .h files from the kernel), which define the interface between userspace and the kernel (system calls, data structures, etc.).

For Buildroot, this backend supports several C libraries: uClibc, the glibc and eglibc.

Buildroot also supports other external toolchains instead of creating its own (such as CodeSourcery).

Buildroot by default pulls the kernel source from a git repo. You can change this to a local directory in the make menuconfig. I think when you do this, the source tree (or just headers rather?) is stored under output/build/linux-custom as opposed to the kernel packed with buildroot at output/build/linux-headers-<version>, for example -3.14.5

It looks like the default setting is for Buildroot to go out and grab the kernel headers from the internet (kernel.org) with the specified version.

The easiest way to rebuild a single package from scratch is to remove its build directory in output/build. Buildroot will then re-extract, re-configure, re-compile and re-install this package from scratch. You can ask buildroot to do this with the make <package>-dirclean command.

Force recompile of kernel uImage

Although it's happy to rebuild the rootfs, Buildroot doesn't seem to rebuild the image unless you force it. Any time you make a change to the kernel code, do an rm -rf output/build/<linux-folder>... make linux-rebuild also useful.

If you change the kernel config with make linux-menuconfig note that make linux-reconfigure will undo what you changed.

The uImage is the Uboot friendly image, but will only be built if you add LOADADDR=* to the make command. If not, you must use mkimage to create the uImage.

What if I want to force a Uboot build?

use make uboot-rebuild

How about building the .dtb only?

make ARCH=arm CROSS_COMPILE=arm-none-eabi- <soc>-<board>.dtb
This is done in the Linux kernel directory, not Buildroot top.

Application cross-compile

This needs to be done with the target toolchain, and needs to link against the right libraries, such as uclibc in this case. If you can't run the executable on the target even though the file output looks right, try running ldd on it. If you get libc.so.6 =>not found (0x00000000) then it looks like you linked against glibc instead of uclibc, which uses a libc.so.0 symlink instead.

Printing the make variables

make -s printvars

When I make a new Linux config with make linux-menuconfig, where does it go?

output/build/linux-custom/.config

How to update the Linux config in an external out-of-tree configuration folder?

There are two options:

  • make linux-update-config will copy like so, to the destination set by BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE
cp -f /mnt/newHDD/sandbox/pcu_buildroot/buildroot-at91/output/build/linux-custom/.config 
/mnt/newHDD/sandbox/pcu_buildroot/reap_buildroot_external/board/aac/reap_rev1/linux.config
  • make linux-update-defconfig will actually do some additional steps and copy over a pared-down output/build/linux-custom/defconfig file instead (BR manual says it simplifies the config file by removing default values, and says the former -config command is for older kernels like pre-2.6)

But it turns out, you need to be doing the make linux-menuconfig and make linux-rebuild and similar in the subfolder for your build where you actually execute make for your target. For example, if you want to make module and Kconfig changes, you don't do that in the buildroot/output/build/linux-custom/ folder, you need to do that in your buildroot/<project>/build/linux-custom/ location. The menuconfig controls are actually apparently separate.

How to update the .config in the project output folder?

Normally the make O=projname command would do this, but it won't work if you have made modifications to a package's package/<name>/Config.in.host file. It may be that this is only the case for an external build, because apparently the package updates should be done in that external folder.

This may be a bug in Buildroot's ability to add available packages to a build you already ran, and don't want to delete the whole thing and start over:

Note that with these BR instructions:

cd buildroot-at91
BR2_EXTERNAL=../reap_buildroot_external/ make O=reap reap_rev1_defconfig
# or
BR2_EXTERNAL=../reap_buildroot_external/ make O=reap reap_rev0_defconfig
cd reap
make

… this creates the master .config that BR uses based on the reap defconfig… so if you go and make manual changes in menuconfig, those will be overwritten if you do that command again. After menuconfig changes, just run make.

To add applets to busybox, I selected the item in make menuconfig and then removed the reap/build/busyboxXXXX folder to force a rebuild of the whole tool. Then look for tcpdump in the new rootfs.tar, but it isn’t there. Now I’m thinking that’s because this isn’t the busybox version of tcpdump I’m trying to build, it’s a separate package. In fact, if you go into make busybox-menuconfig, there is no option for adding tcpdump.

So now how to make buildroot include this new package? It’s not detecting automatically that I’ve added it to the .config. The answer turned out to be to instruct make on that package directly, make tcpdump, and then find the binary in reap/target/usr/bin

Seems like something is broken in buildroot if not recognizing the change in the .config file, as the documentation says that should work without doing an entire rebuild.

How to make kernel modifications in external build?

Changes to the buildroot main folder in output/build/linux-custom/ will be ignored. You must make changes in your external folder's build/linux-custom/ location where the kernel is copied from original source archive. You can manually apply patches here for example. If the Kconfig of a module is updated with new options for example, then when you do your next make linux-rebuild it will ask you to select Y/N/M for those new options and adjust the build/linux-custom/.config file accordingly.

Changing GCC compiler version

Understanding when a full rebuild (make clean all) is necessary

Buildroot does not attempt to detect what parts of the system should be rebuilt when the system configuration is changed through make menuconfig, make xconfig or one of the other configuration tools. In some cases, Buildroot should rebuild the entire system, in some cases, only a specific subset of packages. But detecting this in a completely reliable manner is very difficult, and therefore the Buildroot developers have decided to simply not attempt to do this.

Instead, it is the responsibility of the user to know when a full rebuild is necessary. As a hint, here are a few rules of thumb that can help you understand how to work with Buildroot:

  • When the target architecture configuration is changed, a complete rebuild is needed. Changing the architecture variant, the binary format or the floating point strategy for example has an impact on the entire system.
  • When the toolchain configuration is changed, a complete rebuild generally is needed. Changing the toolchain configuration often involves changing the compiler version, the type of C library or its configuration, or some other fundamental configuration item, and these changes have an impact on the entire system. (Change the version of the GCC compiler, binutils and the C library.)
  • others in the BR manual

This example shows how to upgrade from one version of GCC to another.

There are two ways to update packages.
These examples are based on the gcc package. The procedure may be different for non-dropdown menus.

Option 1: Add configuration to menuconfig

Add version selection option to package/gcc/Config.in.host.

config BR2_GCC_VERSION_13_X
    # What is displayed as a selection option
    bool "gcc 13.x"
    # What this option may depend on to be true/false
    depends on !BR2_powerpc_SPE
    depends on !BR2_sparc
    depends on !BR2_archs4x_rel31
    # Set any other variables
    select BR2_TOOLCHAIN_GCC_AT_LEAST_13

Add version string in package/gcc/Config.in.host.

config BR2_GCC_VERSION
    string
    default "8.4.0"     if BR2_GCC_VERSION_POWERPC_SPE
    default "9.4.0"     if BR2_GCC_VERSION_9_X
    default "10.4.0"    if BR2_GCC_VERSION_10_X
    default "11.3.0"    if BR2_GCC_VERSION_11_X
    # What should the version be if the boolean is set.
    default "13.2.0"    if BR2_GCC_VERSION_13_X
    default "arc-2020.09-release" if BR2_GCC_VERSION_ARC

Add hash value to package/gcc/gcc.hash. The file should have links to where the other versions' hashes are for reference.

# From https://gcc.gnu.org/pub/gcc/releases/gcc-13.2.0/sha512.sum
sha512  <insert-hash-here>  gcc-13.2.0.tar.xz

make menuconfig select the option and build.

DISCLAIMER
Note that if you do it this way it's for a standard tree build.  
If you have an external tree, you will break the build because the .config file will not correctly update when these 
package file changes have been made.  There are instructions in the manual for doing this with external tree folder.

Option 2 works for an external tree.
Edit gcc.mk version number with hardcoded value.

GCC_VERSION = 13.2.0

Add hash value to gcc.hash. The file should have links to where the other versions' hashes for reference.

# From https://gcc.gnu.org/pub/gcc/releases/gcc-13.2.0/sha512.sum
sha512  d99e4826a70db04504467e349e9fbaedaa5870766cda7c5cab50cdebedc4be755ebca5b789e1232a34a20be1a0b60097de9280efe47bdb71c73251e30b0862a2  gcc-13.2.0.tar.xz

make

Changing the name of the output/ folder

You can use a different folder name with an option on the make instruction, "(output/ by default, another value can be specified using O=)" as in BR2_EXTERNAL=../reap_buildroot_external/ make O=reap reap_rev1_defconfig which will use a folder called reap/ instead.

As default, everything built by Buildroot is stored in the directory output in the Buildroot tree. Buildroot also supports building out of tree with a syntax similar to the Linux kernel. To use it, add O=<directory> to the make command line:

$ make O=/tmp/build menuconfig

Note it's the letter O, not a zero!!!!

Customizing the build process

You can use patches for the kernel and uboot and always build off of a source repo snapshot if you want, rather than maintaining your own source. There's a global patch directories field under Build options. In the indicated folder you can place a series of numbered patch files (i.e. linux-<patchnum>-<boardname>.patch

Tell BR where to get kernel patches under Kernel at Custom kernel patches

You can also specify the Configuration file path as external to BR. The BR2_EXTERNAL variable is the path mechanic for this.

Under System configuration you'll find the fields for Root filesystem overlay directories and Custom scripts to run after. The latter is the post-image.sh script, here's an example:

#!/bin/sh

BOARD_DIR="$(dirname $0)"

if ! [ -e ${BINARIES_DIR}/rootfs.ext2.gz ]
then
	gzip ${BINARIES_DIR}/rootfs.ext2
fi

mkimage -n "ramdisk Image" -A arm -O linux -T ramdisk \
	-C gzip -d ${BINARIES_DIR}/rootfs.ext2.gz \
	${BINARIES_DIR}/rootfs.img
if [ -e ${BINARIES_DIR}/rootfs.img ]
then
	echo "root image created"
fi

rm  ${BINARIES_DIR}/rootfs.ext4

exit $?

What is with BR2_ prefix on variables?

It appears some time back they changed all the user-configurable variables to be called such.

Patching Packages

The manual shows one example where the patches/<packagename>/ folder is added with patches inside, like patches/linux/0001-some-change.patch. That works only if you want to patch the linux-custom package, specifically using the package name of linux instead as in the example. This doesn't actually work generically for other packages, even if you set BR2_GLOBAL_PATCH_DIR to that <packagename> path. Instead of looking in those subfolders, BR is looking for *.patch files in the patches/ folder itself.

So you must use a modified version of the scheme shown in the "Quick guide":
To add custom patches to certain packages, set BR2_GLOBAL_PATCH_DIR to board/<manufacturer>/<boardname>/patches/ and add your patches for each package in a subdirectory named after the package. Each patch should be called <packagename>-<num>-<description>.patch .

It also mentions the subdir but since that doesn't work, we just use the above naming scheme in the patches/ folder.

Once upon a kernel module

If you want to build a kernel module...

    YOU CAN NOT use stdio.h in the kernel space development
    YOU CAN NOT use main() in the kernel module C code
    YOU CAN NOT use printf() in the kernel module C code

INSTEAD of using stdio.h, you have to use the following includes

  1. include <linux/module.h> /* Needed by all modules */
  2. include <linux/kernel.h> /* Needed for KERN_INFO */

INSTEAD of using int main(), you have to use

int init_module(void) {

INSTEAD of using printf() use printk()

There's some trickiness with loading the module because the vermagic must be exactly correct for the kernel. It can be seen with the modinfo command on the .ko. That's not all, since even if the kernel versions match you could have a problem with the symbol CRCs for unknown reasons. You can see those values with a modprobe --dump-modversions on the .ko.

To get these to match your buildroot created kernel, you can't simply point to the matching version linux kernel source. Instead, you must point to the buildroot/output/build/linux-custom location (this is where Kbuild resides, which is the kernel and module building tool). Note that this is the buildroot output directory, and this is for a kernel that is already built. Thus, an external kernel module. Once you do a make clean, this is blown away.

Here is a sample module makefile:

obj-m += hello.o

KERNELDIR=../buildroot/output/build/linux-custom
ARCH=arm
CC_TOOL=arm-buildroot-linux-gnueabi-
CFLAGS=

all:
	make ARCH=$(ARCH) CROSS_COMPILE=$(CC_TOOL) -C $(KERNELDIR) M=$(PWD) $(CFLAGS) modules

clean:
	make ARCH=$(ARCH) CROSS_COMPILE=$(CC_TOOL) -C  $(KERNELDIR) M=$(PWD) clean


Here is a sample module:

/*  
 *  hello.c - The simplest kernel module.
 */
#include <linux/module.h>   /* Needed by all modules */
#include <linux/version.h>  /* Added for insmod prob */
#include <linux/kernel.h>   /* Needed for KERN_INFO */

int init_module(void)
{
   // do stuff
}

void cleanup_module(void)
{
  // do stuff
}

MODULE_LICENSE("GPL");


If you don't put the module license tag in there, you get a warning on loading. Also, use printk instead of printf.

Setting Up rootfs

To include stuff in the rootfs that is created and tar'ed up by buildroot, set the following in system/Config.in to the location of your stuff.

config BR2_ROOTFS_OVERLAY
	string "Root filesystem overlay directories"
	default ""
	help
	  Specify a list of directories that are copied over the target
	  root filesystem after the build has finished and before it is
	  packed into the selected filesystem images.

	  They are copied as-is into the rootfs, excluding files ending with
	  ~ and .git, .svn and .hg directories.

Looks like there is another way to do this in make menuconfig under the System configuration option (overlay).

Step by step process

1) BR: download the needed archives etc. to DL_DIR
2) mypackage.mk: you can access the DL files
3) BR: build and add packages to RFS working dir
4) BR: add the overlays to RFS working dir
5) post-build.sh: I think it's here either before or after the overlays
6) post-fakeroot.sh: fake root operations, add final /usr stuff etc. to RFS working dir
7) BR: auto-generates the RFS image
8) post-image.sh: tar/zip up the package

Note: The difference between post-build scripts and fakeroot scripts, is that post-build scripts are not called in the fakeroot context. This would suggest the script is run after the overlays, right before post-fakeroot.

Init

http://buildroot.uclibc.org/downloads/manual/manual.html

What if I don't get a prompt after Linux kernel comes up?

Try checking your TTY port setting in menuconfig under System configuration. Telltale sign for this is hanging after "Starting network...".

Device trees

dtb = device tree blob
dts = device tree source
dtsi = like dts, but I think the 'i' is to indicate that this file is supposed to be included in another dts(i) file.
dtbo = DTB overlay

You can change the .dts file that is used by changing the DTS_NAME under Kernel in menuconfig.

Notes

http://free-electrons.com/~thomas/br-manual.pdf

Packages

Removing a package is unsupported by Buildroot without rebuilding from scratch.
Note that the variable names in the <package>.mk file cannot have dashes in the names, use underscores instead.

About Target Package Utilities

mmc-utils commands are used with mmc on the command line, and can set fuses, write-protect, boot partition flags, et al, but cannot do the file system. parted has a lot of partition creating abilities. e2fsprogs is for the extX series of file systems.

For the python package .mk file, the BR docs say you don't need to put python- or host-python- in front of the dependencies for HOST_LIBFOO_DEPENDENCIES, but I find you can have problems if you don't.

You would think that host packages would be built first, but they are NOT.

Note that when you go to build or assign dependency to a host-side package, the name to use for the make target etc is host-<package> rather than simply <package> as is the case with a target package.

What if I want to auto-select a package from another in menuconfig?

Add the select line to the Config.in file for the dependent package. Example:

if BR2_PACKAGE_FOO

choice
   prompt "Hardware model"

config BR2_PACKAGE_M5
   bool "Model M5"

config BR2_PACKAGE_M7
   bool "Model M7"
   select BR2_PACKAGE_HOST_TOOLNAME

endchoice

endif 

Once the package builds, how do I call the tool?

At the end of the .mk file, add command paths like so:

TOOLNAME = $(HOST_DIR)/usr/bin/toolname

...which points to the temporary outputs/host/ directory for host tools executable storage. Then, you can invoke the tool by using $(TOOLNAME) in the .mk files of other dependent packages.

Paths Notes

$(BINARIES_DIR) is output/images/
$(HOST_DIR) is output/host/
$(TARGET_DIR) is output/target/ (this is the showpiece for your RFS)
Archives downloaded are stored your Buildroot's cache/dl/ folder.

Does my package need a Makefile, even though I have the .mk?

Yes! The .mk only appears to define the make command.

Building packages static vs. dynamic (this an unsolved issue)

https://stackoverflow.com/questions/45958904/buildroot-build-only-one-package-as-both-shared-and-static-lib-all-others-shar
https://stackoverflow.com/questions/44341188/how-to-pass-extra-custom-configure-autotools-options-to-a-buildroot-package
https://stackoverflow.com/questions/49564878/what-is-the-proper-method-to-modify-the-autotools-options-of-a-buildroot-source

The problem is that the absence or presence of BR2_STATIC_LIBS in the _defconfig overrides everything else in the package .mk.

Useful package debug commands

make <pkg>-show-depends
make <pkg>-graph-depends
make <pkg>-dirclean
make <pkg>-reinstall
make <pkg>-rebuild
make <pkg>-reconfigure

You can extend this with your custom platform targets with make <target>-<pkg>-<command>.

Troubleshooting

What's with the "available toolchains" message on options I can't select?

https://git.busybox.net/buildroot/commit/?id=ea6b277539bc5eebef64767dae3499b4209cd563

EABI vs. EABIhf
hf = hard float, appears to be simply an indicator for how floating point arguments are passed in registers, a processor may support EABI or EABIhf

Using download package, error while checking hash? (No hash found)

Make sure you have a newline at the end of your .hash file, or else it will skip the last entry. Note that if the hash file is not present, then this check is skipped.

Package I included is missing binaries after build!!!

I saw this with the oprofile tool, where the .mk file was bad and missing the operf tool. I changed the oprofile.mk file under support/buildroot/package/oprofile/:

# OPROFILE_BINARIES = \
# 	utils/ophelp pp/opannotate pp/oparchive pp/opgprof \
# 	pp/opreport opjitconv/opjitconv \
# 	utils/op-check-perfevents libabi/opimport \
# 	pe_counting/ocount pe_profiling/operf

OPROFILE_BINARIES = pe_profiling/operf

ERROR: <pkglocalpath> does not exist

Ran into the problem trying to add a locally sourced package. This could be related to Docker, which apparently executes the build in a separate environment. I found the pkg-generic.mk was executing in a temporary location /src/support/buildroot and it could not get out to find my local LIB_SITE path. I guess there is actually really no way to do this going outside the Buildroot tree.

Package executable won't run on target: not found

Check the toolchain selection. I believe you can compare the interpreter for running and non-running executables with the file command:

helloworld: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), 
dynamically linked, interpreter /lib/ld-linux-armhf.so.3, 
for GNU/Linux 2.6.32,...

The dynamic linker may not be found because a different one is used than that for which the FS was built?

Valgrind failed to start tool 'memcheck'

This happens if you only copy the binary over and not the needed libraries. Make to sure grab all the stuff under usr/lib/valgrind/ in the target folder.

What the bloody bink is this?

>>> ntp 4.2.8p8 Installing to target
install -m 755 .../build/ntp-4.2.8p8/ntpd/ntpd .../target/usr/sbin/ntpd
install: cannot create regular file '.../target/usr/sbin/ntpd': No such file or directory

This happens because the target/usr/sbin/ folder is not there which can be the case when it's not created in the RFS skeleton directory, the foundation for creating the RFS. You can add the folder there to solve the problem. Interestingly, some of the folders are added automatically and don't need to be present in the skeleton it would seem.


Page last modified on November 13, 2024, at 05:14 PM