任务
空任务
如果不想使用某个任务可以在配方文件将任务定义为空,比如将do_install
任务定义为空:
do_install() {
}
禁用任务
如果不想使用某个任务且也不想在配方文件将任务定义为空,则可以使用下面的语句,比如将禁用do_install
任务:
do_install[noexec] = "1"
如果想确保一个任务一定执行(某个任务可能在bb
配方设置了noexec
标志),那可以在bbappend
追加配方中加入以下:
unset do_install[noexec]
删除任务
使用deltask
命令可以删除任务,例如:
deltask do_install
但是,官方不建议这样做,似乎会破坏隐式依赖?比如运行时依赖RDEPENDS
?
重载任务
如果某个任务不仅仅需要完成构建系统默认的安装功能,还需要完成额外任务,那可以重装该任务,比如下面:
do_install() {
oe_runmake DESTDIR=${D}${libdir} install #执行Makefile文件中的安装任务,并传入安装目录
install -m 0644 -d ${D}${includedir}/api
install -m 0644 ${S}/api_common.h ${D}${includedir}/api
}
添加额外任务
如果想添加其他非标准任务咋办?别担心,yocto有提供机制,在配方中使用如下语句:
addtask mytask after do_configure before do_compile
do_mytask() {
ehco "test"
}
上面这句表示在配方do_compile
任务执行前且在do_configure
任务执行后插入mytask
任务。
向构建任务环境中传递信息
如果想要向构建任务中传递信息怎么做?
运行构建任务时,bitbake会严格控制构建任务的shell执行环境,以防止构建主机中不需要的环境参数影响构建过程。默认情况下,bitbake会清理环境,只包括那些导出或在白名单中列出的东西,以确保构建环境是可重复和一致的。可以通过设置BB_PRESERVE_ENV
变量来防止这种“清理”。
因此,如果想要传递一些东西到构建任务环境中,必须采取以下两个步骤:
-
告诉bitbake把想要的变量从环境中加载到数据存储中。可以通过BB_ENV_WHITELIST和BB_ENV_EXTRAWHITE变量来实现。比如:
export BB_ENV_EXTRAWHITE="$BB_ENV_EXTRAWHITE CCACHE_DIR"
-
告诉bitbake将你已经加载到数据存储中的内容导出到每个运行任务的任务环境中。比如(一般在conf/local.conf文件中配置):
export CCACHE_DIR
这样构建任务中就可以使用CCACHE_DIR
变量了,但不清楚具体使用场景,官方未给出示例。
基本语法
参考于https://www.yoctoproject.org/docs/3.0.2/mega-manual/mega-manual.html文档第7.3.23章节。
参考于https://www.yoctoproject.org/docs/2.7/bitbake-user-manual/bitbake-user-manual.html#bitbake-user-manual-metadata文档第3章节。
以下仅列出常用语法,更多语法规则请查阅官方手册。
变量赋值(=、:=、?=、??=、+=、=+、.=、=.)
变量赋值允许将值赋给变量。赋值可以是静态文本,也可以包含其他变量的内容。赋值方式分为6种,以下分别进行讲解:
直接赋值(=)
简单说就是在完全解析完配方文件后才会决定变量的值(与makefile规则一致),举个例子:
x = "foo"
y = "${x} bar"
x = "xyz"
y的值将会是 “xyz bar” ,而不是 “foo bar”,也就是说=的赋值在后面某个变量变化了的话,也会影响前面的赋值。
立即赋值(:=)
解析到变量所在位置时,立即决定变量的值(与makefile规则一致),举个例子:
x := "foo"
y := "${x} bar"
x := "xyz"
或
x = "foo"
y := "${x} bar"
x = "xyz"
y的值将会是 “foo bar” ,而不是 “xyz bar” ,也就是说:=赋值就将表达式立即展开。
默认赋值(?=)
解析到变量所在位置时,若变量在此之前未被赋值,则将赋值为?=后面的值(与makefile规则一致),举个例子:
A ?= "aval"
弱默认赋值(??=)
解析到变量所在位置时,若变量在此之前未被赋值,则继续往下解析,取最后一个??=赋值为最终值,当然若其间出现=或:=或?=等更强赋值,则将使用强赋值语句所赋值,举例:
A ??= "somevalue"
A ??= "someothervalue"
A的值为someothervalue
。
A ??= "somevalue"
A ?= "test"
A ??= "someothervalue"
A的值为test
。
空格式后增(+=)
将+=号后面的值追加到变量尾部,并在原值与追加值之间添加空格,举例:
SRC_URI = "xxx yyy"
SRC_URI += "zzz"
执行后结果:
SRC_URI = "xxx yyy zzz"
空格式前增(=+)
将+=号后面的值添加到变量头部,并在原值与添加值之间添加空格,举例:
SRC_URI = "xxx yyy"
SRC_URI =+ "zzz"
执行后结果:
SRC_URI = "zzz xxx yyy"
后增(.=)
如果尾部追加不需要添加空格,则采用.=,它将.=号后面的值追加到变量尾部,且不会添加空格,举例:
SRC_URI = "xxx yyy"
SRC_URI .= "zzz"
执行后结果:
SRC_URI = "xxx yyyzzz"
前增(=.)
如果头部添加不需要添加空格,则采用=.,它将=.号后面的值添加到变量头部,且不会添加空格,举例:
SRC_URI = "xxx yyy"
SRC_URI .= "zzz"
执行后结果:
SRC_URI = "zzzxxx yyy"
操作符
追加操作符(_append)
使用_append
运算符将值附加到现有变量。此运算符不会在原值与附加值之间增加空格。此外,此运算符在所有的=、+=、=+、.=、=.、?=、??=运算符起效后才起效,举例:
SRC_URI_append = " file://fix-makefile.patch" #注意双引号与file之间的空格
_append
运算符还可以与覆盖操作(下面讲解)一起使用,也就是说,只有指定machine
才会执行追加,比如某个配方给所有machine
使用,但某个machine
需要额外添加patch,举例:
SRC_URI_append_4u-x201 = " file://fix-makefile.patch" #注意双引号与file之间的空格
前增操作符(_prepend)
使用_prepend
运算符将值添加到现有变量头部。此运算符不会在原值与添加值之间增加空格。此外,此运算符在所有的=、+=、=+、.=、=.、?=、??=运算符起效后才起效,举例:
SRC_URI = "xxx yyy"
SRC_URI_prepend = "zzz"
执行后结果:
SRC_URI = "zzzxxx yyy"
_prepend
运算符还可以与覆盖操作(下面讲解)一起使用,也就是说,只有指定machine
才会执行追加,比如某个配方给所有machine
使用,但某个machine
需要额外添加patch,举例:
SRC_URI_prepend_4u-x201 = " file://fix-makefile.patch" #注意双引号与file之间的空格
移除操作符(_remove)
使用_remove
运算符可以将变量中匹配值(完全匹配)移除,同样也是等所有的=、+=、=+、.=、=.、?=、??=运算符起效后才起效,举例:
FOO = "123 456 789 123456 123 456 123 456"
FOO_remove = "123"
FOO_remove = "456"
FOO2 = "abc def ghi abcdef abc def abc def"
FOO2_remove = "abc def"
执行后结果:变量FOO
变为" 789 123456
",FOO2
变为" ghi abcdef "
。注意空格符依然保留。
这个操作符一般用于移除某个通用配方中不需要的配置或文件,比如某个配方中SRC_URI = "xxx yyy"
,而当前目标机型只需要使用xxx
,这样就可以结合覆盖操作移除yyy
,举例:
SRC_URI_remove_4u-x201 = "yyy"
操作符分隔符(:)
操作符分隔符,BitBake会从右到左处理条件,放右边的优先级要高于左边。示例:
FILES:${PN}:append = " ${libdir}/ipmid-providers/lib*${SOLIBS}" #等同于FILES_${PN}_append
FILES:${PN}:append = " ${libdir}/host-ipmid/lib*${SOLIBS}"
FILES:${PN}:append = " ${libdir}/net-ipmid/lib*${SOLIBS}"
PACKAGECONFIG:remove:class-native = "libintel_dbus" #等同于PACKAGECONFIG_remove_class-native
PACKAGECONFIG:remove:class-nativesdk = "libintel_dbus"
提示:建议后续都是用:
符号分割操作符,因为后续的yocto版本将切换成:
形式。
其他
注释
所有以#符号开头的都会视作注释,注意不能接在有用语句后面,比如:
SRC_URI_remove_4u-x201 = "yyy" #这是一条注释
上面的语句将会报错。
行需符
如果一个语句很长,可以用\符号需行,比如:
SRC_URI += " \
file://Makefile \
file://make.libs \
file://api_common.h \
file://api_common.c \
file://api_ethernet.c \
file://api_ethernet.h \
"
变量引用
使用${VARNAME}
语法访问变量的内容:
SRC_URI = "${SOURCEFORGE_MIRROR}/libpng/zlib-${PV}.tar.gz"
关键字
如同c语言一样,bitbake也有关键字,但数量仅有几个:
inherit:继承关键字,例如继承某个菜谱类(基础类,如autotool类)功能
include:包含另外的文件的关键字
require:强制包含另外文件的关键字,如果另外文件不存在bitbake会抛出错误
export:导出环境变量
示例:
export POSTCONF = "${STAGING_BINDIR}/postconf"
inherit autoconf
require otherfile.inc
覆盖
使用覆盖来有条件地设置值,通常基于食谱的构建方式。例如,在配方中将任何machine
使用的KBRANCH
变量设置为“standard/base”
,但部分machine
使用其他值,示例:
KBRANCH = "standard/base"
KBRANCH_qemuarm = "standard/arm-versatile-926ejs"
KBRANCH_qemumips = "standard/mti-malta32"
KBRANCH_qemuppc = "standard/qemuppc"
KBRANCH_qemux86 = "standard/common-pc/base"
KBRANCH_qemux86-64 = "standard/common-pc-64/base"
KBRANCH_qemumips64 = "standard/mti-malta64"
覆盖操作可以结合其他操作符使用。
缩进方式
yocto项目的策略是使用空格作为缩进,而shell函数中可以出现tab符号,但为了避免弄混,建议统一使用空格作为缩进。
使用shell语法
可以在任务中使用shell语法,比如使用cp:
do_install() {
install -m 0644 -d ${D}${includedir}/api #创建头文件目录
cp -rf ${S}/api ${D}${includedir}/api
}
使用python语法
对于更高级的处理,可以在变量赋值期间使用Python
代码(例如,对变量进行搜索和替换)。
使用${@python_code}
语法表示使用Python
代码为变量赋值:
SRC_URI = "ftp://ftp.info-zip.org/pub/infozip/src/zip${@d.getVar('PV',1).replace('.', '')}.tgz
总结:这里只讲解了基本语法,事实上部分语法还可以与函数(任务)组合使用,更高级的用法请查阅手册。
下个章节见~~~