buildroot教程

1 引入buildroot#

Buildroot是Linux平台上一个开源的嵌入式Linux系统自动构建框架。用来制作根文件系统,我们还要自己去移植一些第三方软件和库,比如 alsaiperfmplayer 等等。

那么有没有一种傻瓜式的方法或软件,它不仅包含了 busybox 的功能,而且里面还集成了各种软件,需要什么软件就选择什么软件,不需要我们去移植。答案肯定是有的,buildroot 就是这样一种工具。

1.1 下载buildroot#

Buildroot版本每2个月,2月,5月,8月和11月发布一次。版本号的格式为YYYY.MM,例如2013.02、2014.08。

可以从http://buildroot.org/downloads/获得发行包。

也可通过github仓库获取最新版本:

1
git clone git://git.busybox.net/buildroot

buildroot ubootLinux kernel 一样也支持图形化配置:
make menuconfig
image

1.2 buildroot目录结构#

1.2.0 buildroot源目录#

  • arch: CPU架构相关的配置脚本

  • board: 在构建系统时,board默认的boot和Linux kernel配置文件,以及一些板级相关脚本

  • boot: uboot配置脚本目录

  • configs: 板级配置文件,该目录下的配置文件记录着该机器平台或者方案使用的工具链,boot, kernel,各种应用软件包的配置

  • dl: download的简写,下载一些开源包。第一次下载后,下次就不会再去从官网下载了,而是从dl/目录下拿开源包,以节约时间

  • docs:

  • fs: 各种文件系统的自动构建脚本

  • linux: 存放Linux kernel的自动构建脚本

  • package: 第三方开源包的自动编译构建脚本,用来配置编译dl目录下载的开源包

  • support:

  • system: 存放文件系统目录的和设备节点的模板,这些模板会被拷贝到output/目录下,用于制作根文件系统rootfs

  • toolchain/ 目录中存放着各种制作工具链的脚本

1.2.1 编译出的output输出目录介绍#

  • images/存储所有映像(内核映像,引导加载程序和根文件系统映像)的位置。这些是您需要放在目标系统上的文件。

  • build/构建所有组件的位置(包括主机上Buildroot所需的工具和针对目标编译的软件包)。该目录为每个组件包含一个子目录。

  • host/包含为主机构建的工具和目标工具链。

  • staging/是到内部目标工具链host/的符号链接

  • target/它几乎包含了目标的完整根文件系统。除了设备文件/dev/(Buildroot无法创建它们,因为Buildroot不能以root身份运行并且不想以root身份运行)之外,所需的一切都存在。

1.3 配置 Target options#

1
2
3
4
5
6
7
Target options
-> Target Architecture = ARM (little endian)
-> Target Binary Format = ELF
-> Target Architecture Variant = cortex-A7
-> Target ABI = EABIhf
-> Floating point strategy = NEON/VFPv4
-> ARM instruction set = ARM

配置输出目标选项,架构,格式,浮点策略,指令集啊。配置好后如下:
image

1.4 配置工具链#

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

1.4.1 内部工具链#

  • 内部工具链,称为Buildroot toolchainbuildroot 其实是可以自动下载交叉编译器的,但是都是从国外服务器下载的, 鉴于国内的网络环境,推荐大家设置成自己所使用的交叉编译器(也就是外部工具链)。
    image

1.4.2 外部工具链#

  • 外部工具链External toolchain
1
2
3
4
5
6
7
8
9
10
11
12
13
Toolchain
-> Toolchain type = External toolchain
-> Toolchain = Custom toolchain //选择用户自己的交叉编译器
-> Toolchain origin = Pre-installed toolchain //选择预装的编译器,否则Toolchain to be downloaded and installed
-> Toolchain path =/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf
-> Toolchain prefix = $(ARCH)-linux-gnueabihf //前缀
-> External toolchain gcc version = 4.9.x
-> External toolchain kernel headers series = 4.1.x
-> External toolchain C library = glibc/eglibc
-> [*] Toolchain has SSP support? (NEW) //选中
-> [*] Toolchain has RPC support? (NEW) //选中
-> [*] Toolchain has C++ support? //选中
-> [*] Enable MMU support (NEW) //选中

