Buildroot — part 2. Creating a configuration of your board; application of external tree, rootfs-overlay, post-build scripts
In this section, I consider some of the customization capabilities that I needed. This is not a complete list of what buildroot offers, but they are quite working and do not require intervention in the files of buildroot itself.
Using the EXTERNAL mechanism for customization
In a previous article we considered a simple example of adding your configuration by adding a defconfig’s board and the necessary files directly to the Buildroot directory.
But this method is not very convenient, especially when updating buildroot. To solve this problem, there is a external tree mechanism. Its essence is that you can store board, configs, packages, and other directories in a separate directory (for example, I use the patches directory to apply patches to packages, more in a separate section) and buildroot will add them to those in its own directory.
Note: you can apply several external trees at once, there is an example in the buildroot manual
Create the my_tree directory located next to the buildroot’s directory and transfer our configuration there. The output should be the following file structure:
[alexey @ alexey-pc my_tree] $ tree
.
├── board
│ └── my_x86_board
│ ├── bef_cr_fs_img.sh
│ ├── linux.config
│ ├── rootfs_overlay
│ └── users.txt
├── Config.in
├── configs
│ └── my_x86_board_defconfig
├── external.desc
├── external.mk
├── package
└── patches6 directories, 7 files
As you can see, in general, the structure follows the structure of buildroot.
The board directory contains files specific to each board in our case:
- bef_cr_fs_img.sh — a script that will be executed after building the target-file system, but before packing it into images. In the future we will use it
- linux.config — kernel configuration
- rootfs_overlay — a directory to overlay on top of the target file system
- users.txt — file with a description of the created users
The configs directory contains defconfig’s and our boards. We have only one.
Package — catalog with our packages. Initially, buildroot contains descriptions and rules for building a limited number of packages. Later we will add icewm window manager and Slim graphical login manager here.
Patches — allows you to conveniently store your patches for different packages. More details in a separate section below.
Now we need to add the description files of our external-tree. 3 files are responsible for this: external.desc, Config.in, external.mk.
external.desc contains the actual description:
[alexey @ alexey-pc my_tree] $ cat external.desc
name: my_tree
desc: My simple external-tree for article
The first line is the name. In the future, buildroot create the variable $ (BR2_EXTERNAL_MY_TREE_PATH), which you need to use when configuring the assembly. For example, the path to the file with users can be set in the following way:
$ (BR2_EXTERNAL_my_tree_PATH) /board/my_x86_board/users.txt
The second line is a brief, human-readable description.
Config.in,external.mk — files for the description of added packages. If you do not add your packages, then these files can be left empty. So far we will do so.
Now we have our external-tree ready, containing the defconfig of our board and the files it needs. We’ll go to the buildroot directory, we will specify the use of external-tree:
[alexey@alexey-pc buildroot] $ make BR2_EXTERNAL = ../my_tree/my_x86_board_defconfig
#
# configuration written to /home/alexey/dev/article/ramdisk/buildroot/.config
#
[alexey@alexey-pc buildroot] $ make menuconfig
In the first command, we use the argument BR2_EXTERNAL = ../my_tree/, indicating the use of an external tree. You can specify several external-trees for use at the same time. It is enough to do this once, after which the output/.br-external.mk file is created that stores information about the external-tree used:
[alexey @ alexey-pc buildroot] $ cat output/.br-external.mk
#
# Automatically generated file; DO NOT EDIT.
#BR2_EXTERNAL? =/Home/alexey/dev/article/ramdisk/my_small_linux/my_tree
BR2_EXTERNAL_NAMES =
BR2_EXTERNAL_DIRS =
BR2_EXTERNAL_MKS =BR2_EXTERNAL_NAMES + = my_tree
BR2_EXTERNAL_DIRS + =/home/alexey/dev/article/ramdisk/my_small_linux/my_tree
BR2_EXTERNAL_MKS + = /home/alexey/dev/article/ramdisk/my_small_linux/my_tree/external.mk
export BR2_EXTERNAL_my_tree_PATH =/home/alexey/dev/article/ramdisk/my_small_linux/my_tree
export BR2_EXTERNAL_my_tree_DESC = My simple external-tree for article
Important! In this file, the paths will be absolute!
The External options item appeared in the menu:
This submenu will contain our packages from our external-tree. Now this section is empty.
Now it’s more important for us to rewrite the necessary paths to use an external-tree.
Please note that in the section Build options → Location to save buildroot config, there will be an absolute path to the saved defconfig. It is formed at the time of specifying the use of extgernal_tree.
Also in the System configuration section, fix the paths. For a table with user created:
$ (BR2_EXTERNAL_my_tree_PATH) /board/my_x86_board/users.txt
In the Kernel section, change the path to the kernel configuration:
$ (BR2_EXTERNAL_my_tree_PATH) /board/my_x86_board/linux.config
Now, the assembly will use our files from our external-tree. When transferring to another directory, updating buildroot, we will have a minimum of problems.
Adding root fs overlay:
This mechanism makes it easy to add/replace files in the target file system.
If the file is in root fs overlay, but not in target, then it will be added
If the file is in root fs overlay and in target, then it will be replaced.
First, set the path to root fs overlay dir. This is done in the System configuration → Root filesystem overlay directories section:
$(BR2_EXTERNAL_my_tree_PATH)/board/my_x86_board/rootfs_overlay/
Now let’s create two files.
[alexey@alexey-pc my_small_linux] $ cat my_tree/board/my_x86_board/rootfs_overlay/etc/hosts
127.0.0.1 localhost
127.0.1.1 my_small_linux
8.8.8.8 google-public-dns-a.google.com.
[alexey@alexey-pc my_small_linux] $ cat my_tree/board/my_x86_board/rootfs_overlay/new_file.txt
This is new file from overlay
The first file (my_tree/board/my_x86_board/rootfs_overlay/etc/hosts) will replace the/etc/hosts file on the finished system. A second file (cat my_tree/board/my_x86_board/rootfs_overlay/new_file.txt) will be added.
We collect and check:
Execution of customization scripts at different stages of system assembly
Often, you need to perform some actions inside the target file system before it is packaged into images.
This can be done in the System configuration section:
The first two scripts are executed after building the target file system, but before packing it into images. The difference is that the fakeroot script is executed in the context of the fakeroot, they simulate work from the root user.
The last script is executed after creating the system images. You can perform additional actions in it, for example, copy the necessary files to the nfs server or create an image of your device firmware.
As an example, I will create a script that will write the version and build date in/etc /.
First, I will indicate the path to this file in my external-tree:
And now the script itself:
[alexey@alexey-pc buildroot] $ cat ../my_tree/board/my_x86_board/bef_cr_fs_img.sh
#!/bin/sh
echo "my small linux 1.0 pre alpha"> output/target/etc/mysmalllinux-release
date >> output/target/etc/mysmalllinux-release
After assembly, you can see this file in the system.
In practice, a script can become big. Therefore, in a real project, I went a more advanced way:
- Created a directory (my_tree/board_my_x86_board/inside_fakeroot_scripts), which contains scripts for execution, with serial numbers. For example, 0001-add-my_small_linux-version.sh, 0002-clear-apache-root-dir.sh
- I wrote a script (my_tree/board_my_x86_board/run_inside_fakeroot.sh) that goes through this directory and sequentially runs the scripts that are in it
- I specified this script in the board settings in the System configuration -> Custom scripts to run inside the fakeroot environment ($(BR2_EXTERNAL_my_tree_PATH)/board/my_x86_board/run_inside_fakeroot.sh)