Buildroot 用户手册 (中文)

文章目录

本文为译文,英文原文地址:The Buildroot user manual

I. Getting started

1. About Buildroot

Buildroot是一个工具,它使用交叉编译简化了为嵌入式系统构建完整Linux系统的过程,并实现了自动化。

为了实现这一点,Buildroot能够为您的目标生成交叉编译工具链( a cross-compilation toolchain)、根文件系统(a root filesystem)、Linux内核映像(a Linux kernel image)和引导加载程序(a bootloader)。Buildroot可以独立地用于这些选项的任何组合(例如,您可以使用现有的交叉编译工具链,只用Buildroot构建您的根文件系统)。

Buildroot主要适用于使用嵌入式系统的人。嵌入式系统通常使用的处理器不是每个人都习惯在个人电脑中使用的常规x86处理器。它们可以是PowerPC处理器,MIPS处理器,ARM处理器等。

Buildroot支持许多处理器及其变体;它还提供了几种现成电路板的默认配置。除此之外,很多第三方项目都是基于,或者在Buildroot之上开发他们的BSP[1]或SDK[2]。

2. System requirements

Buildroot设计用于在Linux系统上运行。

虽然Buildroot本身将构建它编译所需的大多数主机包,但某些标准的Linux实用程序预计已经安装在主机系统上。下面是强制包和可选包的概述(注意,不同发行版的包名称可能有所不同)。

2.1. Mandatory packages

以下是 Linux 环境上必须安装的程序:

// Build tools:
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

//Source fetching tools:
wget

2.2. Optional packages

以下是可选安装的程序:

  • Recommended dependencies:

Buildroot中的一些特性或实用程序,如the legal-infothe graph generation tools,有额外的依赖关系。尽管它们不是简单构建的强制要求,但仍然强烈推荐使用:

python (version 2.7 or any later)
  • Configuration interface dependencies:

对于这些库,您需要同时安装运行时数据和开发数据,在许多发行版中,这些数据是单独打包的。开发包通常有一个-dev-devel后缀。

ncurses5 to use the menuconfig interface
qt5 to use the xconfig interface
glib2, gtk2 and glade2 to use the gconfig interface
  • Source fetching tools:

在官方树中,大多数包源都是使用wgetftphttphttps位置检索的。少数软件包只能通过版本控制系统获得。此外,Buildroot还可以通过其他工具下载资源,如rsyncscp(参阅第20章,下载基础设施了解更多细节)。如果您使用以下任何一种方法启用包,您将需要在主机系统上安装相应的工具:

bazaar
cvs
git
mercurial
rsync
scp
subversion
  • Java-related packages, if the Java Classpath needs to be built for the target system:
The javac compiler
The jar tool
  • Documentation generation tools:
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)
  • Graph generation tools:
graphviz to use graph-depends and <pkg>-graph-depends
python-matplotlib to use graph-build

3. Getting Buildroot

Buildroot版本每3个月发布一次,分别是在2月、5月、8月和11月。版本号的格式为YYYY.MM,例如2013.02,2014.08。发布tarball可以在http://buildroot.org/downloads/上找到。

有两种方式可以搭建起 Buildroot 开发环境:

  • 1、Virtualbox 虚拟机

为方便起见,在Buildroot源代码树的support/misc/Vagrantfile中提供了一个Vagrantfile,用于快速设置一个虚拟机,其中包含启动所需的依赖项。

如果你想在Linux或Mac Os X上建立一个独立的构建根环境,请将这一行粘贴到你的终端上:

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
  • 2、手工下载

如果您想继续开发,可以使用日常快照或复制Git存储库。更多详细信息,请参考Buildroot网站的下载页面

4. Buildroot quick start

重要:你可以并且应该像普通用户一样构建一切。配置和使用Buildroot不需要是root。通过作为普通用户运行所有命令,可以保护系统免受包在编译和安装期间行为不正常的影响。

4.1 configuration

使用Buildroot的第一步是创建一个配置。Buildroot有一个很好的配置工具,类似于您可以在Linux内核或BusyBox中找到的那个。

From the buildroot directory, run

 $ make menuconfig

for the original curses-based configurator, or

 $ make nconfig

for the new curses-based configurator, or

 $ make xconfig

for the Qt-based configurator, or

 $ make gconfig

for the GTK-based configurator.

所有这些make命令都需要构建一个配置实用程序(包括接口),因此您可能需要为配置实用程序使用的相关库安装“开发”包。请参阅第2章 系统需求,以获得更多的细节,特别是可选的需求,以获得您喜欢的接口的依赖关系。

对于配置工具中的每个菜单项,您可以找到描述该项用途的相关帮助。关于一些具体配置方面的细节,请参阅第6章 Buildroot配置

一旦一切配置完成,配置工具将生成一个包含整个配置的.config文件。这个文件将由顶级Makefile读取。

4.2 build

要启动构建过程,只需运行:

 $ make

默认情况下,Buildroot不支持顶级并行构建,所以没有必要运行make -jN。不过,也有对顶层并行构建的实验性支持,请参见8.12节“顶层并行构建”

上述make命令一般执行如下步骤:

  • download source files (as required);// 下载源文件(根据需要);
  • configure, build and install the cross-compilation toolchain, or simply import an external toolchain;// 配置、构建和安装交叉编译工具链,或者简单地导入外部工具链;
  • configure, build and install selected target packages;// 配置、构建和安装选定的目标包;
  • build a kernel image, if selected;// 如果选择,构建一个内核映像;
  • build a bootloader image, if selected;// 如果选择,构建一个引导加载程序映像;
  • create a root filesystem in selected formats.// 以选定的格式创建根文件系统。

Buildroot输出存储在单个目录output/中。这个目录包含几个子目录:

  • images/ where all the images (kernel image, bootloader and root filesystem images) are stored. These are the files you need to put on your target system.
  • // 存储所有映像(内核映像、引导加载程序映像和根文件系统映像)的地方。这些是您需要放到目标系统中的文件。
  • build/ where all the components are built (this includes tools needed by Buildroot on the host and packages compiled for the target). This directory contains one subdirectory for each of these components. // 所有组件都是在这里构建的(这包括Buildroot在主机上需要的工具和为目标编译的包)。这个目录包含每个组件的一个子目录。
  • host/ contains both the tools built for the host, and the sysroot of the target toolchain. The former is an installation of tools compiled for the host that are needed for the proper execution of Buildroot, including the cross-compilation toolchain. The latter is a hierarchy similar to a root filesystem hierarchy. It contains the headers and libraries of all user-space packages that provide and install libraries used by other packages. However, this directory is not intended to be the root filesystem for the target: it contains a lot of development files, unstripped binaries and libraries that make it far too big for an embedded system. These development files are used to compile libraries and applications for the target that depend on other libraries.
  • // 包含为该主机构建的工具和目标工具链的sysroot。前者是为正确执行Buildroot所需的主机编译的工具的安装,包括交叉编译工具链。后者是类似于根文件系统层次结构的层次结构。它包含所有提供和安装其他包使用的库的用户空间包的头和库。但是,这个目录并不打算作为目标的根文件系统:它包含大量开发文件、未剥离的二进制文件和库,这使得它对于嵌入式系统来说太大了。这些开发文件用于为依赖于其他库的目标编译库和应用程序。
  • staging/ is a symlink to the target toolchain sysroot inside host/, which exists for backwards compatibility.
  • // 指向host/内部目标工具链sysroot的符号链接,它的存在是为了向后兼容。
  • target/ which contains almost the complete root filesystem for the target: everything needed is present except the device files in /dev/ (Buildroot can’t create them because Buildroot doesn’t run as root and doesn’t want to run as root). Also, it doesn’t have the correct permissions (e.g. setuid for the busybox binary). Therefore, this directory should not be used on your target. Instead, you should use one of the images built in the images/ directory. If you need an extracted image of the root filesystem for booting over NFS, then use the tarball image generated in images/ and extract it as root. Compared to staging/, target/ contains only the files and libraries needed to run the selected target applications: the development files (headers, etc.) are not present, the binaries are stripped.
  • // 几乎包含了目标的完整根文件系统:所有需要的东西都存在,除了/dev/中的设备文件(Buildroot不能创建它们,因为Buildroot不是作为root运行的,也不想作为root运行)。此外,它没有正确的权限(例如busybox二进制文件的setuid)。因此,不应该在目标上使用这个目录。相反,您应该使用images/目录中构建的映像。如果您需要根文件系统的解压映像以用于在NFS上引导,那么使用images/中生成的tarball映像并将其解压为根文件。与staging/相比,target/只包含运行所选目标应用程序所需的文件和库:开发文件(头文件等)不存在,二进制文件被剥离调试信息。

这些命令make menuconfig|nconfig|gconfig|xconfigmake是最基本的命令,它们允许您通过启用的所有特性和应用程序轻松快速地生成符合您需求的图像。

关于make命令使用的更多细节在8.1节“make tips”中给出。

5. Community resources

社区资源 (略)。

II. User guide

6. Buildroot configuration

make *config中的所有配置选项都有一个帮助文本,提供关于该选项的详细信息。

make *config命令也提供了一个搜索工具。阅读不同前端菜单中的帮助信息,了解如何使用它:

  • menuconfig中,搜索工具通过按/;
  • xconfig中,通过按Ctrl + f调用搜索工具。

搜索结果显示匹配项的帮助信息。在menuconfig中,左边列中的数字为相应的条目提供了快捷方式。只要输入这个数字就可以直接跳转到条目,或者跳转到包含的菜单(如果条目由于缺少依赖项而无法选择的话)。

尽管条目的菜单结构和帮助文本应该具有足够的自解释性,但有一些主题需要额外的解释,这些内容不容易在帮助文本中介绍,因此将在下面的部分中介绍。

6.1. Cross-compilation toolchain

编译工具链是一组允许您为系统编译代码的工具。它包括一个编译器(在我们的例子中是gcc)、汇编器和链接器之类的二进制utils(在我们的例子中是binutils)和一个C标准库(例如GNU Libc, uClibc-ng)。

安装在开发站上的系统肯定已经有一个编译工具链,您可以使用它编译在系统上运行的应用程序。如果您使用的是PC,那么编译工具链运行在x86处理器上,并为x86处理器生成代码。在大多数Linux系统下,编译工具链使用GNU libc (glibc)作为C标准库。这个编译工具链称为“宿主编译工具链”。运行它和您工作的机器称为“主机系统”[3]。

编译工具链由您的发行版提供,而Buildroot与它无关(除了使用它来构建交叉编译工具链和在开发主机上运行的其他工具)。

如上所述,系统附带的编译工具链运行在主机系统中的处理器上并为其生成代码。由于嵌入式系统具有不同的处理器,因此需要一个交叉编译工具链——一个运行在主机系统上但为目标系统(和目标处理器)生成代码的编译工具链。例如,如果您的主机系统使用x86,而目标系统使用ARM,那么主机上的常规编译工具链运行在x86上并生成针对x86的代码,而交叉编译工具链运行在x86上并生成针对ARM的代码。

Buildroot为交叉编译工具链提供了两种解决方案:

  • 内部工具链后端(Internal toolchain backend),在配置界面中称为Buildroot工具链(Buildroot toolchain)。
  • 外部工具链后端(External toolchain backend),在配置界面中称为外部工具链(External toolchain)。

使用Toolchain菜单中的Toolchain Type选项可以在这两个解决方案之间进行选择。一旦选择了一个解决方案,就会出现许多配置选项,以下部分将详细介绍这些选项。

6.1.1. Internal toolchain backend

在为目标嵌入式系统构建用户空间应用程序和库之前,内部工具链后端是Buildroot自己构建交叉编译工具链的后端。

这个后端支持几个C库:uClibc-ngglibcmusl

一旦您选择了这个后端,就会出现许多选项。最重要的是以下选项:

  • Change the version of the Linux kernel headers used to build the toolchain. This item deserves a few explanations. In the process of building a cross-compilation toolchain, the C library is being built. This library provides the interface between userspace applications and the Linux kernel. In order to know how to “talk” to the Linux kernel, the C library needs to have access to the Linux kernel headers (i.e. the .h files from the kernel), which define the interface between userspace and the kernel (system calls, data structures, etc.). Since this interface is backward compatible, the version of the Linux kernel headers used to build your toolchain do not need to match exactly the version of the Linux kernel you intend to run on your embedded system. They only need to have a version equal or older to the version of the Linux kernel you intend to run. If you use kernel headers that are more recent than the Linux kernel you run on your embedded system, then the C library might be using interfaces that are not provided by your Linux kernel.
  • // 更改用于构建工具链的Linux内核头文件的版本。这一项值得作一些解释。在构建交叉编译工具链的过程中,正在构建C库。这个库提供了用户空间应用程序和Linux内核之间的接口。为了知道如何与Linux内核“对话”,C库需要访问Linux内核的头文件(即来自内核的.h文件),它定义了用户空间和内核之间的接口(系统调用、数据结构等)。因为这个接口是向后兼容的,所以用于构建工具链的Linux内核头的版本不需要与您打算在嵌入式系统上运行的Linux内核的版本完全匹配。它们只需要一个与您要运行的Linux内核版本相同或更老的版本即可。如果您使用的内核头比您在嵌入式系统上运行的Linux内核更新,那么C库可能使用的接口不是由您的Linux内核提供的。
  • Change the version of the GCC compiler, binutils and the C library.
  • // 更改GCC编译器、binutils和C库的版本。
  • Select a number of toolchain options (uClibc only): whether the toolchain should have RPC support (used mainly for NFS), wide-char support, locale support (for internationalization), C++ support or thread support. Depending on which options you choose, the number of userspace applications and libraries visible in Buildroot menus will change: many applications and libraries require certain toolchain options to be enabled. Most packages show a comment when a certain toolchain option is required to be able to enable those packages. If needed, you can further refine the uClibc configuration by running make uclibc-menuconfig. Note however that all packages in Buildroot are tested against the default uClibc configuration bundled in Buildroot: if you deviate from this configuration by removing features from uClibc, some packages may no longer build.
  • // 选择一些工具链选项(仅限uClibc):工具链是否应该有RPC支持(主要用于NFS)、宽字符支持、区域支持(用于国际化)、c++支持或线程支持。根据您选择的选项,可见于Buildroot菜单中的用户空间应用程序和库的数量将会改变:许多应用程序和库需要启用某些工具链选项。当需要某个工具链选项来启用这些包时,大多数包都会显示注释。如果需要,您可以通过运行make uClibc -menuconfig来进一步优化uClibc配置。但是请注意,Buildroot中的所有包都是根据默认的uClibc配置进行测试的:如果你通过从uClibc中删除特性而偏离这个配置,一些包可能不再构建。

值得注意的是,每当其中一个选项被修改时,就必须重新构建整个工具链和系统。请参阅第8.2节 “了解什么时候需要进行完全重建”

这个后端的优点:

  • Well integrated with Buildroot // 与Buildroot集成良好
  • Fast, only builds what’s necessary // 快速,只构建必要的内容

这个后端的缺点:

  • Rebuilding the toolchain is needed when doing make clean, which takes time. If you’re trying to reduce your build time, consider using the External toolchain backend.
  • // 在做make clean时需要重建工具链,这需要时间。如果您试图减少构建时间,请考虑使用External工具链后端。

6.1.2. External toolchain backend

外部工具链后端允许使用现有的预构建的交叉编译工具链。Buildroot知道许多著名的交叉编译工具链(从Linaro for ARM、Sourcery CodeBench for ARM、x86-64、PowerPC和MIPS),并且能够自动下载它们,或者它可以指向一个定制的工具链,可以下载或在本地安装。

目前,你有三个解决方案来使用外部工具链:

  • Use a predefined external toolchain profile, and let Buildroot download, extract and install the toolchain. Buildroot already knows about a few CodeSourcery and Linaro toolchains. Just select the toolchain profile in Toolchain from the available ones. This is definitely the easiest solution.
  • // 使用预定义的外部工具链概要文件,并让Buildroot下载、提取和安装工具链。Buildroot已经知道一些CodeSourcery和Linaro工具链。只需在Toolchain中从可用的工具链概要文件中选择工具链概要文件。这绝对是最简单的解决方案。
  • Use a predefined external toolchain profile, but instead of having Buildroot download and extract the toolchain, you can tell Buildroot where your toolchain is already installed on your system. Just select the toolchain profile in Toolchain through the available ones, unselect Download toolchain automatically, and fill the Toolchain path text entry with the path to your cross-compiling toolchain.
  • // 使用一个预定义的外部工具链概要文件,但是不必让Buildroot下载和提取工具链,您可以告诉Buildroot您的工具链已经安装在系统的哪个位置。只需在Toolchain中选择工具链配置文件,取消选择自动下载工具链,并在Toolchain path文本条目中填写交叉编译工具链的路径。
  • Use a completely custom external toolchain. This is particularly useful for toolchains generated using crosstool-NG or with Buildroot itself. To do this, select the Custom toolchain solution in the Toolchain list. You need to fill the Toolchain path, Toolchain prefix and External toolchain C library options. Then, you have to tell Buildroot what your external toolchain supports. If your external toolchain uses the glibc library, you only have to tell whether your toolchain supports C++ or not and whether it has built-in RPC support. If your external toolchain uses the uClibc library, then you have to tell Buildroot if it supports RPC, wide-char, locale, program invocation, threads and C++. At the beginning of the execution, Buildroot will tell you if the selected options do not match the toolchain configuration.
  • // 使用完全自定义的外部工具链。这对于使用crosstool-NGBuildroot本身生成的工具链特别有用。为此,在Toolchain列表中选择Custom toolchain解决方案。您需要填充Toolchain pathToolchain prefixExternal toolchain C library选项。然后,你必须告诉Buildroot你的外部工具链支持什么。如果您的外部工具链使用glibc库,您只需告诉您的工具链是否支持c++,以及它是否有内置的RPC支持。如果您的外部工具链使用了uClibc库,那么您必须告诉Buildroot它是否支持RPC、宽字符、区域设置、程序调用、线程和c++。在执行的开始,Buildroot将告诉您所选择的选项是否与工具链配置不匹配。

我们的外部工具链支持已经通过来自CodeSourceryLinaro的工具链、由crosstool-NG生成的工具链和由Buildroot本身生成的工具链进行了测试。一般来说,所有支持sysroot特性的工具链都应该工作。如果没有,不要犹豫联系开发人员。

我们不支持openenembeddedYocto生成的工具链或SDK,因为这些工具链不是纯工具链(即编译器、binutils、C和c++库)。相反,这些工具链带有一组非常大的预编译库和程序。因此,Buildroot不能导入工具链的sysroot,因为它将包含数百兆字节的预编译库,而这些库通常是由Buildroot构建的。

我们也不支持使用发行版工具链(即由发行版安装的gcc/binutils/C库)作为构建目标软件的工具链。这是因为你的分发工具链不是一个“纯”的工具链(即只使用C/ c++库),所以我们不能正确地将它导入Buildroot构建环境中。因此,即使您正在为x86或x86_64目标构建系统,也必须使用Buildroot或crosstool-NG生成交叉编译工具链。

如果你想为你的项目生成一个自定义的工具链,可以在Buildroot中作为外部工具链使用,我们的建议是使用Buildroot本身(见6.1.3节“使用Buildroot构建一个外部工具链”)或者使用crosstool-NG

这个后端的优点:

  • Allows to use well-known and well-tested cross-compilation toolchains. // 允许使用众所周知和经过良好测试的交叉编译工具链。
  • Avoids the build time of the cross-compilation toolchain, which is often very significant in the overall build time of an embedded Linux system. // 避免交叉编译工具链的构建时间,这在嵌入式Linux系统的总体构建时间中通常非常重要。

这个后端的缺点:

  • If your pre-built external toolchain has a bug, may be hard to get a fix from the toolchain vendor, unless you build your external toolchain by yourself using Buildroot or Crosstool-NG.
  • // 如果你预构建的外部工具链有bug,可能很难从工具链供应商那里得到修复,除非你自己使用Buildroot或Crosstool-NG构建自己的外部工具链。

6.1.3. Build an external toolchain with Buildroot

Buildroot内部工具链选项可用于创建外部工具链。下面是构建内部工具链并将其打包以供Buildroot自身(或其他项目)重用的一系列步骤。

1、创建一个新的Buildroot配置,详细信息如下:

  • Select the appropriate Target options for your target CPU architecture
  • In the Toolchain menu, keep the default of Buildroot toolchain for Toolchain type, and configure your toolchain as desired
  • In the System configuration menu, select None as the Init system and none as /bin/sh
  • In the Target packages menu, disable BusyBox
  • In the Filesystem images menu, disable tar the root filesystem

2、然后,我们可以触发构建,并要求Buildroot生成一个SDK。这将方便地为我们生成一个包含工具链的tarball:

make sdk

这将在$(O)/images中生成SDK tarball,其名称类似于arm-buildroot-linux-uclibcgnueabi_sdk-buildroot.tar.gz。保存这个tarball,因为现在它是您可以在其他Buildroot项目中作为外部工具链重用的工具链。

3、在其他的Buildroot项目中,在Toolchain菜单中:

  • Set Toolchain type to External toolchain
  • Set Toolchain to Custom toolchain
  • Set Toolchain origin to Toolchain to be downloaded and installed
  • Set Toolchain URL to file:///path/to/your/sdk/tarball.tar.gz

6.1.4. External toolchain wrapper

当使用外部工具链时,Buildroot生成一个wrapper程序,该程序透明地将适当的选项(根据配置)传递给外部工具链程序。如果您需要调试这个wrapper来检查传递了哪些参数,您可以将环境变量BR2_DEBUG_WRAPPER设置为以下任意一个:

  • 0, empty or not set: no debug
  • 1: trace all arguments on a single line
  • 2: trace one argument per line

6.2. /dev management

在Linux系统中,/dev目录包含特殊的文件,称为设备文件(device files),允许用户空间应用程序访问Linux内核管理的硬件设备。如果没有这些设备文件,您的用户空间应用程序将不能使用硬件设备,即使它们被Linux内核正确识别。

System configuration,/dev management下,Buildroot提供了四种不同的解决方案来处理/dev目录:

  • The first solution is Static using device table. This is the old classical way of handling device files in Linux. With this method, the device files are persistently stored in the root filesystem (i.e. they persist across reboots), and there is nothing that will automatically create and remove those device files when hardware devices are added or removed from the system. Buildroot therefore creates a standard set of device files using a device table, the default one being stored in system/device_table_dev.txt in the Buildroot source code. This file is processed when Buildroot generates the final root filesystem image, and the device files are therefore not visible in the output/target directory. The BR2_ROOTFS_STATIC_DEVICE_TABLE option allows to change the default device table used by Buildroot, or to add an additional device table, so that additional device files are created by Buildroot during the build. So, if you use this method, and a device file is missing in your system, you can for example create a board/<yourcompany>/<yourproject>/device_table_dev.txt file that contains the description of your additional device files, and then you can set BR2_ROOTFS_STATIC_DEVICE_TABLE to system/device_table_dev.txt board/<yourcompany>/<yourproject>/device_table_dev.txt. For more details about the format of the device table file, see Chapter 25, Makedev syntax documentation.
  • // 第一个解决方案是静态使用设备表。这是Linux中处理设备文件的古老的经典方法。使用此方法,设备文件将持久化地存储在根文件系统中(即,它们在重新引导时持久化),当从系统中添加或删除硬件设备时,不会自动创建和删除这些设备文件。因此,Buildroot使用设备表创建一组标准的设备文件,默认的设备表存储在Buildroot源代码中的system/device_table_dev.txt中。这个文件在Buildroot生成最终的根文件系统映像时被处理,因此设备文件在输出/目标目录中是不可见的。BR2_ROOTFS_STATIC_DEVICE_TABLE选项允许更改Buildroot使用的默认设备表,或添加一个额外的设备表,以便Buildroot在构建期间创建额外的设备文件。所以,如果你使用这个方法,并且你的系统中缺少一个设备文件,例如,你可以创建一个board///device_table_dev.txt文件,其中包含你的附加设备文件的描述,然后你可以设置BR2_ROOTFS_STATIC_DEVICE_TABLEsystem/device_table_dev.txt board/<yourcompany>/<yourproject>/device_table_dev.txt。有关设备表文件格式的更多详细信息,请参见第25章Makedev语法文档。
  • The second solution is Dynamic using devtmpfs only. devtmpfs is a virtual filesystem inside the Linux kernel that has been introduced in kernel 2.6.32 (if you use an older kernel, it is not possible to use this option). When mounted in /dev, this virtual filesystem will automatically make device files appear and disappear as hardware devices are added and removed from the system. This filesystem is not persistent across reboots: it is filled dynamically by the kernel. Using devtmpfs requires the following kernel configuration options to be enabled: CONFIG_DEVTMPFS and CONFIG_DEVTMPFS_MOUNT. When Buildroot is in charge of building the Linux kernel for your embedded device, it makes sure that those two options are enabled. However, if you build your Linux kernel outside of Buildroot, then it is your responsibility to enable those two options (if you fail to do so, your Buildroot system will not boot).
  • // 第二个解决方案是仅使用devtmpfs动态。devtmpfs是内核2.6.32中引入的Linux内核中的一个虚拟文件系统(如果使用旧内核,则不可能使用此选项)。当挂载到/dev中时,这个虚拟文件系统将自动使设备文件随着硬件设备的添加和从系统中移除而出现和消失。这个文件系统在重新引导时不是持久的:它是由内核动态填充的。使用devtmpfs需要启用以下内核配置选项:CONFIG_DEVTMPFSCONFIG_DEVTMPFS_MOUNT。当Buildroot负责为您的嵌入式设备构建Linux内核时,它会确保启用这两个选项。但是,如果您在Buildroot之外构建Linux内核,那么您就有责任启用这两个选项(如果您没有这样做,那么您的Buildroot系统将无法引导)。
  • The third solution is Dynamic using devtmpfs + mdev. This method also relies on the devtmpfs virtual filesystem detailed above (so the requirement to have CONFIG_DEVTMPFS and CONFIG_DEVTMPFS_MOUNT enabled in the kernel configuration still apply), but adds the mdev userspace utility on top of it. mdev is a program part of BusyBox that the kernel will call every time a device is added or removed. Thanks to the /etc/mdev.conf configuration file, mdev can be configured to for example, set specific permissions or ownership on a device file, call a script or application whenever a device appears or disappear, etc. Basically, it allows userspace to react on device addition and removal events. mdev can for example be used to automatically load kernel modules when devices appear on the system. mdev is also important if you have devices that require a firmware, as it will be responsible for pushing the firmware contents to the kernel. mdev is a lightweight implementation (with fewer features) of udev. For more details about mdev and the syntax of its configuration file, see http://git.busybox.net/busybox/tree/docs/mdev.txt.
  • // 第三种解决方案是动态使用devtmpfs + mdev。这个方法还依赖于上面详细介绍的devtmpfs虚拟文件系统(因此在内核配置中启用CONFIG_DEVTMPFS和CONFIG_DEVTMPFS_MOUNT的要求仍然适用),但是在它上面添加了mdev用户空间实用程序。mdev是BusyBox的一个程序部分,每次添加或删除设备时内核都会调用它。由于/etc/mdev.conf配置文件,mdev可以配置为例如,设置特定的权限或对设备文件的所有权,每当设备出现或消失时调用脚本或应用程序,等等。基本上,它允许用户空间对设备添加和删除事件做出反应。例如,当设备出现在系统上时,可以使用Mdev自动加载内核模块。如果您有需要固件的设备,Mdev也很重要,因为它将负责将固件内容推送到内核。Mdev是udev的一个轻量级实现(具有更少的特性)。有关mdev及其配置文件语法的详细信息,请参见http://git.busybox.net/busybox/tree/docs/mdev.txt。
  • The fourth solution is Dynamic using devtmpfs + eudev. This method also relies on the devtmpfs virtual filesystem detailed above, but adds the eudev userspace daemon on top of it. eudev is a daemon that runs in the background, and gets called by the kernel when a device gets added or removed from the system. It is a more heavyweight solution than mdev, but provides higher flexibility. eudev is a standalone version of udev, the original userspace daemon used in most desktop Linux distributions, which is now part of Systemd. For more details, see http://en.wikipedia.org/wiki/Udev.
  • // 第四种解决方案是动态使用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作为init系统,/dev管理将由systemd提供的udev程序执行。