Toolchain:设置为 Custom toolchain,表示使用用户自己的交叉编译器。
Toolchain origin:设置为 Pre-installed toolchain,表示使用预装的交叉编译器。
Toolchain path:设置自己安装的交叉编译器绝对路径!buildroot 要用到。
Toolchain prefix:设置交叉编译器前缀,要根据自己实际所使用的交叉编译器来设置,比如我们使用的是 arm-linux-gnueabihf-gcc,因此前缀就是$(ARCH)-linux-gnueabihf,其中 ARCH 我们前面已经设置为了 arm。
image

1.5 配置 build options#

编译选项,编译第三方插件使用静态还是动态链接等。

1.6 配置 System configuration#

系统配置,比如开发板名字、欢迎语、用户名、密码等。

1
2
3
4
5
6
7
System configuration
-> System hostname = alpha_imx6ull //平台名字,自行设置
-> System banner = Welcome to alpha i.mx6ull //欢迎语
-> Init system = BusyBox //使用 busybox
-> /dev management = Dynamic using devtmpfs + mdev //使用 mdev
-> [*] Enable root login with password (NEW) //使能登录密码
-> Root password = 123456 //登录密码为 123456

1.7 配置 Filesystem images#

根文件系统格式。

1
2
3
4
-> Filesystem images
-> [*] ext2/3/4 root filesystem //如果是 EMMC 或 SD 卡的话就用 ext3/ext4
-> ext2/3/4 variant = ext4 //选择 ext4 格式
-> [*] ubi image containing an ubifs root filesystem //如果使用 NAND 的话就用 ubifs

image

1.8 禁止编译 Linux 内核和 uboot#

一版不建议uboot和kernel也用buildroot。buildroot 不仅仅能构建根文件系统,也可以编译 linux 内核和 uboot。

buildroot如果开启了uboot和Linux内核的编译,会自动下载最新的 linux 内核和 uboot,那么最新的内核和uboot会对编译器版本号有要求,可能导致编译失败。

1
2
-> Kernel
-> [ ] Linux Kernel //不要选择编译 Linux Kernel 选项!

image

image

1.9 配置 Target packages#

配置要选择的第三方库或软件、比如 alsa-utils、ffmpeg、iperf等工具。
image

2 编译buildroot#

2.1 make help#

可以看到buildroot下make的使用细节,包括对package、uclibc、busybox、linux以及文档生成等配置。

2.2 make print-version#

打印buildroot版本号

2.3 make menuconfig#

或者(make linux-menuconfig…):进行图形化配置

2.4 make xxxx_defconfig#

1
2
3
4
5
6
7
8
9
10
Buildroot_2020.02.x/configs$ ls
100ask nexbox_a95x_defconfig
100ask_imx6ull_mini_ddr512m_systemV_core_defconfig nitrogen6sx_defconfig
100ask_imx6ull_mini_ddr512m_systemV_qt5_defconfig nitrogen6x_defconfig
100ask_imx6ull_pro_ddr512m_systemV_core_defconfig nitrogen7_defconfig
100ask_imx6ull_pro_ddr512m_systemV_qt5_defconfig nitrogen8m_defconfig
100ask_stm32mp157_pro_ddr512m_busybox_core_defconfig odroidxu4_defconfig
100ask_stm32mp157_pro_ddr512m_systemD_core_defconfig olimex_a10_olinuxino_lime_defconfig
100ask_stm32mp157_pro_ddr512m_systemD_qt5_defconfig olimex_a13_olinuxino_defconfig
100ask_stm32mp157_pro_ddr512m_systemV_core_defconfig olimex_a20_olinuxino_lime2_defconfig

make 100ask_imx6ull_pro_ddr512m_systemV_core_defconfig即可产生.configoutput目录
image

2.5 make#

sudo make //注意不能-jxxx,来指定多核编译

