Project-specific customization
Typical actions you may need to perform for a given project are:
-
configuring Buildroot (including build options and toolchain, bootloader, kernel, package and filesystem image type selection)
-
configuring other components, like the Linux kernel and BusyBox
-
customizing the generated target filesystem
-
adding or overwriting files on the target filesystem (using
BR2_ROOTFS_OVERLAY
) -
modifying or deleting files on the target filesystem (using
BR2_ROOTFS_POST_BUILD_SCRIPT
) -
running arbitrary commands prior to generating the filesystem image (using
BR2_ROOTFS_POST_BUILD_SCRIPT
) -
setting file permissions and ownership (using
BR2_ROOTFS_DEVICE_TABLE
) -
adding custom devices nodes (using
BR2_ROOTFS_STATIC_DEVICE_TABLE
)
-
-
adding custom user accounts (using
BR2_ROOTFS_USERS_TABLES
) -
running arbitrary commands after generating the filesystem image (using
BR2_ROOTFS_POST_IMAGE_SCRIPT
) -
adding project-specific patches to some packages (using
BR2_GLOBAL_PATCH_DIR
) -
adding project-specific packages
An important note regarding such 'project-specific' customizations: please carefully consider which changes are indeed project-specific and which changes are also useful to developers outside your project. The Buildroot community highly recommends and encourages the upstreaming of improvements, packages and board support to the official Buildroot project. Of course, it is sometimes not possible or desirable to upstream because the changes are highly specific or proprietary.
This chapter describes how to make such project-specific customizations in Buildroot and how to store them in a way that you can build the same image in a reproducible way, even after running 'make clean'. By following the recommended strategy, you can even use the same Buildroot tree to build multiple distinct projects!
Recommended directory structure
When customizing Buildroot for your project, you will be creating one or more project-specific files that need to be stored somewhere. While most of these files could be placed in any location as their path is to be specified in the Buildroot configuration, the Buildroot developers recommend a specific directory structure which is described in this section.
Orthogonal to this directory structure, you can choose where you place this structure itself: either inside the Buildroot tree, or outside of it using a br2-external tree. Both options are valid, the choice is up to you.
+-- board/ | +-- <company>/ | +-- <boardname>/ | +-- linux.config | +-- busybox.config | +-- <other configuration files> | +-- post_build.sh | +-- post_image.sh | +-- rootfs_overlay/ | | +-- etc/ | | +-- <some file> | +-- patches/ | +-- foo/ | | +-- <some patch> | +-- libbar/ | +-- <some other patches> | +-- configs/ | +-- <boardname>_defconfig | +-- package/ | +-- <company>/ | +-- Config.in (if not using a br2-external tree) | +-- <company>.mk (if not using a br2-external tree) | +-- package1/ | | +-- Config.in | | +-- package1.mk | +-- package2/ | +-- Config.in | +-- package2.mk | +-- Config.in (if using a br2-external tree) +-- external.mk (if using a br2-external tree) +-- external.desc (if using a br2-external tree) ------ Details on the files shown above are given further in this chapter. Note: if you choose to place this structure outside of the Buildroot tree but in a br2-external tree, the <company> and possibly <boardname> components may be superfluous and can be left out. ==== Implementing layered customizations It is quite common for a user to have several related projects that partly need the same customizations. Instead of duplicating these customizations for each project, it is recommended to use a layered customization approach, as explained in this section. Almost all of the customization methods available in Buildroot, like post-build scripts and root filesystem overlays, accept a space-separated list of items. The specified items are always treated in order, from left to right. By creating more than one such item, one for the common customizations and another one for the really project-specific customizations, you can avoid unnecessary duplication. Each layer is typically embodied by a separate directory inside `board/<company>/`. Depending on your projects, you could even introduce more than two layers. An example directory structure for where a user has two customization layers 'common' and 'fooboard' is:
+-- board/ +-- <company>/ +-- common/ | +-- post_build.sh | +-- rootfs_overlay/ | | +-- … | +-- patches/ | +-- … | +-- fooboard/ +-- linux.config +-- busybox.config +-- <other configuration files> +-- post_build.sh +-- rootfs_overlay/ | +-- … +-- patches/ +-- …
For example, if the user has the `BR2_GLOBAL_PATCH_DIR` configuration option set as:
BR2_GLOBAL_PATCH_DIR="board/<company>/common/patches board/<company>/fooboard/patches"
then first the patches from the 'common' layer would be applied, followed by the patches from the 'fooboard' layer. // -*- mode:doc -*- ; // vim: set syntax=asciidoc: [[outside-br-custom]] === Keeping customizations outside of Buildroot As already briefly mentioned in xref:customize-dir-structure[], you can place project-specific customizations in two locations: * directly within the Buildroot tree, typically maintaining them using branches in a version control system so that upgrading to a newer Buildroot release is easy. * outside of the Buildroot tree, using the _br2-external_ mechanism. This mechanism allows to keep package recipes, board support and configuration files outside of the Buildroot tree, while still having them nicely integrated in the build logic. We call this location a _br2-external tree_. This section explains how to use the br2-external mechanism and what to provide in a br2-external tree. One can tell Buildroot to use one or more br2-external trees by setting the `BR2_EXTERNAL` make variable set to the path(s) of the br2-external tree(s) to use. It can be passed to any Buildroot `make` invocation. It is automatically saved in the hidden `.br2-external.mk` file in the output directory. Thanks to this, there is no need to pass `BR2_EXTERNAL` at every `make` invocation. It can however be changed at any time by passing a new value, and can be removed by passing an empty value. .Note The path to a br2-external tree can be either absolute or relative. If it is passed as a relative path, it is important to note that it is interpreted relative to the main Buildroot source directory, *not* to the Buildroot output directory. .Note: If using an br2-external tree from before Buildroot 2016.11, you need to convert it before you can use it with Buildroot 2016.11 onward. See xref:br2-external-converting[] for help on doing so. Some examples:
buildroot/ $ make BR2_EXTERNAL=/path/to/foo menuconfig
From now on, definitions from the `/path/to/foo` br2-external tree will be used:
buildroot/ $ make buildroot/ $ make legal-info
We can switch to another br2-external tree at any time:
buildroot/ $ make BR2_EXTERNAL=/where/we/have/bar xconfig
We can also use multiple br2-external trees: ---- buildroot/ $ make BR2_EXTERNAL=/path/to/foo:/where/we/have/bar menuconfig ---- Or disable the usage of any br2-external tree:
buildroot/ $ make BR2_EXTERNAL= xconfig
==== Layout of a br2-external tree A br2-external tree must contain at least those three files, described in the following chapters: * `external.desc` * `external.mk` * `Config.in` Apart from those mandatory files, there may be additional and optional content that may be present in a br2-external tree, like the `configs/` or `provides/` directories. They are described in the following chapters as well. A complete example br2-external tree layout is also described later. ===== The `external.desc` file That file describes the br2-external tree: the _name_ and _description_ for that br2-external tree. The format for this file is line based, with each line starting by a keyword, followed by a colon and one or more spaces, followed by the value assigned to that keyword. There are two keywords currently recognised: * `name`, mandatory, defines the name for that br2-external tree. That name must only use ASCII characters in the set `[A-Za-z0-9_]`; any other character is forbidden. Buildroot sets the variable `BR2_EXTERNAL_$(NAME)_PATH` to the absolute path of the br2-external tree, so that you can use it to refer to your br2-external tree. This variable is available both in Kconfig, so you can use it to source your Kconfig files (see below) and in the Makefile, so that you can use it to include other Makefiles (see below) or refer to other files (like data files) from your br2-external tree. + .Note: Since it is possible to use multiple br2-external trees at once, this name is used by Buildroot to generate variables for each of those trees. That name is used to identify your br2-external tree, so try to come up with a name that really describes your br2-external tree, in order for it to be relatively unique, so that it does not clash with another name from another br2-external tree, especially if you are planning on somehow sharing your br2-external tree with third parties or using br2-external trees from third parties. * `desc`, optional, provides a short description for that br2-external tree. It shall fit on a single line, is mostly free-form (see below), and is used when displaying information about a br2-external tree (e.g. above the list of defconfig files, or as the prompt in the menuconfig); as such, it should relatively brief (40 chars is probably a good upper limit). The description is available in the `BR2_EXTERNAL_$(NAME)_DESC` variable. Examples of names and the corresponding `BR2_EXTERNAL_$(NAME)_PATH` variables: * `FOO` -> `BR2_EXTERNAL_FOO_PATH` * `BAR_42` -> `BR2_EXTERNAL_BAR_42_PATH` In the following examples, it is assumed the name to be set to `BAR_42`. .Note: Both `BR2_EXTERNAL_$(NAME)_PATH` and `BR2_EXTERNAL_$(NAME)_DESC` are available in the Kconfig files and the Makefiles. They are also exported in the environment so are available in post-build, post-image and in-fakeroot scripts. ===== The `Config.in` and `external.mk` files Those files (which may each be empty) can be used to define package recipes (i.e. `foo/Config.in` and `foo/foo.mk` like for packages bundled in Buildroot itself) or other custom configuration options or make logic. Buildroot automatically includes the `Config.in` from each br2-external tree to make it appear in the top-level configuration menu, and includes the `external.mk` from each br2-external tree with the rest of the makefile logic. The main usage of this is to store package recipes. The recommended way to do this is to write a `Config.in` file that looks like: ------ source "$BR2_EXTERNAL_BAR_42_PATH/package/package1/Config.in" source "$BR2_EXTERNAL_BAR_42_PATH/package/package2/Config.in" ------ Then, have an `external.mk` file that looks like: ------ include $(sort $(wildcard $(BR2_EXTERNAL_BAR_42_PATH)/package/*/*.mk)) ------ And then in `$(BR2_EXTERNAL_BAR_42_PATH)/package/package1` and `$(BR2_EXTERNAL_BAR_42_PATH)/package/package2` create normal Buildroot package recipes, as explained in xref:adding-packages[]. If you prefer, you can also group the packages in subdirectories called <boardname> and adapt the above paths accordingly. You can also define custom configuration options in `Config.in` and custom make logic in `external.mk`. ===== The `configs/` directory One can store Buildroot defconfigs in the `configs` subdirectory of the br2-external tree. Buildroot will automatically show them in the output of `make list-defconfigs` and allow them to be loaded with the normal `make <name>_defconfig` command. They will be visible in the 'make list-defconfigs' output, below an `External configs` label that contains the name of the br2-external tree they are defined in. .Note: If a defconfig file is present in more than one br2-external tree, then the one from the last br2-external tree is used. It is thus possible to override a defconfig bundled in Buildroot or another br2-external tree. ===== The `provides/` directory For some packages, Buildroot provides a choice between two (or more) implementations of API-compatible such packages. For example, there is a choice to choose either libjpeg ot jpeg-turbo; there is one between openssl or libressl; there is one to select one of the known, pre-configured toolchains... It is possible for a br2-external to extend those choices, by providing a set of files that define those alternatives: * `provides/toolchains.in` defines the pre-configured toolchains, which will then be listed in the toolchain selection; * `provides/jpeg.in` defines the alternative libjpeg implementations; * `provides/openssl.in` defines the alternative openssl implementations; * `provides/skeleton.in` defines the alternative skeleton implementations; * `provides/init.in` defines the alternative init system implementations, this can be used to select a default skeleton for your init. ===== Free-form content One can store all the board-specific configuration files there, such as the kernel configuration, the root filesystem overlay, or any other configuration file for which Buildroot allows to set the location (by using the `BR2_EXTERNAL_$(NAME)_PATH` variable). For example, you could set the paths to a global patch directory, to a rootfs overlay and to the kernel configuration file as follows (e.g. by running `make menuconfig` and filling in these options): ---- BR2_GLOBAL_PATCH_DIR=$(BR2_EXTERNAL_BAR_42_PATH)/patches/ BR2_ROOTFS_OVERLAY=$(BR2_EXTERNAL_BAR_42_PATH)/board/<boardname>/overlay/ BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=$(BR2_EXTERNAL_BAR_42_PATH)/board/<boardname>/kernel.config ---- ===== Additional Linux kernel extensions Additional Linux kernel extensions (see xref:linux-kernel-ext[]) can be added by storing them in the `linux/` directory at the root of a br2-external tree. ===== Example layout Here is an example layout using all features of br2-external (the sample content is shown for the file above it, when it is relevant to explain the br2-external tree; this is all entirely made up just for the sake of illustration, of course): ---- /path/to/br2-ext-tree/ |- external.desc | |name: BAR_42 | |desc: Example br2-external tree | `---- | |- Config.in | |source "$BR2_EXTERNAL_BAR_42_PATH/toolchain/toolchain-external-mine/Config.in.options" | |source "$BR2_EXTERNAL_BAR_42_PATH/package/pkg-1/Config.in" | |source "$BR2_EXTERNAL_BAR_42_PATH/package/pkg-2/Config.in" | |source "$BR2_EXTERNAL_BAR_42_PATH/package/my-jpeg/Config.in" | | | |config BAR_42_FLASH_ADDR | | hex "my-board flash address" | | default 0x10AD | `---- | |- external.mk | |include $(sort $(wildcard $(BR2_EXTERNAL_BAR_42_PATH)/package/*/*.mk)) | |include $(sort $(wildcard $(BR2_EXTERNAL_BAR_42_PATH)/toolchain/*/*.mk)) | | | |flash-my-board: | | $(BR2_EXTERNAL_BAR_42_PATH)/board/my-board/flash-image \ | | --image $(BINARIES_DIR)/image.bin \ | | --address $(BAR_42_FLASH_ADDR) | `---- | |- package/pkg-1/Config.in | |config BR2_PACKAGE_PKG_1 | | bool "pkg-1" | | help | | Some help about pkg-1 | `---- |- package/pkg-1/pkg-1.hash |- package/pkg-1/pkg-1.mk | |PKG_1_VERSION = 1.2.3 | |PKG_1_SITE = /some/where/to/get/pkg-1 | |PKG_1_LICENSE = blabla | | | |define PKG_1_INSTALL_INIT_SYSV | | $(INSTALL) -D -m 0755 $(PKG_1_PKGDIR)/S99my-daemon \ | | $(TARGET_DIR)/etc/init.d/S99my-daemon | |endef | | | |$(eval $(autotools-package)) | `---- |- package/pkg-1/S99my-daemon | |- package/pkg-2/Config.in |- package/pkg-2/pkg-2.hash |- package/pkg-2/pkg-2.mk | |- provides/jpeg.in | |config BR2_PACKAGE_MY_JPEG | | bool "my-jpeg" | `---- |- package/my-jpeg/Config.in | |config BR2_PACKAGE_PROVIDES_JPEG | | default "my-jpeg" if BR2_PACKAGE_MY_JPEG | `---- |- package/my-jpeg/my-jpeg.mk | |# This is a normal package .mk file | |MY_JPEG_VERSION = 1.2.3 | |MY_JPEG_SITE = https://example.net/some/place | |MY_JPEG_PROVIDES = jpeg | |$(eval $(autotools-package)) | `---- | |- provides/init.in | |config BR2_INIT_MINE | | bool "my custom init" | | select BR2_PACKAGE_MY_INIT | | select BR2_PACKAGE_SKELETON_INIT_MINE if BR2_ROOTFS_SKELETON_DEFAULT | `---- | |- provides/skeleton.in | |config BR2_ROOTFS_SKELETON_MINE | | bool "my custom skeleton" | | select BR2_PACKAGE_SKELETON_MINE | `---- |- package/skeleton-mine/Config.in | |config BR2_PACKAGE_SKELETON_MINE | | bool | | select BR2_PACKAGE_HAS_SKELETON | | | |config BR2_PACKAGE_PROVIDES_SKELETON | | default "skeleton-mine" if BR2_PACKAGE_SKELETON_MINE | `---- |- package/skeleton-mine/skeleton-mine.mk | |SKELETON_MINE_ADD_TOOLCHAIN_DEPENDENCY = NO | |SKELETON_MINE_ADD_SKELETON_DEPENDENCY = NO | |SKELETON_MINE_PROVIDES = skeleton | |SKELETON_MINE_INSTALL_STAGING = YES | |$(eval $(generic-package)) | `---- | |- provides/toolchains.in | |config BR2_TOOLCHAIN_EXTERNAL_MINE | | bool "my custom toolchain" | | depends on BR2_some_arch | | select BR2_INSTALL_LIBSTDCPP | `---- |- toolchain/toolchain-external-mine/Config.in.options | |if BR2_TOOLCHAIN_EXTERNAL_MINE | |config BR2_TOOLCHAIN_EXTERNAL_PREFIX | | default "arch-mine-linux-gnu" | |config BR2_PACKAGE_PROVIDES_TOOLCHAIN_EXTERNAL | | default "toolchain-external-mine" | |endif | `---- |- toolchain/toolchain-external-mine/toolchain-external-mine.mk | |TOOLCHAIN_EXTERNAL_MINE_SITE = https://example.net/some/place | |TOOLCHAIN_EXTERNAL_MINE_SOURCE = my-toolchain.tar.gz | |$(eval $(toolchain-external-package)) | `---- | |- linux/Config.ext.in | |config BR2_LINUX_KERNEL_EXT_EXAMPLE_DRIVER | | bool "example-external-driver" | | help | | Example external driver | |--- |- linux/linux-ext-example-driver.mk | |- configs/my-board_defconfig | |BR2_GLOBAL_PATCH_DIR="$(BR2_EXTERNAL_BAR_42_PATH)/patches/" | |BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_BAR_42_PATH)/board/my-board/overlay/" | |BR2_ROOTFS_POST_IMAGE_SCRIPT="$(BR2_EXTERNAL_BAR_42_PATH)/board/my-board/post-image.sh" | |BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="$(BR2_EXTERNAL_BAR_42_PATH)/board/my-board/kernel.config" | `---- | |- patches/linux/0001-some-change.patch |- patches/linux/0002-some-other-change.patch |- patches/busybox/0001-fix-something.patch | |- board/my-board/kernel.config |- board/my-board/overlay/var/www/index.html |- board/my-board/overlay/var/www/my.css |- board/my-board/flash-image `- board/my-board/post-image.sh |#!/bin/sh |generate-my-binary-image \ | --root ${BINARIES_DIR}/rootfs.tar \ | --kernel ${BINARIES_DIR}/zImage \ | --dtb ${BINARIES_DIR}/my-board.dtb \ | --output ${BINARIES_DIR}/image.bin `---- ---- The br2-external tree will then be visible in the menuconfig (with the layout expanded): ---- External options ---> *** Example br2-external tree (in /path/to/br2-ext-tree/) [ ] pkg-1 [ ] pkg-2 (0x10AD) my-board flash address ---- If you are using more than one br2-external tree, it would look like (with the layout expanded and the second one with name `FOO_27` but no `desc:` field in `external.desc`): ---- External options ---> Example br2-external tree ---> *** Example br2-external tree (in /path/to/br2-ext-tree) [ ] pkg-1 [ ] pkg-2 (0x10AD) my-board flash address FOO_27 ---> *** FOO_27 (in /path/to/another-br2-ext) [ ] foo [ ] bar ---- Additionally, the jpeg provider will be visible in the jpeg choice: ---- Target packages ---> Libraries ---> Graphics ---> [*] jpeg support jpeg variant () ---> ( ) jpeg ( ) jpeg-turbo *** jpeg from: Example br2-external tree *** (X) my-jpeg *** jpeg from: FOO_27 *** ( ) another-jpeg ---- And similarly for the toolchains: ---- Toolchain ---> Toolchain () ---> ( ) Custom toolchain *** Toolchains from: Example br2-external tree *** (X) my custom toolchain ---- .Note The toolchain options in `toolchain/toolchain-external-mine/Config.in.options` will not appear in the `Toolchain` menu. They must be explicitly included from within the br2-external's top-level `Config.in` and will thus appear in the `External options` menu. // -*- mode:doc; -*- // vim: set syntax=asciidoc: [[customize-store-buildroot-config]] === Storing the Buildroot configuration The Buildroot configuration can be stored using the command `make savedefconfig`. This strips the Buildroot configuration down by removing configuration options that are at their default value. The result is stored in a file called `defconfig`. If you want to save it in another place, change the `BR2_DEFCONFIG` option in the Buildroot configuration itself, or call make with `make savedefconfig BR2_DEFCONFIG=<path-to-defconfig>`. The recommended place to store this defconfig is `configs/<boardname>_defconfig`. If you follow this recommendation, the configuration will be listed in `make list-defconfigs` and can be set again by running `make <boardname>_defconfig`. Alternatively, you can copy the file to any other place and rebuild with `make defconfig BR2_DEFCONFIG=<path-to-defconfig-file>`. [[customize-store-package-config]] === Storing the configuration of other components The configuration files for BusyBox, the Linux kernel, Barebox, U-Boot and uClibc should be stored as well if changed. For each of these components, a Buildroot configuration option exists to point to an input configuration file, e.g. `BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE`. To store their configuration, set these configuration options to a path where you want to save the configuration files, and then use the helper targets described below to actually store the configuration. As explained in xref:customize-dir-structure[], the recommended path to store these configuration files is `board/<company>/<boardname>/foo.config`. Make sure that you create a configuration file 'before' changing the `BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE` etc. options. Otherwise, Buildroot will try to access this config file, which doesn't exist yet, and will fail. You can create the configuration file by running `make linux-menuconfig` etc. Buildroot provides a few helper targets to make the saving of configuration files easier. * `make linux-update-defconfig` saves the linux configuration to the path specified by `BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE`. It simplifies the config file by removing default values. However, this only works with kernels starting from 2.6.33. For earlier kernels, use `make linux-update-config`. * `make busybox-update-config` saves the busybox configuration to the path specified by `BR2_PACKAGE_BUSYBOX_CONFIG`. * `make uclibc-update-config` saves the uClibc configuration to the path specified by `BR2_UCLIBC_CONFIG`. * `make barebox-update-defconfig` saves the barebox configuration to the path specified by `BR2_TARGET_BAREBOX_CUSTOM_CONFIG_FILE`. * `make uboot-update-defconfig` saves the U-Boot configuration to the path specified by `BR2_TARGET_UBOOT_CUSTOM_CONFIG_FILE`. * For at91bootstrap3, no helper exists so you have to copy the config file manually to `BR2_TARGET_AT91BOOTSTRAP3_CUSTOM_CONFIG_FILE`. // -*- mode:doc; -*- // vim: set syntax=asciidoc: [[rootfs-custom]] === Customizing the generated target filesystem Besides changing the configuration through `make *config`, there are a few other ways to customize the resulting target filesystem. The two recommended methods, which can co-exist, are root filesystem overlay(s) and post build script(s). Root filesystem overlays (`BR2_ROOTFS_OVERLAY`):: + A filesystem overlay is a tree of files that is copied directly over the target filesystem after it has been built. To enable this feature, set config option `BR2_ROOTFS_OVERLAY` (in the +System configuration+ menu) to the root of the overlay. You can even specify multiple overlays, space-separated. If you specify a relative path, it will be relative to the root of the Buildroot tree. Hidden directories of version control systems, like `.git`, `.svn`, `.hg`, etc., files called `.empty` and files ending in `~` are excluded from the copy. + When `BR2_ROOTFS_MERGED_USR` is enabled, then the overlay must not contain the '/bin', '/lib' or '/sbin' directories, as Buildroot will create them as symbolic links to the relevant folders in '/usr'. In such a situation, should the overlay have any programs or libraries, they should be placed in '/usr/bin', '/usr/sbin' and '/usr/lib'. + As shown in xref:customize-dir-structure[], the recommended path for this overlay is `board/<company>/<boardname>/rootfs-overlay`. Post-build scripts (`BR2_ROOTFS_POST_BUILD_SCRIPT`):: + Post-build scripts are shell scripts called 'after' Buildroot builds all the selected software, but 'before' the rootfs images are assembled. To enable this feature, specify a space-separated list of post-build scripts in config option `BR2_ROOTFS_POST_BUILD_SCRIPT` (in the `System configuration` menu). If you specify a relative path, it will be relative to the root of the Buildroot tree. + Using post-build scripts, you can remove or modify any file in your target filesystem. You should, however, use this feature with care. Whenever you find that a certain package generates wrong or unneeded files, you should fix that package rather than work around it with some post-build cleanup scripts. + As shown in xref:customize-dir-structure[], the recommended path for this script is `board/<company>/<boardname>/post_build.sh`. + The post-build scripts are run with the main Buildroot tree as current working directory. The path to the target filesystem is passed as the first argument to each script. If the config option `BR2_ROOTFS_POST_SCRIPT_ARGS` is not empty, these arguments will be passed to the script too. All the scripts will be passed the exact same set of arguments, it is not possible to pass different sets of arguments to each script. + In addition, you may also use these environment variables: - `BR2_CONFIG`: the path to the Buildroot .config file - `CONFIG_DIR`: the directory containing the .config file, and therefore the top-level Buildroot Makefile to use (which is correct for both in-tree and out-of-tree builds) - `HOST_DIR`, `STAGING_DIR`, `TARGET_DIR`: see xref:generic-package-reference[] - `BUILD_DIR`: the directory where packages are extracted and built - `BINARIES_DIR`: the place where all binary files (aka images) are stored - `BASE_DIR`: the base output directory Below three more methods of customizing the target filesystem are described, but they are not recommended. Direct modification of the target filesystem:: + For temporary modifications, you can modify the target filesystem directly and rebuild the image. The target filesystem is available under `output/target/`. After making your changes, run `make` to rebuild the target filesystem image. + This method allows you to do anything to the target filesystem, but if you need to clean your Buildroot tree using `make clean`, these changes will be lost. Such cleaning is necessary in several cases, refer to xref:full-rebuild[] for details. This solution is therefore only useful for quick tests: _changes do not survive the `make clean` command_. Once you have validated your changes, you should make sure that they will persist after a `make clean`, using a root filesystem overlay or a post-build script. Custom target skeleton (`BR2_ROOTFS_SKELETON_CUSTOM`):: + The root filesystem image is created from a target skeleton, on top of which all packages install their files. The skeleton is copied to the target directory `output/target` before any package is built and installed. The default target skeleton provides the standard Unix filesystem layout and some basic init scripts and configuration files. + If the default skeleton (available under `system/skeleton`) does not match your needs, you would typically use a root filesystem overlay or post-build script to adapt it. However, if the default skeleton is entirely different than what you need, using a custom skeleton may be more suitable. + To enable this feature, enable config option `BR2_ROOTFS_SKELETON_CUSTOM` and set `BR2_ROOTFS_SKELETON_CUSTOM_PATH` to the path of your custom skeleton. Both options are available in the `System configuration` menu. If you specify a relative path, it will be relative to the root of the Buildroot tree. + Custom skeletons don't need to contain the '/bin', '/lib' or '/sbin' directories, since they are created automatically during the build. When `BR2_ROOTFS_MERGED_USR` is enabled, then the custom skeleton must not contain the '/bin', '/lib' or '/sbin' directories, as Buildroot will create them as symbolic links to the relevant folders in '/usr'. In such a situation, should the skeleton have any programs or libraries, they should be placed in '/usr/bin', '/usr/sbin' and '/usr/lib'. + This method is not recommended because it duplicates the entire skeleton, which prevents taking advantage of the fixes or improvements brought to the default skeleton in later Buildroot releases. Post-fakeroot scripts (`BR2_ROOTFS_POST_FAKEROOT_SCRIPT`):: + When aggregating the final images, some parts of the process requires root rights: creating device nodes in `/dev`, setting permissions or ownership to files and directories... To avoid requiring actual root rights, Buildroot uses `fakeroot` to simulate root rights. This is not a complete substitute for actually being root, but is enough for what Buildroot needs. + Post-fakeroot scripts are shell scripts that are called at the 'end' of the fakeroot phase, 'right before' the filesystem image generator is called. As such, they are called in the fakeroot context. + Post-fakeroot scripts can be useful in case you need to tweak the filesystem to do modifications that are usually only available to the root user. + .Note: It is recommended to use the existing mechanisms to set file permissions or create entries in `/dev` (see xref:customize-device-permission[]) or to create users (see xref:customize-users[]) + .Note: The difference between post-build scripts (above) and fakeroot scripts, is that post-build scripts are not called in the fakeroot context. + .Note: Using `fakeroot` is not an absolute substitute for actually being root. `fakeroot` only ever fakes the file access rights and types (regular, block-or-char device...) and uid/gid; these are emulated in-memory. // -*- mode:doc; -*- // vim: set syntax=asciidoc: [[customize-device-permission]] ==== Setting file permissions and ownership and adding custom devices nodes Sometimes it is needed to set specific permissions or ownership on files or device nodes. For example, certain files may need to be owned by root. Since the post-build scripts are not run as root, you cannot do such changes from there unless you use an explicit fakeroot from the post-build script. Instead, Buildroot provides support for so-called _permission tables_. To use this feature, set config option `BR2_ROOTFS_DEVICE_TABLE` to a space-separated list of permission tables, regular text files following the xref:makedev-syntax[makedev syntax]. If you are using a static device table (i.e. not using `devtmpfs`, `mdev`, or `(e)udev`) then you can add device nodes using the same syntax, in so-called _device tables_. To use this feature, set config option `BR2_ROOTFS_STATIC_DEVICE_TABLE` to a space-separated list of device tables. As shown in xref:customize-dir-structure[], the recommended location for such files is `board/<company>/<boardname>/`. It should be noted that if the specific permissions or device nodes are related to a specific application, you should set variables `FOO_PERMISSIONS` and `FOO_DEVICES` in the package's `.mk` file instead (see xref:generic-package-reference[]). // -*- mode:doc; -*- // vim: set syntax=asciidoc: [[customize-users]] === Adding custom user accounts Sometimes it is needed to add specific users in the target system. To cover this requirement, Buildroot provides support for so-called _users tables_. To use this feature, set config option `BR2_ROOTFS_USERS_TABLES` to a space-separated list of users tables, regular text files following the xref:makeuser-syntax[makeusers syntax]. As shown in xref:customize-dir-structure[], the recommended location for such files is `board/<company>/<boardname>/`. It should be noted that if the custom users are related to a specific application, you should set variable `FOO_USERS` in the package's `.mk` file instead (see xref:generic-package-reference[]). // -*- mode:doc; -*- // vim: set syntax=asciidoc: === Customization _after_ the images have been created While post-build scripts (xref:rootfs-custom[]) are run _before_ building the filesystem image, kernel and bootloader, *post-image scripts* can be used to perform some specific actions _after_ all images have been created. Post-image scripts can for example be used to automatically extract your root filesystem tarball in a location exported by your NFS server, or to create a special firmware image that bundles your root filesystem and kernel image, or any other custom action required for your project. To enable this feature, specify a space-separated list of post-image scripts in config option `BR2_ROOTFS_POST_IMAGE_SCRIPT` (in the +System configuration+ menu). If you specify a relative path, it will be relative to the root of the Buildroot tree. Just like post-build scripts, post-image scripts are run with the main Buildroot tree as current working directory. The path to the `images` output directory is passed as the first argument to each script. If the config option `BR2_ROOTFS_POST_SCRIPT_ARGS` is not empty, these arguments will be passed to the script too. All the scripts will be passed the exact same set of arguments, it is not possible to pass different sets of arguments to each script. Again just like for the post-build scripts, the scripts have access to the environment variables `BR2_CONFIG`, `HOST_DIR`, `STAGING_DIR`, `TARGET_DIR`, `BUILD_DIR`, `BINARIES_DIR`, `CONFIG_DIR` and `BASE_DIR`. The post-image scripts will be executed as the user that executes Buildroot, which should normally _not_ be the root user. Therefore, any action requiring root permissions in one of these scripts will require special handling (usage of fakeroot or sudo), which is left to the script developer. // -*- mode:doc -*- ; // vim: set syntax=asciidoc: [[customize-patches]] === Adding project-specific patches It is sometimes useful to apply 'extra' patches to packages - on top of those provided in Buildroot. This might be used to support custom features in a project, for example, or when working on a new architecture. The `BR2_GLOBAL_PATCH_DIR` configuration option can be used to specify a space separated list of one or more directories containing package patches. For a specific version `<packageversion>` of a specific package `<packagename>`, patches are applied from `BR2_GLOBAL_PATCH_DIR` as follows: . For every directory - `<global-patch-dir>` - that exists in `BR2_GLOBAL_PATCH_DIR`, a `<package-patch-dir>` will be determined as follows: + * `<global-patch-dir>/<packagename>/<packageversion>/` if the directory exists. + * Otherwise, `<global-patch-dir>/<packagename>` if the directory exists. . Patches will then be applied from a `<package-patch-dir>` as follows: + * If a `series` file exists in the package directory, then patches are applied according to the `series` file; + * Otherwise, patch files matching `*.patch` are applied in alphabetical order. So, to ensure they are applied in the right order, it is highly recommended to name the patch files like this: `<number>-<description>.patch`, where `<number>` refers to the 'apply order'. For information about how patches are applied for a package, see xref:patch-apply-order[] The `BR2_GLOBAL_PATCH_DIR` option is the preferred method for specifying a custom patch directory for packages. It can be used to specify a patch directory for any package in buildroot. It should also be used in place of the custom patch directory options that are available for packages such as U-Boot and Barebox. By doing this, it will allow a user to manage their patches from one top-level directory. The exception to `BR2_GLOBAL_PATCH_DIR` being the preferred method for specifying custom patches is `BR2_LINUX_KERNEL_PATCH`. `BR2_LINUX_KERNEL_PATCH` should be used to specify kernel patches that are available at a URL. *Note:* `BR2_LINUX_KERNEL_PATCH` specifies kernel patches that are applied after patches available in `BR2_GLOBAL_PATCH_DIR`, as it is done from a post-patch hook of the Linux package. // -*- mode:doc; -*- // vim: set syntax=asciidoc: [[customize-packages]] === Adding project-specific packages In general, any new package should be added directly in the `package` directory and submitted to the Buildroot upstream project. How to add packages to Buildroot in general is explained in full detail in xref:adding-packages[] and will not be repeated here. However, your project may need some proprietary packages that cannot be upstreamed. This section will explain how you can keep such project-specific packages in a project-specific directory. As shown in xref:customize-dir-structure[], the recommended location for project-specific packages is `package/<company>/`. If you are using the br2-external tree feature (see xref:outside-br-custom[]) the recommended location is to put them in a sub-directory named `package/` in your br2-external tree. However, Buildroot will not be aware of the packages in this location, unless we perform some additional steps. As explained in xref:adding-packages[], a package in Buildroot basically consists of two files: a `.mk` file (describing how to build the package) and a `Config.in` file (describing the configuration options for this package). Buildroot will automatically include the `.mk` files in first-level subdirectories of the `package` directory (using the pattern `package/\*/*.mk`). If we want Buildroot to include `.mk` files from deeper subdirectories (like `package/<company>/package1/`) then we simply have to add a `.mk` file in a first-level subdirectory that includes these additional `.mk` files. Therefore, create a file `package/<company>/<company>.mk` with following contents (assuming you have only one extra directory level below `package/<company>/`):
include $(sort $(wildcard package/<company>//.mk))
For the `Config.in` files, create a file `package/<company>/Config.in` that includes the `Config.in` files of all your packages. An exhaustive list has to be provided since wildcards are not supported in the source command of kconfig. For example:
source "package/<company>/package1/Config.in" source "package/<company>/package2/Config.in"
Include this new file `package/<company>/Config.in` from `package/Config.in`, preferably in a company-specific menu to make merges with future Buildroot versions easier. If using a br2-external tree, refer to xref:outside-br-custom[] for how to fill in those files. // -*- mode:doc; -*- // vim: set syntax=asciidoc: === Quick guide to storing your project-specific customizations Earlier in this chapter, the different methods for making project-specific customizations have been described. This section will now summarize all this by providing step-by-step instructions to storing your project-specific customizations. Clearly, the steps that are not relevant to your project can be skipped. 1. `make menuconfig` to configure toolchain, packages and kernel. 1. `make linux-menuconfig` to update the kernel config, similar for other configuration like busybox, uclibc, ... 1. `mkdir -p board/<manufacturer>/<boardname>` 1. Set the following options to `board/<manufacturer>/<boardname>/<package>.config` (as far as they are relevant): * `BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE` * `BR2_PACKAGE_BUSYBOX_CONFIG` * `BR2_UCLIBC_CONFIG` * `BR2_TARGET_AT91BOOTSTRAP3_CUSTOM_CONFIG_FILE` * `BR2_TARGET_BAREBOX_CUSTOM_CONFIG_FILE` * `BR2_TARGET_UBOOT_CUSTOM_CONFIG_FILE` 1. Write the configuration files: * `make linux-update-defconfig` * `make busybox-update-config` * `make uclibc-update-config` * +cp <output>/build/at91bootstrap3-*/.config board/<manufacturer>/<boardname>/at91bootstrap3.config+ * `make barebox-update-defconfig` * `make uboot-update-defconfig` 1. Create `board/<manufacturer>/<boardname>/rootfs-overlay/` and fill it with additional files you need on your rootfs, e.g. `board/<manufacturer>/<boardname>/rootfs-overlay/etc/inittab`. Set `BR2_ROOTFS_OVERLAY` to `board/<manufacturer>/<boardname>/rootfs-overlay`. 1. Create a post-build script `board/<manufacturer>/<boardname>/post_build.sh`. Set `BR2_ROOTFS_POST_BUILD_SCRIPT` to `board/<manufacturer>/<boardname>/post_build.sh` 1. If additional setuid permissions have to be set or device nodes have to be created, create `board/<manufacturer>/<boardname>/device_table.adoc` and add that path to `BR2_ROOTFS_DEVICE_TABLE`. 1. If additional user accounts have to be created, create `board/<manufacturer>/<boardname>/users_table.adoc` and add that path to `BR2_ROOTFS_USERS_TABLES`. 1. 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`. 1. Specifically for the Linux kernel, there also exists the option `BR2_LINUX_KERNEL_PATCH` with as main advantage that it can also download patches from a URL. If you do not need this, `BR2_GLOBAL_PATCH_DIR` is preferred. U-Boot, Barebox, at91bootstrap and at91bootstrap3 also have separate options, but these do not provide any advantage over `BR2_GLOBAL_PATCH_DIR` and will likely be removed in the future. 1. If you need to add project-specific packages, create `package/<manufacturer>/` and place your packages in that directory. Create an overall `<manufacturer>.mk` file that includes the `.mk` files of all your packages. Create an overall `Config.in` file that sources the `Config.in` files of all your packages. Include this `Config.in` file from Buildroot's `package/Config.in` file. 1. `make savedefconfig` to save the buildroot configuration. 1. `cp defconfig configs/<boardname>_defconfig`