Introduction
In this series of articles, I want to review the buildroot distribution's build system and share my experience in customizing it. There will be practical experience in creating a small OS with a graphical interface and minimal functionality.
First of all, don't confuse the build system with the distribution. Buildroot can build a system from a set of packages that are offered to it. Buildroot is built on makefiles and therefore has a lot of customization options. Replace the package with another version, add your own package, change the rules for building the package, customize the file system after installing all the packages? All this can buildroot.
In Russia, buildroot is used, but in my opinion there is little Russian-language information for beginners.
The purpose of the work is to build a distribution kit with live download, icewm interface and browser. The target platform is virtualbox.
Why build your own distribution? Often you need limited functionality with limited resources. More often in automation, you need to create firmware. Adapting a general purpose distribution by cleaning out redundant packages and turning it into firmware is a more time consuming way than putting together a new distribution. Using Gentoo also has its limitations.
The Buildroot system is very powerful, but it won't do anything for you. It can only enable and automate the assembly process.
Alternative build systems (yocto, open build system, etc.) are not considered or compared.
Where to get and how to start
Project website -
Buildroot operates with defconfigs for the target build board. Defconfig is a configuration file that contains only options that do not have a default value. It is he who determines what and how will be collected. In this case, you can separately configure the busybox, linux-kernel, uglibc, u-boot and barebox bootloader configs, but they will all be tied to the target board.
After unpacking the downloaded archive or cloning from git, we get buildroot ready for work. You can read more about the directory structure in the manual, I'll tell you about the most important ones:
board — directory with files specific to each board. These can be system imaging scripts (iso, sdcart, cpio and others), overlay directory, kernel config, etc.
settings - the actual defconfig of the board. Defconfig is an incomplete board configuration. It stores only parameters other than the default settings.
dl - directory with downloaded source codes / files for assembly
output/target - the assembled file system of the received OS. In the future, images are created from it for download / installation
output/host - host utilities for assembly
output/build - assembled packages
Assembly configuration is done via KConfig. The same system is used to build the linux kernel. List of the most frequently used commands (execute in the buildroot directory):
- make menuconfig - call the build configuration. You can also use the GUI (make nconfig,make xconfig,make gconfig)
- make linux-menuconfig - call kernel configuration.
- make clean - clean build results (everything that is stored in output)
- make - build the system. This does not rebuild already built processes.
- make defconfig_name - switch configuration to specific defconfig
- make list-defconfigs - show a list of defconfigs
- make source - only download the installation files, no assembly.
- make help - display a list of possible commands
Important Notes and Helpful Hints
Buildroot does not rebuild already built packages! Therefore, a situation may arise when a complete reassembly is required.
You can rebuild a single package with the command make packagename-rebuild. For example, you can rebuild the linux kernel:
make linux-rebuild
Buildroot stores the state of any package by creating .stamp files in the output/build/$packagename directory:
Therefore, it is possible to rebuild root-fs and images without rebuilding packages:
rm output/build/host-gcc-final-*/.stamp_host_installed;rm -rf output/target;find output/ -name ".stamp_target_installed" |xargs rm -rf ; make
Useful Variables
buildroot has a set of variables for easy configuration
- $TOPDIR - buildroot root directory
- $BASEDIR - OUTPUT directory
- $HOST_DIR, $STAGING_DIR, $TARGET_DIR - host fs, staging fs, target fs build directories.
- $BUILD_DIR - directory with unpacked and built packages
Visualization
buildroot has the ability to visualize. You can build a dependency diagram, build time graph, package size graph in the final system. Results as pdf files (you can choose from svn,png) in the output/graph directory.
Examples of render commands:
make graph-depends
build dependency treemake <pkg>-graph-depends
build the dependency tree of a specific packageBR2_GRAPH_OUT=png make graph-build
plot build time graph with PNG outputmake graph-size
plot the packet size
Useful scripts
The buildroot directory has a subdirectory utils with useful scripts. For example, there is a script that checks the correctness of package descriptions. This can be useful when adding custom packages (I'll do that later). The utils/readme.txt file has a description of these scripts.
Let's build a stock distribution
It is important to recall that all operations are carried out on behalf of a regular user, not root.
All commands are executed in buildroot. The buildroot distribution already has a set of configurations for many common boards and virtualization.
See the list of configurations:
Switch to qemu_x86_64_defconfig config
make qemu_x86_64_defconfig
And start the build
make
The build completes successfully, look at the results:
Buildroot has put together images that you can run in Qemu and see if they work.
qemu-system-x86_64 -kernel output/images/bzImage -hda output/images/rootfs.ext2 -append "root=/dev/sda rw" -s -S
The result is a system running in qemu:
Create your own board configuration
Adding Board Files
See the list of configurations:
In the list we see pc_x86_64_efi_defconfig. We will create our board by copying it from the configuration:
cp configs/pc_x86_64_bios_defconfig configs/my_x86_board_defconfig
Immediately create a board directory to store our scripts, rootfs-overlay and other necessary files:
mkdir board/my_x86_board
Switch to this defconfig:
make my_x86_board_defconfig
So now the build config (stored in .config at the root of buildroot's directory) matches the x86-64 legacy(bios) target machine by boot.
Copy the linux-kernel configuration (useful later):
cp board/pc/linux.config board/my_x86_board/
Configuring Build Options via KConfig
Let's start the setup:
make menuconfig
The KConfig window will open. It is possible to configure with a graphical interface (make nconfig, make xconfig, make gconfig):
We enter the first section Target Options. Here you can select the target architecture for which the assembly will be carried out.
Build options - there are various build options here. You can specify directories with source codes, the number of build threads, mirrors for downloading source codes, and other settings. Let's leave the default settings.
Toolchain - the build toolkit itself is configured here. More about him.
Toolchain type - the type of toolchain used. This can be built into buildroot or an external toolchain (you can specify a directory with an already built one or a url for downloading). There are additional options for different architectures. For example, for arm, you can simply select the version of the external Linaro toolchain.
C library - selection of the C library. The operation of the entire system depends on this. Usually glibc is used, which supports all possible functionality. But it can be too big for an embedded system, so uglibc or musl is often chosen. We will choose glibc (this will be required later to use systemd).
Kernel Headers and Custom Kernel Headers series - must match the version of the kernel that will be in the system being built. For kernel headers, you can also specify the path to the tarball or the git repository.
GCC COMPILER VERSIONS - select the compiler version that will be used for building
Enable C++ support - select to build with support for c++ libraries in the system. We will need this later on.
Additional gcc options - you can set additional compiler options. We don't need it for now.
System configuration allows you to set the future parameters of the created system:
Most of the points are clear from the title. Let's pay attention to the following points:
Path to the users tables - table with created users (
File example. The user user will be created with password admin, automatically gid/uid, /bin/sh shell, default group user, member of group root, comment Foo user
[alexey@alexey-pc buildroot ]$ cat board/my_x86_board/users.txt
user -1 user -1 =admin /home/user /bin/sh root Foo user
Root filesystem overlay directories - a directory that is overlaid on top of the compiled target-fs. Adds new files and replaces existing ones.
Custom scripts to run before creating filesystem images Leave the script empty for now.
Let's go to the Kernel section
This is where the kernel settings are set. The kernel itself is configured via make linux-menuconfig.
You can set the kernel version in different ways: choose from those offered, enter the version manually, specify a repository or a ready-made tarball.
Kernel configuration - path to the kernel config. You can choose the default configuration for the selected architecture or defocnfig from Linux. The Linux sources have a set of defconfigs for different target systems. You can find the one you need
The Target packages section allows you to select which packages will be installed on the target system. Let's leave it unchanged for now. Later we will add our packages to this list.
Filesystem images - List of filesystem images to be built. Add an iso image
Bootloaders - the choice of collected bootloaders. Choose isolinix
Configuring Systemd
Systemd becomes one of the pillars of linux, along with kernel and glibc. Therefore, I took out its setting in a separate paragraph.
Configured via make menuconfig, then Target packages → System tools → systemd. Here you can specify which systemd services will be installed and started at system startup.
Saving the system configuration
We save this config via KConfig.
Then we save our defconfig:
make savedefconfig
Linux kernel configuration
The linux kernel configuration is invoked by the following command:
make linux-menuconfig
Add support for Virtualbox video card
Add Virtualbox Guest integration support
Save and exit. IMPORTANT: configuration will be saved in output/build/linux-$version/config but not in board/my_x86_board/linux.config
Therefore, you need to manually copy the config to the storage location:
cp output/build/linux-4.19.25/.config board/my_x86_board/linux.config
After that, we will perform a complete reassembly of the entire system. buildroot does not rebuild what has already been built, you must manually specify the packages to rebuild. In order not to waste time and nerves, it is easier to rebuild a small system as a whole):
make clean;make
Upon completion of the assembly, we launch VirtualBox (tested on versions 5.2 and 6.0) with boot from the cd-disk. System parameters:
Starting from the built iso:
List of used materials
- Buildroot manual
Source: habr.com