8.7.4. 常见任务
8.7.4.1. 创建layer
8.7.4.1.1. 创建layer
可以使用以下命令来创建layer
bitbake-layers create-layer your_layer_name
bitbake-layers create-layer --help #获取命令的更详细用法
创建layer后,对应的目录中会存在conf/layer.conf文件
# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"
# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "meta-vir"
BBFILE_PATTERN_meta-vir = "^${LAYERDIR}/"
BBFILE_PRIORITY_meta-vir = "6"
LAYERDEPENDS_meta-vir = "core"
LAYERSERIES_COMPAT_meta-vir = "honister"
BBPATH: 将层的根目录添加到bitbake的搜索路径,bitbake可以定位class文件(.bbclass)、配置文件以及包含在include和require语句中的文件
BBFILES: 定义layer中所有recipes的位置
BBFILE_COLLECTIONS: 通过在整个openembedded构建系统中用于引用层的唯一标识来建立当前层
BBFILE_PRIORITY: 当openembedded构建在不同layer中找到同名的recipes时,为layer中的recipes建立优先级
LAYERDEPENDS: 列出该layer所依赖的layer
LAYERSRIES_COMPAT: 列出当前版本兼容的yocto项目版本
8.7.4.1.2. 启用layer
要启动layer只需要将layer的路径添加到conf/bblayers.conf中的BBLAYERS变量中
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"
BBPATH = "${TOPDIR}"
BBFILES ?= ""
BBLAYERS ?= " \
/home/yinwg/ywg_workspace/yocto/yocto/meta \
/home/yinwg/ywg_workspace/yocto/yocto/meta-poky \
/home/yinwg/ywg_workspace/yocto/yocto/meta-yocto-bsp \
/home/yinwg/ywg_workspace/yocto/yocto/meta-vir \
"
在新建的layer中附加其他layer的元数据
将元数据附加到另一个recipes称为bitbake附加文件,bitbake附加文件使用.bbappend后缀。可以使用.bbappend对其他layer中的的recipes内容进行增加或者修改,而无需将所有 内容复制到本layer中. 但必须使用相同的根名称
8.7.4.1.3. 管理layer
bitbake-layers --help
NOTE: Starting bitbake server...
usage: bitbake-layers [-d] [-q] [-F] [--color COLOR] [-h] <subcommand> ...
BitBake layers utility
optional arguments:
-d, --debug Enable debug output
-q, --quiet Print only errors
-F, --force Force add without recipe parse verification
--color COLOR Colorize output (where COLOR is auto, always, never)
-h, --help show this help message and exit
subcommands:
<subcommand>
add-layer Add one or more layers to bblayers.conf.
remove-layer Remove one or more layers from bblayers.conf.
flatten flatten layer configuration into a separate output
directory.
layerindex-fetch Fetches a layer from a layer index along with its
dependent layers, and adds them to conf/bblayers.conf.
layerindex-show-depends
Find layer dependencies from layer index.
show-layers show current configured layers.
show-overlayed list overlayed recipes (where the same recipe exists
in another layer)
show-recipes list available recipes, showing the layer they are
provided by
show-appends list bbappend files and recipe files they apply to
show-cross-depends Show dependencies between recipes that cross layer
boundaries.
create-layer Create a basic layer
8.7.4.2. 自定义image
8.7.4.2.1. IMAGE_INSTALL
自定义image最简单的方法就是通过local.conf配置文件添加包,但是这种修改对所有的构建都有效,会影响所有的image。使用这种方式的操作如下
IMAGE_INSTALL:append = " strace" #注:需要添加空格
IMAGE_INSTALL:append会影响所有image,可以扩展语法,以便变量仅适用于特定的image, 下面是一个例子
IMAGE_INSTALL:append:pn-core-image-minimal = " strace" #添加strace到core-image-minimal中
8.7.4.2.2. IMAGE_FEATURE
另一种方法是使用IMAGE_FETURES或者EXTRA_IMAGE_FEATURES变量启用或者禁用image高级功能。要了解这些功能的工作原理,最好的参考是meta/classes/image.bbclass
为了说明如何使用这些变量来修改图像,请考虑一个选择 SSH 服务器的示例。Yocto 项目附带了两个可用于图像的 SSH 服务器:Dropbear 和 OpenSSH。Dropbear 是适用于资源受限环境的最小 SSH 服务器, 而 OpenSSH 是众所周知的标准 SSH 服务器实现。默认情况下,core-image-sato映像配置为使用 Dropbear。在core-image-full-cmdline和core-image-lsb 图像都包括OpenSSH的。 该core-image-minimal映像不包含 SSH 服务器。可以通过修改IMAG_FEATURES变量
8.7.4.2.3. 使用自定义的.bb文件
示例如下
IMAGE_INSTALL = "packagegroup-core-x11-base package1 package2"
inherit core-image
或者可以拷贝一个已经存在的,如复制meta/recipes-sato/images/core-image-sato.bb到一个新的.bb,然后在末尾添加需要增加的内容
IMAGE_INSTALL += "strace"
8.7.4.2.4. 使用自定义包组
对于复杂的自定义image,最佳方法时创建用于构建一个或多个image的自定义包组recipes. 包组recipes一个很好的例子是meta/recipes-core/packagegroups/packagegroup-base.bb
PACKAGES列出了需要添加的包,RDEPENDS和RRECOMMENDS来提供父任务应包含的包列表
下面是一个例子
DESCRIPTION = "My Custom Package Groups"
inherit packagegroup
PACKAGES = "\
${PN}-apps \
${PN}-tools \
"
RDEPENDS:${PN}-apps = "\
dropbear \
portmap \
psplash"
RDEPENDS:${PN}-tools = "\
oprofile \
oprofileui-server \
lttng-tools"
RRECOMMENDS:${PN}-tools = "\
kernel-module-oprofile"
8.7.4.3. 编写新的recipes
recipes(.bb)是yocto项目中的基本组件,每个软件都需要一个recipes来定义组件
下面是创建新recipes的基本过程

