9. Buildroot用户手册-定制项目

转载请注明原文链接:https://blog.csdn.net/haimo_free/article/details/107677667

9. 定制项目

对于定制的项目,你可能需要执行的典型操作是:

  • 配置Buildroot(包括编译选项和工具链、引导程序、内核、软件包和文件系统镜像类型)
  • 配置其他模块,如Linux内核和BusyBox
  • 自定义目标文件系统
    • 在目标文件夹添加或覆盖文件(使用BR2_ROOTFS_OVERLAY)
    • 修改或删除目标文件系统上的文件(使用BR2_ROOTFS_POST_BUILD_SCRIPT)
    • 在生成文件系统镜像前执行任意命令(使用BR2_ROOTFS_POST_BUILD_SCRIPT)
    • 设置文件权限和所有者(使用BR2_ROOTFS_DEVICE_TABLE)
    • 添加自定义设备节点(使用BR2_ROOTFS_STATIC_DEVICE_TABLE)
    • 添加自定义用户账号(使用BR2_ROOTFS_USERS_TABLES)
  • 在生成文件系统镜像后执行任意命令(使用BR2_ROOTFS_POST_IMAGE_SCRIPT)
  • 为某些软件包打补丁(使用BR2_GLOBAL_PATCH_DIR)
  • 添加定制项目的软件包

有关定制项目的自定义项的重要说明:请仔细考虑哪些更改是特定于项目的,哪些更改对其他项目的开发人员也有用。Buildroot社区强烈建议并鼓励上游开发者改进软件包和目标板对Buildroot官方项目的支持。当然,由于更改是高度定制或专用的,因此有时上游开发者不可能或不希望这么做。

本节介绍了如何在Buildroot中进行定制项目的自定义配置,以及如何存储使得可以重复构建同一镜像,即使是make clean之后。通过遵循推荐的做法,你甚至可以使用同一Buildroot树来构建多个不同的项目。

9.1 推荐的目录结构

为定制项目自定义Buildroot时,你将创建一个或多个需要存储在某处的特定于项目的文件。虽然大多数文件可以放置在任意位置,并将它们的路径在Buildroot配置中指定,但Buildroot开发人员建议使用本节中描述的特定目录结构。

使用以下目录结构,你可以选择将该目录结构放在何处:在Buildroot目录树中,还是Buildroot目录树外(使用br2-external树)。两个选项均有效,如何选择取决于你:

+-- 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)

本章将进一步详细介绍上面列出的文件。

注意:如果你选择将此目录结构放在Buildroot目录树外但在br2-external目录树中,则以及可能的组件可能是多余的,可以省略。

9.1.1 分层定制实现

用户拥有几个部分自定义项相同的项目是很普遍的,建议使用本节所述的分层自定义方法,而不是为每个项目都复制这些自定义项。

Buildroot中几乎所有可用的自定义方法(例如post-build scripts(构建后脚本)和root filesystem overlays(根文件系统覆盖等))都接受以空格分隔的项目列表,所有指定的项目将按从左到右的顺序被处理。通过创建多个这样的项目,一个用于通用的自定义项目,另一个用于针对项目的自定义项目,你可以避免不必要的重复。每层通常由board//里的独立目录体现。根据你的项目,甚至可以引入两个以上的层。

例如,某用户拥有两个自定义层common和fooboard的目录结构如下:

+-- board/
    +-- <company>/
        +-- common/
        |   +-- post_build.sh
        |   +-- rootfs_overlay/
        |   |   +-- ...
        |   +-- patches/
        |       +-- ...
        |
        +-- fooboard/
            +-- linux.config
            +-- busybox.config
            +-- <other configuration files>
            +-- post_build.sh
            +-- rootfs_overlay/
            |   +-- ...
            +-- patches/
                +-- ...

如果用户将BR2_GLOBAL_PATCH_DIR选项配置为:

BR2_GLOBAL_PATCH_DIR="board/<company>/common/patches board/<company>/fooboard/patches"

那么首先会应用来自common层的补丁,然后是fooboard层的补丁。

9.2 将定制保存在Buildroot之外

