博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BitBake用户手册-3.语法和操作
阅读量:348 次
发布时间:2019-03-04

本文共 30060 字,大约阅读时间需要 100 分钟。

Bitbake用户手册,语法部分篇幅过长,单独整理一篇

英文原文链接:https://www.yoctoproject.org/docs/3.1.2/bitbake-user-manual/bitbake-user-manual.html#bitbake-user-manual-metadata
其他章节翻译链接:

3. 语法和操作

BitBake文件具有自己的语法。 该语法与其他几种语言相似,但也具有一些独特的功能。 本节描述了可用的语法和运算符,并提供了示例。

3.1 基础语法

本节提供一些基本的语法示例。

3.1.1 基本变量设置

下面的示例将VARIABLE设置为“ value”。 该语句在解析后立即生效。 这是一个“硬”赋值(hard assignment)。

VARIABLE =“value”

如预期的那样,如果参数之前或之后带有空格,则这些空格将会被保留:

VARIABLE =“ value”VARIABLE =“value ”

将VARIABLE设置为“”会将其设置为空字符串,而将变量设置为“ ”则将其设置为空格(即,它们的值不同)。

VARIABLE =“”VARIABLE =“ ”

设置变量的值时,可以使用单引号来替代双引号。 这样做允许您使用包含双引号字符的值:

VARIABLE = 'I have a " in my value'

注意

与Bourne shell程序不同,单引号在所有其他方式上的作用与双引号相同。 它们不抑制变量展开。

3.1.2 修改已存在变量

有时您需要修改现有变量。 以下情况下,您可能会想要修改现有变量:

  • 自定义配方中要使用该变量。
  • 更改* .bbclass文件中使用的变量的默认值。
  • 更改* .bbappend文件中的变量以覆盖原始配方中的变量。
  • 更改配置文件中的变量,以使该值覆盖现有配置。

更改变量值有时可能取决于最初分配值的方式以及所需的更改意图。 特别是,将值附加到具有默认值的变量时,结果值可能不是您期望的值。 在这种情况下,您提供的值可能会替换该值,而不是附加到默认值。

如果在更改变量的值后发生了无法解释的情况,则可以使用BitBake来检查可疑变量的实际值。 您可以对配置和配方级别的更改进行以下检查:

  • 对于配置更改,请使用以下命令:
$ bitbake -e

该命令在解析配置文件(即local.conf,bblayers.conf,bitbake.conf等)后,将显示变量值。

注意

导出到环境的变量在命令的输出中以字符串“export”开头。

  • 对于配方更改,请使用以下命令:
$ bitbake recipe -e | grep VARIABLE =“

此命令检查该变量是否确实使它成为特定的配方。

3.1.3 续行

在函数之外,在解析语句之前,BitBake将以反斜杠字符(“ \”)结尾的任何行与下一行连接起来。 “ \”字符最常见的用法是将变量分配拆分为多行,如以下示例所示:

FOO = "bar \       baz \       qaz"

连接行时,“ \”字符和其后的换行符都会被删除。 因此,FOO的值结尾没有换行符。

考虑下面的示例,两个表达式都能实现将“ barbaz”分配给FOO:

FOO = "barbaz"FOO = "bar\baz"

注意

BitBake不会在变量值中解释转义字符,例如“ \ n”。 为了使它们生效,必须将值传递给一些解释转义序列的程序,例如printf或echo -n。

3.1.4 变量展开

变量可以使用类似于Bourne shell中的变量扩展的语法来引用其他变量的内容。 以下语句使A包含“ aval”,B为“ preavalpost”。

A =“ ava”B =“pre${A}post”

注意

与Bourne shell程序不同,花括号是必需的:只有$ {FOO}而不是$ FOO被认为是FOO的扩展。

“ =”运算符不会立即在右侧展开变量引用。 而是将展开推迟到实际使用分配给它的变量之前。 结果取决于引用变量的当前值。 下面的示例应阐明此行为:

A = "${B} baz"B = "${C} bar"C = "foo"*At this point, ${A} equals "foo bar baz"*C = "qux"*At this point, ${A} equals "qux bar baz"*B = "norf"*At this point, ${A} equals "norf baz"**

注意此行为与立即变量展开运算符(即“:=“)的区别。

如果对不存在的变量使用变量展开语法,则字符串将保持原样。 例如,给定以下语句,只要FOO不存在,BAR就会扩展为字符串“ $ {FOO}”。

BAR =“ $ {FOO}”

3.1.5 设置默认值(?=)

您可以使用“?=”运算符来实现对变量的“软”赋值。 这种类型的赋值使您可以在分析语句时定义未定义的变量,但是如果变量具有值,则可以保留该值。 这是一个例子:

A ?= "aval"

如果在分析此语句时设置了A,则变量将保留其值。 但是,如果未设置A,则变量将设置为“ aval”。

注意

这项任务是立即的。 因此,如果存在对单个变量的多个“?=”分配,则其中的第一个最终将被使用。

3.1.6 设置弱默认值(??=)

通过使用“ ?? =”运算符,实现对变量的"弱"赋值。 该赋值的行为与“?=”相同,不同的是该分配是在解析过程结束时生效而不是立即生效。 因此,当存在多个“ ?? =”分配时,将使用最后一个。 另外,任何“ =”或“?=”分配都将覆盖用“?? =”设置的值。 以下是一个例子:

A ??= "somevalue"     A ??= "someothervalue"”

如果在解析以上语句之前设置了A,则变量将保留其值。 如果未设置A,则变量设置为“ someothervalue”。

此分配是“惰性”或“弱”赋值,因为它直到解析过程结束才发生。

3.1.7 变量立即展开(:=)

“:=”运算符会导致变量的内容立即展开,而不是使用变量时展开:

T = "123"     A := "test ${T}"     T = "456"     B := "${T} ${C}"     C = "cval"     C := "${C}append"

在此示例中,即使T的最终值为“ 456”,A的值仍为“test123”。 变量B最终值为“ 456 cvalappend”。 这是因为对未定义变量的引用在(立即)扩展期间被保留。 这与GNU Make相反,在GNU Make中,未定义的变量扩展为空。 由于$ {C}立即扩展为“ cval”,因此变量C为“ cvalappend”。

3.1.8 带空格的前缀(=+)和后缀(+=)

追加值和前置值很常见,可以使用“ + =”和“ = +”运算符来实现。 这些运算符在当前值和前置/附加值之间插入一个空格。

这些运算符在解析期间立即生效。 这里有些例子:

B = "bval"     B += "additionaldata"     C = "cval"     C =+ "test"

变量B为“ bval Extradata”,变量C为“ test cval”。

3.1.9 不带空格的前缀(=.)和后缀(.=)

如果不想在当前值和前置、附加值之间插入空格,请使用“.=“和“ =.” 操作符。

这些运算符在解析期间立即生效。 如:

B = "bval"     B .= "additionaldata"     C = "cval"     C =. "test"

变量B为“ bvaladditionaldata”,而变量C为“ testcval”。

3.1.10 前缀和后缀(覆盖语法)

您还可以使用覆盖样式语法来追加和前置变量的值。 使用此语法时,不会插入空格。

这些运算符与“:=”,“.=”,“=.”,“+=”和“=+”运算符的不同之处在于,它们的效果是在展开时应用的,而不是立即应用的。 这里有些例子:

B = "bval"     B_append = " additional data"     C = "cval"     C_prepend = "additional data "     D = "dval"     D_append = "additional data"

变量B变为“bval additional data”,而C变为“additional data cval”。 变量D变为“dvaladditional data”。

注意

使用覆盖语法时,必须控制所有空格。

也可以为shell函数和BitBake样式的Python函数上添加append和prepend。 有关示例,请参见“ Shell函数”和“ BitBake样式Python函数”部分。

3.1.11 删除(覆盖样式语法)

您可以使用删除覆盖样式语法从列表中删除值。指定要删除的值会使该值从变量中所有出现的地方删除。

使用此语法时,BitBake需要一个或多个字符串。 保留周围的空间和间距。 这是一个例子:

FOO = "123 456 789 123456 123 456 123 456"     FOO_remove = "123"     FOO_remove = "456"     FOO2 = " abc  def ghi abcdef abc def abc  def def"     FOO2_remove = " \         def \         abc \         ghi \     "

变量FOO变为“ 789 123456”,而FOO2变为“ abcdef”。

像“ _append”和“ _prepend”一样,“ _ remove”在变量展开时生效。

3.1.12 覆盖类型操作优势

与“+=”和“=+”运算符相比,覆盖样式操作“ _append”,“ _ prepend”和“ _remove”的优点在于,覆盖样式操作符提供了有保证的操作。 例如,考虑需要将值“ val”添加到变量FOO的类foo.bbclass,以及使用foo.bbclass的配方,如下所示:

inherit fooFOO = “initial”

如果foo.bbclass使用“+=”运算符,如下所示,则FOO的最终值将是“initial”,这不是所希望的:

FOO += “val”

另一方面,如果foo.bbclass使用“_append”运算符,则FOO的最终值将是“initial val”,如预期的那样:

FOO_append = “ val”

注意

永远不需要将“ + =”与“ _append”一起使用。 以下操作将“barbaz”追加到FOO:
FOO_append = “bar”
FOO_append = “baz”
更改上一个示例中的第二个赋值以使用“ + =”的唯一效果是在附加值中的“ baz”之前添加了一个空格(由于“ + =”运算符的工作方式)。

覆盖样式操作的另一个优点是,您可以将它们与“条件语法(覆盖)”部分中所述的其他覆盖组合在一起。

3.1.13 变量标志语法

变量标志是BitBake对变量属性的实现。 这是一种将额外信息标记到变量上的方法。 您通常可以在“变量标志”部分中找到有关变量标志的更多信息。

您可以对变量标志进行定义,附加和前置值。 除覆盖样式语法(即“ _prepend”,“ _ append”和“ _remove”)外,前面提到的所有标准语法操作均适用于变量标志。

以下是一些示例,展示了如何设置变量标志:

FOO[a] = "abc"     FOO[b] = "123"     FOO[a] += "456"

变量FOO具有两个标志:[a]和[b]。 这些标志立即分别设置为“ abc”和“ 123”。 [a]标志变为“ abc 456”。

无需预先定义变量标志。 您可以简单地开始使用它们。 一个极为常见的应用程序是将一些简短的注释附加到BitBake变量,如下所示:

CACHE[doc] = "The directory holding the cache of the metadata."

3.1.14 内联python变量展开

您可以使用内联Python变量扩展来设置变量。 这是一个例子:

DATE = "${@time.strftime('%Y%m%d',time.gmtime())}"

本示例将DATE变量设置为当前日期。

此功能最常见的用途可能是从BitBake的内部数据字典d中提取变量的值。 以下各行分别选择软件包名称和版本号的值:

PN = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[0] or 'defaultpkgname'}"     PV = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[1] or '1.0'}"

注意

目前来说,内联Python表达式展开就像“ =”和“:=”运算符展开一样工作。 考虑以下赋值,每次展开FOO都会调用foo():
FOO = “${@foo()}”
将其与下面的立即分配进行对比,其中foo()仅在解析分配时被调用一次:
FOO := “ ${@ foo()}”

3.1.15 取消设置变量

使用“ unset”关键字可以从BitBake的内部数据字典中完全删除变量或变量标志。 这是一个例子:

unset DATE        unset do_fetch[noexec]

这两个语句删除了DATE和do_fetch[noexec]标志。

3.1.16 提供路径名

指定与BitBake一起使用的路径名时,请勿将波浪号(~)用作家目录的快捷方式。 这样做可能导致BitBake无法识别路径,因为BitBake不会以与Shell相同的方式扩展此字符。

而是提供一个更完整的路径,如以下示例所示:

BBLAYERS ?= " \       /home/scott-lenovo/LayerA \       "

3.2 导出变量到环境变量

您可以使用export关键字将变量导出到正在运行的任务的环境。 例如,在以下示例中,do_foo任务在运行时显示“value from the environment”:

export ENV_VARIABLE     ENV_VARIABLE = "value from the environment"     do_foo() {         bbplain "$ENV_VARIABLE"     }

注意

在这种情况下,BitBake不会展开$ ENV_VARIABLE,因为它没有必须的{}。 $ ENV_VARIABLE由shell扩展。

在对ENV_VARIABLE赋值之前或之后,执行export ENV_VARIABLE都无关紧要。

也可以将导出与设置变量的值结合使用。 这是一个例子:

export ENV_VARIABLE = "variable-value"

在bitbake -e的输出中,导出到环境的变量以“export”开始。

通常输出到环境中的变量是CC和CFLAGS,许多构建系统都采用了这些变量。

3.3 条件语法(覆盖)

BitBake分析配方和配置文件后,BitBake使用OVERRIDES控制要覆盖哪些变量。 本节介绍如何将OVERRIDES用作条件元数据,讨论与OVERRIDES的关系中的密钥扩展,并提供一些示例以帮助理解。

3.3.1 条件元数据

您可以使用OVERRIDES有条件地选择变量的特定版本,并有条件地附加或添加变量的值。

注意

Overrides只能使用小写字符。 此外,override名称中不允许使用下划线,因为它们用于将override彼此之间和变量名称区分开。

  • Selecting a Variable: OVERRIDES变量是一个用冒号分隔的列表,其中包含您要满足条件的条目。因此,如果您有一个以“ arm”为条件的变量,并且“ arm”处于OVERRIDES中,则使用变量的“ arm”特定版本,而不是非条件版本。 这是一个例子:
OVERRIDES = "architecture:os:machine"     TEST = "default"     TEST_os = "osspecific"     TEST_nooverride = "othercondvalue"

在此示例中,OVERRIDES变量列出了三个overrites:“architecture”,“ os”和“machine”。 变量TEST本身的默认值为“ default”。 通过将“ os”override附加到变量(即TEST_os)来选择TEST变量的特定于操作系统的版本。

为了更好地理解这一点,请考虑一个实际的示例,该示例假定基于OpenEmbedded的基于元数据的Linux内核配方文件。 配方文件中的以下几行首先将内核分支变量KBRANCH设置为默认值,然后根据构建的体系结构有条件地覆盖该值:

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"
  • Appending and Prepending:BitBake还支持基于变量是否在OVERRIDES列表中,对变量值进行append和prepend操作。 以下是一个例子:
DEPENDS = "glibc ncurses"     OVERRIDES = "machine:local"     DEPENDS_append_machine = " libmad"