6.3. init system

init程序是由内核启动的第一个用户空间程序(它的PID号为1),负责启动用户空间服务和程序(例如:web服务器、图形应用程序、其他网络服务器等)。

Buildroot允许使用三种不同类型的初始化系统,可以从System configuration, Init system中选择:

  • The first solution is BusyBox. Amongst many programs, BusyBox has an implementation of a basic init program, which is sufficient for most embedded systems. Enabling the BR2_INIT_BUSYBOX will ensure BusyBox will build and install its init program. This is the default solution in Buildroot. The BusyBox init program will read the /etc/inittab file at boot to know what to do. The syntax of this file can be found in http://git.busybox.net/busybox/tree/examples/inittab (note that BusyBox inittab syntax is special: do not use a random inittab documentation from the Internet to learn about BusyBox inittab). The default inittab in Buildroot is stored in system/skeleton/etc/inittab. Apart from mounting a few important filesystems, the main job the default inittab does is to start the /etc/init.d/rcS shell script, and start a getty program (which provides a login prompt).
  • // 第一个解决方案是BusyBox。在许多程序中,BusyBox有一个基本的init程序的实现,这对于大多数嵌入式系统来说已经足够了。启用BR2_INIT_BUSYBOX将确保BusyBox将构建并安装它的init程序。这是Buildroot中的默认解决方案。BusyBox初始化程序将在启动时读取/etc/inittab文件,以知道要做什么。该文件的语法可以在http://git.busybox.net/busybox/tree/examples/inittab中找到(注意,BusyBox的inittab语法是特殊的:不要使用Internet上随机的inittab文档来了解BusyBox的inittab)。“Buildroot”默认的“inittab”存放在“system/skeleton/etc/inittab”中。除了挂载一些重要的文件系统外,默认的inittab所做的主要工作是启动/etc/init. confd/rcS shell脚本,并启动getty程序(提供登录提示)。
  • The second solution is systemV. This solution uses the old traditional sysvinit program, packed in Buildroot in package/sysvinit. This was the solution used in most desktop Linux distributions, until they switched to more recent alternatives such as Upstart or Systemd. sysvinit also works with an inittab file (which has a slightly different syntax than the one from BusyBox). The default inittab installed with this init solution is located in package/sysvinit/inittab.
  • // 第二个解决方案是systemV。这个解决方案使用旧的传统的sysvinit程序,打包在Buildroot中的package/sysvinit。这是在大多数桌面Linux发行版中使用的解决方案,直到他们转向更近期的替代方案,如Upstart或Systemd。sysvinit还可以使用inittab文件(与BusyBox中的文件语法略有不同)。与此init解决方案一起安装的默认inittab位于package/sysvinit/inittab中。
  • The third solution is systemd. systemd is the new generation init system for Linux. It does far more than traditional init programs: aggressive parallelization capabilities, uses socket and D-Bus activation for starting services, offers on-demand starting of daemons, keeps track of processes using Linux control groups, supports snapshotting and restoring of the system state, etc. systemd will be useful on relatively complex embedded systems, for example the ones requiring D-Bus and services communicating between each other. It is worth noting that systemd brings a fairly big number of large dependencies: dbus, udev and more. For more details about systemd, see http://www.freedesktop.org/wiki/Software/systemd.
  • // 第三个解决方案是系统化的。systemd是Linux系统的新一代init系统。它比传统的初始化程序做得更多:使用socket和D-Bus激活来启动服务,提供按需启动守护进程,使用Linux控制组跟踪进程,支持系统状态的快照和恢复等。systemd在相对复杂的嵌入式系统上非常有用。例如需要D-Bus和服务相互通信的。值得注意的是,systemd带来了相当多的大型依赖:dbus, udev等等。有关systemd的更多信息,请参见http://www.freedesktop.org/wiki/Software/systemd。

Buildroot开发人员推荐的解决方案是使用BusyBox init,因为它对于大多数嵌入式系统来说已经足够了。Systemd可以用于更复杂的情况。

7. Configuration of other components

在尝试修改下面的任何组件之前,请确保您已经配置了Buildroot本身,并启用了相应的包。

  • BusyBox

如果您已经有一个BusyBox配置文件,您可以直接在Buildroot配置中指定这个文件,使用BR2_PACKAGE_BUSYBOX_CONFIG。否则,Buildroot将从默认的BusyBox配置文件启动。

要对配置进行后续更改,请使用make busybox-menuconfig打开BusyBox配置编辑器。

还可以通过环境变量指定BusyBox配置文件,不过不建议这样做。请参阅8.6节“环境变量”了解更多细节。

  • uClibc

uClibc的配置方法与BusyBox相同。指定现有配置文件的配置变量是BR2_UCLIBC_CONFIG。进行后续更改的命令是make uclibc-menuconfig

  • Linux kernel

如果您已经有了一个内核配置文件,那么可以使用BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG在Buildroot配置中直接指定这个文件。

如果您还没有内核配置文件,那么您可以使用BR2_LINUX_KERNEL_USE_DEFCONFIG在Buildroot配置中指定defconfig,或者使用BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG创建一个空文件并将其指定为自定义配置文件。

要对配置进行后续更改,请使用make Linux-menuconfig打开Linux配置编辑器。

  • Barebox

Barebox的配置方法与Linux内核的配置方法相同。对应的配置变量是BR2_TARGET_BAREBOX_USE_CUSTOM_CONFIGBR2_TARGET_BAREBOX_USE_DEFCONFIG。要打开配置编辑器,请使用make barebox-menuconfig

  • U-Boot

U-Boot(2015.04及以上版本)的配置方法与Linux内核相同。对应的配置变量是BR2_TARGET_UBOOT_USE_CUSTOM_CONFIGBR2_TARGET_UBOOT_USE_DEFCONFIG。打开配置编辑器,使用make uboot-menuconfig

8. General Buildroot usage

8.1. make tips

这是一组技巧,可以帮助你充分利用Buildroot。

  • Display all commands executed by make:
 $ make V=1 <target>
  • Display the list of boards with a defconfig:
 $ make list-defconfigs
  • Display all available targets:
 $ make help

并不是所有的目标都是可用的,.config文件中的一些设置可能会隐藏一些目标:

busybox-menuconfig only works when busybox is enabled;
linux-menuconfig and linux-savedefconfig only work when linux is enabled;
uclibc-menuconfig is only available when the uClibc C library is selected in the internal toolchain backend;
barebox-menuconfig and barebox-savedefconfig only work when the barebox bootloader is enabled.
uboot-menuconfig and uboot-savedefconfig only work when the U-Boot bootloader is enabled.

  • Cleaning`: Explicit cleaning is required when any of the architecture or toolchain configuration options are changed. // 当任何架构或工具链配置选项发生更改时,需要显式清理。

To delete all build products (including build directories, host, staging and target trees, the images and the toolchain)😕/ 删除所有构建产品(包括构建目录、主机、暂存和目标树、映像和工具链):

 $ make clean
  • Generating the manual: The present manual sources are located in the docs/manual directory. To generate the manual:
 $ make manual-clean
 $ make manual
  • Resetting Buildroot for a new target: To delete all build products as well as the configuration:
 $ make distclean

如果启用了ccache,运行make clean或distclean不会清空Buildroot使用的编译器缓存。要删除它,请参考8.14.3节“在Buildroot中使用ccache”

  • Dumping the internal make variables: 可以dump已知的make变量及其值:
 $ make -s printvars VARS='VARIABLE1 VARIABLE2'
 VARIABLE1=value_of_variable
 VARIABLE2=value_of_variable

可以使用一些变量来调整输出:

VARS will limit the listing to variables which names match the specified make-patterns - this must be set else nothing is printed // 将列表限制为名称与指定make-patterns匹配的变量—这必须设置,否则不打印任何内容
QUOTED_VARS, if set to YES, will single-quote the value // 如果设置为YES,将单引号引用该值
RAW_VARS, if set to YES, will print the unexpanded value // 如果设置为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

8.2. Understanding when a full rebuild is necessary

当通过make menuconfig、make xconfig或其他配置工具改变系统配置时,Buildroot不会试图检测应该重新构建系统的哪些部分。在某些情况下,Buildroot应该重建整个系统,在某些情况下,只重建软件包的特定子集。但是以一种完全可靠的方式检测它是非常困难的,因此Buildroot开发人员决定不尝试这样做。

相反,用户有责任知道什么时候需要进行完全重新构建。作为提示,这里有一些经验法则可以帮助你理解如何使用Buildroot:

  • 当目标体系结构配置发生更改时,需要进行完整的重新构建。改变架构变体(例如二进制格式或浮点策略)会对整个系统产生影响。
  • 当工具链配置发生更改时,通常需要进行一次完整的重新构建。更改工具链配置通常涉及更改编译器版本、C库的类型或其配置,或其他一些基本配置项,这些更改会对整个系统产生影响。
  • 当向配置中添加额外的包时,并不一定需要完全重新构建。Buildroot将检测到这个包从未被构建过,并将其构建。但是,如果这个包是一个可以被已经构建的包使用的库,那么Buildroot将不会自动重新构建这些库。您可以知道应该重新构建哪些包,并且可以手动重新构建它们,也可以进行完整的重新构建。例如,假设您已经构建了一个使用crbt包但不使用openssl的系统。您的系统可以工作,但是您意识到您希望在crbt中有SSL支持,所以您在Buildroot配置中启用openssl包并重新启动构建。Buildroot将检测是否应该构建openssl并将其构建,但它不会检测是否应该重新构建crbt以从openssl中获益以添加对openssl的支持。您将不得不做一个完全重建,或重建ctorrent本身。
  • 当从配置中删除一个包时,Buildroot不会做任何特殊的事情。它不会从目标根文件系统或工具链sysroot中删除该包安装的文件。要摆脱这个包,需要一个完整的重建。但是,通常您不需要立即删除这个包:您可以等到下一次午休时间重新开始构建。
  • 当包的子选项发生更改时,不会自动重新生成包。在做了这些更改之后,通常只重新构建这个包就足够了,除非启用包子选项将一些对已经构建的另一个包有用的特性添加到包中。同样,Buildroot不会跟踪什么时候应该重新构建包:一旦构建了一个包,它就永远不会重新构建,除非明确地告诉它这样做。
  • 当对根文件系统框架进行更改时,需要进行一次完整的重新构建。但是,当对根文件系统覆盖层、构建后脚本或图像后脚本进行更改时,就不需要进行完全的重新构建:一个简单的make调用将考虑这些更改。
  • 当在FOO_DEPENDENCIES中列出的包被重新构建或删除时,包foo不会自动重新构建。例如,如果在带有FOO_DEPENDENCIES = bar的FOO_DEPENDENCIES中列出了一个包bar,并且bar包的配置发生了改变,那么配置的改变不会自动导致foo包的重新构建。在这个场景中,您可能需要重新构建构建中引用bar中的DEPENDENCIES中的任何包,或者执行完整的重新构建以确保任何bar依赖的包都是最新的。

一般来说,当您面临构建错误并且不确定所做的配置更改的潜在后果时,请执行完整的重新构建。如果您得到相同的构建错误,那么您可以肯定这个错误与包的部分重构无关,如果这个错误发生在来自官方Buildroot的包上,请不要犹豫报告这个问题!随着您使用Buildroot的经验的积累,您将逐步了解什么时候真正需要一个完整的重建,您将节省越来越多的时间。

作为参考,完全重建可以通过运行:

$ make clean all

8.3. Understanding how to rebuild packages

Buildroot用户最常问的问题之一是如何重新构建给定的包,或者如何在不重新构建所有内容的情况下删除包。

如果不从头重新构建,Buildroot不支持删除包。这是因为Buildroot没有跟踪哪个包在output/staging目录和output/target目录中安装了什么文件,或者哪个包会根据另一个包的可用性进行不同的编译。

从头重新构建单个包的最简单方法是删除output/build中的构建目录。然后,Buildroot将重新提取、重新配置、重新编译和重新安装这个包。你可以通过make <package>-dirclean命令要求buildroot这样做。

另一方面,如果只希望从编译步骤重新启动包的构建过程,可以运行make <package>-rebuild。它将重新启动包的编译和安装,但不是从头开始:它基本上会在包内重新执行makemake install,因此它只会重新构建更改过的文件。

如果您想从配置步骤重新启动包的构建过程,可以运行make <package>-reconfigure。它将重新启动包的配置、编译和安装。

虽然<package>-rebuild意味着<package>-reinstall<package>-reconfigure意味着<package>-rebuild,但是这些目标以及只对上述<package>起作用,并且不会触发重新创建根文件系统映像。如果需要重新创建根文件系统,还应该运行makemake all

在内部,Buildroot创建所谓的戳文件(stamp files),以跟踪每个包的哪些构建步骤已经完成。它们存储在包构建目录output/build/<package>-<version>/中,命名为.stamp_<step-name>。上面详细介绍的命令只是操作这些戳文件,以强制Buildroot重新启动包构建过程的一组特定步骤。

关于包装特殊制造目标的进一步细节在8.14.5节“特定于包装的制造目标”中解释。

8.4. Offline builds

如果你打算进行离线构建,并且只是想下载你之前在配置器(menuconfig, nconfig, xconfig或gconfig)中选择的所有源代码,那么发出:

 $ make source

现在可以断开dl目录的内容或将其复制到构建主机中。

8.5. Building out-of-tree

默认情况下,Buildroot构建的所有内容都存储在Buildroot树的输出目录中。

Buildroot还支持用类似于Linux内核的语法从树外构建。要使用它,请在make命令行中添加O=<directory>:

 $ make O=/tmp/build

or

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

所有输出文件将位于/tmp/build目录下。如果O路径不存在,Buildroot将创建它。

注意:O路径可以是绝对路径,也可以是相对路径,但如果它作为相对路径传递,需要注意的是,它是相对于Buildroot主源目录解释的,而不是当前工作目录。

当使用树外构建时,Buildroot .config和临时文件也存储在输出目录中。这意味着您可以使用相同的源代码树安全地并行运行多个构建,只要它们使用唯一的输出目录。

为了便于使用,Buildroot在输出目录中生成了一个Makefile包装器-所以在第一次运行之后,你不再需要传递O=<…> and-C <…>,只需运行(在输出目录中):

 $ make <target>

8.6. Environment variables

Buildroot也遵循一些环境变量,当它们被传递到环境中makeset时:

  • HOSTCXX, the host C++ compiler to use // 主机c++编译器
  • HOSTCC, the host C compiler to use // 主机c编译器
  • UCLIBC_CONFIG_FILE=<path/to/.config>, path to the uClibc configuration file, used to compile uClibc, if an internal toolchain is being built. Note that the uClibc configuration file can also be set from the configuration interface, so through the Buildroot .config file; this is the recommended way of setting it.
  • // uClibc配置文件的路径,用于编译uClibc,如果一个内部工具链正在构建。请注意,uClibc配置文件也可以从配置界面设置,所以可以通过Buildroot .config文件;这是推荐的设置方法。
  • BUSYBOX_CONFIG_FILE=<path/to/.config>, path to the BusyBox configuration file. Note that the BusyBox configuration file can also be set from the configuration interface, so through the Buildroot .config file; this is the recommended way of setting it.
  • // BusyBox配置文件的路径。注意,BusyBox配置文件也可以从配置界面设置,所以可以通过Buildroot .config文件;这是推荐的设置方法。
  • BR2_CCACHE_DIR to override the directory where Buildroot stores the cached files when using ccache. // 来覆盖Buildroot在使用ccache时存储缓存文件的目录。
  • BR2_DL_DIR to override the directory in which Buildroot stores/retrieves downloaded files. Note that the Buildroot download directory can also be set from the configuration interface, so through the Buildroot .config file. See Section 8.14.4, “Location of downloaded packages” for more details on how you can set the download directory.
  • // 覆盖Buildroot存储/检索下载文件的目录。注意,也可以从配置界面设置Buildroot下载目录,通过Buildroot .config文件。关于如何设置下载目录的更多细节,请参见8.14.4节“下载包的位置”。
  • vBR2_GRAPH_ALT, if set and non-empty, to use an alternate color-scheme in build-time graphs
  • // (如果设置为非空)用于在构建时图表中使用另一种颜色方案
  • BR2_GRAPH_OUT to set the filetype of generated graphs, either pdf (the default), or png.
  • // 设置生成图形的文件类型,pdf(默认)或png。
  • BR2_GRAPH_DEPS_OPTS to pass extra options to the dependency graph; see Section 8.9, “Graphing the dependencies between packages” for the accepted options
  • // 向依赖关系图传递额外选项;关于可接受的选项,请参见8.9节,“绘制包之间的依赖关系”
  • BR2_GRAPH_DOT_OPTS is passed verbatim as options to the dot utility to draw the dependency graph.
  • // 作为选项逐字传递给dot实用程序,以绘制依赖关系图。
  • BR2_GRAPH_SIZE_OPTS to pass extra options to the size graph; see Section 8.11, “Graphing the filesystem size contribution of packages” for the acepted options
  • // 向size图传递额外的选项;请参阅8.11节,“用图表示包的文件系统大小”来获得可接受的选项

下面是一个使用顶层目录和$HOME中的配置文件的例子:

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

如果您想使用默认的gcc或g++以外的编译器在您的主机上构建辅助二进制文件,那么就这样做:

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

8.7. Dealing efficiently with filesystem images

文件系统映像可以变得相当大,这取决于你选择的文件系统、包的数量,以及你是否提供了空闲空间……然而,文件系统映像中的一些位置可能只是空的(例如,长期运行的0);这样的文件称为稀疏文件。

大多数工具都可以有效地处理稀疏文件,并且只存储或编写稀疏文件中非空的那些部分。

例如:

  • tar accepts the -S option to tell it to only store non-zero blocks of sparse files:
tar cf archive.tar -S [files…] will efficiently store sparse files in a tarball
tar xf archive.tar -S will efficiently store sparse files extracted from a tarball
  • cp accepts the --sparse=WHEN option (WHEN is one of auto, never or always):
cp --sparse=always source.file dest.file will make dest.file a sparse file if source.file has long runs of zeroes

其他工具可能有类似的选项。请参阅他们各自的手册页。

如果您需要存储文件系统映像(例如,从一台机器传输到另一台机器),或者需要发送它们(例如,发送到Q&A团队),那么您可以使用稀疏文件。

但是请注意,当使用dd的稀疏模式时,将文件系统映像烧录到设备上可能会导致文件系统损坏(例如,ext2文件系统的块位图可能损坏;或者,如果您的文件系统中有稀疏文件,那么这些部分在回读时可能不是全零)。您应该只在构建机器上处理文件时使用稀疏文件,而不是将它们传输到目标上使用的实际设备时。

8.8. Details about packages

Buildroot可以生成一个JSON简介,描述当前配置中启用的包集,以及它们的依赖项、许可和其他元数据。这个JSON简介是通过使用show-info make目标产生的:

make show-info

Buildroot还可以使用pkg-stats make 目标生成关于包的HTML和JSON输出的详细信息。除了其他内容外,这些细节包括已知的cve(安全漏洞)是否会影响当前配置中的包。它还显示了这些包是否有更新的上游版本。

make pkg-stats

8.9. Graphing the dependencies between packages

Buildroot的工作之一是了解包之间的依赖关系,并确保它们以正确的顺序构建。这些依赖有时非常复杂,对于一个给定的系统,通常不容易理解为什么Buildroot将这样或那样的包引入构建中。

为了帮助理解依赖关系,从而更好地理解不同组件在嵌入式Linux系统中的角色,Buildroot能够生成依赖关系图。

要生成你所编译的整个系统的依赖关系图,只需运行:

make graph-depends

您将在output/graphs/graph-dependencies.pdf中找到生成的图形。

如果您的系统相当大,依赖关系图可能过于复杂和难以阅读。因此,为给定的包生成依赖关系图是可能的:

make <pkg>-graph-depends

您将在output/graph/<pkg>-graph-depends.pdf中找到生成的图形。

请注意,依赖关系图是使用Graphviz项目中的点工具生成的,要使用此特性,必须在系统上安装该工具。在大多数发行版中,它可以作为graphviz包使用。

默认情况下,依赖关系图是以PDF格式生成的。但是,通过传递BR2_GRAPH_OUT环境变量,您可以切换到其他输出格式,如PNG、PostScript或SVG。支持点工具的-T选项所支持的所有格式。

BR2_GRAPH_OUT=svg make graph-depends

可以通过在BR2_GRAPH_DEPS_OPTS环境变量中设置选项来控制依赖于图形的行为。接受的选项有:

  • --depth N, -d N, to limit the dependency depth to N levels. The default, 0, means no limit.
  • // 将依赖深度限制为N个级别。默认值0表示没有限制。
  • --stop-on PKG, -s PKG, to stop the graph on the package PKG. PKG can be an actual package name, a glob, the keyword virtual (to stop on virtual packages), or the keyword host (to stop on host packages). The package is still present on the graph, but its dependencies are not.
  • // PKG可以是一个实际的包名、一个glob、关键字virtual(在虚拟包上停止)或关键字host(在主机包上停止)。包仍然显示在图中,但是它的依赖项不存在了。
  • --exclude PKG, -x PKG, like --stop-on, but also omits PKG from the graph.
  • // 例如--stop-on,但是也从图中省略了PKG。
  • --transitive, --no-transitive, to draw (or not) the transitive dependencies. The default is to not draw transitive dependencies.
  • // 绘制(或不绘制)传递依赖关系。默认是不绘制传递依赖项。
  • --colors R,T,H, the comma-separated list of colors to draw the root package ®, the target packages (T) and the host packages (H). Defaults to: lightblue,grey,gainsboro
  • // 用逗号分隔的颜色列表来绘制根包®,目标包(T)和主机包(H)。默认为:浅蓝色,灰色,gainsboro
BR2_GRAPH_DEPS_OPTS='-d 3 --no-transitive --colors=red,green,blue' make graph-depends

8.10. Graphing the build duration

当构建一个系统需要很长时间时,有时能够了解哪些包的构建时间最长,看看是否可以做些什么来加快构建速度是很有用的。为了帮助这样的构建时间分析,Buildroot收集每个包的每个步骤的构建时间,并允许从这些数据生成图表。

要在构建后生成构建时间图,运行:

make graph-build

将会生成一系列文件在 output/graphs 中:

  • build.hist-build.pdf, a histogram of the build time for each package, ordered in the build order.
  • // 每个包的构建时间柱状图,按构建顺序排列。
  • build.hist-duration.pdf, a histogram of the build time for each package, ordered by duration (longest first)
  • // 每个包的构建时间柱状图,按持续时间排序(最长的优先)
  • build.hist-name.pdf, a histogram of the build time for each package, order by package name.
  • // 每个包的构建时间柱状图,按包名排序。
  • build.pie-packages.pdf, a pie chart of the build time per package
  • // 每个包的构建时间饼图
  • build.pie-steps.pdf, a pie chart of the global time spent in each step of the packages build process.
  • // 包构建过程的每个步骤所花费的全局时间的饼图。

这个图形构建目标需要安装Python MatplotlibNumpy库(大多数发行版上是Python-Matplotlib和Python-Numpy),如果使用的是2.7以上的Python版本(大多数发行版上是Python-argparse),还需要安装argparse模块。

默认情况下,图形的输出格式是PDF,但是可以使用BR2_GRAPH_OUT环境变量选择另一种格式。唯一支持的其他格式是PNG:

BR2_GRAPH_OUT=png make graph-build

8.11. Graphing the filesystem size contribution of packages

当目标系统增长时,有时了解每个Buildroot包对总体根文件系统大小的贡献是有用的。为了帮助进行这样的分析,Buildroot收集了关于每个包安装的文件的数据,并使用这些数据生成一个图表和CSV文件,详细说明不同包的大小贡献。

要在构建后生成这些数据,运行:

make graph-size

将会生成:

  • output/graphs/graph-size.pdf, a pie chart of the contribution of each package to the overall root filesystem size
  • // 每个包对总的根文件系统大小的贡献饼图
  • output/graphs/package-size-stats.csv, a CSV file giving the size contribution of each package to the overall root filesystem size
  • // CSV文件,给出每个包的大小对整个根文件系统大小的贡献
  • output/graphs/file-size-stats.csv, a CSV file giving the size contribution of each installed file to the package it belongs, and to the overall filesystem size.
  • // CSV文件,它给出了每个安装文件所属包的大小,以及整个文件系统的大小。

这个图形大小的目标需要安装Python Matplotlib库(大多数发行版上是Python - Matplotlib),如果使用的是2.7以上的Python版本(大多数发行版上是Python -argparse),还需要安装argparse模块。

与持续时间图一样,也支持BR2_GRAPH_OUT环境变量来调整输出文件格式。关于这个环境变量的详细信息,请参见8.9节“绘制包之间的依赖关系”。

此外,还可以设置环境变量BR2_GRAPH_SIZE_OPTS来进一步控制生成的图。接受的选项是:

  • --size-limit X, -l X, will group all packages which individual contribution is below X percent, to a single entry labelled Others in the graph. By default, X=0.01, which means packages each contributing less than 1% are grouped under Others. Accepted values are in the range [0.0…1.0].
  • // 将个人贡献低于X %的所有包分组到图中标记为Others的单个条目中。默认情况下,X=0.01,这意味着每个贡献少于1%的包被分组到Others下。可接受的值在[0.0…1.0]范围内。
  • --iec, --binary, --si, --decimal, to use IEC (binary, powers of 1024) or SI (decimal, powers of 1000; the default) prefixes.
  • // 使用iec(二进制,1024的幂)或si(十进制,1000的幂);默认的前缀。
  • --biggest-first, to sort packages in decreasing size order, rather than in increasing size order.
  • // 按大小递减顺序而不是按大小递增顺序对包进行排序。

Note. The collected filesystem size data is only meaningful after a complete clean rebuild. Be sure to run make clean all before using make graph-size.

To compare the root filesystem size of two different Buildroot compilations, for example after adjusting the configuration or when switching to another Buildroot release, use the size-stats-compare script. It takes two file-size-stats.csv files (produced by make graph-size) as input. Refer to the help text of this script for more details:

请注意。收集到的文件系统大小数据只有在完成干净重建后才有意义。确保在使用make graph-size之前运行make clean all

要比较两个不同Buildroot编译的根文件系统大小,例如在调整配置后或切换到另一个Buildroot版本时,可以使用size-stats-compare脚本。它以两个file-size-stats.csv文件(由make graph-size生成)作为输入。有关更多细节,请参阅此脚本的帮助文本:

utils/size-stats-compare -h

8.12. Top-level parallel build

请注意。本节讨论一个非常实验性的特性,它在一些普通的情况下可以实现收支平衡。使用风险自负。

Buildroot一直能够在每个包的基础上使用并行构建:每个包都是由Buildroot使用make -jN(或者对非基于make的构建系统的等价调用)构建的。并行级别的默认值是cpu数量+ 1,但是可以使用BR2_JLEVEL配置选项进行调整。

然而,直到2020.02年,Buildroot还在以串行方式构建包:每个包一个接一个地构建,而没有在包之间并行构建。到2020.02年,Buildroot已经对顶级并行构建提供了实验性的支持,通过并行构建没有依赖关系的包,可以大大节省构建时间。然而,这一特性被标记为实验性的,并且已知在某些情况下不起作用。

为了使用顶层并行构建,必须:

  • Enable the option BR2_PER_PACKAGE_DIRECTORIES in the Buildroot configuration
  • // 在Buildroot配置中启用BR2_PER_PACKAGE_DIRECTORIES选项
  • Use make -jN when starting the Buildroot build
  • // 在启动Buildroot构建时使用make -jN

在内部,BR2_PER_PACKAGE_DIRECTORIES将启用一种名为每个包目录的机制,它将产生以下效果:

  • Instead of a global target directory and a global host directory common to all packages, per-package target and host directories will be used, in $(O)/per-package/<pkg>/target/ and $(O)/per-package/<pkg>/host/ respectively. Those folders will be populated from the corresponding folders of the package dependencies at the beginning of <pkg> build. The compiler and all other tools will therefore only be able to see and access files installed by dependencies explicitly listed by <pkg>.
  • // 与所有包共用的全局目标目录和全局主机目录不同,每个包的目标目录和主机目录将分别在 ( O ) / p e r − p a c k a g e / / t a r g e t / 和 (O)/per-package//target/和 (O)/perpackage//target/(O)/per-package//host/中使用。这些文件夹将从构建开始时包依赖项的相应文件夹中填充。因此,编译器和所有其他工具只能查看和访问由显式列出的依赖项安装的文件。
  • At the end of the build, the global target and host directories will be populated, located in $(O)/target and $(O)/host respectively. This means that during the build, those folders will be empty and it’s only at the very end of the build that they will be populated.
  • // 在构建结束时,将填充全局目标和主机目录,分别位于 ( O ) / t a r g e t 和 (O)/target和 (O)/target(O)/host中。这意味着在构建过程中,这些文件夹将是空的,只有在构建的最后才会填充它们。

8.13. Integration with Eclipse

一部分嵌入式Linux开发人员喜欢经典的文本编辑器(如Vim或Emacs)和基于命令行的界面,而其他一些嵌入式Linux开发人员喜欢更丰富的图形界面来完成他们的开发工作。Eclipse是最流行的集成开发环境之一,Buildroot与Eclipse集成是为了简化Eclipse用户的开发工作。

我们与Eclipse的集成简化了构建在Buildroot系统之上的应用程序和库的编译、远程执行和远程调试。它没有将Buildroot配置和构建过程本身与Eclipse集成在一起。因此,Eclipse集成的典型使用模型是:

  • Configure your Buildroot system with make menuconfig, make xconfig or any other configuration interface provided with Buildroot.
  • // 使用make menuconfig, make xconfig或其他Buildroot提供的配置界面来配置你的Buildroot系统。
  • Build your Buildroot system by running make.
  • // 通过运行make来构建你的Buildroot系统。
  • Start Eclipse to develop, execute and debug your own custom applications and libraries, that will rely on the libraries built and installed by Buildroot.
  • // 启动Eclipse来开发、执行和调试您自己的自定义应用程序和库,这些程序和库将依赖于Buildroot构建和安装的库。

https://github.com/mbats/eclipse-buildroot-bundle/wiki上详细描述了Buildroot Eclipse集成的安装过程和使用方法。

8.14. Advanced usage

8.14.1 Using the generated toolchain outside 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/内容的tar文件,名为<TARGET-TUPLE>_sdk-buildroot.tar.gz(可以通过设置环境变量BR2_SDK_PREFIX来覆盖),该文件位于输出目录output/images/中。

然后,当应用程序开发人员希望开发尚未打包为Buildroot包的应用程序时,可以将这个tarball分发给他们。

在提取SDK压缩包后,用户必须运行脚本relocate-sdk.sh(位于SDK的顶部目录),以确保所有路径都使用新位置更新。

或者,如果你只是想准备SDK而不生成tarball(例如,因为你将只是移动主机目录,或将生成tarball自己),Buildroot也允许你只准备SDK与make prepare-sdk,而不实际生成tarball。

为了方便起见,通过选择BR2_PACKAGE_HOST_ENVIRONMENT_SETUP选项,可以将environment-setup脚本安装到output/host/中,从而安装到SDK中。此脚本可以使用。你的/sdk/path/environment-setup导出一些环境变量,这些变量将帮助你使用Buildroot sdk交叉编译你的项目:PATH将包含SDK二进制文件,标准的autotools变量将用适当的值定义,CONFIGURE_FLAGS将包含基本的。./configure选项来交叉编译autotools项目。它还提供了一些有用的命令。但是请注意,一旦该脚本来源于此脚本,环境就只设置为交叉编译,而不再设置为本机编译。

8.14.2 Using gdb in Buildroot

Buildroot允许进行交叉调试,调试器在构建机器上运行,并与目标上的gdbserver通信,以控制程序的执行。

为实现这一目标:

  • If you are using an internal toolchain (built by Buildroot), you must enable BR2_PACKAGE_HOST_GDB, BR2_PACKAGE_GDB and BR2_PACKAGE_GDB_SERVER. This ensures that both the cross gdb and gdbserver get built, and that gdbserver gets installed to your target.
  • // 如果您正在使用内部工具链(由Buildroot构建),您必须启用BR2_PACKAGE_HOST_GDB、BR2_PACKAGE_GDB和BR2_PACKAGE_GDB_SERVER。这将确保构建交叉gdb和gdbserver,并将gdbserver安装到目标服务器上。
  • If you are using an external toolchain, you should enable BR2_TOOLCHAIN_EXTERNAL_GDB_SERVER_COPY, which will copy the gdbserver included with the external toolchain to the target. If your external toolchain does not have a cross gdb or gdbserver, it is also possible to let Buildroot build them, by enabling the same options as for the internal toolchain backend.
  • // 如果您正在使用外部工具链,您应该启用BR2_TOOLCHAIN_EXTERNAL_GDB_SERVER_COPY,它将外部工具链包含的gdbserver复制到目标。如果您的外部工具链没有跨gdb或gdbserver,也可以让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/,因为该目录中的二进制文件被剥离)。

/output/staging/usr/share/buildroot/gdbinit文件将告诉交叉gdb在哪里可以找到目标库。

最后,从交叉gdb连接到目标:

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

8.14.3 Using ccache in Buildroot

Ccache是一个编译器缓存。它存储每个编译过程产生的目标文件,并且能够通过使用预先存在的目标文件跳过将来对同一源文件(使用相同的编译器和相同的参数)的编译。当多次从头进行几乎相同的构建时,它可以很好地加快构建过程。

ccache支持集成在Buildroot中。你只需要在Build选项中启用编译器缓存。这将自动构建ccache,并在每个主机和目标编译中使用它。

缓存位于$HOME/.buildrooot-ccache中。它存储在Buildroot输出目录之外,以便可以由单独的Buildroot构建共享。如果您想删除缓存,只需删除此目录。

您可以通过运行make ccache-stats获取缓存的统计信息(大小、命中次数、未命中次数等)。

make目标ccache-optionsCCACHE_OPTIONS变量提供了对缓存的更多的访问。例如

# set cache limit size // 设置缓存限制大小
make CCACHE_OPTIONS="--max-size=5G" ccache-options

# zero statistics counters // 清零统计计数器
make CCACHE_OPTIONS="--zero-stats" ccache-options

Ccache对源文件和编译器选项进行hash。如果编译器选项不同,缓存的目标文件将不会被使用。然而,许多编译器选项包含到暂存目录的绝对路径。因此,在不同的输出目录中构建会导致许多缓存丢失。

为了避免这个问题,buildroot有使用相对路径选项(BR2_CCACHE_USE_BASEDIR)。这将把指向输出目录内的所有绝对路径重写为相对路径。因此,更改输出目录不再会导致缓存丢失。

相对路径的一个缺点是,它们最终也是对象文件中的相对路径。因此,例如,调试器将不再找到该文件,除非您首先cd到输出目录。

有关这种重写绝对路径的详细信息,请参阅ccache手册的Compiling in different directories一节。

8.14.4 Location of downloaded packages

Buildroot下载的各种tarball都存储在BR2_DL_DIR中,默认情况下该目录是dl目录。如果您想保留一个完整的Buildroot版本(已知它使用了相关的tarball),您可以对此目录创建一个副本。这将允许您用完全相同的版本重新生成工具链和目标文件系统。

如果您维护多个Buildroot树,那么最好使用一个共享的下载位置。这可以通过将BR2_DL_DIR环境变量指向一个目录来实现。如果设置了此值,则会覆盖Buildroot配置中的BR2_DL_DIR的值。以下一行应该添加到<~/.bashrc>

 export BR2_DL_DIR=<shared download location>

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

8.14.5 Package-specific make targets

运行make <package>会构建并安装那个特定的包及其依赖项。

对于依赖于Buildroot框架的包,有许多特殊的make目标可以像这样独立调用:

make <package>-<target>

包构建目标有(按照执行的顺序):

command/targetDescription
sourceFetch the source (download the tarball, clone the source repository, etc)
dependsBuild and install all dependencies required to build the package
extractPut the source in the package build directory (extract the tarball, copy the source, etc)
patchApply the patches, if any
configureRun the configure commands, if any
buildRun the compilation commands
install-stagingtarget package: Run the installation of the package in the staging directory, if necessary
install-targettarget package: Run the installation of the package in the target directory, if necessary
installtarget package: Run the 2 previous installation commands
host package: Run the installation of the package in the host directory

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

command/targetDescription
show-dependsDisplays the first-order dependencies required to build the package
show-recursive-dependsRecursively displays the dependencies required to build the package
show-rdependsDisplays the first-order reverse dependencies of the package (i.e packages that directly depend on it)
show-recursive-rdependsRecursively displays the reverse dependencies of the package (i.e the packages that depend on it, directly or indirectly)
graph-dependsGenerate a dependency graph of the package, in the context of the current Buildroot configuration. See this section for more details about dependency graphs.
graph-rdependsGenerate a graph of this package reverse dependencies (i.e the packages that depend on it, directly or indirectly)
dircleanRemove the whole package build directory
reinstallRe-run the install commands
rebuildRe-run the compilation commands - this only makes sense when using the OVERRIDE_SRCDIR feature or when you modified a file directly in the build directory
reconfigureRe-run the configure commands, then rebuild - this only makes sense when using the OVERRIDE_SRCDIR feature or when you modified a file directly in the build directory

8.14.6 Using Buildroot during development

Buildroot的正常操作是下载一个tarball,提取它,配置,编译和安装在这个tarball中找到的软件组件。源代码在output/build/<package>-<version>中提取,这是一个临时目录:每当使用make clean时,这个目录将被完全删除,并在下一次调用make时重新创建。即使使用Git或Subversion存储库作为包源代码的输入,Buildroot也会从中创建一个tarball,然后像往常一样使用tarball。

当Buildroot主要用作集成工具来构建和集成嵌入式Linux系统的所有组件时,这种行为非常适合。然而,如果一个人在开发系统的某些组件时使用Buildroot,这种行为就不是很方便了:相反,人们会希望对一个包的源代码做一个小的更改,并能够用Buildroot快速地重建系统。

直接在output/build/<package>-<version>中进行更改不是合适的解决方案,因为make clean时会删除此目录。

因此,Buildroot为这个用例提供了一个特定的机制:<pkg>_OVERRIDE_SRCDIR机制。Buildroot读取覆盖文件,该文件允许用户告诉Buildroot某些包的源代码位置。

覆盖文件的默认位置是$(CONFIG_DIR)/local.mk。由BR2_PACKAGE_OVERRIDE_FILE配置选项定义。$(CONFIG_DIR)是Buildroot .config文件的位置,所以是本地的。local.mk默认与.config文件并排存在,这意味着:

  • In the top-level Buildroot source directory for in-tree builds (i.e., when O= is not used)
  • // 在顶级Buildroot源代码目录中,用于树内构建(也就是说,当O=未被使用时)
  • In the out-of-tree directory for out-of-tree builds (i.e., when O= is used)
  • // 在out-of-tree构建的out-of-tree目录中(即使用O=时)

如果需要不同于这些默认值的位置,可以通过BR2_PACKAGE_OVERRIDE_FILE配置选项指定。

在这个覆盖文件中,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>-rebuildmake <pkg>-reconfigure目标一起使用。make <pkg>-rebuild all序列将把源代码从<pkg>_OVERRIDE_SRCDIR rsync到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源代码树中排除测试和树内构建:

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

9. Project-specific customization

对于一个特定的项目,你可能需要执行的典型行动是:

  • configuring Buildroot (including build options and toolchain, bootloader, kernel, package and filesystem image type selection)
  • // 配置Buildroot(包括构建选项和工具链、引导加载程序、内核、包和文件系统映像类型选择)
  • configuring other components, like the Linux kernel and BusyBox
  • // 配置其他组件,如Linux内核和BusyBox
  • customizing the generated target filesystem
  • 自定义生成的目标文件系统
    • adding or overwriting files on the target filesystem (using BR2_ROOTFS_OVERLAY)
    • // 在目标文件系统上添加或覆盖文件(使用BR2_ROOTFS_OVERLAY)
    • modifying or deleting files on the target filesystem (using BR2_ROOTFS_POST_BUILD_SCRIPT)
    • // 修改或删除目标文件系统上的文件(使用BR2_ROOTFS_POST_BUILD_SCRIPT)
    • running arbitrary commands prior to generating the filesystem image (using BR2_ROOTFS_POST_BUILD_SCRIPT)
    • // 在生成文件系统映像之前运行任意命令(使用BR2_ROOTFS_POST_BUILD_SCRIPT)
    • setting file permissions and ownership (using BR2_ROOTFS_DEVICE_TABLE)
    • // 设置文件权限和所有权(使用BR2_ROOTFS_DEVICE_TABLE)
    • adding custom devices nodes (using BR2_ROOTFS_STATIC_DEVICE_TABLE)
    • // 添加自定义设备节点(使用BR2_ROOTFS_STATIC_DEVICE_TABLE)
  • adding custom user accounts (using BR2_ROOTFS_USERS_TABLES)
  • // 添加自定义用户帐户(使用BR2_ROOTFS_USERS_TABLES)
  • running arbitrary commands after generating the filesystem image (using BR2_ROOTFS_POST_IMAGE_SCRIPT)
  • // 生成文件系统映像后运行任意命令(使用BR2_ROOTFS_POST_IMAGE_SCRIPT)
  • adding project-specific patches to some packages (using BR2_GLOBAL_PATCH_DIR)
  • // 向一些包添加特定于项目的补丁(使用BR2_GLOBAL_PATCH_DIR)
  • adding project-specific packages
  • // 添加特定项目包

关于此类project-specific的自定义的重要说明:请仔细考虑哪些更改确实是特定于项目的,哪些更改对项目之外的开发人员也是有用的。Buildroot社区强烈推荐并鼓励对官方Buildroot项目的改进、包和板的支持。当然,有时上游是不可能或不可取的,因为变更是高度特定或专有的。

本章描述了如何在Buildroot中进行此类特定于项目的定制,以及如何以一种可以以可重复的方式构建相同映像的方式存储它们,甚至在运行make clean之后。通过遵循推荐的策略,您甚至可以使用相同的Buildroot树来构建多个不同的项目!

9.1. Recommended directory structure

在为项目定制Buildroot时,您将创建一个或多个特定于项目的文件,这些文件需要存储在某个地方。虽然大多数这些文件可以放在任何位置,因为它们的路径将在Buildroot配置中指定,但Buildroot开发人员推荐了一个特定的目录结构,这将在本节中描述。

与这个目录结构正交的是,您可以选择将这个结构本身放在哪里:要么放在Buildroot树中,要么使用br2-external tree放在它的外部。这两个选项都是有效的,选择取决于您。

+-- 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树中,那么<company><boardname>组件可能是多余的,可以被删除。

9.1.1. Implementing layered customizations

对于一个用户来说,有几个相关的项目部分需要相同的自定义,这是很常见的。与其为每个项目重复这些定制,不如使用分层定制方法,如本节所述。

Buildroot中几乎所有可用的定制方法,比如构建后脚本post-build scripts和根文件系统root filesystem overlays覆盖,都接受空格分隔的项列表。指定的项总是按从左到右的顺序处理。通过创建多个这样的项,一个用于公共定制,另一个用于真正的特定于项目的定制,您可以避免不必要的重复。每一层通常都包含在board/<company>/内部的一个单独目录中。根据项目的不同,您甚至可以引入两个以上的层。

一个用户有两个自定义层commonfooboard的目录结构示例是:

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

然后首先应用普通层的补丁,然后应用底层的补丁。

9.2. Keeping customizations outside of Buildroot

正如9.1节“推荐的目录结构”中已经简要提到的,您可以将特定于项目的自定义放置在两个位置:

  • 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.
  • // 直接在Buildroot树中,通常使用版本控制系统中的分支来维护它们,这样就可以很容易地升级到新的Buildroot版本。
  • 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.
  • // 在Buildroot树之外,使用br2-external机制。这种机制允许将包菜单、板支持和配置文件保留在Buildroot树之外,同时仍然将它们很好地集成到构建逻辑中。我们称这个位置为br2-external树。本节解释如何使用br2-external机制,以及在br2-external树中提供什么。

通过将BR2_EXTERNAL make变量设置为要使用的br2-external树的路径,可以告诉Buildroot使用一个或多个br2-external树。它可以传递给任何Buildroot make调用。它自动保存在输出目录中隐藏的.br2-external.mk的文件。因此,无需在每次make调用时传递BR2_EXTERNAL。但是,它可以在任何时候通过传递一个新值来更改,也可以通过传递一个空值来删除。

请注意。到br2-external树的路径可以是绝对路径,也可以是相对路径。如果它是作为相对路径传递的,那么一定要注意,它是相对于Buildroot主源目录而不是Buildroot输出目录来解释的。

注意:如果在Buildroot 2016.11之前使用br2-external树,你需要先转换它,然后才能在Buildroot 2016.11之后使用它。请参阅第27.1节,“迁移到2016年11月”,以获得相关帮助。

一些例子:

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

9.2.1. Layout of a br2-external tree

一个br2-external树必须包含至少这三个文件,在以下章节中描述:

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

除了这些强制文件之外,br2-external树中还可能存在其他可选内容,比如configs/provides/目录。它们也将在下面的章节中进行描述。

后面还将描述一个完整的示例br2-external树布局。

The external.desc file

这个文件描述了 br2-external tree: the name and description for that br2-external tree.

该文件的格式是逐行的,每行以一个关键字开头,后面跟着一个冒号和一个或多个空格,然后是分配给该关键字的值。目前识别的关键字有两个:

  • 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.

  • // Name(强制)定义了br2-external树的名称。该名称在集合[A-Za-z0-9_]中只能使用ASCII字符;禁止使用其他任何字符。Buildroot将变量BR2_EXTERNAL_$(NAME)_PATH设置为br2-external树的绝对路径,这样您就可以使用它来引用br2-external树。这个变量在Kconfig中可用,因此您可以使用它来生成Kconfig文件(见下文)和Makefile,这样您就可以使用它来包含其他Makefile(见下文)或引用br2-external树中的其他文件(如数据文件)。

    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.
    // 注意:因为可以一次使用多个br2-external树,所以这个名称被Buildroot用来为每个树生成变量。这个名字是用来识别你的br2-外部树的,所以试着想出一个真正描述你的br2-外部树的名字,为了让它相对独特,这样它就不会和另一个来自另一个br2-外部树的名字冲突,特别是当您计划以某种方式与第三方共享您的br2-external树或使用来自第三方的br2-external树时。

  • 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.

  • // Desc(可选)提供了br2-external树的简短描述。它应该适合一行,大部分是自由形式的(见下文),用于显示关于br2-external树的信息(例如,在defconfig文件列表上面,或作为menuconfig中的提示符);因此,它应该相对简短(40字符可能是一个很好的上限)。该描述可在BR2_EXTERNAL_$(NAME)_DESC变量中获得。

名称示例和相应的BR2_EXTERNAL_$(NAME)_PATH变量:

  • FOOBR2_EXTERNAL_FOO_PATH
  • BAR_42BR2_EXTERNAL_BAR_42_PATH

在下面的例子中,假定名称设置为BAR_42

注意:BR2_EXTERNAL_$(NAME)_PATHBR2_EXTERNAL_$(NAME)_DESC都在Kconfig文件和makefile中可用。它们也被导出到环境中,因此可以在构建后、生成映像后和伪造后脚本中使用。

The Config.in and external.mk files

这些文件(可能每个都是空的)可以用来定义包配方(例如foo/Config.infoo/foo.mk就像Buildroot本身的包)。在和foo / foo。或者其他自定义配置选项或make逻辑。

构建根自动从每个br2-external树中包含Config.in使其显示在顶级配置菜单中,并包含external.mk从每个br2-external树和其余的makefile逻辑。

它的主要用途是存储package recipes。推荐的方法是编写一个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))

然后在$(BR2_EXTERNAL_BAR_42_PATH)/package/package1$(BR2_EXTERNAL_BAR_42_PATH)/package/package2中创建普通的Buildroot包配方,如第18章,添加新包到Buildroot。如果您愿意,还可以将包分组到名为的子目录中,并相应地调整上述路径。

您还可以在Config.in定义自定义配置选项。在external.mk自定义make逻辑。

The configs/ directory

可以将Buildroot defconfigs存储在br2-external树的configs子目录中。Buildroot会自动在make list-defconfigs的输出中显示它们,并允许使用普通的make <name>_defconfig命令加载它们。它们将在make list-defconfigs输出中可见,位于External configs标签下面,该标签包含定义它们的br2-external树的名称。

注意:如果一个defconfig文件存在于多个br2-external树中,那么将使用最后一个br2-external树中的那个。因此,可以覆盖Buildroot或另一个br2-external树中绑定的defconfig。

The provides/ directory

对于某些包,Buildroot提供了两个(或更多)api兼容包的实现。例如,可以选择libjpegjpeg-turbo;openssllibressl之间有一个;有一个选择一个已知的,预先配置的工具链…

br2-external可以通过提供一组定义这些替代方案的文件来扩展这些选择:

  • 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;
  • // 定义了可选的libjpeg实现;
  • provides/openssl.in defines the alternative openssl implementations;
  • // 定义了替代的openssl实现;
  • 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

可以将所有特定于板的配置文件存储在那里,比如内核配置、根文件系统覆盖层,或者任何其他Buildroot允许设置位置的配置文件(通过使用BR2_EXTERNAL_$(NAME)_PATH变量)。例如,你可以将路径设置为一个全局补丁目录,一个rootfs覆盖和内核配置文件,如下所示(例如,通过运行make menuconfig并填写这些选项):

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

额外的Linux内核扩展(请参见18.21.2节,“Linux -kernel-extensions”)可以通过将它们存储在br2-external树的根Linux/目录中来添加。

Example layout

下面是一个使用br2-external所有特性的示例布局(示例内容显示在上面的文件中,当它与解释br2-external树相关时;当然,这完全是为了说明而编造的):

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

br2-external树将在menuconfig中可见(布局展开):

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

如果你使用了多个br2-external树,它看起来应该是这样的(布局展开,第二个名字为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将不会出现在工具链菜单中。它们必须显式地包含在br2-external的顶级Config.in和将因此出现在External options菜单中。

9.3. Storing the Buildroot configuration

可以使用make savedefconfig命令存储Buildroot配置。

这将通过删除默认值的配置选项来删除Buildroot配置。结果存储在一个名为defconfig的文件中。如果你想把它保存在另一个地方,请更改Buildroot配置本身的BR2_DEFCONFIG选项,或者使用make savedefconfig BR2_DEFCONFIG=<path-to-defconfig>调用make。

这个defconfig的推荐存储位置是configs/<boardname>_defconfig。如果您遵循此建议,该配置将在make help中列出,并且可以通过运行make <boardname>_defconfig再次设置。

或者,您可以将文件复制到任何其他地方,并使用make defconfig BR2_DEFCONFIG=<path-to-defconfig-file>重新构建。

9.4. Storing the configuration of other components

BusyBox、Linux内核、Barebox、U-Boot和uClibc的配置文件如有更改,也应保存。对于每一个组件,都有一个Buildroot配置选项指向一个输入配置文件,例如BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE。要存储它们的配置,请将这些配置选项设置为您希望保存配置文件的路径,然后使用下面描述的帮助器目标来实际存储配置。

9.1节“推荐的目录结构”所述,这些配置文件的推荐存储路径为board/<company>/<boardname>/foo.config

确保在更改BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE等选项之前创建了一个配置文件。否则,Buildroot将尝试访问这个配置文件,它还不存在,并将失败。您可以通过运行make linux-menuconfig等来创建配置文件。

Buildroot提供了一些帮助器目标,以简化配置文件的保存。

  • 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.

9.5. Customizing the generated target filesystem

除了通过make *config改变配置之外,还有一些其他的方法来定制最终的目标文件系统。

两种推荐的方法可以共存,即根文件系统覆盖root filesystem overlay和后构建脚本post build script

Root filesystem overlays (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/sbin/usr/lib.

9.1节“推荐的目录结构”所示,此覆盖的推荐路径为board/<company>/<boardname>/rootfs-overlay

Post-build scripts (BR2_ROOTFS_POST_BUILD_SCRIPT)

构建后脚本是在Buildroot构建所有选择的软件之后,但在组装rootfs映像之前调用的shell脚本。要启用此特性,请在配置选项BR2_ROOTFS_POST_BUILD_SCRIPT(在System configuration菜单中)中指定一个空格分隔的构建后脚本列表。如果你指定一个相对路径,它将是相对于Buildroot树的根。

使用构建后脚本,您可以删除或修改目标文件系统中的任何文件。但是,您应该小心地使用该特性。每当您发现某个包生成错误或不需要的文件时,您应该修复该包,而不是使用一些构建后清理脚本来处理它。

9.1节“推荐的目录结构”所示,该脚本推荐的路径为board/<company>/<boardname>/post_build.sh

构建后脚本将以主Buildroot树作为当前工作目录运行。目标文件系统的路径作为每个脚本的第一个参数传递。如果配置选项BR2_ROOTFS_POST_SCRIPT_ARGS不是空的,这些参数也将被传递到脚本。所有的脚本都将被传递完全相同的参数集,不可能给每个脚本传递不同的参数集。

此外,你也可以使用这些环境变量:

  • 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 Section 18.5.2, “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

下面将介绍另外三种自定义目标文件系统的方法,但不推荐使用。

Direct modification of the target filesystem

对于临时修改,您可以直接修改目标文件系统并重新构建映像。目标文件系统在output/target/下可用。完成更改后,运行make重新构建目标文件系统映像。

这个方法允许您对目标文件系统做任何操作,但是如果您需要使用make clean来清除Buildroot树,那么这些更改将会丢失。这种清理在一些情况下是必要的,请参阅第8.2节“了解什么时候需要完全重新构建”以了解细节。因此,此解决方案只适用于快速测试:更改无法通过make clean命令保存。一旦您验证了您的更改,您应该确保它们将在make clean之后持久存在,使用根文件系统覆盖或构建后脚本。

Custom target skeleton (BR2_ROOTFS_SKELETON_CUSTOM)

根文件系统映像是从目标框架skeleton创建的,所有包都在目标框架之上安装它们的文件。在构建和安装任何包之前,将框架复制到目标目录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/sbin和/usr/lib.

不建议使用此方法,因为它复制了整个框架,这妨碍了利用在以后的Buildroot版本中对默认框架进行的修复或改进。

Post-fakeroot scripts (BR2_ROOTFS_POST_FAKEROOT_SCRIPT)

当聚合最终的映像时,这个过程的某些部分需要根权限:在/dev中创建设备节点,设置文件和目录的权限或所有权……这并不能完全替代实际的root,但已经足够满足Buildroot的需求了。

fakeroot后脚本是在fakeroot阶段结束时,即在调用文件系统映像生成器之前调用的shell脚本。因此,它们被称为在fakeroot上下文中。

当您需要调整文件系统以进行通常只对根用户可用的修改时,Post-fakeroot脚本可能非常有用。

注意:建议使用现有的机制来设置文件权限或在/dev中创建条目(见9.5.1节,“设置文件权限和所有权并添加自定义设备节点”)或创建用户(见9.6节,“添加自定义用户帐户”)
注意:后构建脚本(上面提到的)和fakeroot脚本之间的区别在于,后构建脚本不会在fakeroot上下文中被调用。
注意:使用fakeroot并不能完全替代实际的root。Fakeroot只会伪造文件访问权限和类型(常规,块或char设备…)和uid/gid;这些是在内存中模拟的。

9.5.1. Setting file permissions and ownership and adding custom devices nodes

有时需要在文件或设备节点上设置特定的权限或所有权。例如,某些文件可能需要root用户拥有。由于构建后脚本不是作为root运行的,因此您不能从那里进行此类更改,除非从构建后脚本中使用显式的fakeroot。

相反,Buildroot提供了对所谓权限表permission tables的支持。要使用此特性,请将配置选项BR2_ROOTFS_DEVICE_TABLE设置为以空格分隔的权限表列表,即遵循makedev语法的常规文本文件。

如果你正在使用一个静态设备表(即不使用devtmpfs, mdev,或(e)udev),那么你可以使用相同的语法添加设备节点,在所谓的设备表device tables。要使用此特性,请将配置选项BR2_ROOTFS_STATIC_DEVICE_TABLE设置为用空格分隔的设备表列表。

9.1节“推荐的目录结构”所示,这些文件的推荐位置是board/<company>/<boardname>/

需要注意的是,如果特定的权限或设备节点与特定的应用程序相关,你应该在包的.mk文件中设置变量FOO_PERMISSIONSFOO_DEVICES(参见18.5.2节,“通用包引用”)。

9.6. Adding custom user accounts

有时需要在目标系统中添加特定的用户。为了满足这一需求,Buildroot提供了对所谓用户表users tables的支持。要使用此特性,请将配置选项BR2_ROOTFS_USERS_TABLES设置为一个空格分隔的用户表列表,即遵循makeusers语法的常规文本文件。

9.1节“推荐的目录结构”所示,这些文件的推荐位置是board/<company>/<boardname>/

需要注意的是,如果自定义用户与特定的应用程序相关,你应该在包的.mk文件中设置变量FOO_USERS(参见18.5.2节,“通用包引用”)。

9.7. Customization after the images have been created

当构建后脚本post-build scripts(第9.5节,“自定义生成的目标文件系统”)在构建文件系统映像、内核和引导加载程序之前运行时,可以使用后映像脚本post-image scripts在创建所有映像之后执行一些特定的操作。

例如,可以使用后映像脚本post-image scripts在NFS服务器导出的位置中自动提取根文件系统tarball,或者创建一个将根文件系统和内核映像绑定在一起的特殊固件映像,或者您的项目所需的任何其他自定义操作。

要启用这个特性,在配置选项BR2_ROOTFS_POST_IMAGE_SCRIPT中指定一个空格分隔的后映像脚本列表(在System configuration菜单中)。如果你指定一个相对路径,它将是相对于Buildroot树的根。

就像编译后脚本一样,编译后图像脚本运行时将主要Buildroot树作为当前工作目录。图像输出目录的路径作为每个脚本的第一个参数传递。如果配置选项BR2_ROOTFS_POST_SCRIPT_ARGS不是空的,这些参数也将被传递到脚本。所有的脚本都将被传递完全相同的参数集,不可能给每个脚本传递不同的参数集。

同样,与构建后脚本一样,脚本可以访问环境变量BR2_CONFIGHOST_DIRSTAGING_DIRTARGET_DIRBUILD_DIRBINARIES_DIRCONFIG_DIRBASE_DIR

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

9.8. Adding project-specific patches

在Buildroot中提供的包的基础上应用额外的补丁有时是有用的。例如,这可能用于支持项目中的自定义特性,或者在处理新体系结构时。

BR2_GLOBAL_PATCH_DIR配置选项可用于指定一个空格分隔的包含包补丁的一个或多个目录列表。

对于特定包<packagename>的特定版本<packageversion>,补丁从BR2_GLOBAL_PATCH_DIR应用,如下所示:

  • 对于BR2_GLOBAL_PATCH_DIR中存在的每个目录 <global-patch-dir><package-patch-dir>将确定,如下所示:

    • <global-patch-dir>/<packagename>/<packageversion>/ if the directory exists.
    • Otherwise, <global-patch-dir>/<packagename> if the directory exists.
  • 然后补丁将会从<package-patch-dir>应用,如下所示:

    • 如果package目录下存在series文件,则根据series文件应用补丁;
    • 否则,打上匹配*.patch的补丁文件。补丁按字母顺序应用。因此,为了确保它们按照正确的顺序应用,强烈建议将补丁文件命名为:<number>-<description>.patch,其中<number>表示应用顺序。

有关如何为一个包应用补丁的信息,请参见第19.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包的补丁后钩子post-patch hook执行的。

9.9. Adding project-specific packages

一般来说,任何新包都应该直接添加到包目录中,并提交给Buildroot上游项目。在第18章“向Buildroot添加新包”中详细介绍了如何向Buildroot添加包,这里不再重复。但是,您的项目可能需要一些不能上行的专有包。本节将解释如何将这些特定于项目的包保存在特定于项目的目录中。

9.1节“推荐的目录结构”所示,项目特定包的推荐位置是package/<company>/。如果你正在使用br2-external树特性(参见9.2节,“保持自定义在Buildroot之外”),推荐的位置是将它们放在br2-external树的名为package/的子目录中。

但是,除非我们执行一些额外的步骤,否则Buildroot不会知道这个位置中的包。正如第18章“向Buildroot添加新包”中所解释的,Buildroot中的包基本上由两个文件组成:一个.mk文件(描述如何构建包)和一个Config.in文件(描述此包的配置选项)。

Buildroot会自动将.mk文件包含在package目录的一级子目录中(使用模式package/*/*.mk)。如果我们想让Buildroot包含更深层次的子目录(比如package/<company>/package1)中的.mk文件,那么我们只需在包含这些额外的.mk文件的第一级子目录中添加一个.mk文件。因此,创建一个文件package/<company>/<company>.mk以下内容(假设你在package/<company>/下面只有一个额外的目录级别):

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

For the Config.in files, create a file package//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:

对于Config.in文件,创建一个文件package/<company>/Config.in其中包括你所有软件包的文件里Config.in。必须提供详尽的列表,因为在kconfig的源命令中不支持通配符。例如:

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

包括这个新的文件package/<company>/Config.inpackage/Config.in。最好是在特定于公司的菜单中,以便与未来的Buildroot版本更容易合并。

如果使用br2-external树,请参考9.2节“保持自定义在Buildroot之外”,了解如何填写这些文件。

9.10. Quick guide to storing your project-specific customizations

在本章的前面,已经描述了用于进行特定于项目的定制的不同方法。本节将通过提供存储特定于项目的自定义的逐步说明来总结所有这些内容。显然,可以跳过与项目无关的步骤。

  • 1.make menuconfig to configure toolchain, packages and kernel.
  • 2.make linux-menuconfig to update the kernel config, similar for other configuration like busybox, uclibc, …
  • 3.mkdir -p board/<manufacturer>/<boardname>
  • 4.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
  • 5.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
  • 6.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.
  • 7.Create a post-build script board/<manufacturer>/<boardname>/post_build.sh. Set BR2_ROOTFS_POST_BUILD_SCRIPT to board/<manufacturer>/<boardname>/post_build.sh
  • 8.If additional setuid permissions have to be set or device nodes have to be created, create board/<manufacturer>/<boardname>/device_table.txt and add that path to BR2_ROOTFS_DEVICE_TABLE.
  • 9.If additional user accounts have to be created, create board/<manufacturer>/<boardname>/users_table.txt and add that path to BR2_ROOTFS_USERS_TABLES.
  • 10.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.
  • 11.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.
  • 12.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.
  • 13.make savedefconfig to save the buildroot configuration.
  • 14.cp defconfig configs/<boardname>_defconfig

10. Using SELinux in Buildroot

SELinux是一个执行访问控制策略的Linux内核安全模块。除了传统的文件权限和访问控制列表之外,SELinux还允许为用户或进程编写访问资源(文件、套接字……)的特定功能的规则。

SELinux有三种操作模式:

  • Disabled: the policy is not applied
  • // 禁用:不应用该策略
  • Permissive: the policy is applied, and non-authorized actions are simply logged. This mode is often used for troubleshooting SELinux issues.
  • // 允许的:策略被应用,未经授权的操作被简单地记录下来。此模式通常用于诊断SELinux问题。
  • Enforcing: the policy is applied, and non-authorized actions are denied
  • // 强制执行:应用策略,拒绝未经授权的操作

在Buildroot中,操作模式由BR2_PACKAGE_REFPOLICY_POLICY_STATE_*配置选项控制。Linux内核还有各种配置选项,这些选项会影响如何启用SELinux(请参阅Linux内核源代码中的security/ ELinux/Kconfig)。

默认情况下,在Buildroot中,SELinux策略是由上游refpolicy项目提供的,由BR2_PACKAGE_REFPOLICY启用。

10.1. Enabling SELinux support

要在Buildroot生成的系统中正确支持SELinux,必须启用以下配置选项:

BR2_PACKAGE_LIBSELINUX
BR2_PACKAGE_REFPOLICY

此外,文件系统映像格式必须支持扩展属性。

10.2. SELinux policy tweaking

SELinux repolicy包含可以在构建时启用或禁用的模块。每个模块都提供了许多SELinux规则。在Buildroot中,默认情况下非基本模块是禁用的,提供了几种启用这些模块的方法:

  • Packages can enable a list of SELinux modules within the refpolicy using the <packagename>_SELINUX_MODULES variable.
  • // 可以使用<packagename>_SELINUX_MODULES变量在refpolicy中启用SELinux模块列表。
  • Packages can provide additional SELinux modules by putting them (.fc, .if and .te files) in package/<packagename>/selinux/.
  • // 可以提供额外的SELinux模块,将它们放在(Fc, .if和.te文件)package/<packagename>/selinux/
  • Extra SELinux modules can be added in directories pointed by the BR2_REFPOLICY_EXTRA_MODULES_DIRS configuration option.
  • // 额外的SELinux模块可以添加到BR2_REFPOLICY_EXTRA_MODULES_DIRS配置选项所指向的目录中。
  • Additional modules in the refpolicy can be enabled if listed in the BR2_REFPOLICY_EXTRA_MODULES_DEPENDENCIES configuration option.
  • // 如果在BR2_REFPOLICY_EXTRA_MODULES_DEPENDENCIES配置选项中列出,则可以启用repolicy中的其他模块。

Buildroot还允许完全覆盖repolicy。这允许提供专门为给定系统设计的完整自定义策略。当采用这种方式时,上述所有机制都将被禁用:没有额外的SElinux模块添加到策略中,并且自定义策略中的所有可用模块都将被启用并构建到最终的二进制策略中。自定义策略必须是官方重新策略的一个分支。

为了完全覆盖repolicy,必须设置以下配置变量:

BR2_PACKAGE_REFPOLICY_CUSTOM_GIT
BR2_PACKAGE_REFPOLICY_CUSTOM_REPO_URL
BR2_PACKAGE_REFPOLICY_CUSTOM_REPO_VERSION

11. Frequently Asked Questions & Troubleshooting

11.1. The boot hangs after Starting network…

引导进程以下消息以后似乎挂起(消息不一定完全相似,取决于所选包的列表):

Freeing init memory: 3972K
Initializing random number generator... done.
Starting network...
Starting dropbear sshd: generating rsa key... generating dsa key... OK

这意味着系统正在运行,但没有在串行控制台上启动shell。为了让系统在您的串行控制台上启动一个shell,您必须进入Buildroot配置,在System configuration,中,修改Run a getty (login prompt) after boot,并在getty options子菜单中设置适当的端口和波特率。这将自动调整生成的系统的/etc/inittab文件,以便shell在正确的串口上启动。

11.2. Why is there no compiler on the target?

已经决定从Buildroot-2012.11版本开始停止对目标板原生编译器的支持,因为:

  • this feature was neither maintained nor tested, and often broken;
  • //这个特性既没有维护也没有测试,而且经常被破坏;
  • this feature was only available for Buildroot toolchains;
  • // 这个特性只适用于Buildroot工具链;
  • Buildroot mostly targets small or very small target hardware with limited resource onboard (CPU, ram, mass-storage), for which compiling on the target does not make much sense;
  • // Buildroot主要针对小的或非常小的目标硬件,其板载资源有限(CPU、ram、大容量存储),因此在目标上编译没有多大意义;
  • Buildroot aims at easing the cross-compilation, making native compilation on the target unnecessary.
  • // Buildroot的目标是简化交叉编译,使目标上的本地编译变得不必要。

如果你的目标上需要一个编译器,那么Buildroot不适合你的目的。在这种情况下,你需要一个真正的发行版,你应该选择如下内容:

11.3. Why are there no development files on the target?

因为目标上没有可用的编译器(参见11.2节,“为什么目标上没有编译器?”),所以在头文件或静态库上浪费空间是没有意义的。

因此,自Buildroot-2012.11发布以来,这些文件总是从目标中删除。

11.4. Why is there no documentation on the target?

因为Buildroot主要针对有限资源(CPU、ram、大容量存储)的小型或非常小的目标硬件,所以用文档数据浪费空间是没有意义的。

如果您无论如何都需要目标上的文档数据,那么Buildroot并不适合您的目的,您应该寻找一个真正的发行版(参见11.2节,“为什么目标上没有编译器?”)。

11.5. Why are some packages not visible in the Buildroot config menu?

如果一个包存在于Buildroot树中,并且没有出现在配置菜单中,这很可能意味着该包的某些依赖项没有满足。

要了解更多关于包的依赖关系,可以在配置菜单中搜索包的符号(见8.1节“make tips”)。

然后,您可能必须递归地启用几个选项(对应于未满足的依赖项),以便最终能够选择包。

如果包因为一些未满足的工具链选项而不可见,那么您当然应该运行一个完整的重新构建(参见8.1节“make tips”以获得更多解释)。

11.6. Why not use the target directory as a chroot directory?

有很多理由不使用目标目录chroot,其中:

  • 目标目录中的文件所有权、模式和权限没有正确设置;
  • 未在目标目录中创建设备节点。

由于这些原因,使用目标目录作为新的根,通过chroot运行的命令很可能会失败。

如果您想在chroot中运行目标文件系统,或者作为NFS根运行,那么使用images/中生成的tarball映像并将其作为根解压。

11.7. Why doesn’t Buildroot generate binary packages (.deb, .ipkg…)?

在Buildroot列表中经常讨论的一个特性是“包管理”package management的一般主题。总的来说,这个想法是添加一些跟踪哪个Buildroot包安装了什么文件,目的是:

  • 当从菜单配置中取消选择包时,可以删除包安装的文件;
  • 能够生成可以安装在目标上的二进制包(ipk或其他格式),而不需要重新生成新的根文件系统映像。

通常,大多数人认为这很容易做到:只需跟踪哪个软件包安装了什么,并在软件包未被选中时删除它。然而,实际情况要复杂得多:

  • It is not only about the target/ directory, but also the sysroot in host/<tuple>/sysroot and the host/ directory itself. All files installed in those directories by various packages must be tracked.
  • // 它不仅是关于target/目录,而且还涉及到host/<tuple>/sysroot中的sysroot和host/目录本身。必须跟踪由各种包安装在这些目录中的所有文件。
  • When a package is unselected from the configuration, it is not sufficient to remove just the files it installed. One must also remove all its reverse dependencies (i.e. packages relying on it) and rebuild all those packages. For example, package A depends optionally on the OpenSSL library. Both are selected, and Buildroot is built. Package A is built with crypto support using OpenSSL. Later on, OpenSSL gets unselected from the configuration, but package A remains (since OpenSSL is an optional dependency, this is possible.) If only OpenSSL files are removed, then the files installed by package A are broken: they use a library that is no longer present on the target. Although this is technically doable, it adds a lot of complexity to Buildroot, which goes against the simplicity we try to stick to.
  • // 当从配置中取消选择一个包时,仅仅删除它安装的文件是不够的。还必须删除所有反向依赖项(即依赖于它的包),并重新构建所有这些包。例如,包A可选依赖于OpenSSL库。两者都被选中,构建Buildroot。包A是使用OpenSSL构建的加密支持。稍后,从配置中取消选择OpenSSL,但是包A仍然存在(因为OpenSSL是一个可选的依赖项,所以这是可能的)。如果只删除OpenSSL文件,那么包A安装的文件就会被破坏:它们使用一个不再存在于目标上的库。虽然这在技术上是可行的,但它给Buildroot增加了很多复杂性,这与我们试图坚持的简单性背道而驰。
  • In addition to the previous problem, there is the case where the optional dependency is not even known to Buildroot. For example, package A in version 1.0 never used OpenSSL, but in version 2.0 it automatically uses OpenSSL if available. If the Buildroot .mk file hasn’t been updated to take this into account, then package A will not be part of the reverse dependencies of OpenSSL and will not be removed and rebuilt when OpenSSL is removed. For sure, the .mk file of package A should be fixed to mention this optional dependency, but in the mean time, you can have non-reproducible behaviors.
  • // 除了前面的问题之外,还有一种情况是,可选依赖项甚至不为Buildroot所知。例如,版本1.0中的包A从未使用过OpenSSL,但在版本2.0中,如果可用,它会自动使用OpenSSL。如果Buildroot .mk文件没有被更新以考虑到这一点,那么包A就不会成为OpenSSL的反向依赖项的一部分,也不会在OpenSSL被删除时被删除和重新生成。当然,包A的.mk文件应该被修复,以提到这个可选的依赖关系,但同时,您可能会有不可复制的行为。
  • The request is to also allow changes in the menuconfig to be applied on the output directory without having to rebuild everything from scratch. However, this is very difficult to achieve in a reliable way: what happens when the suboptions of a package are changed (we would have to detect this, and rebuild the package from scratch and potentially all its reverse dependencies), what happens if toolchain options are changed, etc. At the moment, what Buildroot does is clear and simple so its behaviour is very reliable and it is easy to support users. If configuration changes done in menuconfig are applied after the next make, then it has to work correctly and properly in all situations, and not have some bizarre corner cases. The risk is to get bug reports like “I have enabled package A, B and C, then ran make, then disabled package C and enabled package D and ran make, then re-enabled package C and enabled package E and then there is a build failure”. Or worse “I did some configuration, then built, then did some changes, built, some more changes, built, some more changes, built, and now it fails, but I don’t remember all the changes I did and in which order”. This will be impossible to support.
  • // 该请求还允许将menuconfig中的更改应用于输出目录,而不必从头重新构建所有内容。然而,这很难以可靠的方式实现:当包的子选项发生变化时会发生什么(我们必须检测这一点,并从头开始重新构建包和潜在的所有反向依赖项),如果工具链选项发生变化会发生什么,等等。目前,Buildroot所做的是清晰和简单的,所以它的行为是非常可靠的,并且很容易支持用户。如果在menuconfig中所做的配置更改是在下一次make之后应用的,那么它必须在所有情况下都正确地工作,而不是有一些奇怪的角落情况。风险在于获得错误报告,如“我启用了包A、B和C,然后运行make,然后禁用包C,启用包D,然后运行make,然后重新启用包C,启用包E,然后出现构建失败”。或者更糟糕的“我做了一些配置,然后构建,然后做了一些更改,再构建,再构建,再构建,再构建,现在失败了,但我不记得我做过的所有更改以及更改的顺序。”这将是不可能支持的。

由于所有这些原因,结论是,当包未被选中时,添加已安装文件的跟踪来删除它们,或者生成二进制包的存储库,是非常难以可靠地实现的,并且会增加很多复杂性。

在这个问题上,Buildroot开发者发表了如下立场声明:

  • Buildroot strives to make it easy to generate a root filesystem (hence the name, by the way.) That is what we want to make Buildroot good at: building root filesystems.
  • // Buildroot努力使生成根文件系统更容易(顺便说一下,它的名字也因此而来)。这就是我们希望Buildroot擅长的:构建根文件系统。
  • Buildroot is not meant to be a distribution (or rather, a distribution generator.) It is the opinion of most Buildroot developers that this is not a goal we should pursue. We believe that there are other tools better suited to generate a distro than Buildroot is. For example, Open Embedded, or openWRT, are such tools.
  • // Buildroot不是一个发行版(或者更确切地说,是一个发行版生成器)。大多数Buildroot开发者都认为这不是我们应该追求的目标。我们相信有其他工具比Buildroot更适合生成发行版。例如,开放嵌入式或openWRT就是这样的工具。
  • We prefer to push Buildroot in a direction that makes it easy (or even easier) to generate complete root filesystems. This is what makes Buildroot stands out in the crowd (among other things, of course!)
  • // 我们倾向于将Buildroot推向一个更容易(甚至更容易)生成完整根文件系统的方向。这也是Buildroot脱颖而出的原因(当然还有其他原因!)
  • We believe that for most embedded Linux systems, binary packages are not necessary, and potentially harmful. When binary packages are used, it means that the system can be partially upgraded, which creates an enormous number of possible combinations of package versions that should be tested before doing the upgrade on the embedded device. On the other hand, by doing complete system upgrades by upgrading the entire root filesystem image at once, the image deployed to the embedded system is guaranteed to really be the one that has been tested and validated.
  • // 我们相信,对于大多数嵌入式Linux系统,二进制包是不必要的,而且可能是有害的。当使用二进制包时,这意味着系统可以部分升级,这将创建大量可能的包版本组合,在对嵌入式设备进行升级之前,应该对这些组合进行测试。另一方面,通过一次性升级整个根文件系统映像来完成系统升级,可以保证部署到嵌入式系统的映像确实是经过测试和验证的映像。

11.8. How to speed-up the build process?

由于Buildroot经常涉及到对整个系统进行完整的重建,这可能会很长,所以我们提供以下一些技巧来帮助减少构建时间:

  • Use a pre-built external toolchain instead of the default Buildroot internal toolchain. By using a pre-built Linaro toolchain (on ARM) or a Sourcery CodeBench toolchain (for ARM, x86, x86-64, MIPS, etc.), you will save the build time of the toolchain at each complete rebuild, approximately 15 to 20 minutes. Note that temporarily using an external toolchain does not prevent you to switch back to an internal toolchain (that may provide a higher level of customization) once the rest of your system is working;
  • // 使用预构建的外部工具链,而不是默认的Buildroot内部工具链。通过使用预构建的Linaro工具链(在ARM上)或Sourcery CodeBench工具链(适用于ARM、x86、x86-64、MIPS等),您将在每次完成重建时节省工具链的构建时间,大约15到20分钟。请注意,临时使用外部工具链并不妨碍您在系统的其余部分正常工作后切换回内部工具链(可能提供更高级别的定制);
  • Use the ccache compiler cache (see: Section 8.14.3, “Using ccache in Buildroot”);
  • // 使用ccache编译器缓存(见:8.14.3节,“在Buildroot中使用ccache”);
  • Learn about rebuilding only the few packages you actually care about (see Section 8.3, “Understanding how to rebuild packages”), but beware that sometimes full rebuilds are anyway necessary (see Section 8.2, “Understanding when a full rebuild is necessary”);
  • // 了解如何只重新构建您真正关心的几个包(参见8.3节“了解如何重新构建包”),但要注意,有时完全重新构建是必要的(参见8.2节“了解什么时候需要完全重新构建”);
  • Make sure you are not using a virtual machine for the Linux system used to run Buildroot. Most of the virtual machine technologies are known to cause a significant performance impact on I/O, which is really important for building source code;
  • // 确保没有为用于运行Buildroot的Linux系统使用虚拟机。众所周知,大多数虚拟机技术都会对I/O造成显著的性能影响,这对于构建源代码非常重要;
  • Make sure that you’re using only local files: do not attempt to do a build over NFS, which significantly slows down the build. Having the Buildroot download folder available locally also helps a bit.
  • // 确保您只使用本地文件:不要尝试通过NFS进行构建,这会显著降低构建速度。在本地提供Buildroot下载文件夹也有一定帮助。
  • Buy new hardware. SSDs and lots of RAM are key to speeding up the builds.
  • // 购买新的硬件。ssd和大量RAM是加速构建的关键。
  • Experiment with top-level parallel build, see Section 8.12, “Top-level parallel build”.
  • // 尝试顶层并行构建,请参见8.12节“顶层并行构建”

12. Known issues

  • It is not possible to pass extra linker options via BR2_TARGET_LDFLAGS if such options contain a $ sign. For example, the following is known to break: BR2_TARGET_LDFLAGS="-Wl,-rpath='$ORIGIN/../lib'"
  • // 如果这些选项包含$符号,则不可能通过BR2_TARGET_LDFLAGS传递额外的链接器选项。例如,下面的代码会出错
  • The libffi package is not supported on the SuperH 2 and ARC architectures.
  • // superh2和ARC架构不支持libffi包。
  • The prboom package triggers a compiler failure with the SuperH 4 compiler from Sourcery CodeBench, version 2012.09.
  • // prboom包触发superh4编译器从Sourcery CodeBench,版本2012.09编译失败。

13. Legal notice and licensing

13.1. Complying with open source licenses

Buildroot的所有最终产品(工具链、根文件系统、内核、引导加载器)都包含开源软件,在各种许可下发布。

使用开源软件使您可以自由地构建丰富的嵌入式系统,可以从各种各样的包中进行选择,但也强加了一些您必须知道和遵守的义务。有些许可证要求您在产品文档中发布许可证文本。另一些则要求您将软件的源代码重新分发给接收您产品的人。

每个许可的确切要求都记录在每个包中,遵守这些要求是您的责任(或您的法律办公室的责任)。为了让你更容易做到这一点,Buildroot可以为你收集一些你可能需要的材料。要生成这个材料,在你用make menuconfig、make xconfig或make gconfig配置了Buildroot之后,运行:

make legal-info

Buildroot将在legal-info/子目录下的输出目录中收集与法律相关的材料。在那里你会发现:

  • 一个README文件,它总结生成的材料,并包含有关Buildroot不能生成的材料的警告。
  • buildroot.config:这是通常由make menuconfig生成的Buildroot配置文件,它对于重新生成构建是必要的。
  • 所有软件包的源代码;它分别保存在目标包和主机包的sources/和host-sources/子目录中。设置_REDISTRIBUTE = NO的包的源代码将不会被保存。应用的补丁也会被保存,同时还保存一个名为series的文件,该文件按照应用补丁的顺序列出了补丁。补丁与它们所修改的文件处于相同的许可证之下。注意:Buildroot对基于自动工具的软件包的Libtool脚本应用额外的补丁。这些补丁可以在Buildroot源代码的support/libtool下找到,由于技术限制,没有与包源代码一起保存。您可能需要手动收集它们。
  • 清单文件(一个用于主机,一个用于目标包)列出了配置的包、它们的版本、许可和相关信息。有些信息可能没有在Buildroot中定义;这些项目标记为“未知”。
  • 所有包的许可文本,分别位于目标包和主机包的许可/和主机许可/子目录中。如果在Buildroot中没有定义license文件,则不会生成该文件,并且README中的一个警告指出了这一点。

请注意,Buildroot的法律信息特性的目的是生成所有与软件包许可的法律遵从有关的材料。Buildroot并没有试图生产出你必须以某种方式公开的确切材料。当然,生产的材料比严格遵守法律所需要的要多。例如,它为在类似bsd的许可下发布的包生成源代码,您不需要以源代码的形式重新发布这些包。

此外,由于技术限制,Buildroot不能生成您将要或可能需要的一些材料,例如一些外部工具链的工具链源代码和Buildroot源代码本身。当您运行make legal-info时,Buildroot会在README文件中产生警告,通知您无法保存的相关材料。

最后,请记住,make legal-info的输出基于每个包recipes中的声明性语句。Buildroot开发人员尽其所能保持那些声明性语句尽可能准确,就他们所知。然而,很可能这些陈述性的陈述并不都完全准确或详尽无遗。您(或您的法律部门)在使用make legal-info作为您自己的合规交付之前,必须检查其输出。参见Buildroot发行版根目录的copy文件中的NO WARRANTY条款(第11和12条)。

13.2. Complying with the Buildroot license

Buildroot本身是一个开源软件,根据GNU通用公共许可证(General Public License)版本2或(由您选择)任何更新版本发布,除了下面详细介绍的包补丁。然而,作为一个构建系统,它通常不是最终产品的一部分:如果您为一个设备开发根文件系统、内核、引导加载程序或工具链,那么Buildroot的代码只出现在开发机器上,而不是在设备存储中。

然而,Buildroot开发人员的普遍看法是,当发布包含gpl许可软件的产品时,应该将Buildroot源代码与其他包的源代码一起发布。这是因为GNU GPL将可执行作品的“完整源代码”定义为“它包含的所有模块的所有源代码,加上任何关联的接口定义文件,加上用来控制可执行作品的编译和安装的脚本”。Buildroot是用于控制可执行文件的编译和安装的脚本的一部分,因此它被认为是必须重新分发的材料的一部分。

请记住,这只是Buildroot开发人员的意见,如果您有任何疑问,应该咨询您的法律部门或律师。

13.2.1. Patches to packages

Buildroot还捆绑补丁文件,应用于各种包的源代码。这些补丁不在Buildroot的许可范围内。相反,它们是由应用补丁的软件的许可证所覆盖的。当上述软件在多个许可下可用时,Buildroot补丁只在公共可访问的许可下提供。

技术细节请参见第19章补丁包

14. Beyond Buildroot

14.1. Boot the generated images

14.1.1. NFS boot

要实现nfs引导,请在filesystem映像菜单中启用tar根文件系统。

完成构建后,只需运行以下命令设置nfs根目录:

sudo tar -xavf /path/to/output_dir/rootfs.tar -C /path/to/nfs_root_dir

请记住将此路径添加到/etc/exports.

然后,可以从目标执行nfs引导。

14.1.2. Live CD

要构建一个实时CD映像,请启用文件系统映像菜单中的iso映像选项。注意,这个选项只适用于x86和x86-64体系结构,如果您正在使用Buildroot构建内核的话。

您可以使用IsoLinux、Grub或Grub 2作为引导加载程序构建一个活动CD映像,但只有IsoLinux支持使该映像同时作为活动CD和活动USB使用(通过构建混合映像选项)。

You can test your live CD image using QEMU:

qemu-system-i386 -cdrom output/images/rootfs.iso9660

Or use it as a hard-drive image if it is a hybrid ISO:

qemu-system-i386 -hda output/images/rootfs.iso9660

It can be easily flashed to a USB drive with dd:

dd if=output/images/rootfs.iso9660 of=/dev/sdb

14.2. Chroot

如果你想在生成的映像中使用chroot,那么有几件事你应该注意:

  • you should setup the new root from the tar root filesystem image;
  • // 您应该从tar根文件系统映像中设置新的根;
  • either the selected target architecture is compatible with your host machine, or you should use some qemu-* binary and correctly set it within the binfmt properties to be able to run the binaries built for the target on your host machine;
  • // 选择的目标体系结构与您的主机兼容,或者您应该使用一些qemu-*二进制文件,并在binfmt属性中正确设置它,以便能够在您的主机上运行为目标构建的二进制文件;
  • Buildroot does not currently provide host-qemu and binfmt correctly built and set for that kind of use.
  • // Buildroot目前没有提供正确构建和设置的host-qemu和binfmt。

III. Developer guide

15. How Buildroot works

正如上面提到的,Buildroot基本上是一组makefile文件,它们使用正确的选项下载、配置和编译软件。它还包括各种软件包的补丁——主要是交叉编译工具链(gcc、binutils和uClibc)中涉及的补丁。

基本上每个软件包都有一个Makefile,它们以.mk扩展名命名。makefile被分成许多不同的部分:

  • The toolchain/ directory contains the Makefiles and associated files for all software related to the cross-compilation toolchain: binutils, gcc, gdb, kernel-headers and uClibc.
  • // 包含与交叉编译工具链相关的所有软件的Makefiles和相关文件:binutils、gcc、gdb、kernel-headers和uClibc。
  • The arch/ directory contains the definitions for all the processor architectures that are supported by Buildroot.
  • // 包含Buildroot支持的所有处理器体系结构的定义。
  • The package/ directory contains the Makefiles and associated files for all user-space tools and libraries that Buildroot can compile and add to the target root filesystem. There is one sub-directory per package.
  • // 包含所有用户空间工具和库的makefile和相关文件,Buildroot可以编译这些工具和库并将它们添加到目标根文件系统中。每个包有一个子目录。
  • The linux/ directory contains the Makefiles and associated files for the Linux kernel.
  • // 包含linux内核的Makefiles和相关文件。
  • The boot/ directory contains the Makefiles and associated files for the bootloaders supported by Buildroot.
  • // 包含Buildroot支持的引导加载程序的makefile和相关文件。
  • The system/ directory contains support for system integration, e.g. the target filesystem skeleton and the selection of an init system.
  • // 包含对系统集成的支持,例如目标文件系统骨架和初始化系统的选择。
  • The fs/ directory contains the Makefiles and associated files for software related to the generation of the target root filesystem image.
  • // 包含Makefiles和与生成目标根文件系统映像相关的软件的相关文件。

每个目录至少包含2个文件:

  • something.mk is the Makefile that downloads, configures, compiles and installs the package something.
  • // 是一个Makefile,用来下载,配置,编译和安装包什么的。
  • Config.in is a part of the configuration tool description file. It describes the options related to the package.
  • // 是配置工具描述文件的一部分。它描述了包相关的选项。

主Makefile执行以下步骤(一旦配置完成):

  • Create all the output directories: staging, target, build, etc. in the output directory (output/ by default, another value can be specified using O=)
  • // 在输出目录中创建所有输出目录:staging, target, build等(默认是output/,可以使用O=指定另一个值)
  • Generate the toolchain target. When an internal toolchain is used, this means generating the cross-compilation toolchain. When an external toolchain is used, this means checking the features of the external toolchain and importing it into the Buildroot environment.
  • // 生成工具链目标。当使用内部工具链时,这意味着生成交叉编译工具链。当使用外部工具链时,这意味着检查外部工具链的特性并将其导入Buildroot环境。
  • Generate all the targets listed in the TARGETS variable. This variable is filled by all the individual components’ Makefiles. Generating these targets will trigger the compilation of the userspace packages (libraries, programs), the kernel, the bootloader and the generation of the root filesystem images, depending on the configuration.
  • // 生成targets变量中列出的所有目标。该变量由所有独立组件的makefile填充。生成这些目标将触发用户空间包(库、程序)、内核、引导加载程序的编译,以及根文件系统映像的生成,具体取决于配置。

16. Coding style

总之,这些编码风格规则可以帮助您在Buildroot中添加新文件或重构现有文件。

如果你稍微修改一些现有的文件,重要的是保持整个文件的一致性,这样你就可以:

  • 要么遵循此文件中使用的可能被弃用的编码风格,
  • 或者完全返工以使其符合这些规则。

16.1. Config.in file

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 and help行缩进一个制表符。
  • 帮助文本本身应该用一个制表符和两个空格缩进。
  • 帮助文本应该换行以适应72列,其中制表符计数为8,因此文本本身为62个字符。

16.2. The .mk file

  • Header: The file starts with a header. It contains the module name, preferably in lowercase, enclosed between separators made of 80 hashes. A blank line is mandatory after the header:
  • // 文件以头文件开始。它包含模块名,最好是小写,用由80个散列组成的分隔符包围。标题后必须有一个空行:
################################################################################
#
# libfoo
#
################################################################################
  • Assignment: use = preceded and followed by one space:
  • // 赋值: = 前面和后面加一个空格:
LIBFOO_VERSION = 1.0
LIBFOO_CONF_OPTS += --without-python-support

Do not align the = signs. // 不要将=号对齐。

  • Indentation: use tab only: // 缩进:只使用制表符:
define LIBFOO_REMOVE_DOC
        $(RM) -fr $(TARGET_DIR)/usr/share/libfoo/doc \
                $(TARGET_DIR)/usr/share/man/man3/libfoo*
endef

请注意,定义块中的commands应该总是以tab开始,这样make将它们识别为命令。

  • Optional dependency: // 选项依赖:

    • Prefer multi-line syntax. // 喜欢多行语法。

    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,)
    
    • Keep configure options and dependencies close together.
    • // 保持配置选项和依赖项紧密相连。
  • Optional hooks: keep hook definition and assignment together in one if block.

  • // 可选钩子:将钩子定义和赋值放在一个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
    

16.3. The documentation

The documentation uses the asciidoc format.

For further details about the asciidoc syntax, refer to http://www.methods.co.nz/asciidoc/userguide.html.

16.4. Support scripts

Some scripts in the support/ and utils/ directories are written in Python and should follow the PEP8 Style Guide for Python Code.

17. Adding support for a particular board

Buildroot包含几个公开可用硬件板的基本配置,这样这样一个板的用户就可以轻松地构建一个已知可以工作的系统。你也可以在Buildroot中添加对其他板的支持。

为此,您需要创建一个普通的Buildroot配置,它为硬件构建一个基本的系统:(内部)工具链、内核、引导加载程序、文件系统和一个简单的BusyBox-only用户空间。不应该选择特定的包:配置应该尽可能少,并且应该只为目标平台构建一个可工作的基本BusyBox系统。当然,您可以为您的内部项目使用更复杂的配置,但是Buildroot项目将只集成基本的板配置。这是因为包选择是高度特定于应用程序的。

一旦您有了一个已知的工作配置,运行make savedefconfig。这将在Buildroot源树的根生成一个最小的defconfig文件。将此文件移到configs/目录中,并将其重命名为<boardname>_defconfig。如果配置有点复杂,最好手动重新格式化并将其划分为多个部分,每个部分之前都有注释。典型的部分是架构、工具链选项(通常只是linux头文件版本)、固件、引导装载程序、内核和文件系统。

对于不同的组件,总是使用固定版本或提交散列,而不是“最新”版本。例如,将BR2_LINUX_KERNEL_CUSTOM_VERSION=yBR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE设置为您测试的内核版本。

建议尽可能多地使用Linux内核和引导加载程序的上游版本,并尽可能多地使用默认的内核和引导加载程序配置。如果它们对您的板不正确,或没有默认存在,我们鼓励您发送修复到相应的上游项目。

然而,与此同时,您可能希望存储特定于目标平台的内核或引导加载程序配置或补丁。为此,创建一个board/<manufacturer>和子目录board/<manufacturer>/<boardname>。然后,您可以将补丁和配置存储在这些目录中,并从主要的Buildroot配置中引用它们。有关更多细节,请参阅第9章,特定于项目的定制

18. Adding new packages to Buildroot

本节介绍如何将新的包(用户空间库或应用程序)集成到Buildroot中。它还展示了如何集成现有的包,这是修复问题或调优其配置所需要的。

当您添加一个新的包时,请确保在各种条件下对它进行测试(参见第18.24.3节,“如何测试您的包”),并检查它的编码风格(参见第18.24.2节,“如何检查编码风格”)。

18.1. Package directory

首先,在软件package目录下为您的软件创建一个目录,例如libfoo

有些包按主题分组在子目录中:x11r7qt5gstreamer。如果您的包符合其中一个类别,那么在这些类别中创建您的包目录。但是,不建议创建新的子目录。

18.2. Config files

对于要在配置工具中显示的包,您需要在您的包目录中创建一个Config文件。有两种类型:Config.in and Config.in.host

18.2.1. Config.in file

对于在目标上使用的包,创建一个名为Config.in的文件。这个文件将包含与我们的libfoo软件相关的选项描述,这些选项将在配置工具中使用和显示。它基本上应该包含:

config BR2_PACKAGE_LIBFOO
        bool "libfoo"
        help
          This is a comment that explains what libfoo is. The help text
          should be wrapped.

          http://foosoftware.org/libfoo/

关于配置选项的bool行、help行和其他元数据信息必须用一个tab缩进。帮助文本本身应该缩进一个制表符和两个空格,行应该换行以适应72列,其中制表符计数为8,所以文本本身的62个字符。帮助文本必须在空行之后提到项目的上游URL。

作为特定于Buildroot的约定,属性的顺序如下:

  • The type of option: bool, string… with the prompt
  • // 选项的类型
  • If needed, the default value(s)
  • // 默认值
  • Any dependencies on the target in depends on form
  • // depends on表单,描述对目标的依赖
  • Any dependencies on the toolchain in depends on form
  • // depends on表单,描述对工具链的依赖
  • Any dependencies on other packages in depends on form
  • // depends on表单,描述对其他包的依赖
  • Any dependency of the select form
  • // select表单,描述任何依赖
  • The help keyword and help text.
  • // 帮助关键字和帮助文本。

您可以将其他子选项添加到if BR2_PACKAGE_LIBFOO…endif语句中,以配置软件中的特定内容。您可以查看其他包中的示例。配置的语法与内核Kconfig文件相同。此语法的文档可在 http://kernel.org/doc/Documentation/kbuild/kconfig-language.txt 获得

最后,您必须将新的libfoo/Config添加进package/Config.in(或者在一个类别子目录中,如果您决定将您的包放在一个现有类别中)。其中包含的文件按每个类别的字母顺序排序,除了包的名字之外不应该包含任何内容。

source "package/libfoo/Config.in"

18.2.2. Config.in.host file

还需要为主机系统构建一些包。这里有两个选择:

  • The host package is only required to satisfy build-time dependencies of one or more target packages. In this case, add host-foo to the target package’s BAR_DEPENDENCIES variable. No Config.in.host file should be created.
  • // 宿主包只需要满足一个或多个目标包的构建时依赖关系。在这种情况下,将host-foo添加到目标包的BAR_DEPENDENCIES变量中。不需要创建Config.in.host文件。
  • The host package should be explicitly selectable by the user from the configuration menu. In this case, create a Config.in.host file for that host package:
  • // 用户应该可以从配置菜单中显式地选择主机包。在本例中,为该主机包创建一个Config.in.host文件:
config BR2_PACKAGE_HOST_FOO
        bool "host foo"
        help
          This is a comment that explains what foo for the host is.

          http://foosoftware.org/foo/

Config.in相同的编码风格和选项。在文件中是有效的。

Finally you have to add your new libfoo/Config.in.host to package/Config.in.host. The files included there are sorted alphabetically and are NOT supposed to contain anything but the bare name of the package.

最后,必须添加新的libfoo/Config.in.hostpackage/Config.in.host。其中包含的文件是按字母顺序排序的,除了包的名字之外不应该包含任何内容。

source "package/foo/Config.in.host"

然后主机包在Host utilities菜单中有效。

18.2.3. Choosing depends on or select

在包的Config.in文件中还必须确保启用了依赖项。通常,Buildroot使用以下规则:

  • Use a select type of dependency for dependencies on libraries. These dependencies are generally not obvious and it therefore make sense to have the kconfig system ensure that the dependencies are selected. For example, the libgtk2 package uses select BR2_PACKAGE_LIBGLIB2 to make sure this library is also enabled. The select keyword expresses the dependency with a backward semantic.
  • // 对库上的依赖项使用 select 类型的依赖项。这些依赖关系通常不明显,因此让kconfig系统确保选择了这些依赖关系是有意义的。例如,libgtk2包使用select BR2_PACKAGE_LIBGLIB2来确保也启用了这个库。select关键字用向后语义表示依赖关系。
  • Use a depends on type of dependency when the user really needs to be aware of the dependency. Typically, Buildroot uses this type of dependency for dependencies on target architecture, MMU support and toolchain options (see Section 18.2.4, “Dependencies on target and toolchain options”), or for dependencies on “big” things, such as the X.org system. The depends on keyword expresses the dependency with a forward semantic.
  • // 当用户真正需要知道依赖项时,使用依赖项类型。通常,Buildroot将这种类型的依赖用于目标体系结构、MMU支持和工具链选项(参见18.2.4节“目标和工具链选项的依赖”),或者用于“大”事物的依赖,如X.org系统。依赖关键字用前向语义表示依赖关系。

请注意。kconfig语言的当前问题是这两个依赖语义没有内部链接。因此,有可能select一个包,它的一个依赖项/需求没有被满足。

下面的例子说明了select和depends的用法:

config BR2_PACKAGE_RRDTOOL
        bool "rrdtool"
        depends on BR2_USE_WCHAR
        select BR2_PACKAGE_FREETYPE
        select BR2_PACKAGE_LIBART
        select BR2_PACKAGE_LIBPNG
        select BR2_PACKAGE_ZLIB
        help
          RRDtool is the OpenSource industry standard, high performance
          data logging and graphing system for time series data.

          http://oss.oetiker.ch/rrdtool/

comment "rrdtool needs a toolchain w/ wchar"
        depends on !BR2_USE_WCHAR

请注意,这两种依赖类型仅对相同类型的依赖关系具有传递性。

这意味着,在下面的例子中:

config BR2_PACKAGE_A
        bool "Package A"

config BR2_PACKAGE_B
        bool "Package B"
        depends on BR2_PACKAGE_A

config BR2_PACKAGE_C
        bool "Package C"
        depends on BR2_PACKAGE_B

config BR2_PACKAGE_D
        bool "Package D"
        select BR2_PACKAGE_B

config BR2_PACKAGE_E
        bool "Package E"
        select BR2_PACKAGE_D
  • Selecting Package C will be visible if Package B has been selected, which in turn is only visible if Package A has been selected.
  • // 如果选择了包B,那么选择包C将是可见的,并且只有在选择了包A时才可见。
  • Selecting Package E will select Package D, which will selectPackage B, it will not check for the dependencies ofPackage B, so it will not selectPackage A`.
  • // 选择包E将选择包D,包D将选择包B,它不会检查包B的依赖关系,所以它不会选择包A。
  • Since Package B is selected but Package A is not, this violates the dependency of Package B on Package A. Therefore, in such a situation, the transitive dependency has to be added explicitly:
  • // 因为选择了包B而没有选择包A,这违反了包B对包A的依赖关系。因此,在这种情况下,必须显式地添加传递依赖关系:
config BR2_PACKAGE_D
        bool "Package D"
        select BR2_PACKAGE_B
        depends on BR2_PACKAGE_A

config BR2_PACKAGE_E
        bool "Package E"
        select BR2_PACKAGE_D
        depends on BR2_PACKAGE_A

总的来说,对于包库依赖项,应该首选select

请注意,这些依赖项将确保依赖项选项也被启用,但不一定是在您的包之前构建的。为此,还需要在包的.mk文件中表示依赖关系。

进一步的格式化细节:参见编码风格

18.2.4. Dependencies on target and toolchain options

许多包依赖于工具链的某些选项:C库、c++支持、线程支持、RPC支持、wchar支持或动态库支持的选择。有些包只能在特定的目标体系结构上构建,或者在处理器中有MMU的情况下。

这些依赖项必须用Config.in文件中的适当依赖项语句来表示。此外,对于工具链选项的依赖项,当选项未启用时,应该显示注释comment,以便用户知道包不可用的原因。对目标体系结构或MMU支持的依赖不应该在注释comment中可见:因为用户不太可能自由选择另一个目标,显式地显示这些依赖没有什么意义。

只有当满足工具链选项依赖关系时,config选项本身才会可见,注释comment才应该可见。这意味着包的所有其他依赖项(包括对目标体系结构和MMU支持的依赖项)都必须在注释定义上重复。为了保持清晰,这些非工具链选项的依赖语句应该与工具链选项的依赖语句分开。如果在同一个文件(通常是主包)中存在对配置选项的依赖,最好使用全局If…endif构造,而不是在注释和其他配置选项上重复依赖语句。

