buildroot编译环境
它其实就是一个脚本和补丁的集合,它是一个针对uClibc的交叉编译环境,里面集成了gtk,directFB,Qt embedded,jpeg库等 ,对于每个包,包括Config.in和 .mk文件。
对于每一个包,Makefile的流程是下载 ,解压 ,patch ,configure , make , install 。
这里面最主要的是patch和Config.in,patch解决了source在交叉编译环境下所需要的修改,Congin.in解决了依赖关系。
Buildroot的目录结构如下:
package : 各个user space包的目录,每个包里面包括makefile patch,每个目录下必须有下面2个文件 :
.mk : makefile 包括下载,,解压,patch ,configure ,编译,安装
Config.in : 描述文件,包括包的依赖关系等,一选上就会相应选择其他的包等等信息
toolchain : 交叉工具链gcc .binutils,uclibc 等的makefile patch
docs : help file
target :产生rootfs 的工具的makefile patch , 包括ext2 jffs2 cramfs等制作工具
project : 编译多个rootfs在一个buildroot tree下的一些makefile 等
script : 一些脚本
Buildroot为编译产生的目录 :
dl : 下载的包存放的目录,这样不用每次都去下载
build_ARCH : 不可配置的user space tools 编译目录 ,这样的话 ,如果对于相同的ARCH ,则共享这部分,不用再编译
project_build_ARCH : configurable user space tools 编译目录, 比如busybox , 对于相同的ARCH,也可能配置不一样
toolchain_build_ARCH : toolchain编译目录
binary /$(project) : rootfs ,kernel image ,boot loader在存放目录,可用来下载到产品中
build_ARCH/staging_dir : 交叉工具链 安装的地方
project_buid_ARCH/root : rootfs , 不是打包成.jffs2的那种方式,适合NFS调试
.config 配置文件
Buildroot利用和Linux kernel config一样的原理,直接运行make menuconfig ,图形化选择包,应此比较易用。
Buildroot的编译过程 如下:
a)toolchian的制作,如果选择external toolchain,跳过这一步,否则
1 下载内核代码,通过内核代码 生产内核头文件
2 下载uClibc 库
3 编译binutils (pass 1)
4 编译gcc (pass 1)
5 编译uClibc
6 编译gcc (pass 2)
b) 其他包的编译
1 编译busybox
2 根据选择的包,编译其他的包
3 制作成jffs2 或者ext2 等根文件系统
对于每一个包,都是下载,解压,patch,configure ,make ,install,所以最终对这些文件的修改,比如mplayer,qtopia等,
最好也做成patch的方式。这样也便于管理,以及知道我们对源码的修改有那些。
Buildroot的优点: 1) 易用,直接 make menuconfig ,选择上所需要的包 , 然后 make
2) 支持uClibc,对于很多嵌入式设备,因空间小,需要选择uClibc时,那编译环境最好选择Buildroot了,它
就是针对uClibc的编译
缺点: 1)不能制作glibc的toolchain ,如果用glibc 则用external toolchain
2)还有一些变态的功能,比如为多个平台编译阿 支持不好,不过这些我也不需要
3)修改了代码后,不会重新编译 (这个很麻烦的,一般都是开始的时候全部编译,然后在修改代码,不能直接编译,太麻烦了 )
这个是package中的问题 ,比如 busybox ,修改其中的代码,发现不会重新编译。
如果直接修改了其中的代码,需要删除busybox,然后再编译,这点对于在开发过程中比较麻烦,
如果这样修改busybox.mk
--- $(BUSYBOX_DIR)/busybox: $(BUSYBOX_DIR)/.config
+++ $(BUSYBOX_DIR)/busyboxfake: $(BUSYBOX_DIR)/.config
--- $(TARGET_DIR)/bin/busybox: $(BUSYBOX_DIR)/busybox
+++ $(TARGET_DIR)/bin/busybox: $(BUSYBOX_DIR)/busyboxfake
这样每次修改文件都会重新编译
因为busyboxfake永远不存在,所以他永远会去执行make ,make会去检查是否有文件修改
而buildroot本来的方式 当存在busybox后,它不执行make了
依据同样原理去修改其他的.mk
但是 后果是 即使没有文件修改了,也会执行install动作 。
更好的方法一直没想到。
Buildroot使用
1) 用uClibc工具链,
a) 工具链编译 ,本机环境 ubuntu 9.04 Gcc 4.3
a.1)选择uclibc 以及gcc 版本,然后make
a.2)下载linux-2.6.30.5.tar.bz2,主要是得到linux 头文件 ,uclibc/glibc编译都需要linux
kernel header ,以了解kernel所具备的能力
a.3) 下载uClibc-0.9.30.1.tar.bz2
a.4) 下载 gmp-4.2.4.tar.bz2 (arbitrary precision arithmetic lib on signed number)
a.5) download mpfr (arbitrary precision arithmetic on floating-point numbers)
a.6) 编译出库文件 .a
a.7) 下载 binutils-2.19.1.tar.bz2
a.8) binutils 第一遍编译,
在build_arm/staging_dir/usr/bin生成了很多工具 如 ar ,ld ,此时的工具host为本机
target为arm
a.9) 下载 gcc-4.3.3/gcc-4.3.3.tar.bz2
a.10) gcc 第一遍编译
第一次生成的gcc是不完全的, 只能交叉编译uClibc,不能交叉编译其他的,因为一个关键的工具链组件还不存在:启动代码crt?.o。这些代码其实包括了程序初始化进入main函数之前和退出main函数之后结束所需的步骤。用第一遍的gcc 编译
echo "main(){}" > dummy,c && gcc dummy.c
这是会出错的。
参见 http://www.linuxsir.org/bbs/thread267672-4.html
a.11) 编译uClibc
a.12) gcc 第二遍编译
在build_arm/staging_dir/usr/bin生成了gcc
这次c++也支持了(而c++支持必须要有glibc/uClibc库的支持,所以a.11编译出了uClibc)
参见 http://www.linuxsir.org/bbs/thread267672-4.html
a.13) 编译atk,freetype等,
在build_arm/staging_dir/usr/include 产生出很多头文件
在build_arm/staging_dir/usr/lib 产生出库
这些都是其他user space (比如GTK ,X)的基本库,在make menuconfig的时候,可以看到选择了那些package
a.14) 在看binutils的 makefile的时候,还有 binutils 第2遍编译
此时的工具host为arm
target为arm
也就是此次生产的这些工具,将在arm平台上跑,编译出arm的代码.
如此的话,那gcc 有第3次编译了(此时的gcc run on arm ,编译出arm的代码)
不过我没看到binutils 的第2次编译和gcc的第3次编译,一般都是在pc上编译arm的代码阿,谁还在
arm机器上跑gcc来编译呢?
可能出现的问题 :
1) 安装Texinfo ,出现问题1
版本是4.11 ,需要修改,
将正则表达式改为'texinfo[^0-9]*([1-3] [0-9]|4.[4-9]|4.[1-9][0-9]*|[5-9])'
参见
http://www.lupaworld.com/home/space-32446-do-blog-id-121384.html
2) 出现问题2
/home/lawrencekang/xpndr-infotainment_center_2.0.3/buildroot/toolchain_build_arm_nofpu/gcc-4.2.1-initial/./gcc/as: line 2: exec: -m: 无效的选项
修改 : ./gcc/as文件
exec -c /home/lawrencekang/xpndr-infotainment_center_2.0.3/buildroot/build_arm_nofpu/staging_dir/bin/arm-linux-uclibcgnueabi-as "$@"
b) 编译gtk2 ,用上次生成的toolchain编译
选择了gtk2 /x ,然后make ,结果出现错误,在编译X server的时候 出现 MB_CUR_MAX 没定义的错误
在buildroot ->toolchain中 选择 Enable toolchain locale/i18n support?
Enable WCHAR support
另外,由于我的目标机器没有 hardware floating
我选择 Use software floating point by default
Thread library implementation -》选择NPTL
然后make clean
问题 ? 怎么不重新编译 compiler呢?
solution : 删除 编译的包 重新编译
发现uClibc还不能Enable toolchain locale/i18n support? 这也说明uClibc小但是功能弱
去掉,删除toolchain_build_arm
重新编译
./../gdk/x11/gdkwindow-x11.h:33:36: X11/extensions/Xdamage.h: 没有该文件或目录
但实际上 这个文件是存在的 目录是 build_arm/staging_dir/usr/include/X11/extensions
这是因为编译gtk host时,需要libxdamage-dev
sudo apt-get install libxdamage-dev
[Question] 不明白它为什么要编译host Gtk ?
2) 用外部的external toolchain 编译arm平台 用glibc
a) 选择arm-2006q3
b) 按照buildroot说明文档 ,配置好external tool chains
出现错误 : Incorrect selection of the C library
原因:
在目录toolchain/external-toolchain 里面 ,有个ext-tool.mk,check_glibc
发现他怎么去找 /opt/codesourcery/arm-none-linux-gnueabi/libc 下面的
The programs ld.so and ld-linux.so* find and load the shared libraries needed by a program,
arm-2006q3/libexec/gcc/arm-none-linux-gnueabi/4.1.1/install-tools/mkheaders
里面的prefix = /opt/codesourcery
解决方法:
将./external_toolchain/arm-2006q3 下面的文件全部copy 到 /opt/codesourcery下面
c)编译 fltk OK
d)编译Qtembedded 4.5 OK
3) 用外部的external toolchain 自己添加包
添加qtopia 4.2.1
发现出了一些问题 ,以前用ubuntu 7编译的时候 没出错阿 ,而现在用的是ubuntu 9.04 (linux 2.6.28-15 )
也许buildroot要向poky一样,先编译出一个host环境,而不依赖于本机的环境
a) 在packgage 里 添加 一个包 qtopia
然后 写上 Config.in , .mk
Config.in 主要是写上依赖关系 ,选项
.mk 包括了 解压代码,patch ,然后.configure , make
在package/Config.in 中 加上 source ./qtopia/Config.in
b) 选上,然后 make
b.1) 出现问题 1
The system byte order could not be detected!
Turn on verbose messaging (-v) to see the final report.
solution :
修改 qtopiacore/qt/configure
指定它little-endian
---
+++
if [ "$F" -eq 0 ]; then
CFG_ENDIAN="Q_LITTLE_ENDIAN"
elif [ "$F" -eq 1 ]; then
CFG_ENDIAN="Q_BIG_ENDIAN"
else
+++ CFG_ENDIAN="Q_LITTLE_ENDIAN"
+++ # echo
+++ # echo "The system byte order could not be detected!"
+++ # echo "Turn on verbose messaging (-v) to see the final report."
+++ # echo "You can use the -little-endian or -big-endian switch to"
+++ # echo "$0 to continue."
+++ # exit 101
--- echo
--- echo "The system byte order could not be detected!"
--- echo "Turn on verbose messaging (-v) to see the final report."
--- echo "You can use the -little-endian or -big-endian switch to"
--- echo "$0 to continue."
--- exit 101
b.2) 出现问题2
asm/page.h找不到
原因 :目前的kernel是 ubuntu 9.04 (linux 2.6.28-15 ),没有asm/page.h这个文件了。
而qtopia 4.2.1 那时候 肯定是基于老版本的kernel ,那时候有这个文件
solution :
从 linux 2.6.21.5中 在 asm-i386里找了一个page.h copy 到usr/inculde/asm/page.h中
b.3) 出现问题3
/usr/include/bits/fcntl2.h:51: 错误: 调用‘__open_missing_mode’,声明有错误属性:open with O_CREAT in second argument needs 3 arguments
原因 :
使用open函数的时候,如果在第二个参数中使用了 O_CREAT,就必须添加第三个参数:创建文件时赋予的初始权限,而gcc-4.3对语法错误的检查严格是出了名的(4.1就不会因此错误退出),所以就退出了。
以前用的gcc版本低
solution :
修改 qtopia-phone-4.2.1/src/libraries/qtopiabase/qmemoryfile_unix.cpp
f = ::open(tmpFile.toLatin1(), O_CREAT | O_WRONLY);
改为
f = ::open(tmpFile.toLatin1(), O_CREAT | O_WRONLY,S_IRWXU|S_IRWXG|S_IRWXO);
b.4) 出现问题4
xargs: /media/H/xpndr-multimedia_base_1.1.1_giant/buildroot/build_arm_nofpu/qtopia-phone-4.2.1/bin/qdawggen: 没有该文件或目录
真奇怪阿 !! 为什么qdawggen没被编译呢?
solution :
在device/XXX/custom.pri 里面
PROJECTS+=tools/content_installer
tools/qdawggen
然后删除 .configured
make
此时将重新编译整个qtopia
b.5) 出现问题5
media/H/buildroot-2009.08/build_arm/qtopia-phone-4.2.1/bin/content_installer /media/H/buildroot-2009.08/project_build_arm/lawrence/root/opt/Qtopia-4.2.1-release/qtopia_db.sqlite /opt/Qtopia-4.2.1-release /apps/Settings /media/H/buildroot-2009.08/build_arm/qtopia-phone-4.2.1/apps/Settings/TaskManager.desktop
make[6]: *** [install_docapi_taskmanagerdesktop] 段错误
原因: 未知,没空去理会
solution :
修改 src/tools/content_installer/main.cpp 直接return 0 ; 什么都不做
c) 然后 OK