在此示例中,DEPENDS变为“ glibc ncurses libmad”。

同样,以基于OpenEmbedded的基于元数据的内核配方文件为例,以下几行将根据架构值对应追加到KERNEL_FEATURES变量:

KERNEL_FEATURES_append = " ${KERNEL_EXTRA_FEATURES}"     KERNEL_FEATURES_append_qemux86=" cfg/sound.scc cfg/paravirt_kvm.scc"     KERNEL_FEATURES_append_qemux86-64=" cfg/sound.scc cfg/paravirt_kvm.scc"
  • Setting a Variable for a Single Task:BitBake支持设置仅在单个任务执行期间使用的变量。 以下是一个例子:
FOO_task-configure = "val 1"     FOO_task-compile = "val 2"

在该示例中,FOO在执行do_configure任务时的值为“val 1”,在执行do_compile任务时的值为“val 2”。

在内部,这是通过在do_compile任务的本地数据存储区前面添加任务(例如“ task-compile:”)到OVERRIDES的值来实现的。

您还可以将此语法与其他组合(例如“ _prepend”)结合使用,如以下示例所示:

EXTRA_OEMAKE_prepend_task-compile = "${PARALLEL_MAKE} "

3.3.2 key展开

最终完成BitBake数据存储时,将进行key展开。 为了更好地理解这一点,请考虑以下示例:

A${B} = "X"     B = "2"     A2 = "Y"

在这种情况下,所有解析完成后,BitBake将$ {B}扩展为“ 2”。 该扩展使被之前的扩展设置为“ Y”的A2,变为“ X”。

3.3.3 示例

尽管前面的解释展示了变量定义的不同形式,但是当将变量运算符,条件覆盖和无条件覆盖组合在一起时将很难理解。 本节介绍了一些常见情况,并解释了通常会使用户感到困惑的变量交互。

关于override和各种“追加”运算符生效的顺序的问题,通常会让人感到困惑。 回想一下,使用“ _append”和“ _prepend”进行附加或前置操作不会像“ + =“,“。=”,“ = +”或“ =”那样立即生效。 考虑以下示例:

OVERRIDES = "foo"     A = "Z"     A_foo_append = "X"

对于这种情况,将A无条件地设置为“Z”,并且将“X”无条件地立即追加到变量A_foo。 因为override尚未应用,所以由于附加操作,A_foo设置为“X”,而A等于“Z”。

但是,应用override会改变情况。 由于“foo”在OVERRIDES中列出,因此条件变量A被替换为“ foo”版本,该版本等于“X”。 所以,实际上A_foo替代了A。

下一个示例改变了之前示例中appends和override生效的顺序:

OVERRIDES = "foo"     A = "Y"     A_foo_append = "Z"     A_foo_append = "X"

对于这种情况,在执行任何替代之前,使用“=”将A设置为“Y”。 立即分配之后,将A_foo设置为“ Z”,然后再附加“X”,将变量设置为“ZX”。 最后,对“foo”应用覆盖会导致条件变量A变为“ ZX”(即A替换为A_foo)。

最后一个示例混合了一些不同的运算符:

A = "1"     A_append = "2"     A_append = "3"     A += "4"     A .= "5"

对于这种情况,随着BitBake多次遍历代码,附加操作符的类型会影响分配的顺序。 最初,由于使用立即数运算符的三个语句,A设置为“ 1 45”。 完成这些分配后,BitBake将应用“ _append”操作。 这些操作导致A变为“ 1 4523”。

3.4 通用功能(Sharing Functionality)

BitBake允许通过包含文件(.inc)和类文件(.bbclass)共享元数据。 例如,假设您具有一项通用功能,例如要在多个配方之间共享的任务定义。 在这种情况下,创建一个包含通用功能的.bbclass文件,然后在配方中使用inherit指令来继承该类将是共享任务的一种常用方法。

本节介绍BitBake提供的机制,使您可以在配方之间共享功能。 具体来说,这些机制包括includeinheritINHERITrequire指令。

3.4.1 查找Include文件和Class文件

BitBake使用BBPATH变量来查找所需的include文件和class文件。 此外,对于include和require指令,BitBake还会在当前目录中搜索。

说明

BBPATH变量类似于环境变量PATH。

为了使BitBake可以找到include文件和class文件,BBPATH中需要有classes子目录。

3.4.2 inherit指令

编写recipeclass文件时,可以使用inherit指令来继承类(.bbclass)的功能。 BitBake仅支持在recipe和class文件(即.bb和.bbclass)中使用inherit指令。

inherit指令是指定配方所需的类文件中包含的功能的基本方法。 例如,您可以轻松地提取出使用Autoconf和Automake工具构建软件包的任务,并将这些任务放入类文件中,然后让您的配方继承该类文件。

例如,您的食谱可以使用以下指令继承autotools.bbclass文件。 该类文件包含可以在配方之间共享的Autotools的常用功能:

inherit autotools

在这种情况下,BitBake将在BBPATH中搜索目录classes/autotools.bbclass。

说明

通过在“继承”语句之后执行操作,以覆盖配方中继承类的任何值和函数。

如果要使用指令继承多个类,请用空格分隔它们。 以下示例显示如何继承buildhistoryrm_work类:

inherit buildhistory rm_work

includerequire指令相比,继承指令的一个优点是您可以有条件地继承类文件。 您可以通过在继承语句之后使用变量表达式来完成此操作。 这是一个例子:

inherit ${VARNAME}

如果要设置VARNAME,则需要在分析继承语句之前进行设置。 在这种情况下,实现条件继承的一种方法是使用覆盖:

VARIABLE = ""     VARIABLE_someoverride = "myclass"

另一种方法是使用anonymous Python。 这是一个例子:

python () {         if condition == value:             d.setVar('VARIABLE', 'myclass')         else:             d.setVar('VARIABLE', '')     }

另外,您可以使用以下形式的内联Python表达式:

inherit ${@'classname' if condition else ''}     inherit ${@functionname(params)}

在所有情况下,如果表达式的计算结果为空字符串,则该语句不会触发语法错误,因为它变为空操作。

3.4.3 include指令

BitBake理解include指令。 此指令使BitBake解析您指定的任何文件,并将该文件插入该位置。 该指令与Make中的等效指令非常相似,不同之处在于,如果在include指定的路径是相对路径,则BitBake会使用它可以在BBPATH中找到的第一个文件。

与仅限于类(即.bbclass)文件的inherit指令相比,include指令是一种更为通用的包含功能的方法。 include指令适用于任何其他不适合.bbclass文件的共享或封装的功能或配置。

举例来说,假设您需要一个配方来包含一些自测定义:

include test_defs.inc

注意

找不到文件时,include指令不会产生错误。 因此,建议如果要包含的文件预期存在,则应使用require而不是include。 这样做可以确保如果找不到该文件,则会产生错误。

3.4.4 require指令

BitBake理解require指令。 该指令的行为与include指令相同,不同之处在于,如果找不到要包含的文件,则BitBake会引发解析错误。 因此,您需要的任何文件都将插入到文件中指令位置被解析的地方。

inherit指令相比,require指令就像前面描述的include指令一样,是一种更通用的方法,inherit指令包含功能的继承指令仅限于类(即.bbclass)文件。 require指令适用于任何其他不适合.bbclass文件的共享或封装功能或配置。

