Buildroot构建指南--快速上手与实用技巧
Posted zhou_chenz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Buildroot构建指南--快速上手与实用技巧相关的知识,希望对你有一定的参考价值。
Buildroot官方全英文使用手册的链接是https://buildroot.org/downloads/manual/manual.html,需要知道每一个细节的朋友,可以仔细查阅,这篇文章只是我自己从中提炼出来的一下快速上手的技巧。
如何在现有项目加入自己的APP
Buildroot从零开始构建的过程还是很复杂的,以后的文章会一步步介绍。我们先来看看如何在现有项目中加入一个自己的应用的构建方法,快速上手。实际上,快速添加应用包的方法,在官方网站也有一份英文文档:https://buildroot.org/downloads/manual/manual.html#adding-packages 详细的原理可以参考这篇文档。
这里以加入自己的demo_app应用为例,在mini2440_defconfig的项目下,加入demo_app的package,将demo_app的应用源代码编译生成到rootfs根文件系统中。构建方法如下:
1. 在buildroot/package/ 下执行 mkdir demo_app ,创建demo_app 的文件夹
Figure1 在package/ 目录下创建demo_app/
2. 在demo_app 中touch Config.in , touch demo_app.mk 创建这两个文件,注意,文件名很关键,demo_app.mk要小写,而且不能乱取其它名字,因为Buildroot框架有一套根据命名,展开app package的规则,所以buildroot里面构建项目,一定要遵守文章中的命名规则,否则会有各种报错。
Figure2 添加Config.in 与 demo_app.mk 文件
3. 在package/Config.in 中加入 source "package/demo_app/Config.in" ,以便将demo_app 的配置文件包含到Buildroot的package中来管理。
Figure3 在packahe/Config.in 中加入demo_app的Config.in
4. 在package/demo_app/Config.in 这个类似Kconfig的配置文件中,按照命名格式和Linux Kernel 的 Kconfig文件规范,加入自己的配置变量,参考代码如下:
config BR2_PACKAGE_DEMO_APP
bool"demo app"
help
demo app to show
这段配置中,命名规则也同样重要,BR2_PACKAGE_DEMO_APP是demo_app 可被Buildroot识别编译成package的配置变量。Package应用一定要以BR2_PACKAGE_作为开头,以DEMO_APP即demo_app的大写来填充这个变量名,这样才能被Buildroot命名框架识别、展开,才能通过make menuconfig来配置。
bool是变量的类型,即只要true(编译选中,false(编译未选中),两种情况,和Kconfig的规则是一样的,后面的字符串和help都是在make menuconfig时的提示文本。
实际上,在Config.in中,可以参考Linux Kernel的Kconfig文件,根据语法规范,加入自己的配置逻辑和其它可配置的变量(比如app的下载地址链接),在此就不详细说了,大家可以参考其它的package/的Config.in文件的写法,这里只说重点,就是BR2_PACKAGE_DEMO_APP这个变量一定要有,一定要被选上才能编译。
5. 在demo_app.mk中,按照Makefile文件的格式和语法规范,编写demo_app的上层构建规则,demo_app.mk的参考代码如下:
################################################################################
#
# demo app
#
################################################################################
DEMO_APP_VERSION = master
DEMO_APP_SITE_METHOD = git
DEMO_APP_SITE = /mnt/sdb/git_repo/demo_app
DEMO_APP_SOURCE = demo_app-$(DEMO_APP_VERSION).tar.gz
DEMO_APP_ALWAYS_BUILD = YES
DEMO_APP_INSTALL_STAGING = YES
DEMO_APP_CFLAGS =
DEMO_APP_LDFLAGS =
OUT_BIN = demo_app
DEMO_APP_MAKE_FLAGS += \\
CROSS_COMPILE="$(CCACHE) $(TARGET_CROSS)" \\
CC=$(TARGET_CC) \\
OUT_BIN=$(OUT_BIN) \\
AR=$(TARGET_AR) \\
STRIP=$(TARGET_STRIP) \\
CFLAGS=$(DEMO_APP_CFLAGS) \\
LDFLAGS=$(DEMO_APP_LDFLAGS) \\
STAGING_DIR=$(STAGING_DIR) \\
TARGET_DIR=$(TARGET_DIR)
define DEMO_APP_BUILD_CMDS
$(MAKE) clean -C $(@D)
$(MAKE) $(DEMO_APP_MAKE_FLAGS) -C $(@D)
endef
define DEMO_APP_INSTALL_TARGET_CMDS
$(INSTALL) -m 0755 -D $(@D)/$(OUT_BIN) $(TARGET_DIR)/usr/bin
endef
$(eval $(generic-package))
注意,demo_app.mk并不能实际代替demo_app源代码的Makefile文件,它只是一个上层的make文件,告诉Buildroot,应该到哪个地方拿源代码,应该如何解压源代码,应该给源代码中的Makefile中的变量传递哪些编译参数,编译出来的库和bin文件,应该安装到rootfs的哪个路径下。具体demo_app源代码是如何一步一步编译的,还得靠demo_app源代码本身的Makefile去做。
这段makefile代码大概有什么规范呢:
a) 所有的变量都已DEMO_APP_ 开头,这样Buildroot才能够通过命名框架去解析
b) _VERSION结尾的变量,是下载demo_app源代码的版本号, _SITE_METHOD结尾的变量是demo_app变量的下载方法,_SITE结尾的变量是demo_app的下载地址,其它的变量是干嘛用的,可以慢慢查阅官方手册。
c) 所有define 并以_CMDS结尾的代码块,类似函数的东西,实际上是构建过程中会被Buildroot框架执行的指令,这些指令到底有哪些,具体也得读手册。当然这些类似函数,开头也得是DEMO_APP_, Buildroot中命名规则很重要,重要的话说三遍。
d) _BUILD_CMDS结尾的函数,是构建过程函数,一般是给demo_app源代码传递编译和链接选项,调用源代码的Makefile执行编译。
e) INSTALL_TARGET_CMDS结尾的函数,就是demo_app编译完之后,自动安装的执行,一般是让Buildroot把编译出来库和bin文件安装到指定的目录。
f) $(eval$(generic-package)) 最核心的就是这个东西了,一定不能够漏了,不然demo_app是编译不出来的,这个函数就是把整个demo_app.mk构建脚本,通过Buildroot框架的方式,展开到Buildroot/目录下的Makfile中,生成demo_app的构建目标(构建目标是什么,还记得Makefile中的定义吗?)。
g) 实际上,这些构建命名框架还有$(eval $(generic-package))这个黑魔法,都在package/pkg-generic.mk 这个文件中,generic-package是这个文件最后的调用的函数生成的,其它 _BUILD_CMDS,INSTALL_TARGET_CMDS这些函数如何被Buildroot框架嵌入的, 之前那些变量是如何被调用的,在package/pkg-generic.mk中都能找到,但是还是要一定的Makefile功底才能读懂这个的,以后再解释package/pkg-generic.mk的框架原理。
讲了这么多条规范,那么这段makefile代码大概是什么意思呢?
这段代码描述的流程是, 通过git clone的方法从/mnt/sdb/git_repo/demo_app这个目录下的git仓库中拿到demo_app的源代码-->传递编译参数,并且编译demo_app(DEMO_APP_BUILD_CMDS函数做的事情)-->把编译出来的bin文件安装到$(TARGET_DIR)/usr/bin目录下(DEMO_APP_INSTALL_TARGET_CMDS函数做的事情)。
为什么我们自己不用写从git仓库下载demo_app源代码的函数呢,实际上是Buildroot帮我们写好了,在package/ pkg-download.mk 文件里面,所以我们只有通过DEMO_APP_SITE_METHOD和DEMO_APP_SITE设置下载的方法和地址就可以。至于为什么DEMO_APP_VERSION是master,了解git的朋友应该看得明白,就是git clone之后会checkout到master版本,其实也就是master分支最新的版本啦,当然也可以换成自己的版本号,前提是该版本号存在,能够用git checkout 切换过去。
这段代码的执行前提是要在Linux上搭建自己的git仓库,维护自己的demo_app源代码,在用Buildroot前,git仓库是现成的。
但是不熟悉git 的朋友怎么办呢?其实还有其它方法,demo_app.mk的代码稍做修改:
Figure4 采用file方法下载源代码
主要,DEMO_APP_SITE_METHOD改成了file,这样就不用构建git参考,可以用file,也就是直接cp的方法,把源代码拷贝到buildroot中来。但是buildroot到哪里去cp源代码呢,实际上,这里不是DEMO_APP_SITE = /mnt/sdb/git_repo/demo_app这个地址,这个地方被我注释掉了。
在buildroot/下 makemenuconfig --> Build options -->Mirrors and Download locations 可以看到以下的画面:
Figure5 设置file方法cp文件的路径
只有按照上面的格式,也就是file:// + 你的文件绝对路径的地址的格式配置这个选项,然后保存,就OK,之后Buildroot就知道去该路径下找源代码包了。
另外记得,一定要把demo_app的源代码压缩包保存到该路径下,并且名字一定要和DEMO_APP_SOURCE变量的名字一样哦!
Figure6 demo_app 源代码的存放路径
6. demo_app的源代码
demo_app就是一个hello world 程序参考的makefile和源代码如下:
其中Makefie会被demo_app.mk中的DEMO_APP_BUILD_CMDS函数调用,Makefie中的变量参数的值都可以通过DEMO_APP_BUILD_CMD传入。
Figure7 demo_app 的Makefie
Figure8 demo_app.c 源代码
7. 构建方法
a). make mini2440_defconfig --> makemenuconfig --> Target packages下选中demo app --> make demo_app
Figure9 menuconfig中选中 demo app,
make demo_app这个命令,实际上是只是编译demo_app以及demo_app依赖链上的package, 当然,toolchain会被所有package依赖,所以buildroot会先编译toolchain。
编译完成后,会发现buildroot/output/build/目标下的demo_app-master目录,即demo_app编译后现场,以及在buildroot/output/target/usr/bin/目录下,安装好的编译出来的demo_appbin文件。并且确实是ARM交叉工具链编译出来的。
Figure10 demo_app 源代码编译现场路径
Figure11 安装好的demo_app bin文件
至此,在Buildroot中添加app package的过程就完成了。
如何编译基于现有项目的最小系统
Buildroot 一次make all要把整个系统编译出来,真麻烦,我只想要一个可以boot起来的最小系统,不需要什么其它package,它有什么快捷方式可以办到吗?这个当然问buildroot,我们可以这么做。
make help 看看buildroot怎么说
Figure12 make help 之后的buildroot系统提示
以下是buildroot的help命令提示,其中有一项是
make allnopackageconfig
在make xxx_defconfig 之后,执行make allnopackageconfig,那么再make all就可以只编toolchain,boot,kernel,busybox,rootfs这个几个能构成系统启动的最小系统的模块。
当然,在make mini2440_defconfig时,由于mini2440的toolchain是toolchain-buildroot,即buildroot从零开始制作工具链,而不是toolchain-external,即buildroot使用已经制作好的工具链,这样的话,如果toolchain还没有在前一次生成,则make allnopackageconfig 再make all之后编译过程会报错,因为制作零制作toolchain需要编译某些package作为原材料,而这些package被make allnopackageconfig去掉了。
已经制作好工具链,或者采用toolchain-external模式的情况下,make allnopackageconfig 编译最小系统是没用问题的。
Buildroot实用技巧与指令
最后看看buildroot有哪些实用技巧:
make help
-之前演示过了,打印出帮助菜单
make show-targets
- 显示出本次配置所要编译所有的目标,这些目标可以单独作为模块,用 make <pkg-target> 命令进行单独编译。从这条命令的显示结果来看,mini2440_defconfig需要编译uclibc(微型C库),busybox等目标,当然demo_app也是一个编译目标,是我在menocunfig时候加进去的,所以可以用make demo_app来编译。
Figure13 make show-targets 的显示结果
make <pkg-target>
- 单独编译某个pkg模块以及其依赖的模块,比如make demo_app
make pkg-rebuild
- 重新编译pkg
make pkg-extract
- 只下载解压pkg,不编译,pkg解压后放在 output/build/目录对应的pkg-dir目录下
make pkg-source
- 只下载某pkg,然后不做任何事情
其它还有很多快捷指令,在package/pkg-generic.mk中都能找到,这些快捷指令实际是是由pkg-指令这种命名框架合成的,更详细的内容请参考手册和package/pkg-generic.mk。
Figure14 package/pkg-generic.mk 框架下所支持的指令部分截图呀
以上是关于Buildroot构建指南--快速上手与实用技巧的主要内容,如果未能解决你的问题,请参考以下文章