make命令通常将执行以下步骤:

  1. 下载源文件(根据需要);
  2. 配置、构建和安装交叉编译工具链,或仅导入外部工具链;
  3. 配置、构建和安装选定的目标软件包;
  4. 构建内核映像(如果选择);
  5. 构建引导加载程序映像(如果选择);
  6. 以选定的格式创建一个根文件系统
  • make clean:delete all build products (including build directories, host, staging and target trees, the images and the toolchain)
  • make distclean: 等于make clean+删除配置
  • make show-targets:显示出本次配置所要编译所有的目标
  • make pkg-target:单独编译某个pkg模块
  • make pkg-rebuild:重新编译pkg
  • make pkg-extract:只下载解压pkg,不编译,pkg解压后放在 output/build/对应的pkg-dir目录下
  • make pkg-source:只下载某pkg,然后不做任何事情
  • make list-defconfigs:例举所有可用的defconfigs。
  • make xxx_menuconfig:比如make linux-menuconfig

image

rootfs.tar就是编译出的根文件系统,解压缩后就能使用。

2.5.1 nfs 挂载根文件系统#

1
2
3
setenv bootargs 'console=tty1 console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.253:
/home/zuozhongkai/linux/nfs/buildrootfs rw ip=192.168.1.251:192.168.1.253:192.168.1.1:255.255.
255.0::eth0:off'

image

image

可以看到能进入rootfs,但是驱动ko和第三方软件和库没有。

2.6 make show-targets#

make show-targets显示出本次配置所要编译所有的目标。
image

3 buildroot框架原理#

Buildroot提供了函数框架和变量命令框架,采用它的框架编写的app_pkg.mk这种Makefile格式的自动构建脚本,将被package/pkg-generic.mk 这个核心脚本展开填充到buildroot主目录下的Makefile中去。

最后make all执行Buildroot主目录下的Makefile,生成你想要的image。 package/pkg-generic.mk中通过调用同目录下的pkg-download.mkpkg-utils.mk文件,已经帮你自动实现了下载、解压、依赖包下载编译等一系列机械化的流程。

你只要需要按照格式写app_pkg.mk,填充下载地址,链接依赖库的名字等一些特有的构建细节即可。 总而言之,Buildroot本身提供构建流程的框架,开发者按照格式写脚本,提供必要的构建细节,配置整个系统,最后自动构建出你的系统。

3.1 添加自己的软件包#

3.1.1 package/Config.in总入口添加菜单#

添加如下语句:

1
2
3
menu "myown(fuzidage) package"
source "package/helloworld/Config.in"
endmenu

为自己的软件包添加入口,这样在make menuconfig的时候就可以找到自己的软件包的Config.in,如果在make menuconfig的时候选中helloworld,那么"BR2_PACKAGE_HELLOWORLD=y"也会同步到.config中去。

3.1.2 配置APP对应的Config.in和mk文件#

package中新增目录helloworld,并在里面添加Config.inhelloworld.mk

3.1.2.1 Config.in#

1
2
3
4
config BR2_PACKAGE_HELLOWORLD
bool "helloworld"
help
This is a demo to add myown(fuzidage) package.

helloworld/Config.in文件,可以通过make menuconfig可以对helloworld进行选择。只有在BR2_PACKAGE_HELLOWORLD=y条件下,才会调用helloworld.mk进行编译

3.1.2.2 helloworld.mk#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
################################################################################
#
# helloworld
#
################################################################################
HELLOWORLD_VERSION:= 1.0.0
HELLOWORLD_SITE:= $(CURDIR)/work/helloworld
HELLOWORLD_SITE_METHOD:=local
HELLOWORLD_INSTALL_TARGET:=YES

define HELLOWORLD_BUILD_CMDS
$(MAKE) CC="$(TARGET_CC)" LD="$(TARGET_LD)" -C $(@D) all
endef

define HELLOWORLD_INSTALL_TARGET_CMDS
$(INSTALL) -D -m 0755 $(@D)/helloworld $(TARGET_DIR)/bin
endef

define HELLOWORLD_PERMISSIONS
/bin/helloworld f 4755 0 0 - - - - -
endef
$(eval $(generic-package))

helloworld.mk包括源码位置、安装目录、权限设置等。

3.1.3 编写APP源码和Makefile#

创建一个work/helloworld目录,建立hello_world.cmakefile

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main(){
printf("hello world\n");
return 0;
}
all: helloworld
helloworld: helloworld.o
$(CC) -o helloworld helloworld.o
clean:
rm -rf *.o
rm -rf helloworld
install:
$(INSTALL) -D -m 0755 helloworld $(TARGET_DIR)/bin