与BitBake句柄包含的内容类似,如果require行上指定的路径是相对路径,则BitBake会找到它可以在BBPATH中找到的第一个文件。

举例来说,假设您有一个配方的两个版本(例如foo_1.2.2.bb和foo_2.0.0.bb),其中每个版本都包含一些可以共享的相同功能。 您可以创建一个名为foo.inc的包含文件,其中包含构建“ foo”所需的通用定义。 您需要确保foo.inc与两个配方文件也位于同一目录中。 一旦设置了这些条件,就可以在每个配方中使用require指令共享功能:

require foo.inc

3.4.5 INHERIT配置指令

创建配置文件(.conf)时,可以使用INHERIT配置指令来继承类。 在配置文件中,BitBake仅支持此指令。

例如,假设您需要从配置文件继承一个名为abc.bbclass的类文件,如下所示:

INHERIT += "abc"

此配置指令使命名类在解析过程中在指令解析时被继承。 与inherit指令一样,.bbclass文件必须位于BBPATH中指定的目录之一的“ classes”子目录中。

说明

由于.conf文件是在BitBake执行期间首先解析的,因此使用INHERIT继承类可以有效地全局继承该类(即,对于所有配方)。

如果要使用指令继承多个类,则可以在local.conf文件的同一行上指定。 使用空格分隔类。 以下示例显示如何继承autotools和pkgconfig类:

INHERIT += "autotools pkgconfig"

3.5 函数

与大多数语言一样,函数是用于将操作构建为任务的构造块。 BitBake支持以下类型的函数:

  • Shell函数:用Shell脚本编写并直接作为函数/任务执行的函数。 也可以由其他Shell函数调用它们。

  • BitBake风格的Python函数:用Python编写并由BitBake执行的函数或其他使用bb.build.exec_func() 调用执行的Python函数。

  • Python函数:用Python编写并由Python执行的函数。

  • 匿名Python函数:在解析过程中自动执行的Python函数。

无论函数的类型如何,您都只能在类(.bbclass)和配方(.bb或.inc)文件中定义它们。

3.5.1 shell函数

用Shell脚本编写并直接作为函数、任务执行的函数。 也可以由其他Shell函数调用它们。 这是一个shell函数定义示例:

some_function () {         echo "Hello World"     }

在配方或类文件中创建这些类型的函数时,需要遵循Shell编程规则。 脚本由/bin/sh执行,它可能不是bash shell,但可能是诸如dash之类的东西。 您不应使用特定于Bash的脚本(bashism)。

覆盖和覆盖样式运算符(如_append和_prepend)也可以应用于shell函数。 最常见的是,此应用程序将在.bbappend文件中使用,以修改主配方中的功能。 它也可以用来修改从类继承的函数。

例如,请考虑以下内容:

do_foo() {         bbplain first         fn     }     fn_prepend() {         bbplain second     }     fn() {         bbplain third     }     do_foo_append() {         bbplain fourth     }

运行do_foo将显示以下内容:

recipename do_foo: first     recipename do_foo: second     recipename do_foo: third     recipename do_foo: fourth

注意

覆盖和覆盖样式运算符可以应用于任何Shell函数,而不仅仅是任务。

在应用所有替代后,可以使用bitbake -e recipename命令查看最终整合后的函数。

3.5.2 BitBake风格Python函数

这一类的函数是用Python编写的,由BitBake或其他Python函数使用bb.build.exec_func()执行。

BitBake函数的一个例子是:

python some_python_function () {         d.setVar("TEXT", "Hello World")         print d.getVar("TEXT")     }

因为Python“bb”和“os”模块已经导入,所以不需要导入这些模块。同样在这些类型的函数中,数据存储(“d”)是一个全局变量,总是自动可用的。

注意

变量表达式(例如${X})不再在Python函数中扩展。此行为是有意为之,目的是让您可以自由地将变量值设置为可扩展表达式,而不会让它们过早地展开。如果您确实希望在Python函数中展开变量,请使用d.getVar(“X”)。或者,对于更复杂的表达式,使用d.expand()。

与shell函数类似,还可以将覆盖和覆盖样式的操作符应用于bitbaker样式的Python函数。

作为一个例子,考虑以下情况:

python do_foo_prepend() {         bb.plain("first")     }     python do_foo() {         bb.plain("second")     }     python do_foo_append() {         bb.plain("third")     }

运行do_foo将打印以下内容:

recipename do_foo: first     recipename do_foo: second     recipename do_foo: third

您可以使用bitbake -e recipename命令查看应用所有覆盖后的最终函数。

3.5.3 Python函数

这些函数是用Python编写的,由其他Python代码执行。Python函数的一个例子是您打算从内联Python或其他Python函数中调用的实用函数。如:

def get_depends(d):         if d.getVar('SOMECONDITION'):             return "dependencywithcond"         else:             return "dependency"     SOMECONDITION = "1"     DEPENDS = "${@get_depends(d)}"

这将导致DEPENDS包含dependencywithcond

下面是一些关于Python函数需要了解的事情:

  • Python函数可以带参数。
  • BitBake数据存储不是自动可用的。因此,必须将其作为参数传递给函数。
  • “bb”和“os”Python模块是自动可用的。您不需要导入它们。

3.5.4 BitBake风格Python函数和Python函数的对比

以下是BitBake样式的Python函数与用“ def”定义的常规Python函数之间的一些重要区别:

  • 只有BitBake样式的Python函数可以作为任务(tasks)。
  • 覆盖和覆盖样式运算符只能应用于BitBake样式的Python函数。
  • 只有常规的Python函数才能接受参数并返回值。
  • 诸如[dirs],[cleandirs]和[lockfiles]之类的变量标志可以在BitBake样式的Python函数上使用,但不能在常规Python函数上使用。
  • BitBake样式的Python函数会生成一个单独的$ {T} /run.function-name.pid运行脚本,使该函数得以执行。如果该函数作为任务执行,则还会在$ {T} /log.function-name.pid中生成一个日志文件。
    常规Python函数被作为“内联函数”执行,不会在$ {T}中生成任何文件。

    译注:T表示biibake在构建特定配方时,放置log,scripts等文件的临时目录

  • 常规Python函数使用常规的Python语法进行调用。 BitBake样式的Python函数通常是任务,由BitBake直接调用,但是也可以使用bb.build.exec_func()函数从Python代码中手动调用。 如:
    bb.build.exec_func(“ my_bitbake_style_function”,d)

    注意

    bb.build.exec_func()也可被Python代码使用,以运行shell函数。 如果要 在同一任务中的Python函数之前运行shell函数,则可以使用调用者Python函数,该父函数先通过bb.build.exec_func()运行shell函数,然后运行Python代码。

要从bb.build.exec_func()执行的函数中检测错误,可以通过bb.build.FuncFailed捕获异常。

注意

元数据(配方和类)中的函数本身不应引发bb.build.FuncFailed。 相反,应该将bb.build.FuncFailed视为通过引发异常而导致被调用函数失败的一般指示。 例如,由bb.fatal()引发的异常将被捕获在bb.build.exec_func()中,并且将引发bb.build.FuncFailed作为响应。

由于它们的简单性,除非需要特定于BitBake风格的Python函数的功能,否则您应该更喜欢常规Python函数而不是BitBake风格的Python函数。 元数据中的常规Python函数是比BitBake风格的Python函数更新的发明,并且老的代码倾向于更频繁地使用bb.build.exec_func()。

