Buildroot - part 2. Creating a configuration for your board; application of external tree, rootfs-overlay, post-build scripts

In this section, I consider some of the customization options that I needed. This is not a complete list of what buildroot offers, but they are quite working and do not require interference with the files of the buildroot itself.

Using the EXTERNAL mechanism for customization

In a previous article a simple example of adding your own configuration was considered, by adding the defconfig of the board and the necessary files directly to the Buildroot directory.

But this method is not very convenient, especially when updating buildroot. There is a mechanism to solve this problem. external tree. Its essence is that board, configs, packages and other directories can be stored in a separate directory (for example, I use the patches directory to apply patches to packages, more details in a separate section) and buildroot will add them to those in its directory.

Note: you can overlay multiple external trees at once, there is an example in the buildroot manual

Let's create a my_tree directory next to the buildroot directory and move 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
└── patches

6 directories, 7 files

As you can see, in general, the structure repeats the structure of buildroot.

Catalog board contains files specific to each board in our case:

  • bef_cr_fs_img.sh is 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 - directory to overlay on top of the target file system
  • users.txt - a file with a description of the created users

Catalog settings contains defconfig'i of our boards. We only have one.

Package — directory with our packages. Initially buildroot contains descriptions and rules for building a limited number of packages. Later we will add the icewm window manager and the 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 description itself:

[alexey@alexey-pc my_tree]$ cat external.desc 
name: my_tree
desc: My simple external-tree for article

The first line is the title. In the future buildroot create a variable $(BR2_EXTERNAL_MY_TREE_PATH)The to use when configuring the assembly. For example, the path to a file with users can be specified in the following way:

$(BR2_EXTERNAL_my_tree_PATH)/board/my_x86_board/users.txt

The second line is a short, human-readable description.

config.in, external.mk — files for description of added packages. If you do not add your packages, then these files can be left empty. For now, that's what we'll do.
Now we have our external-tree ready, containing the defconfig of our board and the files it needs. Let's go to the buildroot directory, specify to use 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 at the same time to use. In this case, it is enough to do this once, after which the output/.br-external.mk file is created, storing 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 paths will be absolute!

The menu item External options appeared:

Buildroot - part 2. Creating a configuration for your board; application of external tree, rootfs-overlay, post-build scripts

This submenu will contain our packages from our external-tree. This section is currently empty.

Now it is more important for us to rewrite the necessary paths to use external-tree.

Please note that in the Build options → Location to save buildroot config section, there will be an absolute path to the saved defconfig. It is formed at the moment of specifying the use of extgernal_tree.

We will also fix the paths in the System configuration section. For a table with created users:

$(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 build will use our files from our external-tree. When moving 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 the root fs overlay, but not in the target, then it will be added
If the file is in root fs overlay and in target, then it will be replaced.
First, let's set the path to the 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. The second file (cat my_tree/board/my_x86_board/rootfs_overlay/new_file.txt) will be added.

We collect and check:

Buildroot - part 2. Creating a configuration for your board; application of external tree, rootfs-overlay, post-build scripts

Execution of customization scripts at different stages of system assembly

Often, some work needs to be done inside the target filesystem before it is packaged into images.

This can be done in the System configuration section:

Buildroot - part 2. Creating a configuration for your board; application of external tree, rootfs-overlay, post-build scripts

The first two scripts are executed after the target file system is built, but before it is packaged into images. The difference is that the fakeroot script is executed in the context of fakeroot, which simulates running as the root user.

The last script is executed after the system images have been created. 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 to /etc/.
First, I will specify the path to this file in my external-tree:

Buildroot - part 2. Creating a configuration for your board; application of external tree, rootfs-overlay, post-build scripts

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, the script can become large. Therefore, in a real project, I went a more advanced way:

  1. Created a directory (my_tree/board_my_x86_board/inside_fakeroot_scripts), which contains scripts to be executed, with serial numbers. For example, 0001-add-my_small_linux-version.sh, 0002-clear-apache-root-dir.sh
  2. I wrote a script (my_tree/board_my_x86_board/run_inside_fakeroot.sh) that goes through this directory and sequentially executes the scripts contained in it
  3. Specified this script in the board settings in the section System configuration -> Custom scripts to run inside the fakeroot environment ($(BR2_EXTERNAL_my_tree_PATH)/board/my_x86_board/run_inside_fakeroot.sh)

Source: habr.com

Add a comment