8.11 打包:定义包类及其内容
一个bitbake"配方"就是一组创建一个或者多个在目标设备上安装的包的命令集合.典型的包就是
.ipkg或者.deb包(尽管bitbake本身并没有跟任何特殊的包格式相关联).
默认情况下会自动生成一些包,这些包并没有包含任何"配方"作者要求的特定动作.上面的helloworld
例子的包输出信息就说明了这些:
[NOTE: package helloworld-0.1-r0: task do_package_write: started
NOTE: Not creating empty archive for helloworld-dbg-0.1-r0
Packaged contents of helloworld into /home/lenehan/devel/oe/build/titan-glibc-25/tmp/deploy/ipk/sh4/helloworld_0.1-r0_sh4.ipk
Packaged
contents of helloworld-doc into
/home/lenehan/devel/oe/build/titan-glibc-25/tmp/deploy/ipk/sh4/helloworld-doc_0.1-r0_sh4.ipk
NOTE: Not creating empty archive for helloworld-dev-0.1-r0
NOTE: Not creating empty archive for helloworld-locale-0.1-r0
NOTE: package helloworld-0.1-r0: task do_package_write: completed
我们可以看到上面的打包动作做了如下事情:
* 创建主包,helloworld_0.1-r0_sh4.ipk.这个包包含了helloworld的二进制文件
/usr/bin/helloworld.
*创建了文档包, helloworld-doc_0.1-r0_sh4.ipk.这个包包含了readme文件
/usr/share/doc/helloworld/README.txt.
*尝试创建调试包,helloworld-dbg-0.1-r0_sh4.ipk,一个开发包helloworld-dev-0.1-r0_sh4.ipk
和一个本地化(locale)包helloworld-locale-0.1-r0_sh4.ipk.但是这些包最终并没有创建,因为没有找到任何
应该属于该包的文件.
这里发生了几件需要重点理解的事情:
1.有一类默认的包会被尝试去创建.这些包在变量PAKAGES里控制.
2.对于每个包会默认认为有些文件是属于它的.比如文档包就会包含任何在/usr/share/doc里面的文件.这些文件和目录
3.默认情况下,不包含任何文件的空包是不会被创建的,也不会产生错误.要不要产生空包可以在变量ALLOW_EMPTY里来设置.
8.11.1 基本规则
尽可能的分离包是OE的设计的一个高明之处.许多设备的内存和存储空间是有限的,对于发行者和用户来说可以选择不安装一个包的
不需要的部分可以节省可观的存贮空间.
比如没有哪个PC发行版会包含用户不需要使用的文档和开发库包(译者注:当然这个不怎么正确,文档包一般都有,lfs还默认安装开发库),
因为用户的日常使用根本用不到这些东西.特别的,如果你的包提供多种二进制格式,用户可能一般会只选择其中一种,所以你应该分离这些包.
默认情况下文件将会被自动分组而分离,包括:
开发包(dev)
任何开发才会需要的文件.这会包含头文件,静态链接库,动态链接库等.这些只会是想要在设备上编译程序的人才需要的.
但是通常情况这种需要并不多,所以这些文件就会自动移动到分离的包(开发包).
文档包(doc)
任何文档相关文件,包括man手册页.这些文件只是处于提供帮助信息的目的.对于大多数嵌入式设备并没有让用户去查看文档
的方式或者需要.不过文档文件比较占用空间.分离出来这些就可以节省空间,如果用户需要查看也可以选择自己安装.
本地化包(locale)
本地化信息是软件包的翻译信息.许多用户不需要这些翻译,许多设备只是想提供用户界面相关的组件的翻译信息但不是系统
程序的,分离这部分出来然后用户可以选择他们到底需不需要.
8.11.2.默认包类和文件
默认的打包设置在conf/bitbake.conf里面定义,而且对于大多数"配方"来说这些设置是很合适的,下面的列表展示了一些默认的
打包相关变量的值:
PACKAGES
这个变量列出了每个软件包都需要创建那些包:
PACKAGES = "${PN}-dbg ${PN} ${PN}-doc ${PN}-dev ${PN}-locale"
注意,包的顺序是很重要的:这些包是按照数序来创建的,所以如果两种包同时指定了一个文件,那么按照顺序的第一种包将包含这个文件.
这在使用通配符来指定包内容的时候就很重要了.
例如,如果主包${PN}包含了/usr/bin/*(/usr/bin下面的所有文件),但是你又希望/usr/bin/tprogram到一个独立的包
${PN}-tpackage里面,你需要把在PACKAGES变量里设置的${PN}-tpackage安排在${PN}的前面,或者编辑FILES_${PN}
的通配符叫它不要匹配到/usr/bin/tprogram文件.
注意-dbg包包含了从二进制和库文件里过滤出来的调试信息.这个类型的包应该永远设置优先与其他的包以保证调试信息能正确的
提取出来.
FILES_${PN}
主包,包含了一切在设备上运行程序需要的东西.
FILES_${PN} = "\
${bindir}/* \
${sbindir}/* \
${libexecdir}/* \
${libdir}/lib*.so.* \
${sysconfdir} \
${sharedstatedir} \
${localstatedir} \
/bin/* \
/sbin/* \
/lib/*.so* \
${datadir}/${PN} \
${libdir}/${PN}/* \
${datadir}/pixmaps \
${datadir}/applications \
${datadir}/idl \
${datadir}/omf \
${datadir}/sounds \
${libdir}/bonobo/servers"
FILES_${PN}-dbg
从为过滤的库和可执行文件里提取的调试信息.OE会自动的提取调试信息到.debug文件夹里然后过滤原文件.
FILES_${PN}-dbg = "\
${bindir}/.debug \
${sbindir}/.debug \
${libexecdir}/.debug \
${libdir}/.debug \
/bin/.debug \
/sbin/.debug \
/lib/.debug \
${libdir}/${PN}/.debug"
FILES_${PN}-doc
文档相关文件.所有文档将会自动的被分离到它自己的文档包里,除非需要,文档默认将不会被安装.
FILES_${PN}-doc = "\
${docdir} \
${mandir} \
${infodir} \
${datadir}/gtk-doc \
${datadir}/gnome/help"
FILES_${PN}-dev
开发相关的文件.任何头文件,库文件或者支持开发用的文件.
FILES_${PN}-dev = "\
${includedir} \
${libdir}/lib*.so \
${libdir}/*.la \
${libdir}/*.a \
${libdir}/*.o \
${libdir}/pkgconfig \
/lib/*.a \
/lib/*.o \
${datadir}/aclocal"
FILES_${PN}-locale
本地化相关文件.
FILES_${PN}-locale = "${datadir}/locale"
8.11.3.通配符
FILES变量的通配符是通过python的fnmatch函数来处理的.下面是这个函数的一些相关注意事项:
* /
/*: 这个会匹配到所有在dir下面的目录和文件.
* /
/a*: 这个只会匹配到文件,不包含目录.
* /dir: 这个会包含dir目录,当然会包含dir下面的一切子目录和文件.
注意,包类的前后顺序将会影响通配符的匹配效果,假设我们有三个二进制文件在/usr/bin/目录下面,
然后我们想要test程序到一个单独的包里面:
/usr/bin/programa /usr/bin/programb /usr/bin/test
所以,我们定义一个新的包然后告诉bitbake在这个包里包含/usr/bin/test.
FILES-${PN}-test = "${bindir}/test"
PACKAGES += "FILES-${PN}-test"
这样打包时其实${PN}-test 包不会产生,原因是 PACKAGES变量现在看起来是这样了:
{PN}-dbg ${PN} ${PN}-doc ${PN}-dev ${PN}-locale ${PN}-test
注意到${PN}在${PN}-test的前面,然后我们看到FILES-${PN}里面定义了${bindir}/*通配符,
所以,${PN}会第一个匹配到它然后它会被移动到${PN}包里而不是${PN}-test包.
想要做到预期的效果我们有两种选择:
1.编辑${PN}的设置不让它匹配到test程序.
比如我们可以这样做
FILES-${PN} = "${bindir}/p*"
所以,现在这将只会匹配到p开头的文件,不会包含test程序.注意,FILES-${PN}通常
会包含很多通配符的设置项,然后会包含很多其他的文件进来,这个例子里我们并没有其
他文件,所以这么简单的定义是可行的.
2. 编辑${PN}-test包以使它在前面.
最显而易见的办法是把${PN}-test包"前加"(作为前缀)到PACKAGES变量里面:
PACKAGES =+ "FILES-${PN}-test"
有时候这样会工作的很好,但是这里有了一个问题,这个包现在处于-dbg包的前面,这将
导致.debug目录包含进包里面(译者注:官方文档这里貌似弄错了,其实test包如果在前面,
意味着在过来debug信息之前test程序已经被移动了,所以只会导致对应的.debug目录没有
被创建而不是包含到了里面,可能是exclude被误写为include了.)
通常情况下最常用的办法可能是重新定义PACKAGES变量了:
PACKAGES = "${PN}-dbg ${PN}-test ${PN} ${PN}-doc ${PN}-dev ${PN}-locale"
8.11.4.查看包
在开发"配方"的过程中如果能检查和确认那个文件进了那个包,或者那个包没有创建,那个包里没有文件之类的应该
是非常之有用的.
其中之一最简单的办法就是在install目录里面运行find命令.在install目录里面每个包都会有一个子目录,然后
文件也被移动到了相关匹配的包里.下面的例子展示了这些:
$ find tmp/work/helloworld-0.1-r0/install
tmp/work/helloworld-0.1-r0/install
tmp/work/helloworld-0.1-r0/install/helloworld-locale
tmp/work/helloworld-0.1-r0/install/helloworld-dbg
tmp/work/helloworld-0.1-r0/install/helloworld-dev
tmp/work/helloworld-0.1-r0/install/helloworld-doc
tmp/work/helloworld-0.1-r0/install/helloworld-doc/usr
tmp/work/helloworld-0.1-r0/install/helloworld-doc/usr/share
tmp/work/helloworld-0.1-r0/install/helloworld-doc/usr/share/doc
tmp/work/helloworld-0.1-r0/install/helloworld-doc/usr/share/doc/helloworld
tmp/work/helloworld-0.1-r0/install/helloworld-doc/usr/share/doc/helloworld/README.txt
tmp/work/helloworld-0.1-r0/install/helloworld
tmp/work/helloworld-0.1-r0/install/helloworld/usr
tmp/work/helloworld-0.1-r0/install/helloworld/usr/bin
tmp/work/helloworld-0.1-r0/install/helloworld/usr/bin/helloworld
$
上面的信息说明-local,-dbg,-dev包是空包,然后-doc和主包都各自包含了一个文件.使用"-type f"选项
可以只显示文件,这样看起来更清晰.
相比较之下,image目录(也就是所谓的目标目录D)将会包含任何没有打包的文件:
$ find tmp/work/helloworld-0.1-r0/image
tmp/work/helloworld-0.1-r0/image
tmp/work/helloworld-0.1-r0/image/usr
tmp/work/helloworld-0.1-r0/image/usr/bin
tmp/work/helloworld-0.1-r0/image/usr/share
tmp/work/helloworld-0.1-r0/image/usr/share/doc
tmp/work/helloworld-0.1-r0/image/usr/share/doc/helloworld
$
这样一来,所有被打包了的文件都不会留到这里,使用"-type f"更清晰些:
$ find tmp/work/helloworld-0.1-r0/image -type f
$
bitbake也会在打包过程中警示没有被打包进的文件:
NOTE: package helloworld-0.1-r0: task do_package: started
NOTE: the following files were installed but not shipped in any package:
NOTE: /usualdir/README.txt
NOTE: package helloworld-0.1-r0: task do_package: completed
除非是不正常的情况,否则,一个"配方"应该不留下任何没有被打包的文件.
8.11.5.不需要的文件
OE里没有明确的支持不包含文件的方法.你可以简单的留到包外,但是你会得到警告或者错误(如果
你做完整的包检查的话),而且其他人或许会知道你存心没有打包某个文件.
在某些时候或许在安装任务结束后手动删除不需要的文件要相对容易些.下面从samba配方里截取的例子
显示了在用autotools类安装任务完成之后删除一些文件.这里是在autotools产生的install任务之后
运行do_install_append命令:
do_install_append() {
...
rm -f ${D}${bindir}/*.old
rm -f ${D}${sbindir}/*.old
...
}
8.11.6.debian命名机制
打包的时候应用一种特殊的debian库命名规则.如果启用了,包会被按照debian的习惯重新命名.
debian命名方式可以通过在local.conf文件或者您的发行版的配置文件里包含debian类来实现:
INHERIT += "debian"
根据规则,包会被根据查看共享库的名字和版本自动重命名为
的样子.比如,包名为foo,然后这个包里包含了一个libfoo.so.1.2.3这样的文件,那么包将会被
自动重命名为libfoo1.
如果我们查看lzo_1.08.bb的配方,当前的发布号14,它产生了一个单个共享库文件:
$ find tmp/work/lzo-1.08-r14/install/
tmp/work/lzo-1.08-r14/install/lzo
tmp/work/lzo-1.08-r14/install/lzo/usr
tmp/work/lzo-1.08-r14/install/lzo/usr/lib
tmp/work/lzo-1.08-r14/install/lzo/usr/lib/liblzo.so.1
tmp/work/lzo-1.08-r14/install/lzo/usr/lib/liblzo.so.1.0.0
如果不使用debian命名方式,包名字会叫做lzo_1.08-r14_sh4.ipk(然后对应的dev和dbg包就会
是lzo-dbg_1.08-r14_sh4.ipk 和 lzo-dev_1.08-r14_sh4.ipk),但是,如果使用了debian
命名机制,根据liblzo.so.1.0.0包就lzo会被重命名为liblzo1:
$ find tmp/deploy/ipk/ -name '*lzo*'
tmp/deploy/ipk/sh4/liblzo1_1.08-r14_sh4.ipk
tmp/deploy/ipk/sh4/liblzo-dev_1.08-r14_sh4.ipk
tmp/deploy/ipk/sh4/liblzo-dbg_1.08-r14_sh4.ipk
这里有一些变量会影响debian重命名类的具体操作:
LEAD_SONAME
如果一个包实际包含了多重共享库,那么其中一个会被自动选择,然后产生一个警告.
这个变量是一个正则表达式,用来选择那些共享库是debian重命名可用的.
如果这个变量的值设置为1,那么该包就不会自动使用debian命名机制.
AUTO_LIBNAME_PKGS
设置那些包会应用debian命名机制.这个选项用来设置不需要所有包都使用debian
命名机制的情况.
8.11.7.空包
默认情况下空包是被忽略的.或许您可能希望去创建空包,典型的应用就是你可能需要创建一个虚拟包
然后里面只有依赖关系的情况.ALLOW_EMPTY变量是用来控制产不产生空包的:
ALLOW_EMPTY
控制产不产生空包.默认这个设置是0,空包不会被创建,设置为1就允许创建不包含文件的空包.
8.12任务:用“任务“工作
8.13类:分离常用的功能
8.14中间处理:为编译配置头文件和库
8.15自动配置:autotools主题
8.16安装脚本:运行脚本安装和移除包
8.17配置文件
8.18包之间的关系
8.19虚拟根:处理“root”的“需要“
8.20本地:为主机编译的包
8.21开发:开发“配方”的方法策略
8.22高级的版本号:如何处理rc和per版本
8.23包含:重用“配方”的内容
8.24Python语言:python的高级功能
8.25初始化脚本:怎么处理守护进程
8.26两者选一:怎样处理多个包使用相同的命令
8.26.1.例子
8.26.2.使用新的
8.27转瞬即逝:如何处理/var目录
8.27.1.声明
8.27.2.写日志和日志文件
8.27.3.摘要
8.28其他杂项
剩余章节翻译中。。。。。。。。。