可以通过以下三种方式创建一个新的recipes
devtool add: 借助devtool命令
recipetool create: yocto提供的命令,可根据源文件自动创建基本配方
现有recipet: 在功能与需要创建的recipet类似的上修改
recipetool create -o OUTFILE source #基于源生成recipes
可以使用以下结构来填充新recipet的基本区域
DESCRIPTION = ""
HOMEPAGE = ""
LICENSE = ""
SECTION = ""
DEPENDS = ""
LIC_FILES_CHKSUM = ""
SRC_URI = ""
openembedded构建系统通过layer的conf/layer.conf文件和BBFILES变量来定位recipets. 当命名一个新的recipet时,一般遵循以下方式
basename_version.bb
通过以下方式可以编译一个新的recipet
bitbake basename
在构建过程中openembedded会为每个recipet创建一个临时工作目录,其中保存提取的源文件,日志文件,中间编译和打包文件等。每个recipet临时工作路径取决于 构建它的上下文,找到此路径的最快方法就是运行以下命令
bitbake -e basename | grep ^WORKDIR=
do_fetch
下面是tarball和git源的例子
#git的方式获取源文件
SRCREV = "d6918c8832793b4205ed3bfede78c2f915c23385"
PR = "r6"
PV = "1.0.5+git${SRCPV}"
SRC_URI = "git://git.kernel.dk/blktrace.git \
file://ldflags.patch"
#tarball的方式获取源文件
SRC_URI = "${KERNELORG_MIRROR}/software/scm/git/git-${PV}.tar.gz;name=tarball \
${KERNELORG_MIRROR}/software/scm/git/git-manpages-${PV}.tar.gz;name=manpages"
SRC_URI[tarball.md5sum] = "166bde96adbbc11c8843d4f8f4f9811b"
SRC_URI[tarball.sha256sum] = "ad5334956301c86841eb1e5b1bb20884a6bad89a10a6762c958220c7cf64da02"
SRC_URI[manpages.md5sum] = "31c2272a8979022497ba3d4202df145d"
SRC_URI[manpages.sha256sum] = "9a7ae3a093bea39770eb96ca3e5b40bff7af0b9f6123f089d7821d0e5b8e1230"
为了确保URL下载的文件没有被篡改,需要使用两个校验和 SRC_URI[md5sum]和SRC_URI[sha256sum]
当使用file://协议来指定本地文件时,构建系统从本地获取文件,该路径相对于FILESPATH变量并安特定顺序搜索特定目录,${BP}, ${BPN}, 和files
do_unpack
构建过程中,do_unpack任务使用${S}指向解包位置来解压源代码。如果源是tarball并且按照${BPN}-${PV}的方式命名,则不需要设置${S},如果是git方式获取则 需要设置${S}
SRC_URI = "file://init \
file://rc.local.sample \
"
S = "${WORKDIR}"
LICENSE
recipet中需要同时包含LICENSE和LIC_FILES_CHKSUM变量
LICENSE: 此变量指向软件的许可证
LIC_FILES_CHKSUM: 为软件指定使用的许可文件
LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://COPYING:md5=25cf44512b7bc8966a48b6b1a9b7605f"
依赖
大多数的软件包都会依赖其他的软件包,这种依赖一般分为两类,第一类是构建时依赖,另一类是运行时依赖. 构建时依赖可以通过DEPENDS变量来定义, 而运行时依赖则在打包时自动设置
do_configure
Autotools: 如果源文件包含configure.ac文件,那么软件就是使用Autotool构建的,这种方式下,recipet需要继承autotools类,且recipet中不需要包含do_configure任务。如果需要调整,则可以设置EXTRA_OECONF或PACKAGECONFIG_CONFARGS以传递配置选项
CMake: 如果源文件包含CMakeList.txt文件,那么软件就是使用CMake构建的,recipet需要继承cmake类,且不需要包含do_configure任务,如果需要调整则设置EXTRA_OECMAKE来传递参数
其他: 不是以上两种方式,则需要在recipet中提供一个do_configure任务,如果没有任何配置也可以不提供
do_install
do_install期间,安装过程将文件从${S}、${B}和${WORKDIR}目录复制到${D}目录
开启系统服务
如果recipet中存在do_install函数,则在函数结束位置添加对应的操作,如果不存在则可以使用do_install:append在recipet中完成这项操作
openembedded支持以下两种方式启动服务
SysVinit: SysVinit 是一个系统和服务管理器,用于管理用于控制系统最基本功能的 init 系统。init 程序是 Linux 内核在系统启动时启动的第一个程序。Init 然后控制所有其他程序的启动、运行和关闭。要使用 SysVinit启用服务,recipet中需要继承update-rc.d类,需要在recipet中设置INITSCRIPT_PACKGES、INITSCRIPT_NAME和INITSCRIPT_PARAMS变量
systemd: 系统管理守护进程 (systemd) 旨在取代 SysVinit 并提供增强的服务管理。启用systemd需要recipet继承systemd类
8.7.4.4. 示例
本地c文件包
从本地存储的文件构建应用程序,需要手动编写do_compile和do_install任务
SUMMARY = "Simple helloworld application"
SECTION = "examples"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://helloworld.c"
S = "${WORKDIR}"
do_compile() {
${CC} ${LDFLAGS} helloworld.c -o helloworld
}
do_install() {
install -d ${D}${bindir}
install -m 0755 helloworld ${D}${bindir}
}
autotools
使用autotools的应用程序,其recipet中需要继承autotools类,该类包含构建基于autotool的应用程序所需的所有步骤定义,构建结果会自动打包
SUMMARY = "GNU Helloworld application"
SECTION = "examples"
LICENSE = "GPLv2+"
LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe"
SRC_URI = "${GNU_MIRROR}/hello/hello-${PV}.tar.gz"
inherit autotools gettext
Makefile
基于Makefile的应用程序,recipet中不需要自己添加do_compile步骤,默认情况下bitbake会启动make编译应用。如果需要其他make选项,则应该设置EXTRA_OEMAKE或PACKAGECONFIG_CONFARGS变量. 但 do_install仍然需要一个任务。
SUMMARY = "Tools for managing memory technology devices"
SECTION = "base"
DEPENDS = "zlib lzo e2fsprogs util-linux"
HOMEPAGE = "http://www.linux-mtd.infradead.org/"
LICENSE = "GPLv2+"
LIC_FILES_CHKSUM = "file://COPYING;md5=0636e73ff0215e8d672dc4c32c317bb3 \
file://include/common.h;beginline=1;endline=17;md5=ba05b07912a44ea2bf81ce409380049c"
# Use the latest version at 26 Oct, 2013
SRCREV = "9f107132a6a073cce37434ca9cda6917dd8d866b"
SRC_URI = "git://git.infradead.org/mtd-utils.git \
file://add-exclusion-to-mkfs-jffs2-git-2.patch \
"
PV = "1.5.1+git${SRCPV}"
S = "${WORKDIR}/git"
EXTRA_OEMAKE = "'CC=${CC}' 'RANLIB=${RANLIB}' 'AR=${AR}' 'CFLAGS=${CFLAGS} -I${S}/include -DWITHOUT_XATTR' 'BUILDDIR=${S}'"
do_install () {
oe_runmake install DESTDIR=${D} SBINDIR=${sbindir} MANDIR=${mandir} INCLUDEDIR=${includedir}
}
PACKAGES =+ "mtd-utils-jffs2 mtd-utils-ubifs mtd-utils-misc"
FILES:mtd-utils-jffs2 = "${sbindir}/mkfs.jffs2 ${sbindir}/jffs2dump ${sbindir}/jffs2reader ${sbindir}/sumtool"
FILES:mtd-utils-ubifs = "${sbindir}/mkfs.ubifs ${sbindir}/ubi*"
FILES:mtd-utils-misc = "${sbindir}/nftl* ${sbindir}/ftl* ${sbindir}/rfd* ${sbindir}/doc* ${sbindir}/serve_image ${sbindir}/recv_image"
PARALLEL_MAKE = ""
BBCLASSEXTEND = "native"
将一个应用拆分成多个包
可以使用变量PACKAGES和FILES将应用程序拆分为多个包。以下是libxpm recipet的示例,默认情况下,这个recipet生成一个包含库和一些二进制文件的包。可以通过修改recipet将二机制文件拆分成单独的包
require xorg-lib-common.inc
SUMMARY = "Xpm: X Pixmap extension library"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://COPYING;md5=51f4270b012ecd4ab1a164f5f4ed6cf7"
DEPENDS += "libxext libsm libxt"
PE = "1"
XORG_PN = "libXpm"
PACKAGES =+ "sxpm cxpm"
FILES:cxpm = "${bindir}/cxpm"
FILES:sxpm = "${bindir}/sxpm"
以上操作将会把sxpm和cxpm可执行文件放到单独的包中
打包外部生成的可执行文件
do_configure[noexec] = "1"
do_compile[noexec] = "1"
do_install () {
install -m 0755 ${target} ${D}${bindir}
}