I.MX6ULL_Linux_系统篇(26) buildroot分析

发布于:2025-05-24 ⋅ 阅读:(9) ⋅ 点赞:(0)

关于 Buildroot

Buildroot 是一个工具, 它使用交叉编译, 可以简化和自动化为嵌入式系统构建一个完整 Linux 系统的过程。为了实现这一目标, Buildroot 能够为您的目标对象生成交叉编译工具链、 根文件系统、 Linux 内核镜像和 bootloader 引导加载程序。 Buildroot 可以独立应用于这些选项的任意组合(例如, 您可以使用现有的交叉编译工具链,通过 Buildroot 来单独构建根文件系统)。Buildroot 主要对使用嵌入式系统的用户有用。嵌入式系统通常使用的处理器并不是那些每个人在 PC 电脑上使用的常规 x86 处理器。它们可以是 PowerPC 处理器、 MIPS 处理器、 ARM处理器等。Buildroot 支持多种处理器及其变体; 它还为一些现成板子提供默认配置。除此之外,许多第三方的项目都是基于 Buildroot 或者在 Buildroot 之上开发其 BSP 或 SDK 。

系统要求

Buildroot 被设计为在 Linux 系统上运行。
尽管 Buildroot 会自行构建用于编译的大多数宿主机软件包,但一些标准 Linux 工具需要提前在宿主机系统上安装好。下面,您将看到强制软件包和可选软件包的概述(请注意,软件包名称在不同的发行版之间可能会有所不同)。

强制软件包

• 构建工具
- Which
- sed
- make (version 3.81 or any later)
- binutils
- build-essential (only for Debian based systems)
- gcc (version 4.8 or any later)
- g++ (version 4.8 or any later)
- bash
- patch
- gzip
- bzip2
- perl (version 5.8.7 or any later)
- tar
- cpio
- unzip
- rsync
- file (must be in /usr/bin/file)
- bc
• 源码获取工具
- wget

可选软件包

• 推荐的依赖项
Buildroot 中一些功能或实用程序(例如 legal-info 或图形生成工具)具有附加依赖项。尽管这对于简单的构建并不是必需的,但仍强烈建议安装:
- Python(2.7 或更高版本)
• 配置界面依赖项:
对于这些库,您需要同时安装 runtime 和 development 数据,在许多发行版中,这些是单独打包的。 development 软件包通常具有-dev 或-devel 后缀。
- ncurses5 使用 menuconfig 界面
- qt5 使用 xconfig 界面
- glib2, gtk2 和 glade2 使用 gconfig 界面
• 源码获取工具
在官方源码树中,大多数软件包源码是使用 wget 工具从 ftp、http 或 https 位置检索获取的。只有少数软件包是从版本控制系统获取。此外, Buildroot 能够通过其他工具下载源码, 例如 rsync 或 scp。如果使用其中任何一种方法启用软件包,则需要在宿主机系统上安装相应的工具:
- bazaar
- cvs
- git
- mercurial
- rsync
- scp
- subversion
• 与 Java 有关的软件包,如果需要为目标系统构建 Java Classpath:
- The javac compiler
- The jar tool
• 文档生成工具:
- asciidoc, version 8.6.3 or higher
- w3m
- python with the argparse module(automatically present in 2.7+ and 3.2+)
- dblatex (required for the pdf manual only)
• 图表生成工具:
- graphviz to use graph-depends and <pkg>-graph-depends
- python-matplotlib to use graph-build

获取 Buildroot

Buildroot 每 3 个月发布一次,分别在 2 月、 5 月、 8 月、 11 月发布。 发布版本号格式为 YYYY.MM,例如 2013.02、 2014.08。buildroot 源码包可以在 http://buildroot.org/downloads/获取。为了您的方便, 可以在 Buildroot 源码树的 support/misc/Vagrantfile 中找到工具 Vagrantfile,通过它来快速设置具有所需依赖关系的虚拟机,进行开始使用。如果要在 Linux 或 Mac Os X 上设置隔离的 buildroot 环境,请将此行粘贴到终端上:

curl -O https://buildroot.org/downloads/Vagrantfile; vagrant up

如果您使用的是 Windows,请将其粘贴到您的 Powershell 中:

(new-object System.Net.WebClient).DownloadFile(
"https://buildroot.org/downloads/Vagrantfile","Vagrantfile");
vagrant up

如果您想要关注 buildroot 开发, 则可以使用它的每日快照或克隆 Git 存储库。 可访问 Buildroot 网站查阅 Downloadpage 以获取更多详细信息。

Buildroot 快速入门

重要:您可以并且应该以普通用户身份来构建所有内容。 不需要使用 root 用户去配置和使用 Buildroot。以常规用户身份去运行所有命令, 能够保护系统免受在编译和安装过程中表现异常的软件包的侵害。使用 Buildroot 的第一步是创建配置。 Buildroot 有一个不错的配置工具,类似于您可以在 Linux 内核或在 BusyBox 找得到的配置工具。
在 buildroot 目录中,运行

$ make menuconfig

用于原始的 curses-based 的配置,或者运行

$ make nconfig

用于新的 curses-based 的配置,或者运行

$ make xconfig

用于 Qt-based 的配置,或者运行

$ make gconfig

用于 GTK-based 的配置。
所有这些“make” 命令都需要构建一个配置实用程序(包括界面),因此您可能需要为配置实用程序所使用的相关库安装“development” 软件包。特别是获取您所喜欢的界面的依赖项可选要求。
对于配置工具中的每个菜单条目,您都可以找得到描述条目用途的相关帮助。有关一些特定配置方面的详细信息,请参阅第 6 章。完成所有配置后,配置工具将生成一个包含全部配置的.config 文件。该文件将被顶级 Makefile 文件读取。要开始构建过程,只需运行:

$ make

默认情况下, Buildroot 不支持顶级并行构建,因此无需运行 make -jN。但是。
make 命令通常将执行以下步骤
• 下载源文件(根据需要);
• 配置,构建和安装交叉编译工具链,或者仅导入外部工具链;
• 配置,构建和安装选定的目标软件包;
• 构建内核镜像(如果选择);
• 构建引导加载程序镜像(如果选择);
• 以选定的格式创建一个根文件系统。

Buildroot 编译后的输出保存在单个目录 output/中。 该 output 目录下包含几个子目录:
• images/ 存储着所有镜像(包括内核镜像,引导加载程序和根文件系统镜像)。这些是您需要放在目标系统上的文件。
• build/ 构建所有组件(这包括 Buildroot 在宿主机上所需的工具以及为目标编译的软件包)。该目录包含着每个组件的一个子目录。
• host/ 包含为宿主机构建的工具, 以及目标工具链的 sysroot。前者是宿主机正确执行 Buildroot 时所需安装的工具,包括交叉编译工具链。 后者是一种类似于根文件系统层次结构的目录结构。它包含所有用户空间软件包的头文件和库,这些软件包可提供并安装由其他软件包使用的库。但是,该目录并不旨在成为目标的根文件系统:它包含许多开发文件、 未剥离的二进制文件和库,这些文件对于嵌入式系统而言太大了。这些开发文件用于为依赖于其他库的目标去编译库和应用程序。
• staging/ 是一个指向 host/中目标工具链 sysroot 的符号链接,为了向后兼容而存在。
• target/ 包含指定目标的几乎完整根文件系统:除了/dev/中的设备文件,所有需要的东西都存在(Buildroot 无法创建设备文件,因为 Buildroot 不能以 root 身份运行,也不想以 root 身份运行)。另外, 它没有正确的权限(例如 busybox 中的 setuid 权限)。因此,该 target 目录不应在您的目标上使用。相反,您应该使用 images/目录下编译生成的其中一个镜像。如果您需要提取根文件系统镜像来通过 NFS 进行引导,请使用 images/中生成的压缩包镜像并将其提取为 root。与 staging/相比, target/仅包含运行目标应用程序所需的文件和库:不存在开发文件(例如 headers 等等),剥离了二进制文件。

这些命令 make menuconfig | nconfig | gconfig | xconfig 和 make 是基本的命令,它们可以轻松、 快速地生成符合您需要的镜像, 并带有您启用的所有功能和应用程序。

社区资源

像任何开源项目一样, Buildroot 能够通过不同的方式在社区内部和外部来共享信息。

Buildroot 配置

make *config 中的所有配置选项都有一个帮助文本,它能够提供有关该选项的详细信息。
make *config 命令还提供了搜索工具。在不同的前台菜单中来查看帮助消息, 以了解如何使用它:
• 在 menuconfig 中, 按“/”调用搜索工具。
• 在 xconfig 中, 按 Ctrl+f 调用搜索工具。
搜索结果将显示匹配目标的帮助信息。在 menuconfig 中,左栏中的数字提供了相应条目的快捷方式。只需输入该数字即可直接跳转至该条目,或者在因缺少依赖而无法选择该条目的情况下跳转至包含该条目的菜单。尽管条目的菜单结构和帮助文本应该充分解释清楚自身,但一些主题难以在帮助文本中完全覆盖到, 而需要进行额外的说明,因此将在下面各节中对它们进行介绍。