如第9.1节“推荐的目录结构”所述,你可以将定制项目的自定义配置放在两个位置:

  • 直接放在Buildroot目录树中,通常使用版本控制系统中的分支来维护他们,这样方便升级到Buildroot新版本。
  • 使用br2-external机制放在Buildroot目录树外。该机制允许将软件包配置、目标板支持和配置文件保留在Buildroot目录树外,同时仍可以将它们很好地集成到构建环境中,我们称此为br2-external 目录树。本节说明如何使用外部树机制,以及需要在外部树中提供的内容。

可以通过BR2_EXTERNAL make变量指定要使用的外部树的路径,并且可以指定一个或多个外部树。该变量将传给Buildroot的所有make调用。它会自动保存在output/.br2-external.mk文件中,因此无需每次make都指定BR2_EXTERNAL。但是,可以随时通过传递新值来改变,也可以通过传递空值删除它。

注意:外部树目录可以是绝对路径,也可以是相对路径。如果传递相对路径,必须注意,它是相对于Buildroot源目录而不是相对Buildroot输出目录。

注意:如果使用Buildroot 2016.11之前的外部树,则需要先对其进行转换,然后才能将其用于Buildroot 2016.11及更高版本。请参阅第25.1节“迁移到2016.11版本”。

示例:

buildroot/ $ make BR2_EXTERNAL=/path/to/foo menuconfig

之后,/path/to/foo外部树将被使用:

buildroot/ $ make
buildroot/ $ make legal-info

可以随时切换到另一个外部树:

buildroot/ $ make BR2_EXTERNAL=/where/we/have/bar xconfig

使用多个外部树:

buildroot/ $ make BR2_EXTERNAL=/path/to/foo:/where/we/have/bar menuconfig

禁用外部树:

buildroot/ $ make BR2_EXTERNAL= xconfig

9.2.1 外部树布局

外部树必须至少包含以下三个文件,以下各章对此进行介绍:

  • external.desc
  • external.mk
  • Config.in

除了这些强制性文件外,外部树中可能还存在其他可选内容,例如configs/或provides/目录。以下各章将对它们进行描述。稍后还将介绍完整的外部树布局示例。

9.2.1.1 external.desc

该文件用于描述外部树:外部树的名称和描述。

该文件的格式以行分隔,每行以关键字开头,后跟冒号和一个或多个空格,之后是该关键字的值。目前有两个已定义的关键字:

  • name
    必填,定义了外部树的名称。名称只能使用[A-Za-z0-9_]内的ASCII字符,不允许使用其他字符。Buildroot将 BR2_EXTERNAL_$(NAME)_PATH环境变量设置为外部树的绝对路径,可以使用它来引用外部树。该变量在Kconfig中也可以用,因此你可以使用它为Kconfig和Makefile提供源,以及使用它来从外部树中包含其他Makefile或引用其他文件。
    注意:由于一次可以使用多个外部树,因此Buildroot使用此名称为每个外部树生成变量。该名称用于Buildroot标识你的外部树,因此请尽量提供一个能真正描述你的外部树的名称,并保持唯一避免与其他外部树冲突,尤其是当你计划以某种方式与第三方共享外部树或使用第三方外部树时。
  • desc
    可选,提供该外部树的简短描述。它应该放在一行上,并且大部分是自由格式的(请参见下文),在显示有关该外部树的信息时使用(例如,在defconfig文件列表上方,或作为menuconfig中的提示)。因此,应该相对简短(40个字符可能是一个比较好的上限)。可以使用BR2_EXTERNAL_$(NAME)_DESC环境变量访问该值。

示例,外部树名称及其对应的BR2_EXTERNAL_$(NAME)_PATH环境变量:

FOO → BR2_EXTERNAL_FOO_PATH
BAR_42 → BR2_EXTERNAL_BAR_42_PATH

以下示例中,假设外部树名称为BAR_42。

注意:BR2_EXTERNAL_KaTeX parse error: Expected group after '_' at position 25: …TH和BR2_EXTERNAL_̲(NAME)_DESC在Kconfig和Makefile中都有效。这些变量在环境变量中导出,因此可以在post-build、post-image和in-fakeroot脚本中使用。

9.2.1.2 Config.in和external.mk

这些文件(可以为空)用于定义软件包的特性(类似Buildroot中的foo/Config.in和foo/foo.mk)或其他自定义配置或make逻辑。