foo包的依赖注释comment的一般格式是:

foo needs a toolchain w/ featA, featB, featC

for example:

mpd needs a toolchain w/ C++, threads, wchar

or

crda needs a toolchain w/ threads

请注意,本文故意保持简短,以便适合80个字符的终端。

本节的其余部分枚举了不同的目标和工具链选项、要依赖的相应配置符号以及注释中要使用的文本。

  • Target architecture

    • Dependency symbol: BR2_powerpc, BR2_mips, … (see arch/Config.in)
    • Comment string: no comment to be added
  • MMU support

    • Dependency symbol: BR2_USE_MMU
    • Comment string: no comment to be added
  • Gcc _sync* built-ins used for atomic operations. They are available in variants operating on 1 byte, 2 bytes, 4 bytes and 8 bytes. Since different architectures support atomic operations on different sizes, one dependency symbol is available for each size:

    • Dependency symbol: BR2_TOOLCHAIN_HAS_SYNC_1 for 1 byte, BR2_TOOLCHAIN_HAS_SYNC_2 for 2 bytes, BR2_TOOLCHAIN_HAS_SYNC_4 for 4 bytes, BR2_TOOLCHAIN_HAS_SYNC_8 for 8 bytes.
    • Comment string: no comment to be added
  • Gcc _atomic* built-ins used for atomic operations.

    • Dependency symbol: BR2_TOOLCHAIN_HAS_ATOMIC.
    • Comment string: no comment to be added
  • Kernel headers

    • Dependency symbol: BR2_TOOLCHAIN_HEADERS_AT_LEAST_X_Y, (replace X_Y with the proper version, see toolchain/Config.in)
    • Comment string: headers >= X.Y and/or headers <= X.Y (replace X.Y with the proper version)
  • GCC version

    • Dependency symbol: BR2_TOOLCHAIN_GCC_AT_LEAST_X_Y, (replace X_Y with the proper version, see toolchain/Config.in)
    • Comment string: gcc >= X.Y and/or gcc <= X.Y (replace X.Y with the proper version)
  • Host GCC version

    • Dependency symbol: BR2_HOST_GCC_AT_LEAST_X_Y, (replace X_Y with the proper version, see Config.in)
    • Comment string: no comment to be added
    • Note that it is usually not the package itself that has a minimum host GCC version, but rather a host-package on which it depends.
  • C library

    • Dependency symbol: BR2_TOOLCHAIN_USES_GLIBC, BR2_TOOLCHAIN_USES_MUSL, BR2_TOOLCHAIN_USES_UCLIBC
    • Comment string: for the C library, a slightly different comment text is used: foo needs a glibc toolchain, or foo needs a glibc toolchain w/ C++
  • C++ support

    • Dependency symbol: BR2_INSTALL_LIBSTDCPP
    • Comment string: C++
  • D support

    • Dependency symbol: BR2_TOOLCHAIN_HAS_DLANG
    • Comment string: Dlang
  • Fortran support

    • Dependency symbol: BR2_TOOLCHAIN_HAS_FORTRAN
    • Comment string: fortran
  • thread support

    • Dependency symbol: BR2_TOOLCHAIN_HAS_THREADS
    • Comment string: threads (unless BR2_TOOLCHAIN_HAS_THREADS_NPTL is also needed, in which case, specifying only NPTL is sufficient)
  • NPTL thread support

    • Dependency symbol: BR2_TOOLCHAIN_HAS_THREADS_NPTL
    • Comment string: NPTL
  • RPC support

    • Dependency symbol: BR2_TOOLCHAIN_HAS_NATIVE_RPC
    • Comment string: RPC
  • wchar support

    • Dependency symbol: BR2_USE_WCHAR
    • Comment string: wchar
  • dynamic library

    • Dependency symbol: !BR2_STATIC_LIBS
    • Comment string: dynamic library

18.2.5. Dependencies on a Linux kernel built by buildroot

有些包需要一个Linux内核来由buildroot构建。这些通常是内核模块或固件。应该在Config.in文件中添加注释表达这种依赖关系,类似于工具链选项上的依赖关系。一般格式为:

foo needs a Linux kernel to be built

如果工具链选项和Linux内核都有依赖关系,请使用以下格式:

foo needs a toolchain w/ featA, featB, featC and a Linux kernel to be built

18.2.6. Dependencies on udev /dev management

如果一个包需要 udev /dev管理,它应该依赖于符号BR2_PACKAGE_HAS_UDEV,并且应该添加以下注释:

foo needs udev /dev management

如果同时存在对工具链选项和udev /dev管理的依赖,使用以下格式:

foo needs udev /dev management and a toolchain w/ featA, featB, featC

18.2.7. Dependencies on features provided by virtual packages

一些特性可以由多个包提供,比如openGL库。

关于虚拟包的更多信息,请参见第18.11节“虚拟包的基础结构”

18.3. The .mk file

最后,这是最困难的部分。创建一个名为libfoo.mk的文件。它描述了该包应该如何下载、配置、构建、安装等。

