Buildroot构建指南--快速上手与实用技巧【转】

时间:2024-01-18 14:10:26

本文转载自:http://blog.csdn.net/zhou_chenz/article/details/52335634

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 的文件夹

Buildroot构建指南--快速上手与实用技巧【转】

Figure1 在package/ 目录下创建demo_app/

2.      在demo_app 中touch Config.in , touch demo_app.mk 创建这两个文件,注意,文件名很关键,demo_app.mk要小写,而且不能乱取其它名字,因为Buildroot框架有一套根据命名,展开app package的规则,所以buildroot里面构建项目,一定要遵守文章中的命名规则,否则会有各种报错。

Buildroot构建指南--快速上手与实用技巧【转】

Figure2  添加Config.in 与 demo_app.mk 文件

3.      在package/Config.in 中加入 source "package/demo_app/Config.in" ,以便将demo_app 的配置文件包含到Buildroot的package中来管理。

Buildroot构建指南--快速上手与实用技巧【转】

Figure3  在packahe/Config.in 中加入demo_app的Config.in

4.      在package/demo_app/Config.in 这个类似Kconfig的配置文件中,按照命名格式和Linux Kernel 的 Kconfig文件规范,加入自己的配置变量,参考代码如下:

  1. config BR2_PACKAGE_DEMO_APP
  2. bool"demo app"
  3. help
  4. 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的参考代码如下:

  1. ################################################################################
  2. #
  3. # demo app
  4. #
  5. ################################################################################
  6. DEMO_APP_VERSION = master
  7. DEMO_APP_SITE_METHOD = git
  8. DEMO_APP_SITE = /mnt/sdb/git_repo/demo_app
  9. DEMO_APP_SOURCE = demo_app-$(DEMO_APP_VERSION).tar.gz
  10. DEMO_APP_ALWAYS_BUILD = YES
  11. DEMO_APP_INSTALL_STAGING = YES
  12. DEMO_APP_CFLAGS =
  13. DEMO_APP_LDFLAGS =
  14. OUT_BIN = demo_app
  15. DEMO_APP_MAKE_FLAGS += \
  16. CROSS_COMPILE="$(CCACHE) $(TARGET_CROSS)" \
  17. CC=$(TARGET_CC)      \
  18. OUT_BIN=$(OUT_BIN)  \
  19. AR=$(TARGET_AR)      \
  20. STRIP=$(TARGET_STRIP) \
  21. CFLAGS=$(DEMO_APP_CFLAGS) \
  22. LDFLAGS=$(DEMO_APP_LDFLAGS) \
  23. STAGING_DIR=$(STAGING_DIR)  \
  24. TARGET_DIR=$(TARGET_DIR)
  25. define DEMO_APP_BUILD_CMDS
  26. $(MAKE) clean  -C $(@D)
  27. $(MAKE) $(DEMO_APP_MAKE_FLAGS)  -C $(@D)
  28. endef
  29. define DEMO_APP_INSTALL_TARGET_CMDS
  30. $(INSTALL) -m 0755 -D $(@D)/$(OUT_BIN)  $(TARGET_DIR)/usr/bin
  31. endef
  32. $(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的代码稍做修改:

Buildroot构建指南--快速上手与实用技巧【转】

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 可以看到以下的画面:

Buildroot构建指南--快速上手与实用技巧【转】

Figure5  设置file方法cp文件的路径

只有按照上面的格式,也就是file:// + 你的文件绝对路径的地址的格式配置这个选项,然后保存,就OK,之后Buildroot就知道去该路径下找源代码包了。

另外记得,一定要把demo_app的源代码压缩包保存到该路径下,并且名字一定要和DEMO_APP_SOURCE变量的名字一样哦!

Buildroot构建指南--快速上手与实用技巧【转】

Figure6  demo_app 源代码的存放路径

6.      demo_app的源代码

demo_app就是一个hello world 程序参考的makefile和源代码如下:

其中Makefie会被demo_app.mk中的DEMO_APP_BUILD_CMDS函数调用,Makefie中的变量参数的值都可以通过DEMO_APP_BUILD_CMD传入。

Buildroot构建指南--快速上手与实用技巧【转】

Figure7 demo_app 的Makefie

Buildroot构建指南--快速上手与实用技巧【转】

Figure8  demo_app.c 源代码

7.      构建方法

a). make mini2440_defconfig  --> makemenuconfig --> Target packages下选中demo app --> make demo_app

Buildroot构建指南--快速上手与实用技巧【转】

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交叉工具链编译出来的。

Buildroot构建指南--快速上手与实用技巧【转】

Figure10  demo_app 源代码编译现场路径

Buildroot构建指南--快速上手与实用技巧【转】

Figure11  安装好的demo_app  bin文件

至此,在Buildroot中添加app package的过程就完成了。

如何编译基于现有项目的最小系统

Buildroot 一次make all要把整个系统编译出来,真麻烦,我只想要一个可以boot起来的最小系统,不需要什么其它package,它有什么快捷方式可以办到吗?这个当然问buildroot,我们可以这么做。

make help 看看buildroot怎么说

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来编译。

Buildroot构建指南--快速上手与实用技巧【转】

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。

Buildroot构建指南--快速上手与实用技巧【转】

Figure14  package/pkg-generic.mk 框架下所支持的指令部分截图呀