交叉编译工具链

编译工具链是一组允许您为目标系统编译代码的工具。它由一个编译器(在我们环境下为gcc)、 二进制工具(比如汇编器和链接器, 在我们环境下为 binutils)以及一个 C 标准库(如 GNU Libc、 uClibc-ng)组成。安装在开发工作站上的系统肯定已有一个编译工具链,可用它来编译在系统上运行的应用程序。如果使用的是 PC,则该编译工具链可在 x86 处理器上运行,并为 x86 处理器生成代码。在大多数 Linux 系统中,编译工具链使用 GNU libc(glibc)作为 C 标准库。 这种编译工具链称为“宿主机编译工具链”。 工具链在上面运行并且您在其上工作的计算机称为“宿主机系统” 。编译工具链由您的发行版提供,而 Buildroot 与它无关(除了使用它来构建交叉编译工具链和在开发主机上运行的其他工具)。
如上所述,系统随附的编译工具链可在宿主机上运行并为宿主机系统中的处理器生成代码。由于您的嵌入式系统具有不同的处理器,因此您需要交叉编译工具链-一种能在您的主机系统上运行但为目标系统(和目标处理器)生成代码的编译工具链。 例如,如果您的主机系统使用 x86,而目标系统使用 ARM,则主机上的常规编译工具链是在 x86 上运行并为 x86 生成代码,而交叉编译工具链是在 x86 上运行并为 ARM 生成代码。
Buildroot 为交叉编译工具链提供两种解决方案:
• 内部工具链后端,在配置界面中调用“Buildroot toolchain”。
• 外部工具链后端,在配置界面中调用“External toolchain”。

可以在“Toolchain” 菜单下“Toolchain Type” 选项中进行这两种方案的选择。选择一种方案后,将出现许多配置选项,以下各节将详细介绍它们。

内部工具链后端

内部工具链后端是 Buildroot 在构建目标嵌入式系统用户应用程序和库之前,自行构建一个交叉编译工具链。该后端支持几个 C 库: uClibc-ng, glibc 和 musl。选择该后端后,将显示许多配置选项。其中最重要的是允许:
• 更改用于构建工具链的 Linux 内核头文件的版本。这个选项简要说明下。在构建交叉编译工具链的过程中, C 库也会被构建。该库提供了用户空间应用程序和 Linux 内核之间的接口。为了知道如何与 Linux 内核进行“对话”, C 库需要访问 Linux 内核头文件(即来自内核的.h 文件),这些头文件定义了用户空间和内核之间的接口(系统调用,数据结构等)。由于此接口是向后兼容的,因此用于构建工具链的 Linux 内核头文件的版本不需要与打算在目标嵌入式系统上运行的 Linux 内核的版本完全匹配。 它们只需与要运行的 Linux 内核具有相同或更低的版本即可。如果所使用的内核头文件比在嵌入式系统上运行的 Linux 内核的头文件更新,则 C 库可能正在使用 Linux 内核尚未提供的接口。
• 更改 GCC 编译器、 binutils 和 C 库三者的版本。
• 选择一些工具链选项(仅限 uClibc):工具链是否应该具有 RPC 支持(主要用于 NFS)、宽字符支持、 语言环境支持(用于国际化)、 C++支持或者线程支持。 根据您所选择的选项, Buildroot 菜单中可见的用户空间应用程序和库的数量将会发生变化:许多应用程序和库需要开启某些工具链选项。当需要指定某个工具链选项才能启用那些软件包时,大多数软件包会显示提示。如果需要, 您可以通过运行“make uclibc-menuconfig” 来进一步优化 uClibc 配置。 请注意,尽管已针对 Buildroot 中附带的 uClibc 默认配置所涉及的所有软件包进行了测试,但如果通过从 uClibc 中删除功能而使之偏离该默认配置,则某些软件包可能不再构建。值得注意的是,只要修改这些选项中的其中一个,就必须重新构建整个工具链和系统。
该后端的优点:
• 与 Buildroot 良好集成;
• 快速,只编译必要的;
此后端的缺点:
• 进行“make clean” 清理时需要重新构建工具链,这需要时间。如果您想减少构建时间,请考虑使用外部工具链后端。

外部工具链后端

外部工具链后端允许使用现有的预先构建好的交叉编译工具链。 Buildroot 集成许多著名的交叉编译工具链, 如 Linaro for ARM、 Sourcery CodeBenc for ARM、 x86-64、 PowerPC 和 MIPS,并且能够自动下载它们,也可以指定可供下载的或本地已安装的自定义工具链。然后,您有三种方法来使用外部工具链:
• 使用预定义的外部工具链配置文件,并让 Buildroot 下载、 提取和安装工具链。 Buildroot已经集成了一些 CodeSourcery 和 Linaro 工具链, 只需在“Toolchain” 可用选项中选择工具链配置文件。这绝对是最简单的解决方案。
• 使用预定义的外部工具链配置文件, 告诉 Buildroot 您的工具链在系统中的安装位置,而不是让 Buildroot 去下载并提取工具链。只需在“Toolchain” 可用选项中选择工具链配置文件,不需要选择“Download toolchain automatically”,然后在“Toolchain path” 文本条目中填入交叉编译工具链的路径即可。
• 使用完全自定义的外部工具链。这对于使用 crosstool-NG 或 Buildroot 本身生成的工具链特别有用。为此,请在“Toolchain”列表中选择“Custom toolchain” 条目。您需要填写“Toolchain path”、“Toolchain prefix” 和“External toolchain C library” 选项。然后,您必须告诉 Buildroot 您的外部工具链支持什么。如果您的外部工具链使用 glibc 库,则只需告诉 Buildroot 您工具链是否支持 C++,以及是否具有内置的 RPC 支持。如果您的外部工具链使用 uClibc 库,那么您必须告诉 Buildroot 它是否支持 RPC、宽字符、语言环境、程序调用、 线程和 C++。在执行开始时, 如果所选的选项与工具链配置不匹配,则 Buildroot 会告诉您。

我们外部工具链支持 CodeSourcery 和 Linaro 的工具链、 由 crosstool-NG 生成的工具链以及由 Buildroot 本身生成的工具链。通常来说,所有支持 sysroot 功能的工具链都应该正常工作。如果没有,请与 Buildroot 开发人员联系。我们不支持由 OpenEmbedded 或 Yocto 生成的工具链或 SDK,因为它们不是纯粹的工具链(即仅编译器、 binutils、 C 和 C++库)。相反,这些工具链带有大量预编译的库和程序。因此,Buildroot 不能导入这些工具链的 sysroot, 因为它将包含数百兆字节预编译库会被 Buildroot 正常构建。我们也不支持使用发行版工具链(例如发行版中安装的 gcc/binutils/C 库)作为工具链来构建目标软件。这是因为发行版工具链不是“纯”工具链(即仅使用 C/C++库),因此我们无法将其正确导入到 Buildroot 构建环境中。因此,即使您正在为 x86 或 x86_64 目标构建系统,您务必使用 Buildroot 或 crosstool-NG 来生成交叉编译工具链。如果您想为自己项目生成一个能够在 Buildroot 中用作外部工具链的自定义工具链,我们建议是使用 Buildroot 本身来构建或使用 crosstool-NG 来构建。
该后端的优点:
• 允许使用众所周知的并且经过充分测试的交叉编译工具链。
• 避免了交叉编译工具链的构建时间,这通常在嵌入式 Linux 系统的整体构建时间中非常重要。
该后端的缺点:
• 如果您预先构建的外部工具链存在 bug,则这可能很难从工具链供应商处获得修复,除非您自己使用 Buildroot 或 Crosstool-NG 来构建外部工具链。

使用 Buildroot 构建外部工具链

Buildroot 内部工具链选项可用于创建外部工具链。以下是构建一个内部工具链并将其打包以供 Buildroot 本身(或其他项目)重复使用的一系列步骤。使用以下详细信息来创建一个新的 Buildroot 配置:
• 为您的目标 CPU 架构选择适当的“Target options”;
• 在“Toolchain” 菜单中,“Toolchain type” 选项保留默认的“Buildroot toolchain”,并根据需要配置工具链;
• 在“System configuration” 菜单中, “Init system” 选项选择“None”,“/bin/sh” 选项选择“none”;
• 在“Target packages” 菜单中,禁用“BusyBox”;
• 在“Filesystem images” 菜单中,禁用“tar the root filesystem”;
然后,我们可以启动构建, 让 Buildroot 生成 SDK。以下命令将方便地为我们生成一个包含工具链的压缩包:

make sdk