根据包类型的不同,.mk文件必须以不同的方式编写,使用不同的基础结构:

  • Makefiles for generic packages (not using autotools or CMake): These are based on an infrastructure similar to the one used for autotools-based packages, but require a little more work from the developer. They specify what should be done for the configuration, compilation and installation of the package. This infrastructure must be used for all packages that do not use the autotools as their build system. In the future, other specialized infrastructures might be written for other build systems. We cover them through in a tutorial and a reference.
  • // 通用包的生成文件(不使用自动工具或CMake):它们基于与基于自动工具的包类似的基础架构,但需要开发人员多做一些工作。它们指定应该为包的配置、编译和安装做什么。对于所有不使用自动工具作为其构建系统的包,必须使用此基础结构。将来,可能会为其他构建系统编写其他专门的基础结构。我们将在教程和参考资料中详细介绍它们。
  • Makefiles for autotools-based software (autoconf, automake, etc.): We provide a dedicated infrastructure for such packages, since autotools is a very common build system. This infrastructure must be used for new packages that rely on the autotools as their build system. We cover them through a tutorial and reference.
  • // 为基于自动工具的软件(autoconf, automake等)生成文件:我们为这些包提供了专门的基础设施,因为自动工具是一个非常常见的构建系统。这个基础设施必须用于依赖于自动工具作为其构建系统的新包。我们通过教程和参考来介绍它们。
  • Makefiles for cmake-based software: We provide a dedicated infrastructure for such packages, as CMake is a more and more commonly used build system and has a standardized behaviour. This infrastructure must be used for new packages that rely on CMake. We cover them through a tutorial and reference.
  • // 基于CMake的软件的makefile:我们为这类包提供了专门的基础设施,因为CMake是一个越来越常用的构建系统,并且具有标准化的行为。这个基础设施必须用于依赖于CMake的新包。我们通过教程和参考来介绍它们。
  • Makefiles for Python modules: We have a dedicated infrastructure for Python modules that use either the distutils or the setuptools mechanism. We cover them through a tutorial and a reference.
  • // Python模块的生成文件:我们有一个专门用于Python模块的基础结构,可以使用distutils或setuptools机制。我们通过教程和参考来介绍它们。
  • Makefiles for Lua modules: We have a dedicated infrastructure for Lua modules available through the LuaRocks web site. We cover them through a tutorial and a reference.
  • // 为Lua模块生成文件:我们在LuaRocks网站上有专门的Lua模块基础设施。我们通过教程和参考来介绍它们。

进一步的格式化细节:请参见编写规则

18.4. The .hash file

如果可能,您必须添加第三个名为libfoo.hash的文件。它包含libfoo包下载文件的哈希值。不添加.hash文件的唯一原因是由于下载包的方式而无法进行hash检查。

当一个包有版本选择选项时,哈希文件可以存储在以版本命名的子目录中,例如package/libfoo/1.2.3/libfoo.hash。如果不同的版本具有不同的许可条款,但它们存储在同一个文件中,那么这一点尤其重要。否则,hash 文件应该留在包的目录中。

存储在该文件中的 hash 用于验证下载文件和许可证文件的完整性。

这个文件的格式是每行检查哈希值的文件,每行有以下三个字段,用两个空格分隔:

  • the type of hash, one of:
    • md5, sha1, sha224, sha256, sha384, sha512, none
  • the hash of the file:
    • for none, one or more non-space chars, usually just the string xxx
    • for md5, 32 hexadecimal characters
    • for sha1, 40 hexadecimal characters
    • for sha224, 56 hexadecimal characters
    • for sha256, 64 hexadecimal characters
    • for sha384, 96 hexadecimal characters
    • for sha512, 128 hexadecimal characters
  • the name of the file:
    • for a source archive: the basename of the file, without any directory component,
    • for a license file: the path as it appears in FOO_LICENSE_FILES.

#符号开头的行被认为是注释,并被忽略。空行会被忽略。

一个文件可以有多个hash,每个hash在它自己的行上。在这种情况下,所有hash必须匹配。

请注意。理想情况下,存储在该文件中的哈希值应该与上游发布的哈希值匹配,例如,在其网站上,在电子邮件公告中……如果upstream不提供任何哈希值,或者只提供md5哈希值,那么至少自己计算一个强散列(最好是sha256,但不是md5),并在散列上面的注释行中提到这一点。

请注意。许可证文件的哈希值用于检测许可证变更,当软件包版本被碰撞时。在make legal-info目标运行期间检查哈希值。对于具有多个版本的包(如Qt5),在该包的子目录<packageversion>中创建哈希文件(参见第19.2节,“如何应用补丁”)。

nonehash类型保留给那些从存储库下载的档案,比如git克隆,subversion签出…

下面的例子定义了上游发布的libfoo-1.2.3.tar.bz2主版本的sha1sha256。来自上游的md5和本地计算的sha256哈希值(二进制blob), sha256值(下载的补丁),以及没有哈希值的存档:

# Hashes from: http://www.foosoftware.org/download/libfoo-1.2.3.tar.bz2.{sha1,sha256}:
sha1  486fb55c3efa71148fe07895fd713ea3a5ae343a  libfoo-1.2.3.tar.bz2
sha256  efc8103cc3bcb06bda6a781532d12701eb081ad83e8f90004b39ab81b65d4369  libfoo-1.2.3.tar.bz2

# md5 from: http://www.foosoftware.org/download/libfoo-1.2.3.tar.bz2.md5, sha256 locally computed:
md5  2d608f3c318c6b7557d551a5a09314f03452f1a1  libfoo-data.bin
sha256  01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b  libfoo-data.bin

# Locally computed:
sha256  ff52101fb90bbfc3fe9475e425688c660f46216d7e751c4bbdb1dc85cdccacb9  libfoo-fix-blabla.patch

# No hash for 1234:
none  xxx  libfoo-1234.tar.gz

# Hash for license files:
sha256  a45a845012742796534f7e91fe623262ccfb99460a2bd04015bd28d66fba95b8  COPYING
sha256  01b1f9f2c8ee648a7a596a1abe8aa4ed7899b1c9e5551bda06da6e422b04aa55  doc/COPYING.LGPL

如果存在.hash文件,并且它包含一个或多个用于下载文件的哈希值,则Buildroot(下载后)计算的哈希值必须与.hash文件中存储的哈希值匹配。如果一个或多个哈希值不匹配,Buildroot认为这是一个错误,删除下载的文件,并中止。

如果.hash文件存在,但它不包含下载文件的哈希值,Buildroot认为这是一个错误并终止。但是,下载的文件留在下载目录中,因为这通常表明.hash文件是错误的,但是下载的文件可能是正确的。

哈希值目前检查的是从http/ftp服务器、Git存储库、使用scp复制的文件和本地文件中获取的文件。对于其他版本控制系统(如Subversion、CVS等),不会检查哈希值,因为从这些版本控制系统获取源代码时,Buildroot目前不会生成可重复的tarballs。

哈希应该只添加在.hash文件中,用于保证稳定的文件。例如,Github自动生成的补丁不能保证是稳定的,因此它们的哈希值会随着时间的推移而改变。不应该下载此类补丁,而应该在本地将其添加到包文件夹中。

如果.hash文件丢失,则根本不进行检查。

18.5. Infrastructure for packages with specific build systems

对于带有特定构建系统的包,我们的意思是所有的构建系统不是标准的包(比如autotools或CMake)。这通常包括构建系统基于手工编写的makefile或shell脚本的包。

18.5.1. generic-package tutorial

01: ################################################################################
02: #
03: # libfoo
04: #
05: ################################################################################
06:
07: LIBFOO_VERSION = 1.0
08: LIBFOO_SOURCE = libfoo-$(LIBFOO_VERSION).tar.gz
09: LIBFOO_SITE = http://www.foosoftware.org/download
10: LIBFOO_LICENSE = GPL-3.0+
11: LIBFOO_LICENSE_FILES = COPYING
12: LIBFOO_INSTALL_STAGING = YES
13: LIBFOO_CONFIG_SCRIPTS = libfoo-config
14: LIBFOO_DEPENDENCIES = host-libaaa libbbb
15:
16: define LIBFOO_BUILD_CMDS
17:     $(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D) all
18: endef
19:
20: define LIBFOO_INSTALL_STAGING_CMDS
21:     $(INSTALL) -D -m 0755 $(@D)/libfoo.a $(STAGING_DIR)/usr/lib/libfoo.a
22:     $(INSTALL) -D -m 0644 $(@D)/foo.h $(STAGING_DIR)/usr/include/foo.h
23:     $(INSTALL) -D -m 0755 $(@D)/libfoo.so* $(STAGING_DIR)/usr/lib
24: endef
25:
26: define LIBFOO_INSTALL_TARGET_CMDS
27:     $(INSTALL) -D -m 0755 $(@D)/libfoo.so* $(TARGET_DIR)/usr/lib
28:     $(INSTALL) -d -m 0755 $(TARGET_DIR)/etc/foo.d
29: endef
30:
31: define LIBFOO_USERS
32:     foo -1 libfoo -1 * - - - LibFoo daemon
33: endef
34:
35: define LIBFOO_DEVICES
36:     /dev/foo  c  666  0  0  42  0  -  -  -
37: endef
38:
39: define LIBFOO_PERMISSIONS
40:     /bin/foo  f  4755  foo  libfoo   -  -  -  -  -
41: endef
42:
43: $(eval $(generic-package))
  • Makefile从第7行到第11行开始,包含元数据信息:包的版本(LIBFOO_VERSION)、包含包的tarball名称(LIBFOO_SOURCE)(推荐使用xz格式的tarball)、可以从Internet上下载tarball的位置(LIBFOO_SITE)、许可证(LIBFOO_LICENSE)和带有许可证文本的文件(LIBFOO_LICENSE_FILES)。所有变量都必须以相同的前缀开始,在本例中是LIBFOO_。这个前缀总是包名的大写版本(请参阅下面了解包名的定义位置)。

  • 在第12行,我们指定这个包想要安装一些东西到暂存空间。库经常需要这样做,因为它们必须在暂存空间中安装头文件和其他开发文件。这将确保执行LIBFOO_INSTALL_STAGING_CMDS变量中列出的命令。

  • 在第13行中,我们指定需要对LIBFOO_INSTALL_STAGING_CMDS阶段安装的一些libfoo-config文件进行一些修复。这些*-config文件是位于$(STAGING_DIR)/usr/bin目录下的可执行shell脚本文件,由其他第三方包执行,以找出这个特定包的位置和链接标志。

    问题是,所有这些*-config文件默认情况下给出错误的主机系统链接标志,不适合交叉编译。

    For example: -I/usr/include instead of -I$(STAGING_DIR)/usr/include or: -L/usr/lib instead of -L$(STAGING_DIR)/usr/lib

    因此,对这些脚本执行了一些sed魔法,使它们给出正确的标志。给LIBFOO_CONFIG_SCRIPTS的参数是需要修复的shell脚本的文件名。所有这些名称都相对于$(STAGING_DIR)/usr/bin,如果需要,可以给出多个名称。

    另外,LIBFOO_CONFIG_SCRIPTS中列出的脚本将从$(TARGET_DIR)/usr/bin中删除,因为它们在目标上不需要。

    Example 18.1. Config script: divine package

    包 divine 的安装shell脚本$(STAGING_DIR)/usr/bin/divine-config

    所以它的修正是:

    DIVINE_CONFIG_SCRIPTS = divine-config
    

    Example 18.2. Config script: imagemagick package:

    Package imagemagick 安装以下脚本: $(STAGING_DIR)/usr/bin/{Magick,Magick++,MagickCore,MagickWand,Wand}-config

    So it’s fixup would be:

    IMAGEMAGICK_CONFIG_SCRIPTS = \
    Magick-config Magick++-config \
    MagickCore-config MagickWand-config Wand-config
    
  • 在第14行,我们指定了这个包所依赖的依赖项列表。这些依赖项是用小写的包名列出的,可以是目标包(没有host-前缀),也可以是主机包(有host-前缀)。Buildroot将确保在当前包启动其配置之前构建和安装所有这些包。

  • Makefile的其余部分,第16到29行。定义了在包的配置、编译和安装的不同步骤中应该做什么。LIBFOO_BUILD_CMDS告诉应该执行哪些步骤来构建包。LIBFOO_INSTALL_STAGING_CMDS告诉应该执行哪些步骤来将包安装到staging空间中。LIBFOO_INSTALL_TARGET_CMDS告诉在目标空间中安装包应该执行哪些步骤。

    所有这些步骤都依赖于$(@D)变量,该变量包含提取包源代码的目录。

  • 对31到33行,我们定义了一个由这个包使用的用户(例如,以非root身份运行守护进程)(LIBFOO_USERS)。

  • 在第35到37行,我们定义了一个由这个包使用的设备节点文件(LIBFOO_DEVICES)。

  • 在39到41行,我们定义了权限来设置这个包安装的特定文件(LIBFOO_PERMISSIONS)。

  • 最后,在第43行,我们调用泛型包函数,该函数根据前面定义的变量生成使包工作所需的所有Makefile代码。

18.5.2. generic-package reference

通用目标有两种变体。generic-package宏用于为目标交叉编译包。host-generic-package宏用于宿主包,宿主包是为宿主编译的。可以在一个.mk文件中同时调用它们:一次创建规则来生成目标包,一次创建规则来生成主机包:

$(eval $(generic-package))
$(eval $(host-generic-package))

如果编译目标包需要在主机上安装一些工具,这可能很有用。如果包名是libfoo,那么目标器的包名也是libfoo,而主机的包名是host-libfoo。这些名称应该在其他包的DEPENDENCIES变量中使用,如果它们依赖于libfoohost-libfoo

generic-package和/或host-generic-package宏的调用必须位于.mk文件的末尾,在所有变量定义之后。如果有的话,对host-generic-package的调用必须在对generic-package的调用之后。

对于目标包,generic-package使用.mk文件定义的变量,并以大写的包名为前缀:LIBFOO_*. host-generic-package 使用 HOST_LIBFOO_* 变量.。对于某些变量,如果HOST_LIBFOO_前缀变量不存在,包基础结构将使用相应的LIBFOO_前缀变量。对于目标包和主机包可能具有相同值的变量,可以这样做。详情见下文。

