转自:http://blog.csdn.net/fmddlmyy/archive/2008/11/08/3254033.aspx
1 概述
OpenEmbedded(OE)是一个开源的嵌入式linux系统构建环境。
Openmoko和poky都使用了定制过的OpenEmbedded环境。
Openmoko是一个开放软硬件设计的手机平台。Poky的本意是一个定制过的OpenEmbedded环境。
Poky环境包含了一个叫作Sato的UI方案,我们有时也把这个方案叫作poky。其实我们可以在poky环境开发其它基于GTK+/Macthbox
的UI方案。
构建一个嵌入式linux系统需要构建引导模块、内核和文件系统。这是一个相当复杂的过程,特别是文件系统的构建。一个典型的文件系统可能需要下
载、编译、安装几百个软件包。如果你做过LFS(Linux From
Scratch),就可以体会到手工创建文件系统的复杂性。嵌入式系统因为是交叉编译(在PC环境编译、在嵌入式环境运行),所以构建过程更加复杂。
OpenEmbedded 就是为了简化嵌入式系统的构建过程而设计的。尽管存在着体积大、速度慢等缺点,但OpenEmbedded确实简化了嵌入式系统的构建过程。例如,在安装过需要的工具后,构建poky的完整过程只是在进入poky目录后,执行两条命令:
. poky-init-build-env
bitbake poky-image-sato
然后就是等待构建完成。构建过程可能需要12-36小时。目标系统的复杂程度、网速、软硬件环境都会影响构建时间。
在完成一次成功构建后,我们就可以在这个环境开发应用程序。这时我们只需要编译变化的部分。在应用开发完成后,我们可以手工将其安装到目标系统上测
试。在需要的时候,也可以重新构建文件系统。这时,OE仅编译变化的软件包,并重做一次文件系统映像。重做一次文件系统映像大约需要10-15分钟。
2 程序员看到的OpenEmbedded
2.1 脚本和数据
在程序员看来,OpenEmbedded是一些脚本(shell和python脚本)和数据构成的自动构建系统。
脚本实现构建过程,包括下载(fetch)、解包(unpack)、打补丁(patch)、configure(如果使用了autotool)、编
译(compile)、安装(install)、打包(package)、staging(以后讨论)、做安装包
(package_write_ipk)、构建文件系统等。
数据主要提供两个方面的信息:
- 特定软件包的构建信息。怎样获取源代码和补丁?怎样构建,用Makefile还是Autotool?需要向目标编译环境输出哪些文件?需要安装哪些文件?每个软件包都需要描述文件。事实上,每个软件包的不同版本都有一个描述文件。
- 软件包之间的依赖关系。构建软件包A需要先构建什么主机平台工具,什么目标平台工具?软件包A在编译时依赖哪些软件包?软件包A在运行时依赖哪些软件包?一个目标应包含那些软件包?这些依赖关系把几百个软件包联系在一起,构成了一个完整的系统。
脚本和数据本来是一起打天下的。随着系统的完善,两者的独立性越来越强,就像《围城》中灌满了泥浆的裤子可以不依赖主人的腿而独自站立一样,数据和脚本也希望脱离对方独立发展。希望独立的脚本被称作bitbake。希望独立的数据就是OE元数据。
2.2 bitbake和OE元数据
可以把bitbake看作实现具体步骤的烹饪工具。把元数据看作食谱。如果只有烹饪工具,没有食谱,我们不知道要做什么。如果只有食谱,没有烹饪工具,就无法完成具体操作。
作为烹饪工具的bitbake是构建系统中代表稳定的部分。各种烹饪工具可以日趋完善,食谱可以随意选择自己需要的工具。
作为食谱的OE元数据是构建系统中代表变化的部分。变化来自两个方面:
- 虽然食谱系统不断完善,包含了大多数嵌入式系统可能用到的软件包。但还是会有新的软件包被开发出来。已有的软件包也会出新版本
- 每个系统总有自己独特的爱好和口味。Openmoko和Poky是定制过的OE环境。它们所定制的就是OE元数据。
Openmoko根据手机平台的需要,增加和定制了一些软件包,以及软件包的依赖关系。
Poky的主要风格是精简的GTK+/Macthbox系统。Openmoko环境有5千多个食谱文件,poky环境只有7百多个食谱文件。
我们可以根据自己的需要定制自己的元数据。Openmoko和poky都是不错的起点。一个不错的选择是以poky为起点,再从openmoko中取己所需。当然,我们总要根据设计目标开发特有的应用。
3 文件系统里的OpenEmbedded
OE环境中最重要的目录有3个:放工具的bitbake目录、放元数据的目录、和执行构建的build目录。
3.1 bitbake目录
这个目录里是我们的烹饪工具:bitbake。我们使用它,但通常不需要访问它
3.2 元数据目录
在poky中元数据目录是meta。Openmoko中元数据目录是openembedded。在元数据目录中,有3个目录里是真正的元数据。它们是:classes、conf和packages。
3.2.1 packages目录
所有的食谱文件(以.bb为后缀名)都放在package目录。每个相对独立的软件包或构建任务在package目录下都有自己的子目录。在一个子目录中可以有多个食谱文件。它们可能是同一个软件包的不同版本。也可能描述了基于同一个软件包的不同构建目标。
有的食谱简单,有的食谱复杂。简单的食谱仅描述一个软件包的构建。最复杂的食谱就是要求构建文件系统的食谱,例如poky环境中的poky-
image-sato,openmoko中的openmoko-devel-image。这个食谱文件本身并不长,甚至还很短,但它通过依赖关系将几百个
甚至几千个其它食谱文件卷入了构建过程。 packages目录的images子目录下就是这些要求构建文件系统的食谱。
3.2.2 classes目录
这个目录放的是食谱的类文件(以.bbclass为后缀名)。类文件包含了一些bitbake任务的定义,例如怎么配置、怎么安装。食谱文件继承类
文件,就继承了这些任务的定义。例如:我们如果增加一个使用autotool的软件包,只要在食谱文件中继承autotools.bbclass:
inherit autotools
bitbake就知道怎样使用autotool工具配置、编译、安装了。所有的食谱文件都自动继承了base.bbclass。 base.bbclass提供了大部分bitbake任务的默认实现。
一个食谱文件可以继承多个类文件。以后的文章会介绍bitbake的任务,届时会更详细地讨论bitbake的继承。目前,我们只要知道继承类文件是一种构建过程的复用方式就可以了。
3.2.3 conf目录
conf目录包含编译系统的配置文件(以.conf为后缀名)。bitbake在启动时会执行bitbake.conf。
bitbake.conf会装载用户提供的local.conf。然后根据用户在local.conf中定义的硬件平台(MACHINE)和发布目标
(DISTRO)装载machine子目录和distro子目录的配置文件。
machine子目录里是硬件平台相关的配置文件。distro子目录里是与发布目标相关的配置文件。配置文件负责设置bitbake内部使用的环境变量。这些变量会影响整个构建过程。
3.3 build目录
build是我们烹饪嵌入式系统的大厨房。整个构建过程就是在build目录的tmp子目录完成的。 build目录的conf子目录里是用户的配置文件local.conf。
tmp目录有7个子目录:cache、cross、rootfs、staging、work、deploy和stamps目录。其中cache是
bitbake内部使用的缓存目录。cross是构建过程中产生的交互编译器。所谓交互编译器就是在主机平台运行,用于编译目标平台代码的编译器。
rootfs是制作文件系统映像前临时建立的根文件系统。我们在工作中通常不需要访问这3个目录。我们访问比较多的是其它4个目录:staging、
work、deploy和stamps目录。
3.3.1 staging目录
软件包B在构建时可能依赖软件包A提供的头文件、库文件,也可能要使用软件包C生成的工具。 staging目录就是放这些输出文件的地方。
我们必须在食谱文件中用“DEPENDS”变量声明构建时的依赖关系。
bitbake就会在构建软件包B前先构建软件包A和软件包C,并将软件包B需要的头文件、库文件、和工具放在staging目录。这样,在构建软件包B
时就可以从staging目录得到需要的头文件、库文件、和工具。
3.3.2 work目录
所有软件包的解包、打补丁、配置、编译、安装等工作都是在work目录进行的。所以work目录包含了整个嵌入式系统的完整源代码。
work目录下按照硬件平台、发行人、目标平台的不同又分了几个子目录。所有软件包都被放在对应子目录中。每个软件包都有一个独立的目录。因为软件包总是
根据一个食谱文件构建的,所以软件包所在的目录就是对应食谱文件的工作目录。在讨论bitbake和食谱文件时我们还会回来,更仔细地观察食谱文件的工作
目录。
3.3.3 deploy目录
这是保存输出成果的目录。其中images目录保存构建成功后产生的文件系统映像、内核映像。 ipk目录保存每个软件包的安装包。我们在修改、构建软件包后,可以在目标平台手工安装ipk目录下的对应安装包。确认没有问题后,再制作文件系统映像。
3.3.4 stamps目录
和work目录类似,stamps目录也按照硬件平台、发行人、目标平台的不同又分了几个子目录。软件包在完成每个bitbake任务后都会在对应子目录里touch一个对应任务的时间戳。有时我们会手工删除某个软件包的时间戳,强制bitbake重新构建这个软件包。
3.4 sources目录
OE环境的sources目录是一个储藏间,用来放从网上下载的源代码包。 fetch任务负责下载代码,放到sources目录。
我通常在OE目录树之外创建一个公共sources目录。然后在OE目录创建一个软链接指向这个sources目录。这样,如果我同时在多个OE环
境编译多个版本,这些OE环境的sources目录可以指向同一个公共sources目录。我让openmoko和poky也使用同一个公共
sources目录。这样,大量构建系统所需的的软件包被保存在公共sources目录。在重新编译一个目标版本时,可以节省下载时间。在没有外网连接时
也能完成整个构建过程。以后,即使有些软件包的链接失效了,我们还是可以构建完整的系统。
4 结束语
在自动化嵌入式系统构建过程的同时,OpenEmbedded 把前人的构建经验用脚本的形式记录下来。我们可以通过阅读OE脚本更直观地学习怎样构建一个嵌入式系统。
无论在windows、linux、还是RTOS上,也无论使用C/C++、Java、还是脚本,程序员总是在将变化从不变中分离出来。
OpenEmbedded 已经将脚本和元数据分离开来,将变化的元数据和不变的元数据分离开来。如果OpenEmbedded
能更有效地区分必须的关联和可选的关联,将关联的配置相对集中起来,定制系统可能会更简单。
本文是OpenEmbedded 的简单介绍,下面我们将进一步了解bitbake世界的风土人情,食谱文件的规则、惯例,在tmp/work目录中究竟发生了什么。后面的文章假设读者已经编译、运行过poky或openmoko。本文的例子主要基于poky。
不管Openmoko和OpenedHand(poky的开发者,已被Intel收购)如何发展,放在我们面前的是一套完整的嵌入式Linux方案。只要我们愿意,我们可以看到这个系统的每个细节,每行代码,包括构建系统本身的每行脚本。