3.5.5 匿名Python函数

有时在解析过程中设置变量或可编程的执行其他操作很有用。 为此,您可以定义特殊的Python函数(称为匿名Python函数),该函数在解析结束时运行。 例如,以下内容基于另一个变量的值设置一个变量:

python () {         if d.getVar('SOMEVAR') == 'value':             d.setVar('ANOTHERVAR', 'value2')     }

将函数标记为匿名函数的等效方法是为其命名为“ __anonymous”,而不是没有名称。

无论定义在何处,匿名Python函数始终在解析结束时运行。 如果配方包含许多匿名函数,则它们将以与配方中定义的顺序相同的顺序运行。 例如,请考虑以下代码片段:

python () {         d.setVar('FOO', 'foo 2')     }     FOO = "foo 1"     python () {         d.appendVar('BAR', ' bar 2')     }     BAR = "bar 1"

以上示例在概念上等效于以下片段:

FOO = "foo 1"     BAR = "bar 1"     FOO = "foo 2"     BAR += "bar 2"

最终FOO值为“ foo 2”,BAR的值为“ bar 1 bar 2”。 就像第二个片段一样,为变量设置值的匿名函数可被任务调用,且始终在解析后运行。

在运行匿名函数之前,将应用覆盖和覆盖样式运算符(例如“ _append”)。 在以下示例中,FOO值最终为“ foo from anonymous”:

FOO = "foo"     FOO_append = " from outside"     python () {         d.setVar("FOO", "foo from anonymous")     }

有关可用于匿名Python函数的方法,请参见“可从Python内部调用的函数(3.11)”一节。 有关在解析过程中运行Python代码的其他方法,请参见“内联Python变量扩展(3.1.14)”部分。

3.5.6 Class函数的灵活继承

通过编码技术和使用EXPORT_FUNCTIONS,BitBake支持从类中导出一个函数,以使该类函数作为该函数的默认实现,但是如果继承该类的配方需要定义自己的版本,则仍可以调用该函数。

要了解此功能的好处,请考虑以下基本场景:类定义了任务函数,而你的自定义配方继承该类。 在这种基本情况下,您的配方将继承类中定义的任务函数。 如果需要,您的配方可以分别使用“ _prepend”或“ _append”操作添加到函数的开头和结尾,也可以完全重新定义函数。 但是,如果重新定义该函数,则无法调用该函数的类版本。 EXPORT_FUNCTIONS提供了一种机制,该机制使配方的函数版本可以调用函数的原始版本。