可以在.mk文件中设置的元数据信息的变量如下(假设包名是libfoo):

  • LIBFOO_VERSION, mandatory, must contain the version of the package. Note that if HOST_LIBFOO_VERSION doesn’t exist, it is assumed to be the same as LIBFOO_VERSION. It can also be a revision number or a tag for packages that are fetched directly from their version control system. Examples:

  • // LIBFOO_VERSION,必选,必须包含包的版本。注意,如果HOST_LIBFOO_VERSION不存在,就会假定它与LIBFOO_VERSION相同。它还可以是版本号或直接从版本控制系统获取的包的标记。例子:

    • a version for a release tarball: LIBFOO_VERSION = 0.1.2
    • a sha1 for a git tree: LIBFOO_VERSION = cb9d6aa9429e838f0e54faa3d455bcbab5eef057
    • a tag for a git tree LIBFOO_VERSION = v0.1.2

    Note: Using a branch name as FOO_VERSION is not supported, because it does not and can not work as people would expect it should:
    // 注意:不支持使用一个分支名作为FOO_VERSION,因为它不像人们期望的那样工作:

    • due to local caching, Buildroot will not re-fetch the repository, so people who expect to be able to follow the remote repository would be quite surprised and disappointed;
    • // 由于本地缓存,Buildroot将不会重新获取存储库,所以那些希望能够跟踪远程存储库的人将会非常惊讶和失望;
    • because two builds can never be perfectly simultaneous, and because the remote repository may get new commits on the branch anytime, two users, using the same Buildroot tree and building the same configuration, may get different source, thus rendering the build non reproducible, and people would be quite surprised and disappointed.
    • // 因为两个构建永远不能完全同步,因为远程存储库可能获得新的分支随时提交,两个用户,使用相同的Buildroot树和建筑相同的配置,可能会得到不同的源,因此呈现构建非可再生的,人们会非常惊讶和失望。
  • LIBFOO_SOURCE may contain the name of the tarball of the package, which Buildroot will use to download the tarball from LIBFOO_SITE. If HOST_LIBFOO_SOURCE is not specified, it defaults to LIBFOO_SOURCE. If none are specified, then the value is assumed to be libfoo-$(LIBFOO_VERSION).tar.gz. Example: LIBFOO_SOURCE = foobar-$(LIBFOO_VERSION).tar.bz2

  • // LIBFOO_SOURCE可能包含包的tarball名称,Buildroot将使用它从LIBFOO_SITE下载tarball。如果未指定HOST_LIBFOO_SOURCE,则默认为LIBFOO_SOURCE。如果没有指定,则假定该值为libfoo- ( L I B F O O V E R S I O N ) . t a r . g z 。 例 如 : L I B F O O S O U R C E = f o o b a r − (LIBFOO_VERSION).tar.gz。例如:LIBFOO_SOURCE = foobar- (LIBFOOVERSION).tar.gz:LIBFOOSOURCE=foobar(LIBFOO_VERSION).tar.bz2

  • LIBFOO_PATCH may contain a space-separated list of patch file names, that Buildroot will download and apply to the package source code. If an entry contains ://, then Buildroot will assume it is a full URL and download the patch from this location. Otherwise, Buildroot will assume that the patch should be downloaded from LIBFOO_SITE. If HOST_LIBFOO_PATCH is not specified, it defaults to LIBFOO_PATCH. Note that patches that are included in Buildroot itself use a different mechanism: all files of the form *.patch present in the package directory inside Buildroot will be applied to the package after extraction (see patching a package). Finally, patches listed in the LIBFOO_PATCH variable are applied before the patches stored in the Buildroot package directory.

  • // LIBFOO_PATCH可能包含一个空格分隔的补丁文件名列表,Buildroot将下载并应用于包源代码。如果一个条目包含://,那么Buildroot会假定它是一个完整的URL,并从这个位置下载补丁。否则,Buildroot会假定补丁应该从LIBFOO_SITE下载。如果未指定HOST_LIBFOO_PATCH,则默认为LIBFOO_PATCH。请注意,包含在Buildroot中的补丁使用了一种不同的机制:所有形式为*.patch的文件。在解压后,Buildroot中的包目录中的补丁将被应用到包中(参见给包打补丁)。最后,在应用Buildroot包目录中的补丁之前,应用LIBFOO_PATCH变量中列出的补丁。

  • LIBFOO_SITE provides the location of the package, which can be a URL or a local filesystem path. HTTP, FTP and SCP are supported URL types for retrieving package tarballs. In these cases don’t include a trailing slash: it will be added by Buildroot between the directory and the filename as appropriate. Git, Subversion, Mercurial, and Bazaar are supported URL types for retrieving packages directly from source code management systems. There is a helper function to make it easier to download source tarballs from GitHub (refer to Section 18.24.4, “How to add a package from GitHub” for details). A filesystem path may be used to specify either a tarball or a directory containing the package source code. See LIBFOO_SITE_METHOD below for more details on how retrieval works. Note that SCP URLs should be of the form scp://[user@]host:filepath, and that filepath is relative to the user’s home directory, so you may want to prepend the path with a slash for absolute paths: scp://[user@]host:/absolutepath. If HOST_LIBFOO_SITE is not specified, it defaults to LIBFOO_SITE. Examples: LIBFOO_SITE=http://www.libfoosoftware.org/libfoo LIBFOO_SITE=http://svn.xiph.org/trunk/Tremor LIBFOO_SITE=/opt/software/libfoo.tar.gz LIBFOO_SITE=$(TOPDIR)/../src/libfoo

  • // LIBFOO_SITE提供了包的位置,可以是URL或本地文件系统路径。HTTP、FTP和SCP是用于从支持的URL类型检索包tarball。在这些情况下,不要包含末尾的斜杠:它将被Buildroot添加到目录和文件名之间。Git、Subversion、Mercurial和Bazaar都是支持的URL类型,可以直接从源代码管理系统检索包。有一个帮助器函数可以使从GitHub下载源压缩包变得更容易(请参阅18.24.4节“如何从GitHub添加一个包”以获得详细信息)。文件系统路径可以用来指定一个tarball或包含包源代码的目录。请参阅下面的LIBFOO_SITE_METHOD了解更多关于检索如何工作的细节。注意,SCP url的格式应该是SCP://[user@]host:filepath,而且filepath是相对于用户的主目录的,所以您可能希望在路径前加一个斜杠来表示绝对路径:SCP://[user@]host:/absolutepath。如果未指定HOST_LIBFOO_SITE,则默认为LIBFOO_SITE。例如:LIBFOO_SITE=http://www.libfoosoftware.org/libfoo LIBFOO_SITE=http://svn.xiph.org/trunk/Tremor LIBFOO_SITE=/opt/software/libfoo.tar.gz LIBFOO_SITE=$(TOPDIR)/…/src/libfoo .gz

  • LIBFOO_DL_OPTS is a space-separated list of additional options to pass to the downloader. Useful for retrieving documents with server-side checking for user logins and passwords, or to use a proxy. All download methods valid for LIBFOO_SITE_METHOD are supported; valid options depend on the download method (consult the man page for the respective download utilities).

  • // LIBFOO_DL_OPTS是一个空格分隔的附加选项列表,用于传递给下载程序。用于检索文档,并通过服务器端检查用户登录和密码,或使用代理。LIBFOO_SITE_METHOD支持所有有效的下载方法;有效的选项取决于下载方法(有关各自的下载实用程序,请参阅手册页)。

  • LIBFOO_EXTRA_DOWNLOADS is a space-separated list of additional files that Buildroot should download. If an entry contains 😕/ then Buildroot will assume it is a complete URL and will download the file using this URL. Otherwise, Buildroot will assume the file to be downloaded is located at LIBFOO_SITE. Buildroot will not do anything with those additional files, except download them: it will be up to the package recipe to use them from $(LIBFOO_DL_DIR).

  • // LIBFOO_EXTRA_DOWNLOADS是一个空格分隔的附加文件列表,Buildroot应该下载这些文件。如果一个条目包含://,那么Buildroot会假定它是一个完整的URL,并使用这个URL下载文件。否则,Buildroot会假定要下载的文件位于LIBFOO_SITE。Buildroot不会对这些额外的文件做任何事情,除了下载它们:它将取决于包配方从$(LIBFOO_DL_DIR)使用它们。

  • LIBFOO_SITE_METHOD determines the method used to fetch or copy the package source code. In many cases, Buildroot guesses the method from the contents of LIBFOO_SITE and setting LIBFOO_SITE_METHOD is unnecessary. When HOST_LIBFOO_SITE_METHOD is not specified, it defaults to the value of LIBFOO_SITE_METHOD. The possible values of LIBFOO_SITE_METHOD are:

  • // LIBFOO_SITE_METHOD确定用于获取或复制包源代码的方法。在很多情况下,Buildroot从LIBFOO_SITE的内容猜测方法,设置LIBFOO_SITE_METHOD是不必要的。当未指定HOST_LIBFOO_SITE_METHOD时,默认为LIBFOO_SITE_METHOD的值。LIBFOO_SITE_METHOD可能的值是:

    • wget for normal FTP/HTTP downloads of tarballs. Used by default when LIBFOO_SITE begins with http://, https:// or ftp://.
    • // wget用于tarball的普通FTP/HTTP下载。LIBFOO_SITE 以http://,开始时默认使用:https://或ftp://.
    • scp for downloads of tarballs over SSH with scp. Used by default when LIBFOO_SITE begins with scp://.
    • // scp用于使用scp通过SSH下载tarball。默认情况下,当LIBFOO_SITE以scp://开头时使用。
    • svn for retrieving source code from a Subversion repository. Used by default when LIBFOO_SITE begins with svn://. When a http:// Subversion repository URL is specified in LIBFOO_SITE, one must specify LIBFOO_SITE_METHOD=svn. Buildroot performs a checkout which is preserved as a tarball in the download cache; subsequent builds use the tarball instead of performing another checkout.
    • // svn从Subversion存储库中检索源代码。当LIBFOO_SITE以svn://开头时默认使用。当在LIBFOO_SITE中指定了http:// Subversion存储库URL时,必须指定LIBFOO_SITE_METHOD=svn。Buildroot执行签出,在下载缓存中以tarball的形式保存;后续构建使用tarball而不是执行另一个签出。
    • cvs for retrieving source code from a CVS repository. Used by default when LIBFOO_SITE begins with cvs://. The downloaded source code is cached as with the svn method. Anonymous pserver mode is assumed otherwise explicitly defined on LIBFOO_SITE. Both LIBFOO_SITE=cvs://libfoo.net:/cvsroot/libfoo and LIBFOO_SITE=cvs://:ext:libfoo.net:/cvsroot/libfoo are accepted, on the former anonymous pserver access mode is assumed. LIBFOO_SITE must contain the source URL as well as the remote repository directory. The module is the package name. LIBFOO_VERSION is mandatory and must be a tag, a branch, or a date (e.g. “2014-10-20”, “2014-10-20 13:45”, “2014-10-20 13:45+01” see “man cvs” for further details).
    • // 用于从cvs存储库检索源代码。当LIBFOO_SITE以cvs://时默认使用。下载的源代码缓存为svn方法。假设匿名pserver模式是LIBFOO_SITE上显式定义的。LIBFOO_SITE=cvs://libfoo.net:/cvsroot/libfoo和LIBFOO_SITE=cvs://:ext:libfoo.net:/cvsroot/libfoo都被接受,假设是在以前的匿名pserver访问模式下。LIBFOO_SITE必须包含源URL以及远程存储库目录。模块是包的名称。LIBFOO_VERSION是强制的,必须是一个标签,一个分支,或者一个日期。“2014-10-20”,“2014-10-20 13:45”,“2014-10-20 13:45+01”详见“man cvs”)。
    • git for retrieving source code from a Git repository. Used by default when LIBFOO_SITE begins with git://. The downloaded source code is cached as with the svn method.
    • // git用于从git存储库检索源代码。当LIBFOO_SITE以git://开头时默认使用。下载的源代码缓存为svn方法。
    • hg for retrieving source code from a Mercurial repository. One must specify LIBFOO_SITE_METHOD=hg when LIBFOO_SITE contains a Mercurial repository URL. The downloaded source code is cached as with the svn method.
    • // hg,用于从Mercurial存储库检索源代码。当LIBFOO_SITE包含Mercurial存储库URL时,必须指定LIBFOO_SITE_METHOD=hg。下载的源代码缓存为svn方法。
    • bzr for retrieving source code from a Bazaar repository. Used by default when LIBFOO_SITE begins with bzr://. The downloaded source code is cached as with the svn method.
    • // bzr用于从Bazaar存储库检索源代码。当LIBFOO_SITE以bzr://开头时默认使用。下载的源代码缓存为svn方法。
    • file for a local tarball. One should use this when LIBFOO_SITE specifies a package tarball as a local filename. Useful for software that isn’t available publicly or in version control.
    • // 文件的本地tarball。当LIBFOO_SITE指定一个包tarball作为本地文件名时,应该使用这个。对于没有公开或版本控制的软件很有用。
    • local for a local source code directory. One should use this when LIBFOO_SITE specifies a local directory path containing the package source code. Buildroot copies the contents of the source directory into the package’s build directory. Note that for local packages, no patches are applied. If you need to still patch the source code, use LIBFOO_POST_RSYNC_HOOKS, see Section 18.22.1, “Using the POST_RSYNC hook”.
    • // Local用于本地源代码目录。当LIBFOO_SITE指定包含包源代码的本地目录路径时,应该使用此方法。Buildroot将源目录的内容复制到包的构建目录中。注意,对于本地包,没有应用补丁。如果你仍然需要修补源代码,请使用LIBFOO_POST_RSYNC_HOOKS,参见18.22.1节“使用POST_RSYNC钩子”
  • LIBFOO_GIT_SUBMODULES can be set to YES to create an archive with the git submodules in the repository. This is only available for packages downloaded with git (i.e. when LIBFOO_SITE_METHOD=git). Note that we try not to use such git submodules when they contain bundled libraries, in which case we prefer to use those libraries from their own package.

  • // LIBFOO_GIT_SUBMODULES可以被设置为YES来创建一个带有git子模块的存档。这只适用于使用git下载的包(即当LIBFOO_SITE_METHOD=git时)。请注意,当这些git子模块包含绑定的库时,我们尽量不使用它们,在这种情况下,我们倾向于使用它们自己包中的那些库。

  • LIBFOO_STRIP_COMPONENTS is the number of leading components (directories) that tar must strip from file names on extraction. The tarball for most packages has one leading component named “-”, thus Buildroot passes --strip-components=1 to tar to remove it. For non-standard packages that don’t have this component, or that have more than one leading component to strip, set this variable with the value to be passed to tar. Default: 1.

  • // LIBFOO_STRIP_COMPONENTS是在提取时,tar必须从文件名中删除的前导组件(目录)的数量。大多数包的tarball都有一个名为<pkg-name>-<pkg-version>的主要组件,因此Buildroot通过--strip-components=1来删除它。对于没有此组件的非标准包,或有多个前置组件需要剥离的非标准包,使用要传递给tar的值设置此变量。默认值:1。

  • LIBFOO_EXCLUDES is a space-separated list of patterns to exclude when extracting the archive. Each item from that list is passed as a tar’s --exclude option. By default, empty.

  • // libfoo_exclude是一个用空格分隔的模式列表,用于在提取归档文件时排除。该列表中的每一项都作为tar的--exclude选项传递。默认情况下,空的。

  • LIBFOO_DEPENDENCIES lists the dependencies (in terms of package name) that are required for the current target package to compile. These dependencies are guaranteed to be compiled and installed before the configuration of the current package starts. However, modifications to configuration of these dependencies will not force a rebuild of the current package. In a similar way, HOST_LIBFOO_DEPENDENCIES lists the dependencies for the current host package.

  • // LIBFOO_DEPENDENCIES列出了编译当前目标包所需的依赖项(根据包名)。这些依赖项保证在启动当前包的配置之前被编译和安装。但是,修改这些依赖项的配置并不会强制重新生成当前包。以类似的方式,HOST_LIBFOO_DEPENDENCIES列出当前主机包的依赖项。

  • LIBFOO_EXTRACT_DEPENDENCIES lists the dependencies (in terms of package name) that are required for the current target package to be extracted. These dependencies are guaranteed to be compiled and installed before the extract step of the current package starts. This is only used internally by the package infrastructure, and should typically not be used directly by packages.

  • // LIBFOO_EXTRACT_DEPENDENCIES列出了要提取当前目标包所需的依赖项(根据包名)。这些依赖项保证在启动当前包的提取步骤之前被编译和安装。这只被包基础结构内部使用,通常不应该被包直接使用。

  • LIBFOO_PATCH_DEPENDENCIES lists the dependencies (in terms of package name) that are required for the current package to be patched. These dependencies are guaranteed to be extracted and patched (but not necessarily built) before the current package is patched. In a similar way, HOST_LIBFOO_PATCH_DEPENDENCIES lists the dependencies for the current host package. This is seldom used; usually, LIBFOO_DEPENDENCIES is what you really want to use.

  • // LIBFOO_PATCH_DEPENDENCIES列出了补丁当前包所需要的依赖项(以包名的形式)。保证在当前包打补丁之前提取并修补这些依赖项(但不一定是构建)。以类似的方式,HOST_LIBFOO_PATCH_DEPENDENCIES列出了当前主机包的依赖项。这种方法很少使用;通常,LIBFOO_DEPENDENCIES是您真正想要使用的。

  • LIBFOO_PROVIDES lists all the virtual packages libfoo is an implementation of. See Section 18.11, “Infrastructure for virtual packages”.

  • // LIBFOO_PROVIDES列出了libfoo实现的所有虚拟包。参见第18.11节,“虚拟包的基础结构”。

  • LIBFOO_INSTALL_STAGING can be set to YES or NO (default). If set to YES, then the commands in the LIBFOO_INSTALL_STAGING_CMDS variables are executed to install the package into the staging directory.

  • // LIBFOO_INSTALL_STAGING可以设置为YES或NO(默认)。如果设置为YES,那么将执行LIBFOO_INSTALL_STAGING_CMDS变量中的命令来将包安装到暂存目录中。

  • LIBFOO_INSTALL_TARGET can be set to YES (default) or NO. If set to YES, then the commands in the LIBFOO_INSTALL_TARGET_CMDS variables are executed to install the package into the target directory.

  • // LIBFOO_INSTALL_TARGET可以设置为YES(默认)或NO。如果设置为YES,则执行LIBFOO_INSTALL_TARGET_CMDS变量中的命令将包安装到目标目录中。

  • LIBFOO_INSTALL_IMAGES can be set to YES or NO (default). If set to YES, then the commands in the LIBFOO_INSTALL_IMAGES_CMDS variable are executed to install the package into the images directory.

  • // LIBFOO_INSTALL_IMAGES可以设置为YES或NO(默认)。如果设置为YES,则执行LIBFOO_INSTALL_IMAGES_CMDS变量中的命令将包安装到images目录中。

  • LIBFOO_CONFIG_SCRIPTS lists the names of the files in $(STAGING_DIR)/usr/bin that need some special fixing to make them cross-compiling friendly. Multiple file names separated by space can be given and all are relative to $(STAGING_DIR)/usr/bin. The files listed in LIBFOO_CONFIG_SCRIPTS are also removed from $(TARGET_DIR)/usr/bin since they are not needed on the target.

  • // LIBFOO_CONFIG_SCRIPTS列出了 ( S T A G I N G D I R ) / u s r / b i n 中 的 文 件 名 称 , 这 些 文 件 需 要 一 些 特 殊 的 修 复 以 使 它 们 能 够 进 行 交 叉 编 译 。 可 以 给 出 多 个 以 空 格 分 隔 的 文 件 名 , 并 且 所 有 文 件 名 都 相 对 于 (STAGING_DIR)/usr/bin中的文件名称,这些文件需要一些特殊的修复以使它们能够进行交叉编译。可以给出多个以空格分隔的文件名,并且所有文件名都相对于 (STAGINGDIR)/usr/bin使(STAGING_DIR)/usr/bin。LIBFOO_CONFIG_SCRIPTS中列出的文件也从$(TARGET_DIR)/usr/bin中删除,因为它们在目标上不需要。

  • LIBFOO_DEVICES lists the device files to be created by Buildroot when using the static device table. The syntax to use is the makedevs one. You can find some documentation for this syntax in the Chapter 25, Makedev syntax documentation. This variable is optional.

  • // LIBFOO_DEVICES列出了在使用静态设备表时由Buildroot创建的设备文件。使用的语法是makedevs语法。您可以在第25章Makedev语法文档中找到关于此语法的一些文档。这个变量是可选的。

  • LIBFOO_PERMISSIONS lists the changes of permissions to be done at the end of the build process. The syntax is once again the makedevs one. You can find some documentation for this syntax in the Chapter 25, Makedev syntax documentation. This variable is optional.

  • // LIBFOO_PERMISSIONS列出了在构建过程结束时要做的权限更改。语法同样是makedevs。您可以在第25章Makedev语法文档中找到关于此语法的一些文档。这个变量是可选的。

  • LIBFOO_USERS lists the users to create for this package, if it installs a program you want to run as a specific user (e.g. as a daemon, or as a cron-job). The syntax is similar in spirit to the makedevs one, and is described in the Chapter 26, Makeusers syntax documentation. This variable is optional.

  • // LIBFOO_USERS列出了要为这个包创建的用户,如果它安装了一个您希望作为特定用户(例如作为守护进程或作为cron-job)运行的程序。该语法在精神上类似于makedevs,在第26章Makeusers语法文档中有描述。这个变量是可选的。

  • LIBFOO_LICENSE defines the license (or licenses) under which the package is released. This name will appear in the manifest file produced by make legal-info. If the license appears in the SPDX License List, use the SPDX short identifier to make the manifest file uniform. Otherwise, describe the license in a precise and concise way, avoiding ambiguous names such as BSD which actually name a family of licenses. This variable is optional. If it is not defined, unknown will appear in the license field of the manifest file for this package. The expected format for this variable must comply with the following rules:

  • // LIBFOO_LICENSE定义了软件包发布时使用的一个或多个许可证。该名称将出现在make legal-info生成的清单文件中。如果license出现在“SPDX license List”中,请使用SPDX短标识符,使清单文件统一。否则,要以精确而简洁的方式描述许可证,避免使用不明确的名称,例如BSD,后者实际上是对许可证家族的名称。这个变量是可选的。如果未定义,则未知将出现在此包的清单文件的license字段中。这个变量的期望格式必须符合以下规则:

    • If different parts of the package are released under different licenses, then comma separate licenses (e.g. LIBFOO_LICENSE = GPL-2.0+, LGPL-2.1+). If there is clear distinction between which component is licensed under what license, then annotate the license with that component, between parenthesis (e.g. LIBFOO_LICENSE = GPL-2.0+ (programs), LGPL-2.1+ (libraries)).
    • // 如果包的不同部分在不同的许可证下发布,则用逗号分隔许可证(例如LIBFOO_LICENSE = GPL-2.0+, LGPL-2.1+)。如果在哪个组件在哪个许可下获得许可之间有明确的区别,那么用该组件注释该许可,在括号(例如LIBFOO_LICENSE = GPL-2.0+(程序),LGPL-2.1+(库))之间。
    • If some licenses are conditioned on a sub-option being enabled, append the conditional licenses with a comma (e.g.: FOO_LICENSE += , GPL-2.0+ (programs)); the infrastructure will internally remove the space before the comma.
    • // 如果某些许可以子选项为条件,则在有条件许可后面加一个逗号(例如:FOO_LICENSE +=, GPL-2.0+ (programs));基础结构将从内部删除逗号之前的空间。
    • If the package is dual licensed, then separate licenses with the or keyword (e.g. LIBFOO_LICENSE = AFL-2.1 or GPL-2.0+).
    • // 如果包是双重许可的,那么用or关键字分隔许可(例如LIBFOO_LICENSE = AFL-2.1或GPL-2.0+)。
  • LIBFOO_LICENSE_FILES is a space-separated list of files in the package tarball that contain the license(s) under which the package is released. make legal-info copies all of these files in the legal-info directory. See Chapter 13, Legal notice and licensing for more information. This variable is optional. If it is not defined, a warning will be produced to let you know, and not saved will appear in the license files field of the manifest file for this package.

  • // LIBFOO_LICENSE_FILES是包tarball中的一个空格分隔的文件列表,其中包含发布包的许可。Make legal-info复制legal-info目录中的所有文件。更多信息见第13章,法律通知和许可。这个变量是可选的。如果未定义,将产生一个警告让您知道,并且not saved将出现在此包的清单文件的许可证文件字段中。

  • LIBFOO_ACTUAL_SOURCE_TARBALL only applies to packages whose LIBFOO_SITE / LIBFOO_SOURCE pair points to an archive that does not actually contain source code, but binary code. This a very uncommon case, only known to apply to external toolchains which come already compiled, although theoretically it might apply to other packages. In such cases a separate tarball is usually available with the actual source code. Set LIBFOO_ACTUAL_SOURCE_TARBALL to the name of the actual source code archive and Buildroot will download it and use it when you run make legal-info to collect legally-relevant material. Note this file will not be downloaded during regular builds nor by make source.

  • // LIBFOO_ACTUAL_SOURCE_TARBALL只适用于LIBFOO_SITE / LIBFOO_SOURCE对指向一个实际上不包含源代码,而是二进制代码的归档包。这是一种非常少见的情况,只适用于已经编译好的外部工具链,尽管理论上它可能适用于其他包。在这种情况下,实际源代码通常附带一个单独的tarball。将LIBFOO_ACTUAL_SOURCE_TARBALL设置为实际源代码归档文件的名称,Buildroot将下载它,并在运行make legal-info时使用它来收集与法律相关的材料。注意,这个文件不会在常规构建期间下载,也不会通过make source下载。

  • LIBFOO_ACTUAL_SOURCE_SITE provides the location of the actual source tarball. The default value is LIBFOO_SITE, so you don’t need to set this variable if the binary and source archives are hosted on the same directory. If LIBFOO_ACTUAL_SOURCE_TARBALL is not set, it doesn’t make sense to define LIBFOO_ACTUAL_SOURCE_SITE.

  • // LIBFOO_ACTUAL_SOURCE_SITE提供了实际源tarball的位置。默认值是LIBFOO_SITE,所以如果二进制归档文件和源归档文件托管在同一个目录中,则不需要设置这个变量。如果没有设置LIBFOO_ACTUAL_SOURCE_TARBALL,那么定义LIBFOO_ACTUAL_SOURCE_SITE没有意义。

  • LIBFOO_REDISTRIBUTE can be set to YES (default) or NO to indicate if the package source code is allowed to be redistributed. Set it to NO for non-opensource packages: Buildroot will not save the source code for this package when collecting the legal-info.

  • // LIBFOO_REDISTRIBUTE可以设置为YES(默认)或NO来指示是否允许重分发包源代码。对于非开源包,设置为NO: Buildroot在收集legal-info时不会保存此包的源代码。

  • LIBFOO_FLAT_STACKSIZE defines the stack size of an application built into the FLAT binary format. The application stack size on the NOMMU architecture processors can’t be enlarged at run time. The default stack size for the FLAT binary format is only 4k bytes. If the application consumes more stack, append the required number here.

  • // LIBFOO_FLAT_STACKSIZE定义了内置于FLAT二进制格式的应用程序的堆栈大小。NOMMU体系结构处理器上的应用程序堆栈大小不能在运行时扩大。FLAT二进制格式的默认堆栈大小只有4k字节。如果应用程序消耗了更多的堆栈,在这里添加所需的数量。

  • LIBFOO_BIN_ARCH_EXCLUDE is a space-separated list of paths (relative to the target directory) to ignore when checking that the package installs correctly cross-compiled binaries. You seldom need to set this variable, unless the package installs binary blobs outside the default locations, /lib/firmware, /usr/lib/firmware, /lib/modules, /usr/lib/modules, and /usr/share, which are automatically excluded.

  • // LIBFOO_BIN_ARCH_EXCLUDE是一个用空格分隔的路径列表(相对于目标目录),当检查包是否正确安装交叉编译的二进制文件时可以忽略它。您很少需要设置这个变量,除非包在默认位置/lib/firmware、/usr/lib/firmware、/lib/modules、/usr/lib/modules和/usr/share之外安装二进制blob,这些会被自动排除。

  • LIBFOO_IGNORE_CVES is a space-separated list of CVEs that tells Buildroot CVE tracking tools which CVEs should be ignored for this package. This is typically used when the CVE is fixed by a patch in the package, or when the CVE for some reason does not affect the Buildroot package. A Makefile comment must always precede the addition of a CVE to this variable. Example:

  • // LIBFOO_IGNORE_CVES是一个空格分隔的CVE列表,它告诉Buildroot CVE跟踪工具在这个包中应该忽略哪个CVE。这通常用于CVE被包中的补丁修复,或者CVE由于某些原因不影响Buildroot包时。Makefile注释必须总是在向该变量添加CVE之前。例子:

# 0001-fix-cve-2020-12345.patch
LIBFOO_IGNORE_CVES += CVE-2020-12345
# only when built with libbaz, which Buildroot doesn't support
LIBFOO_IGNORE_CVES += CVE-2020-54321
  • LIBFOO_CPE_ID_* variables is a set of variables that allows the package to define its CPE identifier. The available variables are:

  • // LIBFOO_CPE_ID_*变量是一组变量,允许包定义它的CPE标识符。可用的变量有:

    • LIBFOO_CPE_ID_PREFIX, specifies the prefix of the CPE identifier, i.e the first three fields. When not defined, the default value is cpe:2.3:a.
    • LIBFOO_CPE_ID_VENDOR, specifies the vendor part of the CPE identifier. When not defined, the default value is _project.
    • LIBFOO_CPE_ID_PRODUCT, specifies the product part of the CPE identifier. When not defined, the default value is .
    • LIBFOO_CPE_ID_VERSION, specifies the version part of the CPE identifier. When not defined the default value is $(LIBFOO_VERSION).
    • LIBFOO_CPE_ID_UPDATE specifies the update part of the CPE identifier. When not defined the default value is *.

如果定义了这些变量中的任何一个,那么通用包基础结构假定包提供了有效的CPE信息。在这种情况下,通用包基础结构将定义LIBFOO_CPE_ID。

对于一个主机包,如果它的LIBFOO_CPE_ID_*变量没有定义,它将从相应的目标包继承这些变量的值。

定义这些变量的推荐方法是使用以下语法:

LIBFOO_VERSION = 2.32

现在,定义在构建过程的不同步骤中应该执行什么的变量:

  • LIBFOO_EXTRACT_CMDS lists the actions to be performed to extract the package. This is generally not needed as tarballs are automatically handled by Buildroot. However, if the package uses a non-standard archive format, such as a ZIP or RAR file, or has a tarball with a non-standard organization, this variable allows to override the package infrastructure default behavior.
  • // LIBFOO_EXTRACT_CMDS列出了提取包时要执行的操作。这通常不需要,因为tarball是由Buildroot自动处理的。但是,如果包使用非标准的归档格式,例如ZIP或RAR文件,或者具有非标准组织的tarball,则此变量允许覆盖包基础结构的默认行为。
  • LIBFOO_CONFIGURE_CMDS lists the actions to be performed to configure the package before its compilation.
  • // LIBFOO_CONFIGURE_CMDS列出了在编译包之前要执行的配置操作。
  • LIBFOO_BUILD_CMDS lists the actions to be performed to compile the package.
  • // LIBFOO_BUILD_CMDS列出了编译包时要执行的操作。
  • HOST_LIBFOO_INSTALL_CMDS lists the actions to be performed to install the package, when the package is a host package. The package must install its files to the directory given by $(HOST_DIR). All files, including development files such as headers should be installed, since other packages might be compiled on top of this package.
  • // HOST_LIBFOO_INSTALL_CMDS列出了当包是一个主机包时,安装包需要执行的操作。这个包必须将它的文件安装到$(HOST_DIR)给出的目录下。应该安装所有文件,包括开发文件(如头文件),因为其他包可能在这个包之上编译。
  • LIBFOO_INSTALL_TARGET_CMDS lists the actions to be performed to install the package to the target directory, when the package is a target package. The package must install its files to the directory given by $(TARGET_DIR). Only the files required for execution of the package have to be installed. Header files, static libraries and documentation will be removed again when the target filesystem is finalized.
  • // LIBFOO_INSTALL_TARGET_CMDS列出了当包是目标包时,将包安装到目标目录所要执行的操作。这个包必须将它的文件安装到$(TARGET_DIR)给定的目录中。只需要安装执行包所需的文件。当目标文件系统完成时,头文件、静态库和文档将再次被删除。
  • LIBFOO_INSTALL_STAGING_CMDS lists the actions to be performed to install the package to the staging directory, when the package is a target package. The package must install its files to the directory given by $(STAGING_DIR). All development files should be installed, since they might be needed to compile other packages.
  • // LIBFOO_INSTALL_STAGING_CMDS列出了当包是目标包时,将包安装到分段目录所要执行的操作。包必须将其文件安装到$(STAGING_DIR)给定的目录中。应该安装所有的开发文件,因为编译其他包可能需要它们。
  • LIBFOO_INSTALL_IMAGES_CMDS lists the actions to be performed to install the package to the images directory, when the package is a target package. The package must install its files to the directory given by $(BINARIES_DIR). Only files that are binary images (aka images) that do not belong in the TARGET_DIR but are necessary for booting the board should be placed here. For example, a package should utilize this step if it has binaries which would be similar to the kernel image, bootloader or root filesystem images.
  • // LIBFOO_INSTALL_IMAGES_CMDS列出了当包是目标包时,将包安装到images目录所要执行的操作。这个包必须将它的文件安装到$(BINARIES_DIR)指定的目录下。只有不属于TARGET_DIR但对于引导板是必需的二进制映像(又名映像)文件应该放在这里。例如,如果一个包有类似于内核映像、引导加载程序或根文件系统映像的二进制文件,那么它应该利用这个步骤。
  • LIBFOO_INSTALL_INIT_SYSV, LIBFOO_INSTALL_INIT_OPENRC and LIBFOO_INSTALL_INIT_SYSTEMD list the actions to install init scripts either for the systemV-like init systems (busybox, sysvinit, etc.), openrc or for the systemd units. These commands will be run only when the relevant init system is installed (i.e. if systemd is selected as the init system in the configuration, only LIBFOO_INSTALL_INIT_SYSTEMD will be run). The only exception is when openrc is chosen as init system and LIBFOO_INSTALL_INIT_OPENRC has not been set, in such situation LIBFOO_INSTALL_INIT_SYSV will be called, since openrc supports sysv init scripts. When systemd is used as the init system, buildroot will automatically enable all services using the systemctl preset-all command in the final phase of image building. You can add preset files to prevent a particular unit from being automatically enabled by buildroot.
  • // LIBFOO_INSTALL_INIT_SYSV、LIBFOO_INSTALL_INIT_OPENRC和LIBFOO_INSTALL_INIT_SYSTEMD列出了为systemv类的init系统(busybox、sysvinit等)、openrc或systemd单元安装初始化脚本的操作。这些命令只在安装了相应的init系统时才会运行(如果在配置中选择systemd作为init系统,则只运行LIBFOO_INSTALL_INIT_SYSTEMD)。唯一的例外是当openrc被选择为初始化系统而LIBFOO_INSTALL_INIT_OPENRC没有被设置时,在这种情况下LIBFOO_INSTALL_INIT_SYSV将被调用,因为openrc支持sysv初始化脚本。当systemd用作初始化系统时,buildroot将在映像构建的最后阶段使用systemctl preset-all命令自动启用所有服务。你可以添加预设文件来防止一个特定的单元被buildroot自动启用。
  • LIBFOO_HELP_CMDS lists the actions to print the package help, which is included to the main make help output. These commands can print anything in any format. This is seldom used, as packages rarely have custom rules. Do not use this variable, unless you really know that you need to print help.
  • // LIBFOO_HELP_CMDS列出了打印包帮助的操作,它包含在主要的make帮助输出中。这些命令可以以任何格式打印任何内容。这很少使用,因为包很少有自定义规则。不要使用此变量,除非您确实知道需要打印帮助。
  • LIBFOO_LINUX_CONFIG_FIXUPS lists the Linux kernel configuration options that are needed to build and use this package, and without which the package is fundamentally broken. This shall be a set of calls to one of the kconfig tweaking option: KCONFIG_ENABLE_OPT, KCONFIG_DISABLE_OPT, or KCONFIG_SET_OPT. This is seldom used, as package usually have no strict requirements on the kernel options.
  • // LIBFOO_LINUX_CONFIG_FIXUPS列出了构建和使用这个包所需的Linux内核配置选项,如果没有这些选项,这个包就会彻底崩溃。这应该是一组对kconfig调整选项之一的调用:KCONFIG_ENABLE_OPT, KCONFIG_DISABLE_OPT或KCONFIG_SET_OPT。这很少使用,因为包通常对内核选项没有严格的要求。

定义这些变量的首选方法是:

define LIBFOO_CONFIGURE_CMDS
        action 1
        action 2
        action 3
endef

action定义中,你可以使用以下变量:

  • $(LIBFOO_PKGDIR) contains the path to the directory containing the libfoo.mk and Config.in files. This variable is useful when it is necessary to install a file bundled in Buildroot, like a runtime configuration file, a splashscreen image…
  • $(@D), which contains the directory in which the package source code has been uncompressed.
  • $(LIBFOO_DL_DIR) contains the path to the directory where all the downloads made by Buildroot for libfoo are stored in.
  • $(TARGET_CC), $(TARGET_LD), etc. to get the target cross-compilation utilities
  • $(TARGET_CROSS) to get the cross-compilation toolchain prefix
  • Of course the $(HOST_DIR), $(STAGING_DIR) and $(TARGET_DIR) variables to install the packages properly. Those variables point to the global host, staging and target directories, unless per-package directory support is used, in which case they point to the current package host, staging and target directories. In both cases, it doesn’t make any difference from the package point of view: it should simply use HOST_DIR, STAGING_DIR and TARGET_DIR. See Section 8.12, “Top-level parallel build” for more details about per-package directory support.

最后,您还可以使用钩子。有关更多信息,请参见第18.22节“各种构建步骤中可用的钩子”

18.6. Infrastructure for autotools-based packages

18.6.1. autotools-package tutorial

首先,让我们看看如何为一个基于自动工具的包编写一个.mk文件,通过一个例子:

01: ################################################################################
02: #
03: # libfoo
04: #
05: ################################################################################
06:
07: LIBFOO_VERSION = 1.0
08: LIBFOO_SOURCE = libfoo-$(LIBFOO_VERSION).tar.gz
09: LIBFOO_SITE = http://www.foosoftware.org/download
10: LIBFOO_INSTALL_STAGING = YES
11: LIBFOO_INSTALL_TARGET = NO
12: LIBFOO_CONF_OPTS = --disable-shared
13: LIBFOO_DEPENDENCIES = libglib2 host-pkgconf
14:
15: $(eval $(autotools-package))
  • On line 7, we declare the version of the package.
  • On line 8 and 9, we declare the name of the tarball (xz-ed tarball recommended) and the location of the tarball on the Web. Buildroot will automatically download the tarball from this location.
  • // 在第8和9行,我们声明了tarball的名称(推荐使用xz-ed tarball)和该tarball在Web上的位置。Buildroot将自动从这个位置下载tarball。
  • On line 10, we tell Buildroot to install the package to the staging directory. The staging directory, located in output/staging/ is the directory where all the packages are installed, including their development files, etc. By default, packages are not installed to the staging directory, since usually, only libraries need to be installed in the staging directory: their development files are needed to compile other libraries or applications depending on them. Also by default, when staging installation is enabled, packages are installed in this location using the make install command.
  • // 在第10行,我们告诉Buildroot将包安装到暂存目录。暂存目录位于output/staging/中,是安装所有包的目录,包括它们的开发文件等。默认情况下,包不会安装到暂存目录中,因为通常只需要将库安装到暂存目录中:它们的开发文件需要用于编译依赖于它们的其他库或应用程序。另外,在默认情况下,当启用分段安装时,将使用make install命令将包安装到这个位置。
  • On line 11, we tell Buildroot to not install the package to the target directory. This directory contains what will become the root filesystem running on the target. For purely static libraries, it is not necessary to install them in the target directory because they will not be used at runtime. By default, target installation is enabled; setting this variable to NO is almost never needed. Also by default, packages are installed in this location using the make install command.
  • // 在第11行,我们告诉Buildroot不要将包安装到目标目录。这个目录包含在目标上运行的根文件系统。对于纯静态库,没有必要将它们安装在目标目录中,因为它们不会在运行时使用。默认情况下,目标安装是启用的;几乎不需要将这个变量设置为NO。同样,默认情况下,使用make install命令将包安装到这个位置。
  • On line 12, we tell Buildroot to pass a custom configure option, that will be passed to the ./configure script before configuring and building the package.
  • // 在第12行,我们告诉Buildroot传递一个自定义配置选项,在配置和构建包之前,这个选项将被传递给./configure脚本。
  • On line 13, we declare our dependencies, so that they are built before the build process of our package starts.
  • // 在第13行中,我们声明了我们的依赖项,以便在启动包的构建过程之前构建它们。
  • Finally, on line line 15, we invoke the autotools-package macro that generates all the Makefile rules that actually allows the package to be built.
  • // 最后,在第15行,我们调用autotools-package宏,该宏生成所有实际允许构建包的Makefile规则。

