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/ "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 managementhttps://buildroot.org/downloads/manual/manual.html#faq-no-binary-packages Getting Started in a Strange BR ProjectFind 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 UnmaskedWhen 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 uImageAlthough 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 Application cross-compileThis 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 variablesmake -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:
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
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 versionUnderstanding 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:
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/ folderYou 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 processYou 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 PackagesThe 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": 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 moduleIf 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
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
/* * 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");
Setting Up rootfsTo 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 process1) BR: download the needed archives etc. to DL_DIR 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. Inithttp://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 treesdtb = device tree blob You can change the .dts file that is used by changing the DTS_NAME under Kernel in menuconfig. Noteshttp://free-electrons.com/~thomas/br-manual.pdf PackagesRemoving a package is unsupported by Buildroot without rebuilding from scratch. About Target Package Utilitiesmmc-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/ 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 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 commandsmake <pkg>-show-depends You can extend this with your custom platform targets with make <target>-<pkg>-<command>. TroubleshootingWhat's with the "available toolchains" message on options I can't select?https://git.busybox.net/buildroot/commit/?id=ea6b277539bc5eebef64767dae3499b4209cd563 EABI vs. 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 existRan 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 foundCheck 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 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. |