这会在$(O)/images 目录下生成 SDK 压缩包,其名称类似于 arm-buildroot-linux-uclibcgnueabi_sdk-buildrot.tar.gz。 请保存此压缩包,因为您可以在其他 Buildroot 项目中将它用作外部工具链。在那些其他的 Buildroot 项目中, 需在“Toolchain”菜单中设置:
• 将“Toolchain type” 设置为“External toolchain”;
• 将“Toolchain” 设置为“Custom toolchain”;
• 将“Toolchain origin” 设置为“Toolchain to be downloaded and installed”;
• 将“Toolchain URL” 设置为“file:///path/to/your/sdk/tarball.tar.gz”。

外部工具链包装器
使用外部工具链时, Buildroot 会生成一个包装程序,该程序会将合适的选项设置(根据配置) 透传给外部工具链程序。如果您需要调试此包装器以检查传递了哪些参数,可以将环境变
量 BR2_DEBUG_WRAPPER 设置为以下任意一个:
• 0, 为空或未设置:无调试
• 1, 在单独一行上跟踪所有参数
• 2, 每行跟踪一个参数

/dev 管理

在 Linux 系统上, /dev 目录包含特殊文件, 即设备文件, 这些文件允许用户空间应用程序访问由 Linux 内核管理的硬件设备。没有这些设备文件,即使 Linux 内核正确识别了硬件设备,您的用户空间应用程序也将无法使用它们。在“System configuration”选项下的“/dev management”, Buildroot 提供了四种方式来处理/dev 目录:
• 第一种方式是“Static using device table”。这是 Linux 处理设备文件的传统方法。使用这种方法,设备文件会被持久存储在根文件系统中(即重新启动后它们仍然存在), 并且在系统添加或者移除硬件设备时, 不能自动创建和删除这些设备文件。因此, Buildroot 使用设备表来创建一组标准的设备文件,默认设备表存储在 Buildroot 源代码的 system/device_table_dev.txt 文件中。 Buildroot 在生成最终根文件系统镜像时才会处理该设备表文件,因此设备文件在 output/target 目录中不可见。 BR2_ROOTFS_STATIC_DEVICE_TABLE 选项允许更改 Buildroot 默认使用的设备表,或者添加其他设备表,以便 Buildroot 在构建过程中可以创建其他设备文件。 因此,如果您使用此方法,并且系统中缺少设备文件,则可以创建一个包含其他设备文件描述的 board/<yourcompany>/<yourproject>/device_table_dev.txt 文件,然后将 BR2_ROOTFS_STATIC_DEVICE_TABLE 设置为“system/device_table_dev.txtboard/<yourcompany>/<yourproject>/device_table_dev.txt”。
• 第二种方式是“Dynamic using devtmpfs only”。 devtmpfs 是 Linux 内核中的一个虚拟文件系统,已在内核 2.6.32 中引入(如果使用较旧的内核,则无法使用此选项)。在挂载到/dev 后,此虚拟文件系统将在系统添加或者移除硬件设备时自动使设备文件显示或消失。该文件系统在重新启动后并不持久:它是由内核动态填充的。使用 devtmpfs 时需要启用以下内核配置选项:
CONFIG_DEVTMPFS 和 CONFIG_DEVTMPFS_MOUNT。当 Buildroot 负责为您的嵌入式设备构建 Linux 内核时,请确保启用了这两个选项。但是如果您是在 Buildroot 之外构建 Linux 内核,则您有责任去启用这两个选项(如果不这么做,则 Buildroot 构建的系统将不会启动)。
• 第三种方式是“Dynamic using devtmpfs+mdev”。该方法依赖于上面介绍的 devtmpfs 虚拟文件系统(因此同样需要在内核配置中启用 CONFIG_DEVTMPFS 和 CONFIG_DEVTMPFS_MOUNT),但在上面添加了 mdev 用户空间程序。 mdev 是 BusyBox 里面的程序部分,每次添加或移除设备时,内核都会调用 mdev。由于使用/etc/mdev.conf 配置文件,因此 mdev 可以进行相关配置, 例如给设备文件设置特定的权限或所有权、 在设备出现或消失时调用脚本或应用程序等等。基本上,它允许用户空间对设备添加和删除事件做出反应。例如,当设备出现在系统上时, mdev 可用于自动加载内核模块。如果您的设备需要固件,则 mdev 也很重要,因为它会负责将固件内容推送到内核。 mdev 是 udev 的轻量级实现(功能较少)。 关于 mdev 及其配置文件语法的更多详细信息, 请参阅 http://git.busybox.net/busybox/tree/docs/mdev.txt。
• 第四种方式是“Dynamic using devtmpfs+eudev”。此方法同样依赖于上面介绍的 devtmpfs 虚拟文件系统, 但在上面添加了 eudev 用户空间守护程序。 eudev 是后台运行的守护程序,当系统添加或者移除设备时,内核将会调用它。与 mdev 相比,它是重量级的解决方案,但是具有更高的灵活性。 eudev 是 udev 的独立版本, udev 是大多数桌面 Linux 发行版中使用的原始用户空间守护程序,现已成为 Systemd 的一部分。 更多详细信息,请参阅 http://en.wikipedia.org/wiki/Udev。
Buildroot 开发人员建议是从“Dynamic using devtmpfs only”方式开始,直到您需要在添加或者删除设备时通知用户空间。如果需要固件, 则“Dynamic using devtmpfs+mdev” 通常是个不错的解决方案。请注意,如果选择 systemd 作为初始化系统,则/dev 管理将由 systemd 提供的 udev 程序执行。

初始化系统

init 程序是由内核启动的第一个用户空间程序(带有 PID 号 1),它负责启动用户空间服务和程序(例如: Web 服务器、图形应用程序、 其他网络服务器等)。Buildroot 允许使用三种不同类型的初始化系统,可以在“System configuration” 选项下的“Init system” 进行选择:
• 第一种是“BusyBox”。 BusyBox 实现了基本的 init 程序,对于大多数嵌入式系统而言,这已经足够了。启用“BR2_INIT_BUSYBOX” 将确保 BusyBox 会生成并安装其 init 程序。这是 Buildroot 的默认解决方案。 BusyBox init 程序会在启动时去读取/etc/inittab 文件,以了解需要处理的内容。 inittab 文件的语法介绍位于: http://git.busybox.net/busybox/tree/examples/inittab(请注意, BusyBox inittab 语法很特殊, 请勿使用 Internet 上随意的 inittab 文档来了解 BusyBox inittab)。 Buildroot 默认的 inittab 文件存储在 system/skeleton/etc/inittab。 除了挂载一些重要的文件系统之外,默认的 inittab 的主要工作是启动/etc/init.d/rcS shell 脚本,并启动一个 getty 程序(提供登录提示)。
• 第二种是“systemV”。该解决方案使用传统的 sysvinit 程序, 位于 Buildroot 目录 package/sysvinit, 这是大多数桌面 Linux 发行版使用的解决方案,直到它们被切换到更新的替代版本(例如 Upstart 或 Systemd)。 Sysvinit 同样使用 inittab 文件(其语法与 BusyBox 中的语法略有不同)。与此 init 解决方案一起安装的默认 inittab 位于 package/sysvinit/inittab。
• 第三种是“systemd”。 systemd 是用于 Linux 的新一代 init 系统。它的功能远远超过传统的 init 程序:强大的并行处理能力、 使用 socket 和 D-Bus 激活启动服务、按需启动守护程序、使用 Linux 控制组跟踪进程、 支持对系统状态进行快照和还原等等。 systemd 在相对复杂的嵌入式系统上很有用,例如需要 D-Bus 和服务之间相互通信的系统。值得注意的是 systemd 带来了大量的大型依赖项: dbus、 udev 等。有关 systemd 的更多详细信息,请参阅 http://www.freedesktop.org/wiki/Software/systemd。
Buildroot 开发人员推荐的解决方案是使用“BusyBox” 作为初始化系统,因为它对于大多数嵌入式系统来说已经够用了。“systemd” 可用于更复杂的情况。

其他组件的配置

在尝试修改下面任何组件之前,请确保您已经配置过 Buildroot 本身,并启用相应的软件包。
• BusyBox
如果您已经有一个 BusyBox 配置文件,则可以在 Buildroot 配置中使用“BR2_PACKAGE_BUSYBOX_CONFIG” 直接指定该文件。否则, Buildroot 将使用默认的 BusyBox 配置文件。 如果要对配置进行后续更改,请使用“make busybox-menuconfig” 打开 BusyBox 配置编辑器。也可以通过环境变量指定 BusyBox 配置文件,尽管不建议这样做。 
• uClibc
uClibc 的配置方式与 BusyBox 相同。用于指定现有配置文件的配置变量是 BR2_UCLIBC_CONFIG。进行后续更改的命令是“make uclibc-menuconfig”。
• Linux kernel
如果已经有了内核配置文件,则可以在 Buildroot 配置中使用“BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG” 变量直接指定该文件。如果还没有内核配置文件,则可以在 Buildroot 配置中使用“BR2_LINUX_KERNEL_USE_DEFCONFIG” 指定一个 defconfig 文件,或者创建一个空文件并使用“BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG” 将其指定为自定义配置文件。要对配置进行后续更改,请使用“make linux-menuconfig” 打开 Linux 配置编辑器。
• Barebox
Barebox 的配置方式与 Linux kernel 配置相同。相应的配置变量是“BR2_TARGET_BAREBOX_USE_CUSTOM_CONFIG” 和“BR2_TARGET_BAREBOX_USE_DEFCONFIG”。使用“make barebox-menuconfig” 打开配置编辑器。
• U-Boot
U-Boot(版本 2015.04 或更高版本)的配置方式与 Linux kernel 配置相同。相应的配置变量是“BR2_TARGET_UBOOT_USE_CUSTOM_CONFIG” 和“BR2_TARGET_UBOOT_USE_DEFCONFIG”。 使用“make uboot-menuconfig” 打开配置编辑器。