Buildroot自动将来自每个外部树的Config.in包含进来,并展现在顶层配置菜单中。同时自动包含每个外部树的external.mk并合并到其余的makefile中。

这些文件的主要用途是用于定义软件包特性。推荐的方法是编写如下所示的Config.in文件:

source "$BR2_EXTERNAL_BAR_42_PATH/package/package1/Config.in"
source "$BR2_EXTERNAL_BAR_42_PATH/package/package2/Config.in"

然后,编写external.mk文件:

include $(sort $(wildcard $(BR2_EXTERNAL_BAR_42_PATH)/package/*/*.mk))

之后,在 ( B R 2 E X T E R N A L B A R 4 2 P A T H ) / p a c k a g e / p a c k a g e 1 和 (BR2_EXTERNAL_BAR_42_PATH)/package/package1和 (BR2EXTERNALBAR42PATH)/package/package1(BR2_EXTERNAL_BAR_42_PATH)/package/package2创建普通的Buildroot软件包,参阅第17章“向Buildroot添加新的软件包”。如果你愿意,可以将软件包分组在名为的子目录中,并相应地调整上述路径。

你还可以在Config.in中添加自定义配置,以及在external.mk中添加make逻辑。

9.2.1.3 configs/目录

可以将Buildroot的默认配置文件defconfigs存储在外部树的configs子目录中。Buildroot将在make list-defconfigs命令的输出中自动展示它们,并且允许make _defconfig命令自动加载它们。执行make list-defconfigs命令时,它们将出现在外部树名称的External configs标签下。

注意:如果多个外部树中存在defconfig文件,则使用最后一个外部树定义的defconfig。因此,可以覆盖Buildroot或另一个外部树中捆绑的defconfig文件。

9.2.1.4 provides/目录

对于某些软件包,Buildroot提供了两个甚至多个API兼容的软件包实现方式。例如,可以选择libjpeg或jpeg-turbo,也可以选择openssl或libressl。最后,可以选择一个已知的预配置的工具链。

外部树可以通过提供一组定义这些选项的文件来扩展这些选择:

  • provides/toolchains.in 定义预配置的工具链,然后将其列在工具链选项中。
  • provides/jpeg.in 定义替代的libjpeg实现。
  • provides/openssl.in 定义替代的openssl实现。
9.2.1.5 其他自定义格式的内容

可以在其中存储特定目标板的配置文件,例如内核配置、根文件系统覆盖或Buildroot允许为其设置位置的其他任何配置文件(通过使用BR2_EXTERNAL_$(NAME)_PATH变量)。例如,你可以按以下方式指定全局补丁、根文件系统覆盖和内核配置文件的路径:

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
9.2.1.6 其他Linux内核扩展

在外部树根目录下的linux/子目录下可以添加Linux内核扩展,参阅第17.20.2节“Linux内核扩展”。

9.2.1.7 布局示例

以下是包含了所有特性的外部树布局示例,示例中的内容都是上边提到过的文件,所有这些文件都是出于演示目的而组建。

/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/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
        `----

该外部树将在menuconfig中可见,以下为展开后的效果:

External options  --->
    *** Example br2-external tree (in /path/to/br2-ext-tree/)
    [ ] pkg-1
    [ ] pkg-2
    (0x10AD) my-board flash address

如果使用了不止一个外部树,则看起来会是这样(第二个外部树的名称为FOO_27,且external.desc文件中没有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

此外,jpeg提供程序将在jpeg选项中可见:

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

类似地,工具链选项如下:

Toolchain  --->
    Toolchain ()  --->
        ( ) Custom toolchain
            *** Toolchains from: Example br2-external tree ***
        (X) my custom toolchain

注意:toolchain/toolchain-external-mine/Config.in.options的配置不会出现在Toolchain菜单中,必须在外部树的顶层Config.in配置文件中包含它们才会显示在External options菜单中。

9.3 保存Buildroot配置

Buildroot的配置文件可以使用make savedefconfig命令保存。

该命令可以删除默认的配置选项从而简化Buildroot配置文件,结果保存在名为defconfig的文件中。如果想保存到其他位置,请更改BR2_DEFCONFIG选项,或者调用make savedefconfig BR2_DEFCONFIG=命令。

推荐的保存Buildroot配置文件的位置是configs/_defconfig。如果遵循此建议,make help将列出该配置,并可以通过make _defconfig命令重新设置。

或者,你也可以将该配置文件复制到任意位置,并使用make defconfig BR2_DEFCONFIG=命令重新构建。

9.4 保存其他组件的配置

如果BusyBox、Linux内核、BareBox、U-Boot和uClibc的配置被修改,这些配置也应该保存。对于每一个组件,Buildroot都有一个对应的配置选项指向输入的配置文件,例如BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE。要保存这些配置,请将对应的配置选项指向要保存配置文件的路径,然后参照下边的帮助手册实际存储配置文件。

如第9.1节“推荐的目录结构”所述,存储这些配置文件的推荐路径为:board///foo.config。

请确保在修改BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE等选项之前创建配置文件。否则,Buildroot将尝试访问该配置文件,并返回失败。可以通过运行make linux-menuconfig等命令创建配置文件。

Buildroot提供了一些帮助程序以简化配置文件的保存。

  • make linux-update-defconfig 将Linux配置保存到BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE变量指定的路径。它通过删除默认值来简化配置文件。然而,这仅适用于2.6.33及以上版本,对于低版本,请使用make linux-update-config命令。
  • make busybox-update-config 将BusyBox配置保存到BR2_PACKAGE_BUSYBOX_CONFIG变量指定的路径。
  • make uclibc-update-config 将uClibc配置保存到BR2_UCLIBC_CONFIG变量指定的路径。
  • make barebox-update-defconfig 将BareBox配置保存到BR2_TARGET_UBOOT_CUSTOM_CONFIG_FILE变量指定的路径。
  • make uboot-update-defconfig 将UBoot配置保存到BR2_TARGET_UBOOT_CUSTOM_CONFIG_FILE变量指定的路径。
  • 对于at91bootstrap3没有帮助程序,需要手动将配置文件复制到BR2_TARGET_AT91BOOTSTRAP3_CUSTOM_CONFIG_FILE变量指定的路径。

9.5 自定义生成的目标文件系统

除了通过make *config命令修改配置外,还有几种方法可以自定义生成的目标文件系统。

推荐的两种方法(可以同时使用)是根文件系统叠加(root filesystem overlay)和构建后脚本(post build script)。

9.5.1 根文件系统叠加 (BR2_ROOTFS_OVERLAY)

根文件系统叠加层是一个文件目录树,在目标系统构建完后,将其直接复制到目标文件系统上。要启用此功能,需将BR2_ROOTFS_OVERLAY变量(在System configuration菜单)设置为叠加目录树的根目录。甚至可以指定多个以空格分隔的叠加层。如果指定相对路径,则它将相对于Buildroot根目录解析。版本控制系统的隐藏目录(如.git、.svn、.hg等)、.empty文件以及以~结尾的文件将被排除。

如果BR2_ROOTFS_MERGED_USR选项被启用,则叠加层不能包含/bin、/lib、/sbin目录,原因是Buildroot将自动创建指向/usr的符号链接。在这种情况下,如果叠加层有任何程序或库文件,则应将它们放到/usr/bin、/usr/lib、/usr/sbin目录中。

如第9.1节“推荐的目录结构”所述,叠加层的推荐路径为:board///rootfs-overlay。

9.5.2 构建后脚本(BR2_ROOTFS_POST_BUILD_SCRIPT)

构建后脚本是Buildroot在构建完所选软件包但组装根文件系统前调用的shell脚本。要启用此功能,需将BR2_ROOTFS_POST_BUILD_SCRIPT变量(在System configuration菜单)设置为以空格分隔的构建后脚本列表。如果指定相对路径,则将相对于Buildroot根目录解析。

使用构建后脚本,可以删除或修改目标文件系统中的任何文件。但是,需要谨慎使用该功能。当发现某个软件包生成错误或有需要删除或修改的文件时,应先修复该软件包的问题,而不是使用构建后脚本来解决问题。

如第9.1节“推荐的目录结构”所述,此脚本的推荐路径为:board///post_build.sh。

构建后脚本以Buildroot主目录树作为当前工作目录运行。目标文件系统的路径将作为第一个参数传递给每个脚本。如果BR2_ROOTFS_POST_SCRIPT_ARGS变量不为空,则这些参数也将传递给脚本。所有脚本都将传递完全相同的参数,不支持将不同参数传递给不同脚本。

此外,还可以使用以下环境变量:

  • BR2_CONFIG Buildroot .config配置文件的路径。
  • HOST_DIR、STAGING_DIR、TARGET_DIR 参阅第17.5.2节“通用软件包参考”。
  • BUILD_DIR 软件包提取和构建的路径。
  • BINARIES_DIR 所有二进制文件(镜像)的存储位置。
  • BASE_DIR 基本输出目录。

下面再介绍三种自定义目标文件系统的方法,但不建议使用。

9.5.3 直接修改目标文件系统

对于临时修改,可以直接修改目标文件系统并重建镜像。目标文件系统位于output/target目录,更改后,运行make命令重建目标文件系统镜像。

此方法允许对目标文件系统执行任何操作,但是如果运行make clean命令,这些修改将会丢失。在某些情况下,必须执行make clean清理,因此这种方法仅对快速测试有效。在验证修改有效后,应使用根文件系统叠加或构建后脚本保留该修改。

9.5.4 自定义目标框架(BR2_ROOTFS_SKELETON_CUSTOM)

根文件系统镜像是从目标框架开始创建的,所有软件包都在其上面安装文件。在构建和安装任何软件包之前,目标框架会被复制到目标目录output/target目录。默认的目标框架提供了标准Unix文件系统布局以及一些基础的初始化脚本和配置文件。

如果默认目标框架(位于system/skeleton目录)不满足需求,通常会使用根文件系统叠加或构建后脚本调整。然而,如果默认框架与你所需的框架完全不同,则使用自定义框架可能更合适。

要启用此功能,需启用BR2_ROOTFS_SKELETON_CUSTOM选项,配置BR2_ROOTFS_SKELETON_CUSTOM_PATH指向自定义框架的路径。System configuration菜单提供了这些选项。如果指定相对目录,则将相对于Buildroot根目录解析。

自定义框架不需要包含/bin、lib或/sbin目录,它们将在构建过程中自动生成。如果BR2_ROOTFS_MERGED_USR选项启用,则自定义框架不能包含/bin、/lib或/sbin目录,原因是Buildroot将自动创建指向/usr的符号链接。在这种情况下,如果框架中有任何程序或库文件,则应将它们放到/usr/bin、/usr/lib、/usr/sbin目录中。

不建议使用此方法,因为它会复制整个框架,从而导致无法利用Buildroot高版本对默认框架的修复和改进。

9.5.5 fakeroot脚本(BR2_ROOTFS_POST_FAKEROOT_SCRIPT)

生成最终镜像时,某些部分需要root权限,如:创建/dev设备节点,设置文件或目录的权限或所有者等。为了避免使用实际的root权限,Buildroot会使用fakeroot模拟root权限。这不能完全替代实际的root权限,但足以满足Buildroot的需要。

fakeroot脚本是在fakeroot阶段最后且生成文件系统镜像之前被调用的shell脚本。因此,它们在fakeroot上下文中被调用。fakeroot脚本通常在需要root权限调整文件系统时有用。

注意:建议使用现有机制设置文件权限或在/dev目录中创建设备节点(参阅第9.5.6节“设置文件权限和所有者及添加自定义设备节点”)或创建用户(参阅第9.6节“添加自定义账户”)。

注意:构建后脚本(post-build script)与fakeroot脚本的区别在于,前者不会在fakeroot上下文中被调用。

注意:使用fakeroot并不能成为实际root的绝对替代。fakeroot仅在内存中模拟伪造文件访问权限和类型(块或字符设备)和uid/gid。

9.5.6 设置文件权限和所有者及添加自定义设备节点

有时需要设置文件或设备节点的访问权限和所有者。例如,某些文件可能需要由root用户拥有。由于构建后脚本不是以root身份运行,因此除非在构建后脚本中显示使用fakeroot,否则无法进行此类修改。

对此,Buildroot提供了所谓的权限表支持。要启用此功能,需要设置BR2_ROOTFS_DEVICE_TABLE变量指向以空格分隔的权限表列表,权限表是遵循makedev语法的普通文本文件。

如果使用的是静态设备表(即不使用devtmpfs、mdev或(e)udev),则可以使用相同的语法在设备表中添加设备节点。要启用此功能,需要设置BR2_ROOTFS_STATIC_DEVICE_TABLE变量指向以空格分隔的设备表列表。

如第9.1节“推荐的目录结构”所述,此类文件推荐的存放位置是:board//。

需要注意的是,如果特定权限或设备节点与特定的应用程序相关,则需要在软件包的.mk文件中定义FOO_PERMISSIONS和FOO_DEVICES变量(参阅第17.5.2节“通用软件包参考”)。

9.6 添加自定义用户账号

有些时候需要在目标系统中添加特定用户。为了满足此需求,Buildroot提供了所谓的用户表支持。要启用此功能,需要设置BR2_ROOTFS_USERS_TABLES变量指向以空格分隔的用户表列表,这些表是遵循makeusers语法的常规文本文件。

如第9.1节“推荐的目录结构”所示,此类文件的推荐位置是:board//。

需要注意的是,如果自定义用户与特定的软件包相关,则应该在软件包的.mk文件中设置变量FOO_USERS(参阅第17.5.2节“通用软件包参考”)。

9.7 创建镜像后进行自定义

构建后脚本(post-build)在系统镜像、内核和引导程序镜像生成前运行,镜像后脚本(post-image)可以在生成所有镜像后执行某些特定操作。

例如,镜像后脚本可以用于提取根文件系统导出到NFS服务器指定位置,或者创建捆绑根文件系统和内核镜像的特殊固件镜像,或项目所需的任何其他自定义操作。

要启用此功能,需要设置BR2_ROOTFS_POST_IMAGE_SCRIPT(在System configuration菜单中)指向以空格分隔的镜像后脚本列表。如果指定相对路径,将相对于Buildroot根目录解析。

类似构建后脚本,镜像后脚本以Buildroot主目录树作为当前工作目录。镜像输出目录将作为第一个参数传递给每个脚本。如果BR2_ROOTFS_POST_SCRIPT_ARGS变量不为空,则这些参数也将传递给脚本。所有脚本都将传递相同的参数,不能将不同参数传递给不同脚本。

类似构建后脚本,这些脚本可以访问这些环境变量:BR2_CONFIG、HOST_DIR、STAGING_DIR、TARGET_DIR、BUILD_DIR、BINARIES_DIR和BASE_DIR。

镜像后脚本将以执行Buildroot的用户身份执行,该用户通常不应该是root用户。因此,这些脚本中任何需要root权限的操作都需要特殊处理(使用fakeroot或sudo),该处理留给脚本开发人员解决。

9.8 添加定制项目的补丁

有时将Buildroot提供的额外补丁程序应用于软件包很有用。例如,用于支持项目中的自定义功能,或者使用新的体系架构时。
BR2_GLOBAL_PATCH_DIR变量可用于指定一个或多个以空格分隔的补丁目录列表。

对于软件包的特定版本的补丁,可通过以下方式应用补丁:

  1. 对于BR2_GLOBAL_PATCH_DIR列出的每个目录,确定目录:
  • 如果/// 目录存在,则使用该目录;
  • 否则,如果/目录存在,则使用该目录
  1. 然后,通过以下方式应用补丁:
  • 如果补丁目录下存在series文件,则根据series应用补丁;
  • 否则,将按*.patch文件的字母顺序应用补丁文件。因此,为确保补丁按正确的顺序应用,强烈建议将补丁文件命名为:-.patch,其中指明了应用顺序。

有关如何应用补丁的信息,请参阅第18.2节“如何应用补丁”。

BR2_GLOBAL_PATCH_DIR选项是为软件包应用自定义补丁的首选方法,它可以用于为Buildroot中的任何软件包指定补丁程序目录。还可以使用它代替某些软件包(如U-Boot和BareBox)自定义的补丁程序目录。这样,它将允许用户从一个顶层目录统一管理其补丁程序。

使用BR2_GLOBAL_PATCH_DIR选项指定自定义补丁目录的例外是BR2_LINUX_KERNEL_PATCH。BR2_LINUX_KERNEL_PATCH用于通过URL指定内核补丁。注意,BR2_LINUX_KERNEL_PATCH指定的补丁在BR2_GLOBAL_PATCH_DIR指定的补丁应用之后应用,这是通过Linux软件包的补丁程序hook实现的。

9.9 添加定制项目的软件包

通常,任何新软件包都应该直接添加到package目录中,并提交到Buildroot项目组。第17章详细介绍了如何向Buildroot添加软件包,此处不再赘述。但是,你的项目可能需要一些无法提交到Buildroot项目组的软件包。本节将说明,如何将此类软件包保存到定制项目的目录中。

如第9.1节“推荐的目录结构”所述,针对特定项目的软件包的推荐存储位置是package//。如果使用外部目录树功能(参阅第9.2节“将定制保存在Buildroot目录树之外”),推荐的位置是外部树package子目录。

但是,除非执行一些其他步骤,否则Buildroot将无法识别此位置的软件包。如第17章“添加软件包”所述,Buildroot中的软件包基本上由两个文件组成:.mk文件(描述如何构建软件包)和Conifg.in文件(描述该软件包的配置选项)。

Buildroot将自动包含在package第一级子目录的.mk文件(使用package//.mk匹配模式)。如果希望Buildroot包含来自更深层次目录的.mk文件(例如package//package1/)的.mk文件,则只需在第一级子目录添加一个.mk文件,并在该.mk文件中包含子目录的.mk文件。因此,创建package//.mk文件,其内容如下(假设package//下只有一个额外的目录):

include $(sort $(wildcard package/<company>/*/*.mk))

