最近在实验室的工作是为嵌入式的Linux系统加速启动,所以必然涉及到重新编译Linux。我需要自定义程度很高的方案,方便实验各种配置,或者加入自己的Bootloader / Kernel patch。配置完善的交叉编译环境,并解决所有依赖包绝对是耗时耗力,而且估计会遇到成堆的问题。

我之前试过一次,花了将近一个白天才搞定,关键是编译完了都不信编译出来的binary能用(结果放板子上一跑,确实没boot起来……)项目的set up阶段要做这么麻烦的工作,我有点害怕。这两周作业又巨多,完全不想手动配置这些。幸好,我发现了Buildroot。

Buildroot是一系列Makefile和脚本的组合,它的功能就是帮助编译(主要用在嵌入式的)Linux系统。用这个来做交叉编译,它会包办一切麻烦无聊的工作,使用者可以专注于调整编译选项和内核。使用者可以自定义Kernel源码从哪里获取,Bootloader用哪一个,要不要加别人或自己写的Patch,预装哪些包,网络怎么配置,GUI要不要,等等。

交叉编译涉及到准确定义目标的硬件参数,如果要自己从头来的话那估计又要查一堆资料,而且出一个错那时间成本挺高(重新编译又要花掉十几分钟)。好在Buildroot自带了很多流行的平台的参数,直接用就行,比如针对Raspberry Pi和Cubieboard都提供了这样的配置文件。下面是给Cubieboard2编译的例子:

获取Buildroot

$ git clone git://git.buildroot.net/buildroot
$ cd build root

载入Cubieboard2的配置

$ make cubieboard2_defconfig

调整系统配置(有命令行交互界面,不用手写配置文件,简直是方便到家了)

$ make menuconfig

编译

$ make

编译完之后,binary放在output/images下面。在board/cubietech/cubieboard里面自带了mksdcard脚本,分别传参binary位置、SD卡在/dev中的位置即可。

这个方便程度不能说不高啊!

刚才第三步调整系统配置,不用调目标的硬件参数,因为那个已经在前一步载入好了,这一步调的是Kernel、Bootloader等参数,改个GCC优化级别什么的(默认的居然是optimize for size,果断直接开到-O3)。

第一次编译的时候,会自动下载需要的源码(默认居然是git clone,所以会把整一个版本库都下下来,我中间遇到一个库有1.5 GB),这一步消耗不少时间,所以我第一次完整编译花了快2小时(所以我看了两小时Youtube)。第一次编译的时候应该不可避免地卡一些error,不用慌,按照报错把要安装的依赖库什么的装好就行。我编译的时候一次是下载源码时莫名其妙的server error(貌似是服务器炸了,不是墙的功劳),另一次是缺了个什么库,反正很快解决了。

最终,生成的是一个磁盘映像。一个Linux仅加入最小的toolchain体积真是非常小啊!我之前用过Linaro,映像文件有好几GB,写入一次SD卡花了将近一个小时。这次居然只有几十M,不到一分钟就搞定了。

写入SD卡用刚刚提到的脚本就行(如果是Cubieboard的话)。没人帮忙写好脚本的话,手动操作也不是什么麻烦事。

用Buildroot实实在在简化了本来很麻烦的工作,至少比一直盯着终端期待不要报错要好得多,总之就是好好好!交叉编译有这么棒的解决方案,接下来就可以愉快地修改Kernel了w

注:以上全部操作在MBP上的Parallel虚拟机上的Ubuntu 14.04 LTS上正常运行,速度OK。用虚拟机,可以防止手残不小心在写SD卡的时候把电脑的磁盘写了,而且不用顾虑临时文件的清理什么的,个人还是蛮推荐的。