Buildroot 的一般用法

make 技巧

这是一系列技巧,可帮助您充分利用 Buildroot。
显示 make 执行的所有命令:

$ make V=1 <target>

显示带有 defconfig 的板级列表:

$ make list-defconfigs

显示所有可用的目标:

$ make help

并非所有目标都始终可用, “.config” 文件中的某些设置可能会隐藏一些目标:
• busybox-menuconfig 仅在启用 busybox 时有效;
• linux-menuconfig 和 linux-savedefconfig 仅在启用 linux 时有效;
• uclibc-menuconfig 仅在内部工具链后端选择 uClibc C 库时可用;
• beadbox-menuconfig 和 beardbox-savedefconfig 仅在启用 barebox 引导加载程序时有效;
• uboot-menuconfig 和 uboot-savedefconfig 仅在启用 U-Boot 引导加载程序时有效;
清理:当更改体系架构或工具链任何配置选项时,需要进行显式清理。要删除所有构建时
生成的产物(包括 build、 host、 staging and target trees、 images 和 toolchain):

$ make clean

生成手册:当前的手册位于 docs/manual 目录中。 要生成手册:

$ make manual-clean
$ make manual

将在 output/docs/manual 中生成手册。
请注意:
• 需要一些工具来构建文档。
为新目标重置 Buildroot: 删除所有构建时的产物以及相关配置:

$ make distclean

请注意, 如果启用了“ccache”,则运行“make clean” 或 distclean 不会清空 Buildroot 所使用的编译器缓存。
转储内部 make 变量:可以转储 make 已知的变量,以及它们的值:

$ make -s printvars VARS='VARIABLE1 VARIABLE2'
VARIABLE1=value_of_variable
VARIABLE2=value_of_variable

可以使用一些变量来调整输出:
• VARS, 会限制列表中的变量名称与指定的 make-patterns 相匹配, 必须设置此项,否则不会打印任何内容;
• QUOTED_VARS, 如果设置为 YES, 则将给变量值赋上单引号;
• RAW_VARS, 如果设置为 YES, 则将打印未扩展的值。
例如:

$ make -s printvars VARS=BUSYBOX_%DEPENDENCIES
BUSYBOX_DEPENDENCIES=skeleton toolchain
BUSYBOX_FINAL_ALL_DEPENDENCIES=skeleton toolchain
BUSYBOX_FINAL_DEPENDENCIES=skeleton toolchain
BUSYBOX_FINAL_PATCH_DEPENDENCIES=
BUSYBOX_RDEPENDENCIES=ncurses util-linux
$ make -s printvars VARS=BUSYBOX_%DEPENDENCIES QUOTED_VARS=YES
BUSYBOX_DEPENDENCIES='skeleton toolchain'
BUSYBOX_FINAL_ALL_DEPENDENCIES='skeleton toolchain'
BUSYBOX_FINAL_DEPENDENCIES='skeleton toolchain'
BUSYBOX_FINAL_PATCH_DEPENDENCIES=''
BUSYBOX_RDEPENDENCIES='ncurses util-linux'
$ make -s printvars VARS=BUSYBOX_%DEPENDENCIES RAW_VARS=YES
BUSYBOX_DEPENDENCIES=skeleton toolchain
BUSYBOX_FINAL_ALL_DEPENDENCIES=$(sort $(BUSYBOX_FINAL_DEPENDENCIES) $(BUSYBOX_FINAL_PATCH_DEPENDENCIES))
BUSYBOX_FINAL_DEPENDENCIES=$(sort $(BUSYBOX_DEPENDENCIES))
BUSYBOX_FINAL_PATCH_DEPENDENCIES=$(sort $(BUSYBOX_PATCH_DEPENDENCIES))
BUSYBOX_RDEPENDENCIES=ncurses util-linux

输出结果为带引号的变量可以在 shell 脚本中重复使用,例如:

$ eval $(make -s printvars VARS=BUSYBOX_DEPENDENCIES QUOTED_VARS=YES)
$ echo $BUSYBOX_DEPENDENCIES
skeleton toolchain

了解何时需要完全重新构建

当通过“make menuconfig”、“make xconfig” 或其他配置工具更改系统配置时, Buildroot不会尝试检测应重建系统的哪些部分。在某些情况下, Buildroot 应当重建整个系统, 而在某些情况下,仅应重建软件包的特定部分。 要以完全可靠的方式去检测是非常困难,因此 Buildroot开发人员已决定不尝试这样做。相反,用户有责任知道 Buildroot 何时需要完全重建。作为提示,以下有一些经验法则可以帮助您了解如何使用 Buildroot:
• 更改目标体系架构配置时,需要完全重建。例如,更改体系架构变体、 二进制格式或浮点策略等,这些更改会影响整个系统。
• 更改工具链配置时,通常需要完全重建。更改工具链配置通常涉及更改编译器版本、 C 库的类型或其配置、 其他一些基本配置项等,这些更改会影响整个系统。
• 在配置中新增软件包时,不一定需要完全重建。Buildroot 将检测到此软件包从未构建过,并对它进行构建。但是,如果此软件包是由已构建过的软件包可选择性使用的库时,则 Buildroot 将不会自动重建它们。 除非您知道应该重建哪些软件包,进而手动重建它们,否则应该进行完全重建。例如,假设您构建了一个具有 ctorrent 软件包的系统,但没有 openssl。 系统工作后,您意识到您想要 ctorrent 提供 SSL 支持,因此您在 Buildroot 配置中启用了 openssl 软件包并重新进行构建。 Buildroot 将检测到 openssl 应该被构建, 并进行构建,但是它不会检测到应该重新构建 ctorrent 以受益于 openssl 软件包来增加 OpenSSL 支持。您务必要进行完全重建,或者重建 ctorrent 本身。
• 从配置中删除软件包时, Buildroot 不会执行任何特殊操作。它不会从目标根文件系统或工具链 sysroot 中删除该软件包所安装的文件。需要完全重建才能移除此软件包。但是,通常您不必立即删除此软件包:您可以等待下一个午餐休息时间以从头开始构建。
• 更改软件包子选项时,不会自动重建软件包。进行此类更改后,仅重建该软件包通常就足够了,除非启用子选项后向该软件包中添加了一些对已构建的另一个软件包很有用的功能。同样, Buildroot 不会跟踪何时应该重新构建软件包:一旦构建了软件包,就不会对其进行重新构建,除非明确要求这样做。
• 更改根文件系统框架(skeleton) 时,需要完全重建。 但是,在更改根文件系统 overlay 层、post-buid 脚本或 post-image 脚本时,不需要完全重建:简单的 make 调用会将它们考虑在内。
• 重建或删除由“FOO_DEPENDENCIES” 列出的软件包时,软件包 foo 不会自动重建。例如, 如果软件包 bar 在“FOO_DEPENDENCIES” 中通过“FOO_DEPENDENCIES = bar”配置列出, 并且 bar 软件包的配置已更改,则该配置更改将不会引起软件包 foo 自动重建。在这种情况下,您可能需要重新构建在其“DEBENDENCIES”中引用 bar 的任何软件包,或者执行完全重建以确保任何依赖于 bar 的软件包都是最新的。(“DEBENDENCIES”是 Buildroot 用于指定各个软件包依赖关系的配置变量, 通常命名为 XXX_DEBENDENCIES)一般来说,当您遇到构建错误并且不确定所做的配置更改可能带来的后果时,请进行完全重建。如果您遇到相同的构建错误且确定该错误与软件包的部分重建无关,并且如果此错误发生在官方 Buildroot 的软件包中,请立即报告该问题! 随着您经验的增多,您将逐步了解何时才真正需要完全重建 Buildroot,并且可以节省越来越多的时间。作为参考,可以通过运行以下命令来进行完全重建: (以下命令是清除全部配置)

$ make clean all

了解如何重建软件包