对于Config.in文件,创建package//Config.in并包含所有软件包的Config.in文件。由于kconfig不支持通配符,因此必须提供详尽的文件列表。

source "package/<company>/package1/Config.in"
source "package/<company>/package2/Config.in"

然后,在package/Config.in中包含package//Config.in,最好将其包含在公司特定的菜单中,以使以后升级Buildroot版本更容易。

如果使用外部目录树,参阅第9.2节““将定制保存在Buildroot目录树之外”了解如何编写这些文件。

9.10 存储定制项目自定义配置的快速指南

在本章的前面,已经描述了进行定制项目的自定义配置的不同方法。本节将通过提供存储定制项目自定义配置的分步说明来总结这一切。显然,与定制项目无关的步骤可以跳过。

  • make menuconfig 配置工具链、软件包和内核。
  • make linux-menuconfig 更新内核配置,以及BusyBox、uClib等其他组件的配置。
  • mkdir -p board// 创建定制项目目标板文件夹。
  • 在board///.config中配置以下选项(如果需要):
    • 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
  • 编写配置文件:
    • make linux-update-defconfig
    • make busybox-update-config
    • make uclibc-update-config
    • cp /build/at91bootstrap3-*/.config board///at91bootstrap3.config
    • make barebox-update-defconfig
    • make uboot-update-defconfig
  • 创建board///rootfs-overlay/并填充所需的文件,例如board///rootfs-overlay/etc/inittab,设置BR2_ROOTFS_OVERLAY=board///rootfs-overlay。
  • 创建board///post_build.sh脚本,设置BR2_ROOTFS_POST_BUILD_SCRIPT=board///post_build.sh。
  • 如果必须设置setuid权限或创建设备节点,创建board///device_table.txt,并该路径添加到BR2_ROOTFS_DEVICE_TABLE。
  • 如果必须创建其他用户账户,创建board///users_table.txt,并将该路径添加到BR2_ROOTFS_USERS_TABLES。
  • 要将自定义补丁添加到某些软件包,设置BR2_GLOBAL_PATCH_DIR=board///patches/,并为每个需要添加补丁的软件包创建子目录。每个补丁应命名为--.patch。
  • 特别是针对Linux内核,还有一个选项BR2_LINUX_KERNEL_PATCH,其主要优点是它可以从指定URL下载补丁。如果不需要此功能,BR2_GLOBAL_PATCH_DIR则是首选。U-Boot、Barebox、at91bootstrap和at91bootstrap3也有单独的选项,但相比BR2_GLOBAL_PATCH_DIR没有任何优势,将来可能会被删除。
  • 如果需要添加定制软件包,创建package//并将软件包放在该目录下。创建一个.mk文件,其中包含了所有定制软件包的.mk文件。创建一个Config.in文件,其中包含了所有定制软件包的Config.in文件,然后将该Config.in文件包含到Buildroot的package/Config.in文件。
  • make savedefconfig 保存Buildroot配置。
  • cp defconfig configs/_defconfig。
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页