3.1.4 通过make menuconfig选中APP#

通过上面对package/Config.in入口的配置, 我们可以通过make menuconfig,进入Target packages可以看见多了一个"myown(fuzidage) package"入口,选中,保存配置到.config
image

然后make savedefconfig,对helloworld的配置就会保存到对应的xxx_defconfig中。
image

3.1.5 编译使用APP#

可以和整个平台一起编译APP;或者make helloworld单独编译。
image

编译过程中,会被拷贝到output/build/helloworld-1.0.0文件夹中。然后生成的bin文件拷贝到output/target/bin/helloworld,这个文件会打包到文件系统中。
image

如果需要清空相应的源文件,通过make helloworld-dirclean

image

3.2 如何重新编译软件包#

经过第一次完整编译后,如果我们需要对源码包重新配置,我们不能直接在buildroot上的根目录下直接make,buildroot是不知道你已经对源码进行重新配置,它只会将第一次编译出来的文件,再次打包成根文件系统镜像文件。

那么可以通过以下2种方式重新编译:

  1. 直接删除源码包,然后make all

    1
    2
    例如我们要重新编译helloworld,那么可以直接删除output/build/helloworld目录,
    那么当你make的时候,就会自动从dl文件夹下,解压缩源码包,并重新安装。这种效率偏低
  2. 进行xxx-rebuild,然后make all

    1
    2
    也是以helloworld为例子,我们直接输入make helloworld-rebuild,
    即可对build/helloworld/目录进行重新编译,然后还要进行make all(或者make world 或者 make target-post-image)
  3. 如果要重新配置编译安装:

    1
    make <package>-reconfigure; make all

3.3 使能第三方软件和库#

前面 1.9配置Targetpackages 有引入介绍。

3.3.1 使能音频的ALSA库套件#

image

3.3.2 使能busybox套件#

image

使能后,buildroot 会自动下载 busybox 压缩包,buildroot 下载的源码压缩包都存 放在/dl 目录下,在 dl 目录下就有一个叫做“busybox”的文件夹,此目录下保存着 busybox 压 缩包:
image

make all编译完后, buildroot 将所有解压缩后的软件保存在/output/build 软件中,我们可以找到/output/build/busybox-1.29.3 这个文件夹,此文件夹就是解压后的 busybox 源码:
image
image

3.3.2.1 修改配置busybox套件#

修改busybox源码就直接在/output/build/busybox-1.29.3修改。

make busybox-menuconfig可以配置busybox套件选择哪些功能:
image

3.3.2.2 rebuild busybox套件#

make busybox或者make busybox-rebuild即可重新编译。

编译完后还要make或者make target-post-image对其进行打包进根文件系统。

3.3.3 PS1环境变量#

我们构建的根文件系统启动以后会发现, 输入命令的时候命令行前面一直都是“#”,如果我们进入到某个目录的话前面并不会显示当前目录路径:
image

PS1 用于设置命令提示符格式,格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PS1 = ‘命令列表’
命令列表中可选的参数如下:
\! 显示该命令的历史记录编号。
\# 显示当前命令的命令编号。
\$ 显示$符作为提示符,如果用户是 root 的话,则显示#号。
\\ 显示反斜杠。
\d 显示当前日期。
\h 显示主机名。
\n 打印新行。
\nnn 显示 nnn 的八进制值。
\s 显示当前运行的 shell 的名字。
\t 显示当前时间。
\u 显示当前用户的用户名。
\W 显示当前工作目录的名字。
\w 显示当前工作目录的路径

我们打开/etc/profie,修改成如下:
image

1
2
PS1='[\u@\h]:\w$:'
export PS1

3.4 单独生成目标(build out of tree)#

make O=/home/XXX/output

4 buildroot官方教程链接#

buildroot官方训练教程

buildroot中文手册

image-20240814004339288

可以下载正点原子翻译的中文版buildroot手册。

5 附录#

5.1 buildroot编译log#

1
2
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v7_defconfig V=1 > log.1 2>&1
make V=1 > buildroot.build.log 2>&1

见附件:https://files.cnblogs.com/files/fuzidage/buildroot.build.rar?t=1724326727&download=true