Buildroot 用户提出的最常见问题之一是在未从头开始重新构建所有内容的情况下如何重建给定的软件包或如何删除软件包。Buildroot 在尚未从头开始重新构建的情况下不支持删除软件包。这是因为 Buildroot 无法跟踪哪个软件包在 output/staging 和 output/target 目录中安装了哪些文件,或者哪个软件包将根据另一个软件包的用途进行不同的编译。从头开始重建单个软件包的最简单方法是在 output/build 中删除其构建目录。然后, Buildroot 将从头开始重新提取、重新配置、 重新编译和重新安装此软件包。您可以要求 Buildroot 使用“make <package>-dirclean” 命令来执行此操作。
另一方面,如果您只想从 build 构建步骤重新启动软件包的构建过程,则可以运行“make<package>-rebuild”。它将重新启动软件包的编译和安装,但不会从头开始:它只是重新执行软件包内部的“make” 和“make install”,因此它仅重建已更改的文件。如果您想从 configuration 配置步骤重新启动软件包的构建过程,可以运行“make <package>-reconfigure”。它将重新启动软件包的配置、 编译和安装。虽然<package>-rebuild 包含<package>-reinstall, <package>-reconfigure 包含<package>-rebuild, 但这些命令以及<package>只作用于指定的软件包,并不会触发创建新的根文件系统镜像。如果有必要重新创建根文件系统,则应另外运行“make” 或“make all”。在内部, Buildroot 通过创建 stamp 文件来跟踪每个软件包完成了哪些构建步骤。 它们保存在软件包构建目录中,位于 output/build/<package>-<version>/,并命名为.stamp_<step-name>。上面详细介绍的命令仅仅操作这些 stamp 文件即可强制 Buildroot 来重新执行软件包构建过程中的特定步骤。

离线构建

如果您打算进行离线构建,只想下载之前在配置菜单(menuconfig, nconfig, xconfig 或 gconfig) 中选择过的所有源程序,则执行:

$ make source

此时您可以断开连接,或者可以将 dl 目录中的内容复制到执行构建的主机。

目录树外构建

默认情况下, Buildroot 构建后生成的所有内容都保存在 Buildroot 目录树的 output 目录中。Buildroot 还支持使用类似 Linux 内核中的语法, 从目录树外进行构建。要使用它,请将“O=<directory>” 添加到 make 命令行:

$ make O=/tmp/build
或者:
$ cd /tmp/build; make O=$PWD -C path/to/buildroot

所有输出的文件将位于/tmp/build 下。如果“O”指定的路径目录不存在,则 Buildroot 将创建它。
注意: “O” 指定的路径可以是绝对路径,也可以是相对路径,但如果是相对路径,则需要注意,它是相对于 Buildroot 的主目录而不是当前工作目录。使用目录树外构建时, Buildroot 的.config 文件和临时文件也保存在输出目录中(需执行“make menuconfig O=<directory>”)。这意味着只要指定唯一的输出目录,就可以在同一源码目录树下安全且并行地执行多个构建。为了易于使用, Buildroot 在输出目录中生成一个 Makefile 包装器。 因此,在第一次运行后,您不再需要传递 O=<...>和-C <...>,只需运行(在输出目录中):

$ make <target>

环境变量

Buildroot 支持一些环境变量,可传递给 make 或者用于设置环境:
• HOSTCXX, 宿主机 C++编译器需要使用;
• HOSTCC, 宿主机 C 编译器需要使用;
• UCLIBC_CONFIG_FILE=<path/to/.config>, 这是 uClibc 配置文件的路径,在构建内部工具链时用于编译 uClibc;注意,也可以通过 Buildroot .config 文件从配置界面设置 uClibc 配置文件; 这是建议的设置方式。
• BUSYBOX_CONFIG_FILE=<path/to/.config>, 这是 BusyBox 配置文件的路径;注意,也可以通过 Buildroot .config 文件从配置界面设置 BusyBox 配置文件; 这是建议的设置方式。
• BR2_CCACHE_DIR, 用于覆盖 Buildroot 在使用 ccache 时存储 cache 文件的目录;
• BR2_DL_DIR, 用于覆盖 Buildroot 存储/检索已下载文件的目录;请注意,也可以通过 Buildroot .config 文件从配置界面设置 Buildroot 下载目录。
• BR2_GRAPH_ALT,如果已设置且为非空值,则在 build-time 图表中使用交替颜色方案;
• BR2_GRAPH_OUT, 设置生成图表的文件类型,可以是 pdf(默认值)或 png;
• BR2_GRAPH_DEPS_OPTS, 将额外的选项传递给依赖关系图;
• BR2_GRAPH_DOT_OPTS, 作为选项逐个传递给 dot 程序以绘制依赖关系图;
• BR2_GRAPH_SIZE_OPTS 将额外的选项传递给 size 图;
使用位于顶层目录和$HOME 中的配置文件的示例:

$ make UCLIBC_CONFIG_FILE=uClibc.config BUSYBOX_CONFIG_FILE=$HOME/bb.config

如果要在主机上使用除了默认 gcc 或 g++以外的其他编译器来构建 helper-linaries,请执行:

$ make HOSTCXX=g++-4.3-HEAD HOSTCC=gcc-4.3-HEAD

有效处理文件系统镜像

文件系统镜像可能会变得非常大,具体取决于您所选择的文件系统、软件包数量以及是否配置可用空间…但是,文件系统镜像中的某些位置可能是空的(例如长时间为零);这样的文件
称为稀疏文件(原文为 sparse file)。大多数工具可以有效地处理稀疏文件,并且只会存储或写入稀疏文件中不为空的部分。例如:
• tar 接受-S 选项,以告诉它仅存储稀疏文件的非零块:
- tar cf archive.tar -S [files ...]将有效地将稀疏文件存储在压缩包中;
- tar xf archive.tar -S 将有效地从压缩包中提取稀疏文件;
• cp 接受--sparse=WHEN 选项(WHEN 可选 auto, never 或 always):
- cp --sparse=always source.file dest.file 如果 source.file 长时间为零, 则生成 dest.file 稀疏文件;其他工具可能具有类似的选项, 请查阅对应的手册页。
如果您需要存储文件系统镜像(例如从一台计算机传输到另一台计算机),或者需要将其发送出去(例如发送给 Q&A 团队),则可以使用稀疏文件。
但是请注意,当使用 dd 命令的稀疏模式来将文件系统镜像烧写到设备时, 可能会导致文件系统受损(例如, ext2 文件系统的块位图可能会受损;或者,如果文件系统中存在稀疏文件,则这部分有可能读回时不是全零)。您仅应在执行构建的计算机上处理文件时使用稀疏文件,而不是在将它们传输到目标实际设备时使用。

绘制软件包之间的依赖关系图

Buildroot 的工作之一就是了解软件包之间的依赖关系,并确保它们以正确的顺序构建。这些依赖关系有时可能相当复杂,对于给定的系统,通常不容易理解为什么 Buildroot 会将这样的软件包引入到构建过程。为了帮助理解依赖关系,从而更好地理解嵌入式 Linux 系统中不同组件的作用, Buildroot能够生成依赖关系图。要生成已编译过的整个系统的依赖关系图,只需运行:

make graph-depends

您可以在 output/graphs/graph-depends.pdf 中找到生成的关系图。
如果您的系统相当大,则依赖关系图可能过于复杂且难以阅读。因此,可以只为给定的软件包生成依赖关系图:

make <pkg>-graph-depends

您可以在 output/graph/<pkg>-graph-depends.pdf 中找到生成的关系图。
请注意,依赖关系图是使用 Graphviz 项目中的 dot 工具生成的,您必须已将其安装在系统上才能使用此功能。在大多数发行版中,可以通过“graphviz” 软件包获取。默认情况下,依赖关系图以 PDF 格式生成。但是,通过传递 BR2_GRAPH_OUT 环境变量,可以切换到其他输出格式,例如 PNG、 PostScript 或 SVG。支持 dot 工具中-T 选项支持的所有格式。

BR2_GRAPH_OUT=svg make graph-depends

可以通过 BR2_GRAPH_DEPS_OPTS 环境变量设置选项来控制“graph-depends” 的行为。
可接受的选项是:
• --depth N, -d N, 将依赖深度限制为 N 级别。默认值为 0,表示没有限制。
• --stop-on PKG, -s PKG, 结束软件包 PKG 的依赖绘图。 PKG 可以是实际的软件包名称、
全局名称、 关键字 virtual(虚拟软件包)或关键字 host(宿主机软件包)。该软件包依然存在于图上,但没有依赖关系。(译者注: 应用示例 BR2_GRAPH_DEPS_OPTS='--stop-on toolchain' m
ake graph-depends)
• --exclude PKG, -x PKG,如同--stop-on,但在关系图中将忽略 PKG。
• --transitive, --no-transitive,绘制(或不绘制)传递依赖关系。默认不绘制传递依赖关系。
• --colors R, T, H,以逗号分隔的颜色列表,用于绘制 root 软件包(R)、 target 软件包(T)和 host 软件包(H)。默认为: lightblue, grey, gainsboro。

BR2_GRAPH_DEPS_OPTS='-d 3 --no-transitive --colors=red,green,blue' make graph-depends

绘制构建持续时间图