要使用此技术,您需要准备以下事情:

  • 需要在类中按如下方式定义函数:
    classname_functionname
    例如,如果您有一个类文件bar.bbclass和一个名为do_foo的函数,则该类必须按以下方式定义该函数:
    bar_do_foo
  • 该类需要包含EXPORT_FUNCTIONS语句:
    EXPORT_FUNCTIONS functionname
    例如,继续同一示例,bar.bbclass中的语句将如下所示:
    EXPORT_FUNCTIONS do_foo
  • 您需要从配方中适当地调用该函数。 继续同一示例,如果您的配方需要调用该函数的类版本,则应调用bar_do_foo。 假设do_foo是shell函数,并且如上所述使用EXPORT_FUNCTIONS,则配方的函数可以有条件地调用该函数的类版本,如下所示:
    do_foo() {             if [ somecondition ] ; then                     bar_do_foo             else                     # Do something else             fi     }
    要调用配方中定义的函数的修改版本,请以do_foo的方式调用。

满足这些条件后,您的单个配方就可以在类文件中定义的原始功能和配方中的修改功能之间自由选择。 如果未满足这些条件,则只能使用其中一种功能。

3.6 任务

任务是BitBake执行单元,构成了BitBake执行给定配方的步骤。 仅配方和类(即.bb文件以及从.bb文件包含或继承的文件)支持任务。 按照约定,任务的名称以“do_”开头。

3.6.1 将函数作为任务

任务是Shell函数或BitBake样式的Python函数,这些函数已通过使用addtask命令提升为任务。 addtask命令还可以描述任务与其他任务之间的依赖关系。 这是一个示例,显示了如何定义任务和声明一些依赖关系:

python do_printdate () {         import time         print time.strftime('%Y%m%d', time.gmtime())     }     addtask printdate after do_fetch before do_build

在do_build之后在do_fetch之后执行addtask打印日期

addtask的第一个参数是要升级为任务的函数的名称。 如果名称不是以“ do_”开头,则会隐式添加“ do_”,这将强制执行所有任务名称均以“ do_”开头的约定。

在前面的示例中,do_printdate任务成为do_build任务的依赖项,而do_build任务是默认任务(即,除非明确指定另一个任务,否则由bitbake命令运行的任务)。 此外,do_printdate任务依赖于do_fetch任务。 运行do_build任务将导致do_printdate任务首先运行。

注意

如果尝试前面的示例,则可能会看到do_printdate任务仅在首次使用bitbake命令构建配方时运行。 这是因为BitBake在首次运行后将任务视为“最新(up-to-date)”。 如果要出于实验目的而强制始终重新运行任务,则可以使用[nostamp]变量标志使BitBake始终将任务视为“过期(out-of-date)”,如下所示:
do_printdate [nostamp] =“ 1”
您还可以显式运行任务并提供-f选项,如下所示:
$ bitbake recipe -c printdate -f
当使用bitbake recipe -c task命令手动选择要运行的任务时,可以省略任务名称的前缀“ do_”。

您可能想知道使用addtask而不指定任何依赖项的实际效果,如以下示例所示:

addtask printdate

在此示例中,假设未通过其他方式添加依赖项,则运行任务的唯一方法是使用bitbake recipe -c printdate显式选择任务。 您可以使用do_listtasks任务列出配方中定义的所有任务,如以下示例所示:

$ bitbake recipe -c listtasks

有关任务依赖性的更多信息,请参见“依赖性(3.10)”部分。

有关可用于任务的变量标志的信息,请参见“变量标志(3.7)”部分。

3.6.2 删除任务

除了可以添加任务之外,您还可以删除它们。 只需使用deltask命令删除任务。 例如,要删除前面几节中使用的示例任务,可以使用:

deltask printdate

如果使用deltask命令删除任务,并且该任务具有依赖,则不会重新连接依赖关系。 例如,假设您有三个名为do_ado_bdo_c的任务。 此外,do_c依赖于do_b,而do_b依赖于do_a。 在这种情况下,如果使用deltask删除do_b,则do_c和do_a到do_b之间的隐式依赖关系不再存在,并且do_c依赖关系不会更新为包括do_a。 因此,do_c可以在do_a之前运行。

如果您希望诸如此类的依赖关系保持完整,请使用[noexec]变量标志禁用任务,而不要使用deltask命令将其删除:

do_b[noexec] = "1"

3.6.3 给编译任务环境传递信息

运行任务时,BitBake紧密控制构建任务的外壳执行环境,以确保来自构建计算机的不必要污染不会影响构建。

注意

默认情况下,BitBake清理环境以仅包括导出或列入其白名单中的那些内容,以确保构建环境是可复制且一致的。 您可以通过设置BB_PRESERVE_ENV变量来防止这种“清理”。

因此,如果您确实希望将某些内容传递到任务构建环境中,则必须执行以下两个步骤:

  1. 告诉BitBake将环境中所需的内容加载到数据存储中。 您可以通过BB_ENV_WHITELISTBB_ENV_EXTRAWHITE变量来实现。 例如,假设您要阻止构建系统访问$ HOME / .ccache目录。 以下命令将环境变量CCACHE_DIR“白名单”,使BitBake允许该变量进入数据存储区:

    export BB_ENV_EXTRAWHITE="$BB_ENV_EXTRAWHITE CCACHE_DIR"
  2. 告诉BitBake将已加载到数据存储中的内容导出到每个正在运行的任务的任务环境。 从环境中将某些内容加载到数据存储中(上一步)只会使其在数据存储中可用。 要将其导出到每个正在运行的任务的任务环境,请在本地配置文件local.conf或分发(distribution)配置文件中使用类似如下命令:

    export BB_ENV_EXTRAWHITE="$BB_ENV_EXTRAWHITE CCACHE_DIR"

    注意

    前面步骤的副作用是,BitBake在诸如setcene校验和之类的内容中将变量当做构建过程的依赖项。 如果这样做会导致不必要的任务重建,则可以将变量列入白名单,以便setcene代码在创建校验和时忽略依赖项。

有时,能够从原始执行环境中获取信息很有用。 BitBake将原始环境的副本保存到名为BB_ORIGENV的特殊变量中。

BB_ORIGENV变量返回一个数据存储对象,可以使用标准数据存储操作符,如getVar(,False)来查询该对象。 数据存储对象非常有用,例如,可以找到原始的DISPLAY变量。 这是一个例子:

origenv = d.getVar("BB_ORIGENV", False)     bar = origenv.getVar("BAR", False)

前面的示例从原始执行环境返回BAR。

3.7 变量标志

变量标志(varflags)有助于控制任务的功能和依赖性。 BitBake使用以下命令从数据存储中读写变量标志:

variable = d.getVarFlags("variable")     self.d.setVarFlags("FOO", {"func": True})

使用varflags时,将应用相同的语法,但覆盖除外。 换句话说,您可以像设置变量一样set,append和prepend变量标志。 有关详细信息,请参见“变量标志语法(3.1.13)”部分。

BitBake具有一组可用于配方和类的已定义varflag。 任务支持许多这些标志,这些标志控制任务的各种功能:

  • [cleandirs]:在任务运行之前应创建的空目录。 已存在的目录将被删除并重新创建以清空它们。

  • [depends]:控制任务间的依赖关系。 有关更多信息,请参见DEPENDS变量和“任务间依赖关系(3.10.5)”部分。

  • [deptask]:控制任务构建时依赖关系。 有关更多信息,请参见DEPENDS变量和“ Build Dependencies(3.10.2)”部分。

  • [dirs]:在任务运行之前应创建的目录。 已存在的目录保留不变。 列出的最后一个目录用作任务的当前工作目录。

  • [lockfiles]:指定一个或多个在执行任务时锁定的文件。 只有一个任务可以持有一个锁定文件,并且任何尝试锁定已经锁定的文件的任务都将阻塞,直到释放该锁定为止。 您可以使用此变量标志来完成互斥。

  • [noexec]:设置为“ 1”时,将任务标记为空,无需执行。 您可以使用[noexec]标志将任务设置为依赖项占位符,或者禁用在特定配方中不需要的其他位置定义的任务。

  • [nostamp]:设置为“ 1”时,告诉BitBake不要为任务生成标记文件,这意味着应始终执行任务。

    警告

    任何(可能间接)依赖于[nostamp]任务的任务也将始终执行。 如果您不小心,可能会导致不必要的重建。

  • [number_threads]:在执行期间将任务限制为特定数量的并发线程。 当构建主机具有大量核心但某些任务由于各种资源限制(例如,避免网络节流)而需要进行速率限制时,此varflag很有用。 number_threads的工作方式类似于BB_NUMBER_THREADS变量,但特定于任务。

    全局设置该标志。 例如,以下语句确保do_fetch任务使用的并行执行线程不超过两个:

    do_fetch [number_threads] =“ 2”

    警告

    • 在单个配方中而不是在全局配方中设置varflag可能导致无法预测的行为。
    • 将varflag设置为大于BB_NUMBER_THREADS变量中使用的值,将导致number_threads无效。
  • [postfuncs]:任务完成后要调用的函数列表。

  • [prefuncs]:任务执行前要调用的函数列表。

  • [rdepends]:控制任务间运行时依赖关系。 有关更多信息,请参见RDEPENDS变量,RRECOMMENDS变量和“任务间依赖关系(3.10.5)”部分。

  • [rdeptask]:控制任务运行时依赖项。 有关更多信息,请参见RDEPENDS变量RRECOMMENDS变量和“运行时依赖项(3.10.3)”部分。

  • [recideptask]:与recrdeptask一起设置时,指定应检查其他依赖项的任务。

  • [recrdeptask]:控制任务递归运行时依赖项。 有关更多信息,请参见RDEPENDS变量,RRECOMMENDS变量和“递归依赖项(3.10.4)”部分。

  • [stamp-extra-info]:要附加到任务stamp的额外stamp信息。 例如,OpenEmbedded使用此标志来允许特定机器的任务。

  • [umask]:运行任务的umask。

几个变量标志可用于控制如何为变量计算签名。 有关此过程的更多信息,请参见“校验和(签名)(2.8)”部分。

  • [vardeps]:指定用空格分隔的其他变量列表,这些变量添加到变量的从属关系中,以计算其签名。 将变量添加到此列表很有用,例如,当函数以不允许BitBake自动确定引用变量的方式引用变量时。

  • [vardepsexclude]:指定用空格分隔的变量列表,在计算其签名时,应从变量的依赖项中排除的变量。

  • [vardepvalue]:如果设置,则指示BitBake忽略变量的实际值,而在计算变量的签名时使用指定的值。

  • [vardepvalueexclude]:指定以竖线分隔的字符串列表,以在计算变量的签名时排除这些值。

3.8 事件

BitBake允许在配方和类文件中安装事件处理程序。 在操作过程中的某些点会触发事件,例如针对给定配方(即* .bb)的操作开始,给定任务的开始,任务失败,任务成功等。 目的是使构建失败时的电子邮件通知等操作变得容易。

以下是示例事件处理程序,该事件处理程序显示事件的名称和FILE变量的内容:

addhandler myclass_eventhandler     python myclass_eventhandler() {         from bb.event import getName         print("The name of the Event is %s" % getName(e))         print("The file we run for is %s" % d.getVar('FILE'))     }     myclass_eventhandler[eventmask] = "bb.event.BuildStarted bb.event.BuildCompleted"

在上一个示例中,已设置了事件掩码,以便处理程序仅识别“BuildStarted”和“BuildCompleted”事件。 每次触发与事件掩码匹配的事件时,都会调用此事件处理程序。 定义了一个全局变量“e”,它代表当前事件。 使用getName(e)方法,可以获取触发事件的名称。 全局数据存储区可作为“ d”使用。 在旧版代码中,您可能会看到使用“e.data”获取数据存储。 但是,请注意“e.data”已被弃用,您之后应该使用“ d”。

数据存储的上下文适合所讨论的事件。 例如,“ BuildStarted”和“ BuildCompleted”事件在执行任何任务之前运行,因此将在全局配置数据存储命名空间中运行。 该命名空间中不存在特定于配方的元数据。 “BuildStarted”和“BuildCompleted”事件也在主cooker/server进程中运行,而不是在任何工作程序上下文中运行。 因此,对数据存储所做的任何更改将被当前内部版本中的其他Cooker /server事件看到,但在该内部版本之外或任何工作程序上下文中则看不到。 因此,在所讨论的实际任务中运行的任务事件具有特定于配方和特定于任务的内容。 这些事件在工作程序上下文中运行,并在任务执行结束时被丢弃。

在标准构建期间,可能会发生以下常见事件。 以下事件是大多数元数据可能感兴趣的最常见事件:

  • bb.event.ConfigParsed():基本配置时触发; 它由bitbake.conf,base.bbclass和任何全局INHERIT语句组成; 已解析。 当每个工作程序解析基本配置时,或者服务器更改配置并重新解析时,您可以看到多个此类事件。 但是,任何给定的数据存储区都只对它执行一个这样的事件。 如果事件处理程序在数据存储区中设置了BB_INVALIDCONF,则将重新解析配置并触发新事件,从而允许元数据更新配置。

  • bb.event.HeartbeatEvent():以一秒的固定时间间隔触发。 您可以使用BB_HEARTBEAT_EVENT变量配置间隔时间。 事件的“时间”属性是触发事件时的time.time()值。 此事件对于诸如系统状态监视之类的活动很有用。

  • bb.event.ParseStarted():当BitBake将要开始解析配方时触发。 此事件的“total”属性表示BitBake计划解析的配方数。

  • bb.event.ParseProgress():在解析过程中触发。 此事件的“current”属性以及“total”属性是已解析的配方数。

  • bb.event.ParseCompleted():解析完成时触发。 此事件的“cached”,“parsed”,“skipped”,“virtuals”,“masked”和“errors”属性提供了分析结果的统计信息。

  • bb.event.BuildStarted():新的构建开始时触发。 启用多个配置(multiconfig)时,BitBake会触发多个“ BuildStarted”事件(每个配置一个)。

  • bb.build.TaskStarted():任务启动时触发。 此事件的“taskfile”属性指向任务源配方。 “taskname”属性(即任务名称)包括do_前缀,“logfile”属性指向任务输出的存储位置。 最后,“时间”属性是任务的执行开始时间。

  • bb.build.TaskInvalid():如果BitBake尝试执行不存在的任务,则触发该事件。

  • bb.build.TaskFailedSilent():对失败且不应向用户详细显示的setcene任务触发。

  • bb.build.TaskFailed():针对失败的常规任务触发。

  • bb.build.TaskSucceeded():任务成功完成时触发。

  • bb.event.BuildCompleted():构建完成时触发。

  • bb.cooker.CookerExit():当BitBake server/cooker关闭时触发。 通常,UI仅将此事件视为它们也应关闭的标志。

接下来的示例事件列表是基于对server的特定请求而发生的。 这些事件通常用于将大量信息从BitBake服务器传递到BitBake的其他部分,例如用户界面:

  • bb.event.TreeDataPreparationStarted()

  • bb.event.TreeDataPreparationProgress()

  • bb.event.TreeDataPreparationCompleted()

  • bb.event.DepTreeGenerated()

  • bb.event.CoreBaseFilesFound()

  • bb.event.ConfigFilePathFound()

  • bb.event.FilesMatchingFound()

  • bb.event.ConfigFilesFound()

  • bb.event.TargetsTreeGenerated()

3.9 变体-类扩展机制

BitBake支持两个功能,这些功能有助于从单个配方文件创建该配方文件的多个化身,所有化身都可以构建。 这些功能通过BBCLASSEXTENDBBVERSIONS变量启用。

注意

该类扩展的机制非常特定于实现。 通常,扩展类需要修改配方的PROVIDESPNDEPENDS变量。 有关特定示例,请参见OE-Core的nativenativesdkmultilib类。

  • BBCLASSEXTEND:此变量是用空格分隔的类列表,用于“扩展”每个变体的配方。 这是导致当前配方的第二个实例可用的示例。 这第二个化身将继承“native”类。
    BBCLASSEXTEND = "native"
  • BBVERSIONS:此变量允许从单个配方文件构建项目的多个版本。 您还可以为单个版本或可选的版本范围指定条件元数据(使用OVERRIDES机制)。 这是一个例子:
BBVERSIONS = "1.0 2.0 git"     SRC_URI_git = "git://someurl/somepath.git"     BBVERSIONS = "1.0.[0-6]:1.0.0+ \ 1.0.[7-9]:1.0.7+"     SRC_URI_append_1.0.7+ = "file://some_patch_which_the_new_versions_need.patch;patch=1"

范围的名称默认为配方的原始版本。 例如,在OpenEmbedded中,配方文件foo_1.0.0 + .bb创建的默认名称范围为1.0.0+。 这是有用的,因为范围名称不仅在overrides中使用,而且还使元数据可用于定义用于file://搜索路径(FILESPATH)的基本配方版本的变量。

3.10 依赖

为了进行高效的并行处理,BitBake在任务级别处理依赖关系。 单个配方中的任务之间以及不同配方中的任务之间都可以存在依赖关系。 以下分别为对应的示例:

  • 对于单个配方中的任务,可能需要先完成配方的do_configure任务,然后它的do_compile任务才能运行。

  • 对于不同配方中的任务,一个配方的do_configure任务可能需要另一个配方的do_populate_sysroot任务首先完成,以便其他配方提供的库和头文件可用。

本节描述了声明依赖关系的几种方法。 请记住,即使依赖项以不同的方式声明,它们都只是任务之间的依赖项。

3.10.1 bb文件内部依赖

BitBake使用addtask指令来管理给定配方文件内部的依赖项。 您可以使用addtask指令来指示某个任务何时依赖于其他任务或何时其他任务依赖于该配方。 这是一个例子:

addtask printdate after do_fetch before do_build

在此示例中,do_printdate任务取决于do_fetch任务的完成,而do_build任务取决于do_printdate任务的完成。

注意

要运行任务,它必须是计划运行的某些其他任务的直接或间接依赖项。
为了举例说明,下面是一些示例:

  • 指令addtask mytask before do_configure导致do_mytaskdo_configure运行之前运行。 请注意,do_mytask仍仅在其输入校验和自上次运行以来已更改的情况下运行。 更改do_mytask的输入校验和也会间接导致do_configure运行。
  • do_configure之后的指令addtask mytask本身不会导致do_mytask运行。 do_mytask仍然可以手动运行,如下所示:
    addtask mytask before do_configure
    将do_mytask声明为计划运行的某些其他任务的依赖项也会导致其运行。 无论如何,该任务在do_configure之后运行。

3.10.2 编译依赖

BitBake使用DEPENDS变量来管理构建时依赖性。 任务的[deptask]变量标志表示必须先完成DEPENDS中列出的每个项目的任务,然后才能执行该任务。 这是一个例子:

do_configure[deptask] = "do_populate_sysroot"

在此示例中,必须先完成DEPENDS中每个项目的do_populate_sysroot任务,然后才能执行do_configure。

3.10.3 运行时依赖

BitBake使用PACKAGESRDEPENDSRRECOMMENDS变量来管理运行时依赖项。

PACKAGES变量列出了运行时程序包。 每个软件包都可以具有RDEPENDSRRECOMMENDS运行时依赖项。 任务的[rdeptask]标志用于表示每个项目运行时依赖项的任务,必须先完成该任务,然后才能执行该任务。

do_package_qa[rdeptask] = "do_packagedata"

在上一个示例中,必须先完成RDEPENDS中每个项目的do_packagedata任务,然后才能执行do_package_qa。 尽管RDEPENDS包含来自运行时依赖项命名空间的条目,但BitBake知道如何将它们映射回定义任务的构建时依赖项命名空间。

3.10.4 递归依赖

BitBake使用[recrdeptask]标志来管理递归任务依赖项。 BitBake查看当前配方的构建时和运行时依赖关系,查看任务的任务间依赖关系,然后为列出的任务添加依赖关系。 一旦BitBake完成了此任务,它将以递归方式处理这些任务的依赖关系。 迭代过程将继续进行,直到发现并添加所有依赖项为止。

[recrdeptask]标志最常用于需要等待某些任务“全局”完成的high-level配方中。 例如,image.bbclass具有以下内容:

do_rootfs[recrdeptask] += "do_packagedata"

该语句表明,必须先运行当前配方的do_packagedata任务以及从image配方可访问(通过依赖关系)的所有配方的do_packagedata任务,然后才能运行do_rootfs任务。

BitBake允许任务通过在任务列表中引用自身来递归地依赖于自身:

do_a[recrdeptask] = "do_a do_b"

与之前一样,这意味着必须先运行当前配方的do_ado_b任务以及该配方可访问的所有配方(通过依赖关系)的do_ado_b任务,然后才能运行do_a任务。 在这种情况下,BitBake将忽略当前配方对其自身的do_a任务循环依赖关系。

3.10.5 任务间依赖

BitBake以更通用的形式使用[depends]标志来管理任务间的依赖关系。 这种更通用的形式允许对特定任务进行相互依赖性检查,而不是检查DEPENDS中的数据。 这是一个例子:

do_patch[depends] = "quilt-native:do_populate_sysroot"

在此示例中,必须先完成目标quilt-nativedo_populate_sysroot任务,然后才能执行do_patch任务。

[rdepends]标志的工作方式类似,但是在运行时命名空间而不是在构建时依赖性名称空间中获取目标。

3.11 Python中可以调用的方法

BitBake提供了许多可以从Python函数中调用的函数。本节列出了最常用的函数,并提到了在哪里可以找到其他函数。

3.11.1 访问数据存储区变量的函数

通常需要使用Python函数访问BitBake数据存储中的变量。BitBake数据存储有一个允许您进行此访问的API。下面是可用操作列表

d.getVar("X", expand)	   # 返回变量“X”的值。使用“expand=True”扩展值。如果变量“X”不存在,返回“None”。d.setVar("X", "value")	   # 将变量“X”设置为“value”。d.appendVar("X", "value")  # 在变量"X"的末尾添加“value”。如果变量“X”不存在,等价于d.s setvar("X", "value")。d.prependVar("X", "value") # 在变量“X”的开头添加“value”。如果变量“X”不存在,就像d.s setvar ("X", "value")。d.delVar("X")	           # 从数据存储中删除变量“X”。如果变量“X”不存在,则不执行任何操作。d.renameVar("X", "Y")	   # 将变量“X”重命名为“Y”。如果变量“X”不存在,则不执行任何操作。d.getVarFlag("X", flag, expand)	# 返回变量“X”的值。使用“expand=True”扩展值。如果变量“X”或指定标志不存在,则返回“None”。d.setVarFlag("X", flag, "value")	# 将变量“X”的命名标志设置为“value”。d.appendVarFlag("X", flag, "value")	# 将“value”附加到变量“X”的命名标志上。如果指定的标志不存在,其作用类似于d.s setvarflag(“X”,flag,“value”)。d.prependVarFlag("X", flag, "value")	# 在变量“X”的命名标志前加上“value”。如果指定的标志不存在,其作用类似于d.s setvarflag(“X”,flag,“value”)。d.delVarFlag("X", flag)	   # 从数据存储中删除变量“X”上的已命名标志。d.setVarFlags("X", flagsdict)	# 设置在flagsdict()参数中指定的标志。setVarFlags不清除以前的标志。可以将此操作看作addVarFlags。d.getVarFlags("X")	    # 返回变量“X”的标志的标志值。如果变量“X”不存在,返回“None”。d.delVarFlags("X")	    # 删除变量“X”的所有标志。如果变量“X”不存在,则不执行任何操作。d.expand(expression)	# 展开指定字符串表达式中的变量引用。对不存在的变量的引用保持原样。例如,如果变量"X"不存在,d.expand("foo ${X}")将扩展为字符串文本"foo ${X}"。

3.11.2 其他函数

通过查看bb模块的源代码(位于bitbake / lib / bb中),可以找到许多可以从Python调用的函数。 例如,bitbake / lib / bb / utils.py包含常用函数bb.utils.contains()bb.utils.mkdirhier(),它们带有使用文档。

3.12 任务校验和和setscene

BitBake使用校验和(或签名)以及setcene来确定是否需要运行任务。 本节介绍该过程。 为了帮助理解BitBake如何做到这一点,本节假设一个OpenEmbedded的基于元数据的示例。

这些校验和存储在`STAMP·中。 您可以使用以下BitBake命令检查校验和:

$ bitbake-dumpsigs

此命令以可读格式返回签名数据,该格式允许您检查OpenEmbedded构建系统生成签名时使用的输入。 例如,使用bitbake-dumpsigs可以检查C应用程序(例如bash)的do_compile任务的“sigdata”。 运行该命令还会显示“ CC”变量是哈希输入的一部分。 对此变量的任何更改都会使标记无效,并导致do_compile任务运行。

以下列表描述了相关变量:

  • BB_HASHCHECK_FUNCTION:指定在任务执行的“setscene”部分期间要调用的函数的名称,以验证任务哈希列表。

  • BB_SETSCENE_DEPVALID:指定BitBake调用的函数,该函数确定BitBake是否需要满足setcene依赖关系。

  • BB_SETSCENE_VERIFY_FUNCTION2:指定要调用的函数,该函数在主任务执行发生之前验证计划的任务执行列表。

  • BB_STAMP_POLICY:定义比较stamp文件时间戳的模式。

  • BB_STAMP_WHITELIST:列出在标记策略为“白名单”时要查看的标记文件。

  • BB_TASKHASH:在正在执行的任务中,此变量保存当前启用的签名生成器返回的任务哈希。

  • STAMP:创建标记文件的base路径。

  • STAMPCLEAN:同样,这是创建标记文件的base路径,但可以使用通配符来匹配一系列文件以进行清洁操作。

3.13 变量通配符

在变量中对通配符使用的支持因使用上下文而异。 例如,某些变量和文件名允许通过“%”和“*”字符来限制使用通配符。 其他变量或名称支持Python的glob语法,fnmatch语法或正则表达式语法。

对于具有通配符替代的变量,文档描述了通配符的哪种形式,其用法及其局限性。

转载地址:http://nvkr.baihongyu.com/

你可能感兴趣的文章