18.6.2. autotools-package reference

autotoolspackage基础结构的主要宏是autotools-package。它类似于generic-package宏。通过host-autotools-package宏,还可以拥有目标包和主机包。

generic基础结构一样,autotools基础结构通过在调用autotools-package宏之前定义大量变量来工作。

首先,所有存在于通用基础架构中的包元数据信息变量也存在于自动工具基础架构中:LIBFOO_VERSION、LIBFOO_SOURCE、LIBFOO_PATCH、LIBFOO_SITE、LIBFOO_SUBDIR、LIBFOO_DEPENDENCIES、LIBFOO_INSTALL_STAGING、LIBFOO_INSTALL_TARGET。

还可以定义一些特定于autotools基础结构的额外变量。它们中的许多只在非常特定的情况下有用,因此典型的包只会使用其中的一些:

  • LIBFOO_SUBDIR may contain the name of a subdirectory inside the package that contains the configure script. This is useful, if for example, the main configure script is not at the root of the tree extracted by the tarball. If HOST_LIBFOO_SUBDIR is not specified, it defaults to LIBFOO_SUBDIR.
  • // LIBFOO_SUBDIR可能包含包含配置脚本的包中的子目录名。这很有用,例如,如果主配置脚本不在tarball提取的树的根上。如果未指定HOST_LIBFOO_SUBDIR,则默认为LIBFOO_SUBDIR。
  • LIBFOO_CONF_ENV, to specify additional environment variables to pass to the configure script. By default, empty.
  • // LIBFOO_CONF_ENV,以指定要传递给配置脚本的其他环境变量。默认情况下,空的。
  • LIBFOO_CONF_OPTS, to specify additional configure options to pass to the configure script. By default, empty.
  • // LIBFOO_CONF_OPTS,以指定传递给配置脚本的其他配置选项。默认情况下,空的。
  • LIBFOO_MAKE, to specify an alternate make command. This is typically useful when parallel make is enabled in the configuration (using BR2_JLEVEL) but that this feature should be disabled for the given package, for one reason or another. By default, set to ( M A K E ) . I f p a r a l l e l b u i l d i n g i s n o t s u p p o r t e d b y t h e p a c k a g e , t h e n i t s h o u l d b e s e t t o L I B F O O M A K E = (MAKE). If parallel building is not supported by the package, then it should be set to LIBFOO_MAKE= (MAKE).Ifparallelbuildingisnotsupportedbythepackage,thenitshouldbesettoLIBFOOMAKE=(MAKE1).
  • // LIBFOO_MAKE,以指定另一个make命令。如果在配置中启用了并行make(使用BR2_JLEVEL),但是由于某种原因,对于给定的包应该禁用此特性,那么这通常是有用的。默认设置为 ( M A K E ) 。 如 果 这 个 包 不 支 持 并 行 构 建 , 那 么 它 应 该 被 设 置 为 L I B F O O M A K E = (MAKE)。如果这个包不支持并行构建,那么它应该被设置为LIBFOO_MAKE= (MAKE)LIBFOOMAKE=(MAKE1)。
  • LIBFOO_MAKE_ENV, to specify additional environment variables to pass to make in the build step. These are passed before the make command. By default, empty.
  • // LIBFOO_MAKE_ENV指定要在构建步骤中传递给make的其他环境变量。这些在make命令之前传递。默认情况下,空的。
  • LIBFOO_MAKE_OPTS, to specify additional variables to pass to make in the build step. These are passed after the make command. By default, empty.
  • // LIBFOO_MAKE_OPTS,以指定在构建步骤中传递给make的其他变量。这些是在make命令之后传递的。默认情况下,空的。
  • LIBFOO_AUTORECONF, tells whether the package should be autoreconfigured or not (i.e. if the configure script and Makefile.in files should be re-generated by re-running autoconf, automake, libtool, etc.). Valid values are YES and NO. By default, the value is NO
  • // LIBFOO_AUTORECONF,告诉是否应该自动重新配置包(即,如果配置脚本和Makefile。在文件中应该通过重新运行autoconf, automake, libtool等重新生成)。取值为“YES”和“NO”。缺省值为NO
  • LIBFOO_AUTORECONF_ENV, to specify additional environment variables to pass to the autoreconf program if LIBFOO_AUTORECONF=YES. These are passed in the environment of the autoreconf command. By default, empty.
  • // LIBFOO_AUTORECONF_ENV,指定当LIBFOO_AUTORECONF=YES时传递给autoreconf程序的附加环境变量。这些是在autoreconf命令的环境中传递的。默认情况下,空的。
  • LIBFOO_AUTORECONF_OPTS to specify additional options passed to the autoreconf program if LIBFOO_AUTORECONF=YES. By default, empty.
  • // LIBFOO_AUTORECONF_OPTS指定当LIBFOO_AUTORECONF=YES时传递给autoreconf程序的附加选项。默认情况下,空的。
  • LIBFOO_GETTEXTIZE, tells whether the package should be gettextized or not (i.e. if the package uses a different gettext version than Buildroot provides, and it is needed to run gettextize.) Only valid when LIBFOO_AUTORECONF=YES. Valid values are YES and NO. The default is NO.
  • // LIBFOO_GETTEXTIZE表示该包是否应该被gettextize(即,如果该包使用的gettext版本与Buildroot提供的不同,并且需要它来运行gettextize)。仅当LIBFOO_AUTORECONF=YES时有效。取值为“YES”和“NO”。默认为NO。
  • LIBFOO_GETTEXTIZE_OPTS, to specify additional options passed to the gettextize program, if LIBFOO_GETTEXTIZE=YES. You may use that if, for example, the .po files are not located in the standard place (i.e. in po/ at the root of the package.) By default, -f.
  • // LIBFOO_GETTEXTIZE_OPTS,如果LIBFOO_GETTEXTIZE=YES,则指定传递给gettextize程序的附加选项。例如,如果.po文件不在标准位置(即在包的根目录po/中),则可以使用。默认情况下,- f。
  • LIBFOO_LIBTOOL_PATCH tells whether the Buildroot patch to fix libtool cross-compilation issues should be applied or not. Valid values are YES and NO. By default, the value is YES
  • // LIBFOO_LIBTOOL_PATCH告诉是否应该应用修复libtool交叉编译问题的Buildroot补丁。取值为“YES”和“NO”。缺省值:YES
  • LIBFOO_INSTALL_STAGING_OPTS contains the make options used to install the package to the staging directory. By default, the value is DESTDIR=$(STAGING_DIR) install, which is correct for most autotools packages. It is still possible to override it.
  • // LIBFOO_INSTALL_STAGING_OPTS包含make选项,用于将包安装到暂存目录。默认情况下,该值为DESTDIR=$(STAGING_DIR) install,这对于大多数自动工具包是正确的。仍然有可能推翻它。
  • LIBFOO_INSTALL_TARGET_OPTS contains the make options used to install the package to the target directory. By default, the value is DESTDIR=$(TARGET_DIR) install. The default value is correct for most autotools packages, but it is still possible to override it if needed.
  • // LIBFOO_INSTALL_TARGET_OPTS包含make选项,用于将包安装到目标目录。默认值为:DESTDIR=$(TARGET_DIR) install。默认值对于大多数自动工具包是正确的,但是如果需要,仍然可以覆盖它。

使用autotools基础结构,已经定义了构建和安装包所需的所有步骤,对于大多数基于autotools的包来说,这些步骤通常可以很好地工作。然而,当需要时,仍然可以自定义在任何特定步骤中所做的事情:

  • 通过添加一个操作后钩子(在提取、修补、配置、构建或安装之后)。请参阅第18.22节,“各种构建步骤中可用的钩子”以获得详细信息。
  • 通过重写其中的一个步骤。例如,即使使用autotools基础架构,如果package .mk文件定义了它自己的LIBFOO_CONFIGURE_CMDS变量,它也将被使用,而不是默认的autotools变量。但是,使用这种方法应该局限于非常具体的情况。不要在一般情况下使用它。

18.7. Infrastructure for CMake-based packages

18.8. Infrastructure for Python packages

18.9. Infrastructure for LuaRocks-based packages

18.10. Infrastructure for Perl/CPAN packages

18.11. Infrastructure for virtual packages

18.12. Infrastructure for packages using kconfig for configuration files

18.13. Infrastructure for rebar-based packages

18.14. Infrastructure for Waf-based packages

18.15. Infrastructure for Meson-based packages

18.16. Integration of Cargo-based packages

18.17. Infrastructure for Go packages

18.18. Infrastructure for QMake-based packages

18.19. Infrastructure for packages building kernel modules

18.20. Infrastructure for asciidoc documents

18.21. Infrastructure specific to the Linux kernel package

Linux内核包可以使用一些基于包挂钩的特定基础设施来构建Linux内核工具或/和构建Linux内核扩展。

18.21.1. linux-kernel-tools

18.21.2. linux-kernel-extensions

18.22. Hooks available in the various build steps

通用基础结构(以及派生的autotools和cmake基础结构)允许包指定钩子。这些定义了在现有步骤之后要执行的进一步操作。大多数钩子对于通用包并不是真正有用,因为.mk文件已经完全控制了包构造的每个步骤中执行的操作。

以下是可用的挂钩点:

  • LIBFOO_PRE_DOWNLOAD_HOOKS
  • LIBFOO_POST_DOWNLOAD_HOOKS
  • LIBFOO_PRE_EXTRACT_HOOKS
  • LIBFOO_POST_EXTRACT_HOOKS
  • LIBFOO_PRE_RSYNC_HOOKS
  • LIBFOO_POST_RSYNC_HOOKS
  • LIBFOO_PRE_PATCH_HOOKS
  • LIBFOO_POST_PATCH_HOOKS
  • LIBFOO_PRE_CONFIGURE_HOOKS
  • LIBFOO_POST_CONFIGURE_HOOKS
  • LIBFOO_PRE_BUILD_HOOKS
  • LIBFOO_POST_BUILD_HOOKS
  • LIBFOO_PRE_INSTALL_HOOKS (for host packages only)
  • LIBFOO_POST_INSTALL_HOOKS (for host packages only)
  • LIBFOO_PRE_INSTALL_STAGING_HOOKS (for target packages only)
  • LIBFOO_POST_INSTALL_STAGING_HOOKS (for target packages only)
  • LIBFOO_PRE_INSTALL_TARGET_HOOKS (for target packages only)
  • LIBFOO_POST_INSTALL_TARGET_HOOKS (for target packages only)
  • LIBFOO_PRE_INSTALL_IMAGES_HOOKS
  • LIBFOO_POST_INSTALL_IMAGES_HOOKS
  • LIBFOO_PRE_LEGAL_INFO_HOOKS
  • LIBFOO_POST_LEGAL_INFO_HOOKS

这些变量是变量名的列表,其中包含在这个钩子点上要执行的操作。这允许在一个给定的钩子点注册几个钩子。下面是一个例子:

define LIBFOO_POST_PATCH_FIXUP
        action1
        action2
endef

LIBFOO_POST_PATCH_HOOKS += LIBFOO_POST_PATCH_FIXUP

18.22.1. Using the POST_RSYNC hook

POST_RSYNC钩子只对使用本地源的包运行,要么通过本地站点方法,要么通过OVERRIDE_SRCDIR机制。在本例中,使用rsync将包源从本地位置复制到buildroot构建目录中。但是,rsync命令不会从源目录复制所有文件。属于版本控制系统的文件,如.git、.hg等目录不会被复制。对于大多数包来说,这已经足够了,但是一个给定的包可以使用POST_RSYNC钩子执行额外的操作。

原则上,钩子可以包含您想要的任何命令。不过,一个特定的用例是有意使用rsync复制版本控制目录。在钩子中使用的rsync命令可以使用以下变量:

  • $(SRCDIR): the path to the overridden source directory
  • $(@D): the path to the build directory

18.22.2. Target-finalize hook

包也可以在LIBFOO_TARGET_FINALIZE_HOOKS中注册钩子。这些钩子在构建所有包之后,但在生成文件系统映像之前运行。它们很少被使用,您的包可能不需要它们。

18.23. Gettext integration and interaction with packages

18.24. Tips and tricks

18.24.1. Package name, config entry name and makefile variable relationship

In Buildroot, there is some relationship between:

  • the package name, which is the package directory name (and the name of the *.mk file);
  • // 包名,这是包的目录名(和*.mk文件名);
  • the config entry name that is declared in the Config.in file;
  • // config中声明的配置项名称在Config.in文件中;
  • the makefile variable prefix.
  • // makefile变量前缀。

It is mandatory to maintain consistency between these elements, using the following rules:
// 必须使用以下规则保持这些元素之间的一致性:

  • the package directory and the *.mk name are the package name itself (e.g.: package/foo-bar_boo/foo-bar_boo.mk);
  • // 包目录和*.mk是包本身的名称(例如:package/foo-bar_boo/foo-bar_boo.mk);
  • the make target name is the package name itself (e.g.: foo-bar_boo);
  • // make目标名称是包本身的名称(例如:foo-bar_boo);
  • the config entry is the upper case package name with . and - characters substituted with , prefixed with BR2_PACKAGE (e.g.: BR2_PACKAGE_FOO_BAR_BOO);
  • // 配置项是大写的包名.-字符替换为_,前缀为BR2_PACKAGE_(例如:BR2_PACKAGE_FOO_BAR_BOO);
  • the *.mk file variable prefix is the upper case package name with . and - characters substituted with _ (e.g.: FOO_BAR_BOO_VERSION).
  • // *.mk文件变量前缀是大写的包名带.-字符替换为_(例如:FOO_BAR_BOO_VERSION)。

18.24.2. How to check the coding style

Buildroot在utils/check-package中提供了一个脚本,用于检查新的或更改的文件的编码风格。它不是一个完整的语言验证器,但它能捕获许多常见错误。在创建提交的补丁之前,它将在您创建或修改的实际文件中运行。

这个脚本可以用于包、文件系统makefiles、Config。在文件等。它不检查定义包基础结构的文件和包含类似公共代码的其他文件。

要使用它,运行检查包脚本,告诉你创建或修改了哪些文件:

$ ./utils/check-package package/new-package/*

If you have the utils directory in your path you can also run:

$ cd package/new-package/
$ check-package *

The tool can also be used for packages in a br2-external:

$ check-package -b /path/to/br2-ext-tree/package/my-package/*

18.24.3. How to test your package

一旦您添加了新的包,在不同的条件下测试它是很重要的:它是为所有架构构建的吗?它使用不同的C库构建吗?它需要线程吗,NPTL?等等……

Buildroot运行连续测试随机配置的autobuilders。但是,这些只构建了git树的主分支,而你的新包还没有在那里。

Buildroot在utils/test-pkg中提供了一个脚本,它使用与autobuilders使用的相同的基本配置,因此您可以在相同的条件下测试您的包。

首先,创建一个配置片段,其中包含启用您的包所需的所有必要选项,但不包含任何架构或工具链选项。例如,让我们创建一个配置片段,只启用libcurl,没有任何TLS后端:

$ cat libcurl.config
BR2_PACKAGE_LIBCURL=y

如果您的包需要更多的配置选项,您可以将它们添加到配置片段中。例如,下面是在openssl作为TLS后端和curl程序的情况下如何测试libcurl:

$ cat libcurl.config
BR2_PACKAGE_LIBCURL=y
BR2_PACKAGE_LIBCURL_CURL=y
BR2_PACKAGE_OPENSSL=y

然后运行test-pkg脚本,告诉它要使用什么配置片段和要测试什么包:

$ ./utils/test-pkg -c libcurl.config -p libcurl

默认情况下,test-pkg将根据autobuilders使用的工具链的子集来构建您的包,Buildroot开发人员将其选为最有用和最有代表性的子集。如果要测试所有工具链,请传递-a选项。请注意,在任何情况下,内部工具链都被排除在外,因为它们的构建时间太长。

输出列出了所有被测试的工具链和相应的结果(摘录,结果是假的):

$ ./utils/test-pkg -c libcurl.config -p libcurl
                armv5-ctng-linux-gnueabi [ 1/11]: OK
              armv7-ctng-linux-gnueabihf [ 2/11]: OK
                        br-aarch64-glibc [ 3/11]: SKIPPED
                           br-arcle-hs38 [ 4/11]: SKIPPED
                            br-arm-basic [ 5/11]: FAILED
                  br-arm-cortex-a9-glibc [ 6/11]: OK
                   br-arm-cortex-a9-musl [ 7/11]: FAILED
                   br-arm-cortex-m4-full [ 8/11]: OK
                             br-arm-full [ 9/11]: OK
                    br-arm-full-nothread [10/11]: FAILED
                      br-arm-full-static [11/11]: OK
11 builds, 2 skipped, 2 build failed, 1 legal-info failed

The results mean:

  • OK: the build was successful.
  • SKIPPED: one or more configuration options listed in the config snippet were not present in the final configuration. This is due to options having dependencies not satisfied by the toolchain, such as for example a package that depends on BR2_USE_MMU with a noMMU toolchain. The missing options are reported in missing.config in the output build directory (~/br-test-pkg/TOOLCHAIN_NAME/ by default).
  • FAILED: the build failed. Inspect the logfile file in the output build directory to see what went wrong:
    • the actual build failed,
    • the legal-info failed,
    • one of the preliminary steps (downloading the config file, applying the configuration, running dirclean for the package) failed.

当出现故障时,您可以使用相同的选项重新运行脚本(在修复包之后);该脚本将尝试为所有工具链重新构建用-p指定的包,而不需要重新构建该包的所有依赖项。

test-pkg脚本接受一些选项,你可以通过运行这些选项得到一些帮助:

$ ./utils/test-pkg -h

18.24.4. How to add a package from GitHub

GitHub上的包通常没有带有发布tarball的下载区域。但是,可以直接从GitHub上的存储库下载tarball。由于GitHub在过去已经改变了下载机制,所以应该如下所示使用GitHub助手函数。

# Use a tag or a full commit ID
FOO_VERSION = 1.0
FOO_SITE = $(call github,<user>,<package>,v$(FOO_VERSION))

Notes:

  • The FOO_VERSION can either be a tag or a commit ID.
  • The tarball name generated by github matches the default one from Buildroot (e.g.: foo-f6fb6654af62045239caed5950bc6c7971965e60.tar.gz), so it is not necessary to specify it in the .mk file.
  • When using a commit ID as version, you should use the full 40 hex characters.
  • When the tag contains a prefix such as v in v1.0, then the VERSION variable should contain just 1.0, and the v should be added directly in the SITE variable, as illustrated above. This ensures that the VERSION variable value can be used to match against release-monitoring.org results.

如果你想要添加的包在GitHub上有一个发布部分,维护人员可能已经上传了一个发布tarball,或者发布可能只是指向git标签中自动生成的tarball。如果有一个由维护人员上传的发布tarball,我们更喜欢使用它,因为它可能有一些细微的不同(例如,它包含一个配置脚本,所以我们不需要做AUTORECONF)。

你可以在发布页面上看到,如果它是一个上传的tarball或git标签:

  • 如果它看起来像上面的图像,那么它是由维护人员上传的,您应该使用那个链接(在那个例子中:mongrel2-v1.9.2.tar.bz2)来指定FOO_SITE,而不是使用github助手。
  • 另一方面,如果只有“源代码”链接,那么它是一个自动生成的tarball,你应该使用github助手函数。

18.24.5. How to add a package from Gitlab

类似于18.24.4节中描述的github宏,“如何从github中添加一个包”,Buildroot还提供了从gitlab库下载的gitlab宏。它可以用来下载由Gitlab生成的自动生成tarball,用于特定的标签或提交:

# Use a tag or a full commit ID
FOO_VERSION = 1.0
FOO_SITE = $(call gitlab,<user>,<package>,v$(FOO_VERSION))

默认情况下,它将使用.tar.gz tarball,但Gitlab也提供了.tar。因此,通过添加一个<pkg>_SOURCE变量,这个.tar.bz2压缩包可以使用:

# Use a tag or a full commit ID
FOO_VERSION = 1.0
FOO_SITE = $(call gitlab,<user>,<package>,v$(FOO_VERSION))
FOO_SOURCE = foo-$(FOO_VERSION).tar.bz2

如果上游开发人员在 https://gitlab.com//releases/ 中上传了一个特定的tarball,不要使用这个宏,而是直接使用到该tarball的链接。

18.25. Conclusion

如您所见,将一个软件包添加到Buildroot仅仅是一个使用现有示例编写Makefile并根据该包所需的编译过程修改它的问题。

如果您打包的软件可能对其他人有用,不要忘记向Buildroot邮件列表发送一个补丁(见第22.5节,“提交补丁”)!

19. Patching a package

在集成新包或更新现有包时,可能需要对软件源代码打补丁,以便在Buildroot中交叉构建。

Buildroot提供了一个基础设施来在构建过程中自动处理这个问题。它支持三种应用补丁集的方式:下载的补丁、内置根中提供的补丁和位于用户定义的全局补丁目录中的补丁。

19.1. Providing patches

19.1.1. Downloaded

如果需要应用一个可以下载的补丁,那么将它添加到<packagename>_PATCH变量中。如果一个条目包含://,那么Buildroot会假定它是一个完整的URL,并从这个位置下载补丁。否则,Buildroot会假设补丁应该从<packagename>_SITE下载。它可以是单个补丁,也可以是包含补丁系列的tarball。

与所有下载一样,应该在中添加一个<packagename>.hash文件。

这种方法通常用于来自Debian的包。

19.1.2. Within Buildroot

大多数补丁都是在Buildroot包目录中提供的;它们通常旨在修复交叉编译、libc支持或其他此类问题。

这些补丁文件应该命名为<number>-<description>.patch

注意:

  • Buildroot附带的补丁文件的文件名中不应该包含任何包版本引用。
  • 补丁文件名中<number>的为申请顺序,从1开始;它更倾向于用0到4位填充数字,就像git-format-patch做的那样。例如:0001-foobar-the-buz.patch
  • 以前,补丁必须以包的名称作为前缀,如<package>-<number>-<description>.patch。但现在不是这样了。现有的包将随着时间的推移而固定。不要用包名作为补丁的前缀。
  • 以前,quilt使用的系列文件也可以添加到包目录中。在这种情况下,系列文件定义了补丁应用程序的顺序。这是不赞成的,并将在将来被删除。不要使用系列文件。

19.1.3. Global patch directory

BR2_GLOBAL_PATCH_DIR配置文件选项可用于指定包含全局包补丁的一个或多个目录的空格分隔列表。参见第9.8节“添加特定于项目的补丁”了解详细信息。

19.2. How patches are applied

  • 1.Run the <packagename>_PRE_PATCH_HOOKS commands if defined;
  • 2.Cleanup the build directory, removing any existing *.rej files;
  • 3.If <packagename>_PATCH is defined, then patches from these tarballs are applied;
  • 4.If there are some *.patch files in the package’s Buildroot directory or in a package subdirectory named , then:
    • 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 refers to the apply order.
  • 5.If BR2_GLOBAL_PATCH_DIR is defined, the directories will be enumerated in the order they are specified. The patches are applied as described in the previous step.
  • 6.Run the <packagename>_POST_PATCH_HOOKS commands if defined.

If something goes wrong in the steps 3 or 4, then the build fails.

19.3. Format and licensing of the package patches

补丁是在与它们所应用的软件相同的许可证下发布的(见章节13.2,“符合Buildroot许可证”)。

一条解释补丁做什么的消息,以及为什么需要它,应该添加在补丁的标题注释中。

您应该在每个补丁的标题中添加一个Signed-off-by声明,以帮助跟踪更改,并证明该补丁是在与被修改的软件相同的许可证下发布的。

如果软件处于版本控制状态,建议使用上游的SCM软件生成补丁集。

否则,将头与diff -purN package-version的输出连接起来。源自/包版本/命令。

如果你更新了一个现有的补丁(例如,当碰撞包版本时),确保现有的From头和Signed-off-by标签没有被删除,但是在适当的时候更新补丁注释的其余部分。

最后,补丁看起来应该是这样的:

configure.ac: add C++ support test

Signed-off-by: John Doe <john.doe@noname.org>

--- configure.ac.orig
+++ configure.ac
@@ -40,2 +40,12 @@

AC_PROG_MAKE_SET
+
+AC_CACHE_CHECK([whether the C++ compiler works],
+               [rw_cv_prog_cxx_works],
+               [AC_LANG_PUSH([C++])
+                AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],
+                               [rw_cv_prog_cxx_works=yes],
+                               [rw_cv_prog_cxx_works=no])
+                AC_LANG_POP([C++])])
+
+AM_CONDITIONAL([CXX_WORKS], [test "x$rw_cv_prog_cxx_works" = "xyes"])

19.4. Integrating patches found on the Web

当集成一个您不是作者的补丁时,您必须在补丁本身的标题中添加一些东西。

根据补丁是从项目存储库本身获得的,还是从web上的某个地方获得的,添加以下标记之一:

Backported from: <some commit id>

Fetch from: <some url>

在补丁中添加一些必要的修改也是明智的。

20. Download infrastructure

在构建包时,可以使用Buildroot所执行的步骤。定义变量BR2_INSTRUMENTATION_SCRIPTS来包含一个或多个脚本(或其他可执行文件)的路径,在一个空格分隔的列表中,您希望在每个步骤之前和之后调用它。这些脚本被依次调用,有三个参数:

  • start or end to denote the start (resp. the end) of a step;
  • the name of the step about to be started, or which just ended;
  • the name of the package.

For example :

make BR2_INSTRUMENTATION_SCRIPTS="/path/to/my/script1 /path/to/my/script2"

The list of steps is:

  • extract
  • patch
  • configure
  • build
  • install-host, when a host-package is installed in $(HOST_DIR)
  • install-target, when a target-package is installed in $(TARGET_DIR)
  • install-staging, when a target-package is installed in $(STAGING_DIR)
  • install-image, when a target-package installs files in $(BINARIES_DIR)

The script has access to the following variables:

  • BR2_CONFIG: the path to the Buildroot .config file
  • HOST_DIR, STAGING_DIR, TARGET_DIR: see Section 18.5.2, “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

21. Debugging Buildroot

22. Contributing to Buildroot

22.1. Reproducing, analyzing and fixing bugs

22.2. Analyzing and fixing autobuild failures

22.3. Reviewing and testing patches

22.4. Work on items from the TODO list

22.5. Submitting patches

22.6. Reporting issues/bugs or getting help

22.7. Using the run-tests framework

23. DEVELOPERS file and get-developers

24. Release Engineering

24.1. Releases

24.2. Development

IV. Appendix

25. Makedev syntax documentation

26. Makeusers syntax documentation

27. Migrating from older Buildroot versions

27.1. Migrating to 2016.11

27.2. Migrating to 2017.08

posted @ 2021-07-15 19:34  pwl999  阅读(8004)  评论(0编辑  收藏  举报