当系统构建耗时很长时, 若能够了解哪些软件包构建耗时最长, 将有助于采取措施来加快构建速度。为了帮助进行此类构建时间分析, Buildroot 收集了每个软件包每个步骤的构建时间,并允许使用该数据来生成图表。要在构建后生成构建时间图,请运行:

make graph-build

这将在 output/graphs 中生成一系列文件:
• build.hist-build.pdf,每个软件包的构建时间直方图,按构建顺序排序;
• build.hist-duration.pdf,每个软件包的构建时间直方图,按持续时间排序(最长的一个);
• build.hist-name.pdf,每个软件包的构建时间直方图,按软件包名称排序;
• build.pie-packages.pdf,每个软件包的构建时间饼图;
• build.pie-steps.pdf, 软件包构建过程中每个步骤所耗费的全部时间的饼图。
该“graph-build” 目标需要安装 Python Matplotlib 和 Numpy 库(在大多数发行版中安装包为 python-matplotlib 和 python-numpy),如果您使用的 Python 版本早于 2.7,则还需要安装 argparse 模块(在大多数发行版中安装包为 python-argparse)。默认情况下,图表输出的格式为 PDF,但可以使用 BR2_GRAPH_OUT 环境变量来选择其他格式。支持的唯一其他格式是 PNG:

BR2_GRAPH_OUT=png make graph-build

绘制软件包对文件系统大小贡献图

当目标系统逐渐增大时,了解 Buildroot 每个软件包对整个根文件系统大小的贡献有时会很有用。为了帮助进行此类分析, Buildroot 收集有关每个软件包已安装文件的数据,并使用此数据生成图表和 CSV 文件, 以详细说明不同软件包的大小贡献。要在构建后生成这些数据,请运行:

make graph-size

这将生成:
• output/graphs/graph-size.pdf,每个软件包对整个根文件系统大小贡献的饼图;
• output/graphs/package-size-stats.csv, CSV 文件,每个软件包对整个根文件系统大小的贡献。
• output/graphs/file-size-stats.csv, CSV 文件,每个已安装文件对其所属软件包大小以及对整个文件系统大小的贡献。
此“graph-size” 目标需要安装 Python Matplotlib 库(在大多数发行版中安装包为 python-matplotlib), 如果您使用的 Python 版本早于 2.7,则还需要安装 argparse 模块(在大多数发行版中安装包为 python-argparse)。
就像持续时间图一样,支持使用 BR2_GRAPH_OUT 环境变量来调整输出文件格式。另外,可以设置环境变量 BR2_GRAPH_SIZE_OPTS 以进一步控制生成的图形。可接受的选项有:
• --size-limit X, -l X,会将单个贡献低于 X%的所有软件包分组到该图中标记为“Others” 的单个条目。默认情况下, X=0.01,这意味着每个贡献少于 1%的软件包都归类为“Others”。
• --iec, --binary, --si, --decimal,使用 IEC(二进制,幂为 1024)或 SI(十进制,幂为 1000;默认值)前缀。
• --biggest-first,按降序而不是升序对软件包大小进行排序。
请注意, 仅在完全清理之后重建,收集的文件系统大小数据才有意义。 在使用“make graph-size” 之前请务必运行“make clean all”。
要比较两个不同 Buildroot 编译的根文件系统大小,例如在调整配置后或切换到另一个 Buildroot 发布版本时,请使用 size-stats-compare 脚本。它需要两个 file-size-stats.csv 文件(由“make graph-size”生成)作为输入。有关更多详细信息,请参阅此脚本的帮助文本:utils/size-stats-compare -h

顶级并行构建

注意, 本节介绍一个具有实验性的功能,该功能在某些非常规情况下会被破坏。使用时风险自负。Buildroot 一直能够在每个软件包基础上使用并行构建:每个软件包都是由 Buildroot 使用 make -jN 进行构建(或者是 non-make-based 构建系统的等效调用)。默认情况下,并行级别为 CPU 数量+1,但可以使用 BR2_JLEVEL 配置选项进行调整。但是,直到 2020.02 为止, Buildroot 都是以串行方式构建软件包:每个软件包都是一个接一个构建的,而没有并行化软件包之间的构建。从 2020.02 开始, Buildroot 对顶级并行构建(top-level parallel build) 提供了实验性的支持,通过并行化构建不具有依赖关系的软件包,可以节省大量构建时间。但是, 该功能被标记为实验性功能,在某些情况下不起作用。
为了使用顶级并行构建,必须执行以下操作:
1. 在 Buildroot 配置中启用选项 BR2_PER_PACKAGE_DIRECTORIES;
2. 启动 Buildroot 构建时使用 make -jN;
在内部, BR2_PER_PACKAGE_DIRECTORIES 选项会启用一种称为“per-package directories” 的机制,这将产生以下影响:
• 代替所有软件包全局通用的“target” 目录和“host” 目录,将使用每个软件包各自的“target” 目录和“host” 目录,分别位于$(O)/per-package/<pkg>/target/和$(O)/per-package/<pkg>/host/。在<pkg>构建开始时,将从软件包依赖项的相应文件夹中获取文件来填充这些文件夹。因此,编译器和所有其他工具将只能查看和访问由<pkg>明确列出的依赖项安装的文件。
• 在构建结束时,将填充全局“target” 目录和“host” 目录,分别位于$(O)/target 和$(O)/host。这意味着在构建期间,这些文件夹将为空,并且仅在构建的最后才填充它们。

与 Eclipse 集成

部分嵌入式 Linux 开发人员喜爱使用 Vim 或 Emacs 等经典文本编辑器和基于命令行的界面,而多数其他嵌入式 Linux 开发人员则喜爱使用更丰富的图形界面来完成他们的开发工作。Eclipse 是最受欢迎的集成开发环境之一, Buildroot 与 Eclipse 集成在一起可以简化 Eclipse 用户的开发工作。与 Eclipse 的集成简化了(在 Buildroot 系统上构建的) 应用程序和库的编译、 远程执行和远程调试。 它不集成 Buildroot 配置,也不使用 Eclipse 构建自身的进程。因此,我们 Eclipse 集成的典型使用模型是:
• 使用“make menuconfig”,“make xconfig” 或 Buildroot 提供的任何其他配置界面来配置Buildroot 系统。
• 通过运行“make” 来构建 Buildroot 系统。
• 启动 Eclipse 以开发、 执行和调试您自己定制的应用程序和库,它们将依赖于由 Buildroot 所构建和安装的库。
有关 Buildroot Eclipse 集成安装过程和用法的详细信息,请查阅 https://github.com/mbats/eclipse-buildroot-bundle/wiki。

高级用法

在 Buildroot 外部使用生成的工具链

您可能想要针对自己的目标,编译自己的程序或者其他未打包在 Buildroot 中的软件。为此,您可以使用 Buildroot 生成的工具链。默认情况下, Buildroot 生成的工具链位于 output/host/中。最简单的使用方法是添加 output/host/bin 到 PATH 环境变量,然后使用 ARCH-linux-gcc, ARCH-linux-objdump, ARCH-linux-ld等。Buildroot 还可以通过运行“make sdk” 命令,将工具链和所有选定的软件包的开发文件导出为 SDK。这将利用宿主机目录 output/host/中的内容来生成名为<TARGET-TUPLE>_sdk-buildroot.tar.gz 的压缩包(前缀可以通过设置环境变量 BR2_SDK_PREFIX 进行覆盖),并输出到目录 output/images 中。然后,当他们要开发尚未打包为 Buildroot 软件包的应用程序时,可以将该工具链压缩包分发给应用程序开发人员。提取 SDK 压缩文件后,用户必须运行脚本 relocate-sdk.sh(位于 SDK 的顶层目录中),以确保使用新位置更新所有路径。另外,如果您只想准备 SDK 而又不生成压缩包(例如,您只是移动 host 目录,或者自己
生成压缩包),则 Buildroot 允许使用“make prepare-sdk” 命令准备 SDK 而不实际生成压缩包。

在 Buildroot 中使用 gdb

Buildroot 允许进行交叉调试,其中调试器在构建主机上运行,并与目标机器上的 gdbserver 进行通信, 以控制程序的执行。为了实现这个:
• 如果使用内部工具链(由 Buildroot 构建),则必须启用 BR2_PACKAGE_HOST_GDB、BR2_PACKAGE_GDB 和 BR2_PACKAGE_GDB_SERVER。这样可以确保交叉 gdb 和 gdbserver都已构建,并且将 gdbserver 安装至目标系统中。
• 如果使用外部工具链,则应启用 BR2_TOOLCHAIN_EXTERNAL_GDB_SERVER_COPY,它将把外部工具链附带的 gdbserver 复制到目标系统。如果您的外部工具链没有交叉 gdb 或gdbserver 程序,也可以通过启用与内部工具链后端(internal toolchain backend) 相同的选项,让 Buildroot 来构建它们。现在,要开始调试一个名为 foo 的程序,您应该在目标机器上运行:

gdbserver:2345 foo

