1、 Buildroot应用 要点 如何在现有项目加入自己的 APP Buildroot从零开始构建的过程还是很复杂的,以后的文章会一步步介绍。我们先来看看如何在现有项目中加入一个自己的应用的构建方法,快速上手。实际上,快速添加应用包的方法,在官方网站也有一份英文文档 :https:/buildroot.org/downloads/manual/manual.html#adding-packages 详细的原理可以参考这篇文档。 这里以加入自己的 demo_app应用为例,在 mini2440_defconfig的项目下,加入demo_app的 package,将 demo_app的应用源代码编译
2、生成到 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里面构建项目,一定要遵守文章中的命名规则,否则会有各种报
3、错 。 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文件规范,加入自己的配置变量,参
4、考代码如下 : plain view plain copy 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来配置。
5、bool是变量的类型,即只要 true(编译选中, false(编译未选中 ),两种情况,和 Kconfig的规则是一样的,后面的字符串和 help都是在 make menuconfig时的提示文本。 实际上,在 Config.in中,可以参考 Linux Kernel的 Kconfig文件,根据语法规范,加入自己的配置逻辑和其它可配置的变量 (比如 app的下载地址链接 ),在此就不详细说了,大家可以参考其它的 package/的 Config.in文件的写法, 这里只说重点,就是BR2_PACKAGE_DEMO_APP这个变量一定要有,一定要被选上才能编译。 5. 在 demo_app.m
6、k中,按照 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. D
7、EMO_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. LDFLAG
8、S=$(DEMO_APP_LDFLAGS) 23. STAGING_DIR=$(STAGING_DIR) 24. TARGET_DIR=$(TARGET_DIR) 25. 26. define DEMO_APP_BUILD_CMDS 27. $(MAKE) clean -C $(D) 28. $(MAKE) $(DEMO_APP_MAKE_FLAGS) -C $(D) 29. endef 30. 31. define DEMO_APP_INSTALL_TARGET_CMDS 32. $(INSTALL) -m 0755 -D $(D)/$(OUT_BIN) $(TARGET_DIR)/usr/
9、bin 33. endef 34. 35. $(eval $(generic-package) 注意, demo_app.mk并不能实际代替 demo_app源代码的 Makefile文件,它只是一个上层的 make文件,告诉 Buildroot,应该到哪个地方拿源代码,应该如何解压源代码,应该给源代码中的 Makefile中的变量传递哪些编译参数,编译出来的库和 bin文件,应该安装到 rootfs的哪 个路径下。具体 demo_app源代码是如何一步一步编译的,还得靠 demo_app源代码本身的 Makefile去做。 这段 makefile代码大概有什么规范呢: a) 所有的变量都已
10、DEMO_APP_ 开头,这样 Buildroot才能够通过命名框架去解析 b) _VERSION结尾的变量,是下载 demo_app源代码的版本号, _SITE_METHOD结尾的变量是 demo_app变量的下载方法, _SITE结尾的变量是 demo_app的下载地址,其它的变量是干嘛用的,可以慢慢查阅官方手册。 c) 所有 define 并以 _CMDS结尾的代码块,类似函数的东西,实际上是构建过程中会被 Buildroot框架执行的指令,这些指令到底有哪些,具体也得读手册。 当然这些类似函数,开头也得是 DEMO_APP_, Buildroot中命名规则很重要,重要的话说三遍。 d)
11、 _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中
12、,生成 demo_app的构建目标 (构建目标是什么,还记得 Makefile中的定义吗? )。 g) 实际上,这些构建命名框架还有 $(eval $(generic-package)这个黑魔法 ,都在package/pkg-generic.mk 这个文件中, generic-package是这个文件最后的调用的函数生成的,其它 _BUILD_CMDS, INSTALL_TARGET_CMDS这些函数如何被Buildroot框架嵌入的 , 之前那些变量是如何被调用的,在 package/pkg-generic.mk中都能找到,但是还是要一定的 Makefile功底才能读懂这个的,以后再解释pa
13、ckage/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_a
14、pp源代码的函数呢,实际上是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仓
15、库 ,维护自己的 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这个地址,这个地方被我注释掉了 。 在
16、 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的源代
17、码 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 menu
18、config中选中 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
19、 demo_app 源代码编译现场路径 Figure11 安装好的 demo_app bin文件 至此,在 Buildroot中添加 app package的过程就完成了。 如何编译基于现有项目 的最小系统 Buildroot 一次 make all要把整个系统编译出来,真麻烦,我只想要一个可以 boot起来的最小系统,不需要什么其它 package,它有什么快捷方式可以办到吗?这个当然问 buildroot,我们可以这么做。 make help 看看 buildroot怎么说 Figure12 make help 之后的 buildroot系统提示 以下是 buildroot的 help命令
20、提示,其中有一项是 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使用已经制作
21、好的工具链,这样的话,如果 toolchain还没有在前一 次生成,则 make allnopackageconfig 再 make all之后编译过程会报错,因为制作零制作 toolchain需要编译某些 package作为原材料,而这些 package 被 make allnopackageconfig 去掉了。 已经制作好工具链,或者采用 toolchain-external模式的情况下, make allnopackageconfig 编译最小系统是没用问题的。 Buildroot实用技巧与指令 最后看看 buildroot有哪些实用技巧: make help -之前演示过了,打 印出
22、帮助菜单 make show-targets - 显示出本次配置所要编译所有的目标,这些目标可以单独作为模块,用 make 命令进行单独编译。从这条命令的显示结果来看, mini2440_defconfig需要编译 uclibc(微型 C库 ), busybox等目标,当然 demo_app也是一个编译目标,是我在 menocunfig时候加进去的,所以可以用 make demo_app来编译。 Figure13 make show-targets 的显示结果 make - 单独编译某个 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 框架下所支持的指令部分截图 。