这将引起 gdbserver 在 TCP 端口 2345 上侦听来自交叉 gdb 的连接。然后,在宿主机上应该启动交叉 gdb, 使用以下命令行:

<buildroot>/output/host/bin/<tuple>-gdb -x <buildroot>/output/staging/usr/share/buildroot/gdbinit foo

当然, foo 必须使用调试符号来进行构建,并且在当前目录中处于可用状态。通常,您是从构建 foo 的目录中启动此命令(而不是从 output/target/中启动,因为该目录中的二进制文件已被移除)。
<buildroot>/output/staging/usr/share/buildroot/gdbinit 文件将告诉交叉 gdb 在哪里找到目标的库。
最后, 通过交叉 gdb 连接到目标:

(gdb) target remote <target ip address>:2345

在 Buildroot 中使用 ccache

ccache 是编译器缓存。它存储每个编译过程所产生的目标文件,并能够通过使用预先存在的目标文件来跳过同一源文件(具有相同的编译器和相同的参数)的进一步编译。 当需要多次从头开始进行几乎相同的构建时, 这可以很好地加快构建过程。Buildroot 已经集成 ccache 支持。 您只需在“Build options”选项中启用“Enable compiler cache”即可。这将自动构建 ccache 并将其用于每个 host 和 target 的编译。缓存位于$HOME/.buildroot-ccache 中。它存储在 Buildroot 的 output 目录之外,以便可以由单独的 Buildroot 构建进行共享。如果要移除缓存,只需删除该目录。可以通过运行“make ccache-stats” 来获取有关缓存的统计信息(其大小、 命中数、 未命中数等)。
make 目标“ccache-options” 和 CCACHE_OPTIONS 变量提供对 ccache 更通用的访问。例如:

# set cache limit size
make CCACHE_OPTIONS="--max-size=5G" ccache-options
# zero statistics counters
make CCACHE_OPTIONS="--zero-stats" ccache-options

ccache 对源文件和编译器选项进行 hash 运算。如果编译器选项不同,则将不使用已缓存的目标文件。但是,许多编译器选项都包含 staging 目录的绝对路径。因此,在不同的输出目录中进行构建将导致许多缓存未命中。为避免此问题, buildroot 具有使用相对路径的“Use relative paths” 选项(BR2_CCACHE_USE_BASEDIR)。这会将所有指向输出目录内部的绝对路径重写为相对路径。因此,更改输出目录不会再导致缓存未命中。相对路径的一个缺点是它们最终还会成为目标文件中的相对路径。因此,除非您先“cd”到输出目录,否则调试器将不再找到该文件。

下载软件包的位置

Buildroot 下载的各种软件压缩包都存储在 BR2_DL_DIR 中,默认情况下为 dl 目录。如果要保留一个完整的 Buildroot 版本, 以便与相关的压缩包一起使用,则可以复制此目录。这将允许您使用完全相同的 Buildroot 版本重新生成工具链和目标文件系统。如果维护多个 Buildroot 源码树,则最好具有共享的下载位置。这可以通过将 BR2_DL_DIR 环境变量指向某个目录来实现。如果设置了该环境变量,则 Buildroot 配置中 BR2_DL_DIR 的值将被覆盖。应将以下行添加到<~/.bashrc>中。

export BR2_DL_DIR=<shared download location>

也可以使用 BR2_DL_DIR 选项在.config 文件中设置下载位置。与.config 文件中大多数选项不同, 该值会被 BR2_DL_DIR 环境变量覆盖。

软件包特定 make 目标

运行 make <package>将构建并安装该特定软件包及其依赖项。
对于依赖 Buildroot 基础结构的软件包,有许多特殊的 make 目标,可以像下面这样独立调用:

make <package>-<target>

软件包构建目标 target 是(按照它们执行的顺序):

命令/目标 描述
source 获取源码 (例如下载压缩包、克隆源码仓库等)
depends 构建软件包时构建和安装所有相关的依赖项
extract 将源码提取到软件包构建目录(例如提取压缩包,复制源码等)
patch 应用提供的补丁
configure 运行提供的配置命令
build 运行构建命令
install-staging target package: 如有必要,在 staging 目录中安装软件包
install-target target package: 如有必要,在 target 目录中安装软件包
install target package: 运行前面 2 条安装命令
host package: 在 host 目录中安装软件包

另外, 还有一些其他有用的 make 目标 target:

命令/目标 描述
show-depends 显示构建软件包所需的一级依赖项
show-recursive-depends 递归显示构建软件包的依赖项
show-rdepends 显示软件包的一级反向依赖项(例如, 软件包直接依赖它)
show-recursive-rdepends 递归显示软件包的反向依赖项(例如,软件包直接或间接依赖它)
graph-depends 在当前 Buildroot 上下文中生成软件包的依赖关系图。
graph-rdepends 生成该软件包的反向依赖关系图(例如,软件包直接或间接依赖它)
dirclean 删除整个软件包构建目录
reinstall 重新运行安装命令
rebuild 重新运行编译命令-仅在使用 OVERRIDE_SRCDIR 特性或在构建
目录中直接修改文件时起作用
reconfigure 重新运行配置命令,然后进行 rebuild-仅在使用 OVERRIDE_SRC
DIR 特性或在构建目录中直接修改文件时起作用

在开发期间使用 Buildroot

Buildroot 的正常操作是下载一个压缩包,对它进行解压缩,然后配置、 编译和安装该压缩包中的软件组件。源代码会被提取到 output/build/<package>-<version>中,这是一个临时目录:当使用“make clean” 时, 该目录将被完全删除,并在下一次 make 调用时重新创建。即使将 Git 或 Subversion 存储仓库用作软件包源代码的输入, Buildroot 也会给它创建一个压缩包,然后像对待正常压缩包那样进行工作。将 Buildroot 主要用作集成工具来构建和集成嵌入式 Linux 系统的所有组件, 是非常合适的。但是,如果是在系统某些组件的开发过程中使用 Buildroot, 则以下行为不是很方便:希望对一个软件包的源代码进行少量更改,并且能够使用 Buildroot 快速重建系统。直接在 output/build/<package>-<version>中进行修改是不合适的,因为在“make clean” 时会删除该目录。因此, Buildroot 针对此场景提供了一种特定的机制: <pkg>_OVERRIDE_SRCDIR 机制。 Buildroot 会读取 override 文件, 而该文件可以让用户告诉 Buildroot 某些软件包的源码位置。override 文件的默认位置是$(CONFIG_DIR)/local.mk,由 BR2_PACKAGE_OVERRIDE_FILE 配置选项定义。 $(CONFIG_DIR)是 Buildroot 中.config 文件的位置,因此默认情况下, local.mk 与.config 文件在同一个目录下,这意味着:
• 在目录树内构建的 Buildroot 源码顶级目录中(即不使用“O=” 时)
• 在目录树外构建的“O” 参数指定的目录中(即使用“O=” 时)
如果需要的位置与默认位置不同,则可以通过 BR2_PACKAGE_OVERRIDE_FILE 配置选项指定该位置。
在该 override 文件中, Buildroot 希望找到以下形式的参数行:

<pkg1>_OVERRIDE_SRCDIR = /path/to/pkg1/sources
<pkg2>_OVERRIDE_SRCDIR = /path/to/pkg2/sources

例如:

LINUX_OVERRIDE_SRCDIR = /home/bob/linux/
BUSYBOX_OVERRIDE_SRCDIR = /home/bob/busybox/

当 Buildroot 发现指定软件包已经定义了<pkg>_OVERRIDE_SRCDIR 时,它将不再尝试下载、 提取和修补软件包。 取而代之的是,它将直接使用指定目录中可用的源代码,并且使用“make clean” 时不会删除该目录。这允许将 Buildroot 指向您自己的目录,该目录可以由 Git、 Subversion 或任何其他版本控制系统进行管理。为此, Buildroot 将使用 rsync 命令将组件的源代码从指定的<pkg>_OVERRIDE_SRCDIR 复制到 output/build/<package>-custom/。此机制最好与 make <pkg>-rebuild 和 make <pkg>-reconfigure 目标结合使用。 make <pkg>-rebuild all 将使源代码从<pkg>_OVERRIDE_SRCDIR 同步到 output/build/<package>-custom(由于 rsync, 它仅复制修改过的文件),然后重新启动该软件包的构建过程。
在上述 linux 软件包示例中,开发人员可以在/home/bob/linux 中更改源代码,然后运行:

make linux-rebuild all

可以在几秒钟内在 output/images 中获取更新过的 Linux 内核镜像。同样, 可以在/home/bob/busybox 中对 BusyBox 源代码进行更改,然后运行:

make busybox-rebuild all

在 output/images 的根文件系统镜像中会包含更新过的 BusyBox。
大型项目的源码树中通常会包含成百上千个在构建过程中不需要的文件, 这些文件会减慢使用 rsync 复制源码的过程。可以选择性地定义<pkg>_OVERRIDE_SRCDIR_RSYNC_EXCLUSIONS 以跳过同步源码树中的某些文件。例如,当使用 webkitgtk 软件包时,以下内容将从本地WebKit 源码树中排除 tests 和 in-tree builds:

WEBKITGTK_OVERRIDE_SRCDIR = /home/bob/WebKit
WEBKITGTK_OVERRIDE_SRCDIR_RSYNC_EXCLUSIONS = \
--exclude JSTests --exclude ManualTests --exclude PerformanceTests \
--exclude WebDriverTests --exclude WebKitBuild --exclude WebKitLibraries \
--exclude WebKit.xcworkspace --exclude Websites --exclude Examples

默认情况下, Buildroot 会跳过 VCS 组件(例如.git 和.svn 目录)的同步。 而一些软件包更偏向于在构建过程中需要使用这些 VCS 目录,例如用于自动确定版本信息的准确提交引用。 如果要以较慢的速度作为代价来撤消此内置过滤, 则可以重新添加该目录:

LINUX_OVERRIDE_SRCDIR_RSYNC_EXCLUSIONS = --include .git

Buildroot 如何工作

如前面所述, Buildroot 基本上是一组 Makefile 文件,可以使用正确的选项来对所需软件进行下载、 配置和编译。它还包含各种软件包的补丁-主要是那些涉及交叉编译工具链(gcc、 binutils 和 uClibc) 的软件包。每个软件包基本上只有一个 Makefile 文件,它们以.mk 扩展名命名。 Makefile 被分为许多不同的部分。
• toolchain/目录包含与交叉编译工具链相关的所有软件的 Makefile 和相关文件: binutils、gcc、 gdb、 kernel-header 和 uClibc。
• arch/目录包含 Buildroot 支持的所有处理器体系架构的定义。
• package/目录包含所有用户空间工具和库(Buildroot 可以将它们编译并添加到目标根文件系统) 的 Makefile 和相关文件。每个软件包都有一个子目录。
• linux/目录包含 Linux 内核的 Makefile 和相关文件。
• boot/目录包含 Buildroot 支持的 Bootloader 的 Makefile 和相关文件。
• system/目录包含对系统集成的支持,例如目标文件系统框架 skeleton 和 init 系统的选择。
• fs/目录包含与生成目标根文件系统镜像有关的软件的 Makefile 和相关文件。
每个目录至少包含 2 个文件:
• something.mk 是用于下载、配置、 编译和安装软件包 something 的 Makefile。
• Config.in 是配置工具描述文件的一部分。它描述与软件包有关的选项。
主 Makefile 执行以下步骤(一旦配置完成):
• 创建所有输出目录: staging、 target、 build 等(默认在 output/目录中,可以使用“O=”来指定另一个路径)。
• 生成工具链目标。当使用内部工具链时,这意味着将生成交叉编译工具链。 当使用外部工具链时,这意味着将检查外部工具链的功能并将其导入到 Buildroot 环境。
• 生成 TARGETS 变量中列出的所有目标。 该变量由所有单个组件的 Makefile 填充。生成这些目标将触发用户空间软件包(库、 程序集)、内核、引导加载程序的编译以及根文件系统镜像的生成,具体取决于配置。

编码风格

总体而言,这些编码风格规则可以帮助您在 Buildroot 中添加新文件或者重构现有文件。如果您需要稍微修改现有的一些文件,那么保持整个文件的一致性是很重要的,因此您可以:
• 要么遵循此文件中使用的可能被弃用的编码风格;
• 要么完全重做, 以使其符合这些规则。

Config.in 文件

Config.in 文件包含 Buildroot 中几乎所有可配置的条目。
条目具有以下样式:

config BR2_PACKAGE_LIBFOO
    bool "libfoo"
    depends on BR2_PACKAGE_LIBBAZ
    select BR2_PACKAGE_LIBBAR
    help
        This is a comment that explains what libfoo is. The help text should be wrapped.
        http://foosoftware.org/libfoo/

• bool、 depends on、 select 和 help 均以一个制表符 tab 缩进(8 字符)。
• help 文本本身应缩进一个制表符 tab 和两个空格。
• help 文本应换行以适配 72 列,其中制表符为 8 个字符,因此文字本身为 62 个字符。
Config.in 文件是 Buildroot 所使用的配置工具(即常规 Kconfig) 的输入。有关 Kconfig 语言的更多详细信息,请参阅 http://kernel.org/doc/Documentation/kbuild/kconfig-language.txt。

 .mk 文件

• 标头: 该文件以标头起始。它包含模块名称,最好用小写字母,并包含在由 80 个“#”字符组成的分隔符之间。标头后必须有一行空白行:

################################################################################
# #
libfoo
#
################################################################################

• 赋值: 使用“=”, 前后加一空格:

LIBFOO_VERSION = 1.0
LIBFOO_CONF_OPTS += --without-python-support

不必将“=”对齐。
• 缩进:仅使用制表符 tab:

define LIBFOO_REMOVE_DOC
    $(RM) -fr $(TARGET_DIR)/usr/share/libfoo/doc \
        $(TARGET_DIR)/usr/share/man/man3/libfoo*
endef

注意, define 块内的命令应始终以制表符 tab 开头, make 才会识别它们为命令。
• 可选依赖项:
- 首选多行语法。

Yes:
ifeq ($(BR2_PACKAGE_PYTHON),y)
LIBFOO_CONF_OPTS += --with-python-support
LIBFOO_DEPENDENCIES += python
else
LIBFOO_CONF_OPTS += --without-python-support
endif

NO:
LIBFOO_CONF_OPTS += --with$(if $(BR2_PACKAGE_PYTHON),,out)-python-support
LIBFOO_DEPENDENCIES += $(if $(BR2_PACKAGE_PYTHON),python,)

- 保持配置选项和依赖项紧密。
• 可选钩子 hooks:将钩子变量定义和赋值放在一个 if 块中。

YES:
ifneq ($(BR2_LIBFOO_INSTALL_DATA),y)
define LIBFOO_REMOVE_DATA
$(RM) -fr $(TARGET_DIR)/usr/share/libfoo/data
endef
LIBFOO_POST_INSTALL_TARGET_HOOKS += LIBFOO_REMOVE_DATA
endif

NO:
define LIBFOO_REMOVE_DATA
$(RM) -fr $(TARGET_DIR)/usr/share/libfoo/data
endef
ifneq ($(BR2_LIBFOO_INSTALL_DATA),y)
LIBFOO_POST_INSTALL_TARGET_HOOKS += LIBFOO_REMOVE_DATA
endif

documentation 文档

documentation 文档使用 asciidoc 格式。有关 asciidoc 语法的更多信息,请参阅 http://www.methods.co.nz/asciidoc/userguide.html。

支持脚本

support/和 utils/目录中的一些脚本是用 Python 编写的, 它们应遵循“PEP8 Style Guide for Python Code”。

添加对特定硬件板的支持

Buildroot 包含了一些公开可用的硬件板的基本配置,因此该硬件板的用户可以很容易地构建一个可正常工作的系统。 欢迎您为 Buildroot 添加对其他硬件板的支持。为了做到这一点,您需要创建一个常规的 Buildroot 配置来为硬件建立一个基本系统:(内部)工具链、内核、引导加载程序、文件系统和一个简单的只有 BusyBox 的用户空间。不应选择特定的软件包:配置应尽可能少,并且应仅为目标平台构建可正常工作的BusyBox基本系统。当然,您可以为您的内部项目使用更复杂的配置,但 Buildroot 项目将仅集成基本的硬件板配置。这是因为软件包的选择是高度特定于应用程序的。一旦您有了一个已知的工作配置后,可运行“make savedefconfig”。这将在 Buildroot 根目录下生成一个最小的 defconfig 文件。 可将此文件移动到 configs/目录中,并将其重命名为<boardname>_defconfig。如果配置有些复杂, 则最好手动将它重新格式化并分成几个部分, 且在每部分前面添加对应的注释。 典型部分是 Architecture、 Toolchain options(通常只是 linux 标头版
本)、 Firmware、 Bootloader、 Kernel 和 Filesystem。对于不同的组件,请始终使用固定的版本或 commit 哈希值,而不是“latest” 版本。例如,设置“BR2_LINUX_KERNEL_CUSTOM_VERSION=y” 和设置 BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE 为您所测试的内核版本。建议尽量使用 Linux 内核和 bootloader 的上游版本,并尽量使用内核和 bootloader 的默认配置。如果它们不适用于您的硬件板或不存在默认值,我们支持您将修复程序发送到对应的上游项目。与此同时,您可能需要存储特定于目标平台的内核或引导加载程序的配置或补丁。为此,请创建目录 board/<manufacturer>和子目录 board/<manufacturer>/<boardname>。然后,您可以将补丁程序和配置存储在这些目录中,并从 Buildroot 主配置中引用它们。

有关更多详细资料,请查看官方最新手册:

Buildroot - Making Embedded Linux Easy


网站公告

今日签到

点亮在社区的每一天
去签到