BitBake用户手册翻译笔记(二)

BitBake用户手册翻译笔记


说明
本文是博主学习BitBake英文版用户手册时做的记录,由于外语水平有限,难免会有一些翻译错误还望留言区指正。
BitBake User Manual
datastore: 数据存储(BitBake解析后的变量都可以在datastore中使用getVar得到)


3. 基本语法

3.1. 基本语法

3.1.1. 基本变量设置

下面的例子为VARIABLE赋值value,这个赋值语句会在这句被解析时直接执行赋值操作,是一个“硬”赋值。

VARIABLE = "value"

若你在赋值部分包含一个前置或后置空格,空格是会保留的:

VARIABLE = " value"
VARIABLE = "value "

设置变量VARIABLE为空或者为一个空格:

VARIBALE = ""
VARIABLE = " "
3.1.2. 变量扩展

BitBake支持变量引用另一个变量的内容,语法与shell类似,下面的这个例子B引用A的内容,扩展开为"preavalpost"

A = "aval"
B = "pre${A}post"

需要明确的是,在上面的例子中,若需要引用B,则同时需要依赖A的内容。

3.1.3. 设置一个默认值(?=)

可以使用"?="操作符对一个变量进行“软”赋值。这种赋值允许你定义一个值,当被赋值对象是未定义时会解析这个赋值操作,但当该变量有一个值时会保留原值,这儿是一个实例:

A ?= "aval"

若A早已被赋值,则A不会被赋值"aval",相反,A会被赋值"aval"。

hint
这个赋值操作是立即的,即若存在多个?=赋值语句,则最后会使用第一个该语句。

3.1.4. 设置一个弱默认值(??=)

相较于"?=","??=“是一个更弱的赋值操作符。除了它不是立即执行而是执行最后一个该赋值语句,”??=“的赋值逻辑与”?=“是相同的。当然,任何”=“与”?=“赋值都会覆盖”??="赋值语句。这有一个例子:

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

若A是未定义的,那么此时A应为"someothervalue",否则保留原值。
再次强调,这个弱赋值语句直到解析程序结束前都不会进行解析。

3.1.5. 直接变量展开(:=)

":="操作符会立即展开变量的内容,而不是在实际使用变量时展开:

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

在本例中,A包含“test 123”,因为解析时的$ {B}和$ {A}未定义,因此只剩下“test 123”。而且,变量C包含"cvalappend",因为${C}立即扩展为"cval"。

3.1.6. 带有空格的追加(+=)和前加(=+)

为一个变量的内容追加或者前加一些内容经常会用到,同时会在两个内容间插入一个空格:

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

最后B的内容为"bval additionaldata",C为"test cval"。

3.1.7. 不带空格的追加(.=)和前加(=.)

与上一节赋值操作类似,只是不再插入空格。

3.1.8. 追加和前加(覆盖风格语法)

这种语法与前一节一样不会插入空格,这儿有几个例子:

     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"。
“_append"与”_prepend"操作符与".=“和”=."是有差异的,它们会被延迟到解析完成后。

3.1.9. 消除(覆盖风格语法)

可以使用删除覆盖样式语法从列表中删除值。指定要删除的值将导致从变量中删除出现的所有该值。
使用此语法时,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"
FOO2_remove = "abc def"

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

3.1.10. 变量标志语法

变量标志是BitBake对变量属性或属性的实现。这是一种给变量加上额外信息的方法。
你可以对变量标志定义、追加和前加值。前面提到的所有标准语法操作都适用于变量标志,但覆盖样式语法除外(例如_prepend、_append和_remove)。下面是一些如何设置变量标志的例子:

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

变量FOO有两个标志,a和b,其值最后分别为"abc456",b为"123"。

3.1.11. 内联Python变量扩展

你可以使用内联Python变量扩展去设置变量。这儿有一个例子:

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

这句代码为DATE赋值当前日期。

3.1.12. 提供路径名

当在使用BitBake指定路径时,不要使用波浪号("~")字符作为主目录的快捷方式。这样做可能会导致BitBake无法识别路径,因为BitBake不像shell那样展开该字符。
相反,应该提供一个完整的路径,如下面的例子所示:

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

3.2. 条件语法(Overrides)

BitBake使用OVERRIDES来控制在解析recipe文件和配置文件后覆盖哪些变量。本节描述如何使用覆盖作为条件元数据,讨论与OVERRIDES相关的键扩展,并提供一些示例来帮助理解。

3.2.1. 条件元数据

可以使用OVERRIDES来有条件地选择变量的特定版本,并有条件地附加或前置变量的值。
选择一个变量:
OVERRIDES变量是一个以冒号分隔的列表,其中包含你希望满足条件的项。因此,如果你有一个以“arm”为条件的变量,并且“arm”在OVERRIDES中,那么将使用该变量的“arm”特定版本,而不是非条件版本。下面是一个例子:

     OVERRIDES = "architecture:os:machine"
     TEST = "default"
     TEST_os = "osspecific"
     TEST_nooverride = "othercondvalue"

在本例中,OVERRIDES变量列出了三种覆盖:“architecture”、“os”和“machine”。变量TEST 本身有一个默认值“default”。通过将“os”覆盖附加到变量(即test_os),可以选择特定于os的TEST变量版本。
追加和前加:
BitBake还支持根据OVERRIDES 中是否列出特定项对变量值进行追加和前加操作。下面是一个例子:

     DEPENDS = "glibc ncurses"
     OVERRIDES = "machine:local"
     DEPENDS_append_machine = "libmad"

在这个例子中,DEPENDS变成了“glibc ncurses libmad”。

3.2.2. 关键字扩展

当BitBake数据存储在BitBake扩展覆盖之前完成时,键展开就会发生。为了更好地理解这一点,考虑下面的例子:

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

在这种情况下,在所有解析完成之后,在任何重写被处理之前,BitBake将${B}展开为“2”。A2在展开之前被设置为“Y”,这次展开导致A2变成了“X”。

3.2.3. 实例

尽管前面的解释说明了变量定义的不同形式,但是很难计算出当变量操作符、条件覆盖和无条件覆盖组合在一起时会发生什么。本节将介绍一些常见的场景,并解释通常会使用户感到困惑的各种变量相互作用。
关于覆盖和各种“追加”操作符的生效顺序,经常会产生混淆。回想一下,使用"_append"和"_prepend"的追加或前加操作不会像"+=",".=", “=+”,或"=."那样直接赋值。考虑下面的例子:

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

在这种情况下,A被无条件地设置为“Z”,而“X”被无条件地立即附加到变量A_foo中。因为覆盖还没有被应用,A_foo由于追加被设置为"X",同时A简单地等于"Z"。
但是,应用覆盖会改变一些事情。由于“foo”在OVERRIDES中被列出,条件变量A被替换为“foo”版本,它等于“X”。实际上,A_foo替换了A。
下面的例子改变了覆盖和追加的顺序:

OVERRIDES = "foo"
A = "Z"
A_append_foo = "X"

在本例中,在处理覆盖之前,A被设置为“Z”,A_append_foo被设置为“X”。一旦对“foo”的覆盖被应用,A就会被附加“X”。因此,A变成了“ZX”。注意,没有添加空格。
下面的例子与第一个例子一样,将附加和覆盖的顺序颠倒:

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

在本例中,在解析任何覆盖之前,使用立即赋值将A设置为“Y”。在立即赋值之后,A_foo被设置为"Z",然后被进一步追加"X",变量被设置为"Z X"。最后,应用对“foo”的覆盖会导致条件变量A变成“Z X”(即用A_foo替换A)。
最后一个例子混合了一些不同的运算符:

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

在这种情况下,当BitBake多次传递代码时,附加操作符的类型会影响赋值的顺序。最初,A被设置为“1 45”,因为这三个语句使用了直接操作符。完成这些赋值后,BitBake应用_append操作。这些操作的结果是变成“1 4523”。

3.3. 共享功能

BitBake允许通过include文件(.inc)和class文件(.bbclass)共享元数据。例如,假设你有一个公共功能,比如希望在多个recipe文件之间共享的任务定义。在这种情况下,创建一个包含通用功能的.bbclass文件,然后在recipe中使用inherit指令来继承类,这是共享任务的常见方法。
本节介绍BitBake提供的机制,允许你在不同recipe之间共享功能。具体来说,机制有包含include, inherit, INHERIT, 以及 require指令。

3.3.1. 定位include和class文件

BitBake使用BBPATH变量来定位所需的include和class文件。BBPATH变量类似于环境变量PATH。
为了让BitBake找到include和class文件,它们需要被定位在BBPATH可以找到的“classes”子目录中。

3.3.2. inherit 指令

在编写recipe或class文件时,可以使用inherit指令来继承类(.bbclass)的功能。BitBake只支持在recipe和class文件(即.bb和.bbclass)中使用这个指令。
inherit指令是指定recipe需要哪些类功能的基本方法。例如,你可以很容易地抽象出使用Autoconf和Automake构建包所涉及的任务,并将这些任务放入你的recipe可以使用的类文件中。
例如,你的recipe可以使用以下指令来继承autotools.bbclass文件。z这个类文件将包含使用Autotools的通用功能,其可以在recipe之间共享:

inherit autotools

在这种情况下,BitBake将在BBPATH中搜索目录classes/autotools.bbclass。
hint
你可以在“inherit”语句之后重写菜谱中继承的类的任何值和函数。

3.3.3. include 指令

这个指令会导致BitBake解析你指定的任何文件,并将该文件插入到该位置。这个指令很像它在Make中的等价指令,除了如果include行指定的路径是一个相对路径,BitBake定位它能在BBPATH中找到的第一个文件。
例如,假设你需要一个recipe来包含一些自测试定义:

include test_defs.inc

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

3.3.4. require 指令

这个指令的行为和include指令一样,只是如果找不到要包含的文件,BitBake会抛出解析错误。因此,你需要的任何文件都被插入到指令所在位置正在被解析的文件中。
与BitBake处理include的方式类似,如果在require行中指定的路径是相对路径,BitBake会定位它在BBPATH中找到的第一个文件。
例如,假设你有一个recipe的两个版本(例如,foo_1.2.2.bb与foo_2.0.0.bb),且每个版本都包含一些可以共享的相同功能。你可以创建一个名为foo.inc的include文件,该文件包含构建“foo”所需的通用定义。你需要确保foo.inc和你的两个recipe文件位于同一个目录中。一旦设置了这些条件,你可以在每个菜谱中使用require指令共享功能:

require foo.inc
3.3.5. INHERIT 配置指令

当创建一个配置文件(.conf)时,你可以使用INHERIT指令继承一个类。BitBake仅仅在配置文件中支持这个指令。
举个例子,假设你要在一个配置文件中继承一个类文件abc.bbclass:

INHERIT += "abc"

这个配置指令使得在解析期间在指令处继承这个类。与inherit指令一样,.bbclass文件必须位于BBPATH中指定的目录之一的“classes”子目录中。
注意
因为.conf文件是在BitBake执行时首先解析的,所以使用INHERIT来继承一个类可以有效地全局继承这个类(例如,对于所有recipe文件)。

3.4. 函数

BitBake支持这些类型的函数:

  • shell函数:用shell脚本编写的函数,可以直接作为函数、任务或两者同时执行。它们也可以被其他shell函数调用
  • BitBake风格的Python函数:用Python编写并由BitBake或其他Python函数使用bb.build.exec_func()执行的函数
  • Python函数:由Python编写且由Python执行
  • 匿名Python函数:在解析期间自动执行Python函数

无论何种类型的函数,你只可以在类文件(.bbclass)和recipe文件(.bb或者.inc)中定义它们。

3.4.1. shell函数

用shell脚本编写的函数,可以直接作为函数、任务或两者同时执行。它们也可以被其他shell函数调用。下面是shell函数定义的一个例子:

     some_function () {
         echo "Hello World"
     }

在recipe或class文件中创建这些类型的函数时,需要遵循shell编程规则。脚本由/bin/sh执行,它可能不是一个bash shell,但可能是dash之类的东西。你不应该使用Bash特定脚本(bashisms)。

3.4.2. BitBake风格Python函数

这些函数用Python编写并由BitBake或其他Python函数使用bb.build.exec_func()执行,一个例子如下:

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

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

3.4.3. Python函数

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

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

这将导致DEPENDS内容变为dependencywithcond。
下面是一些关于Python函数需要了解的事情:

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

有时,在解析期间运行一些代码以设置变量或以编程方式执行其他操作是有用的。为此,你可以定义一个匿名Python函数。这里有一个例子,根据另一个变量的值有条件地设置一个变量:

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

“__anonymous”函数名是可选的,所以下面的例子在功能上与上面的是等价的:

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

因为与其他Python函数不同,匿名Python函数是在解析期间执行的,所以匿名Python函数中的“d”变量表示整个recipe的数据存储。因此,你可以在这里设置变量值,这些值可以被其他函数获取。

3.4.5. 类函数间的灵活继承

通过编码技术和使用EXPORT_FUNCTIONS BitBake支持从一个类中导出一个函数以至于类函数作为函数的默认实现出现,但是如果一个继承该类recipe需要定义它自己的函数版本时仍然可以被调用。
要理解这个特性的好处,请考虑这样一个基本场景:一个类定义了一个任务函数,而你的recipe继承了这个类。在这个基本场景中,你的recipe继承在类中定义的任务函数。如果需要,你的recipe可以分别使用“_prepend”或“_append”操作向函数的开始和结束添加内容,也可以完全重新定义函数。但是,如果它重新定义了函数,它就没有办法调用函数的类版本。EXPORT_FUNCTIONS提供了一种机制,允许recipe函数的版本调用函数的原始版本。
要使用这种技术,你需要以下几点:

  • 这个类需要按如下方式定义函数:
     <classname>_<functionname>

例如,如果你有一个类文件bar.bbclass和一个命名为do_foo的函数,这个类必须按如下方式定义这个函数:

    bar_do_foo
  • 类需要按如下方式包含EXPORT_FUNCTIONS语句:
    EXPORT_FUNCTIONS <functionname>

例如,继续上述实例,在bar.bbclass中语句应写作如下形式:

     EXPORT_FUNCTIONS do_foo
  • 你需要从你的recipe中适当地调用该函数。继续使用相同的示例,如果你的recipe需要调用函数的类版本,它应该调用bar_do_foo。假设do_foo是一个shell函数,并且像上面那样使用EXPORT_FUNCTIONS,那么recipe的函数可以有条件地调用函数的类版本,如下所示:
     do_foo() {
             if [ somecondition ] ; then
                     bar_do_foo
             else
                     # Do something else
             fi
     }

要调用recipe中定义的函数的修改版本,请将其调用为do_foo。
满足了这些条件后,你的单个recipe可以在类文件中定义的原始函数和recipe中修改的函数之间自由选择。如果不设置这些条件,则只能使用其中一个函数。

3.5. 任务

任务是BitBake的执行单元,它们以函数的形式产生,并构成了BitBake运行给定recipe所需的步骤。仅在recipe(.bb或者.inc)和类(.bbclass)文件中支持使用。按照惯例,任务名称以字符串“do_”开头。
这儿是一个打印日期的任务实例:

     python do_printdate () {
         import time
         print time.strftime('%Y%m%d', time.gmtime())
     }
     addtask printdate after do_fetch before do_build
3.5.1. 将一个函数提升为一个任务

任何函数都可以通过应用addtask命令提升为任务。addtask命令还描述了任务间的依赖关系。下面是上一节的函数,但是使用addtask命令将其提升为任务并定义了一些依赖项:

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

本例定义了一个函数,然后将其提升为任务。do_printdate任务成为do_build任务(一个默认任务)的依赖项。而且,do_printdate任务依赖于do_fetch任务。do_build任务的执行会导致先运行do_printdate任务。

3.5.2. 删除一个任务

除了可以添加任务外,任务也可以被删除。这只需使用deltask命令即可完成。例如,要删除前面部分中使用的示例任务,可以使用:

deltask printdate
3.5.3. 在构建任务环境中解析信息

在运行任务时,BitBake严格控制构建任务的执行环境,以确保来自构建机器多余的污染不会影响构建。因此,如果你确实想要一些东西被传递到构建任务环境中,你必须采取以下两个步骤:

  1. 告诉BitBake将你想要的从环境中加载到数据存储中。你可以通过BB_ENV_EXTRAWHITE变量来做到这一点。例如,假设你想阻止构建系统访问你的 $ HOME/.ccache 目录。下面的命令告诉BitBake将CCACHE_DIR从环境加载到数据存储中 : export BB_ENV_EXTRAWHITE = "$BB_ENV_EXTRAWHITE CCACHE_DIR"
  2. 告诉BitBake将已加载到数据存储中的内容导出到每个正在运行任务的任务环境中。将某些内容从环境加载到数据存储中(前一步)只会使其在数据存储中可用。要将其导出到每个正在运行的任务的任务环境中,请在本地配置文件local.conf或分发配置文件中使用类似于下面的命令:export CCACHE_DIR

hint

上述步骤的一个副作用是,BitBake将该变量记录为构建过程的依赖项,比如setscene校验和。如果这样做会导致不必要的任务重建,那么你可以将该变量放到白名单中,以便setscene代码在创建校验和时忽略依赖关系。

有时,能够从原始执行环境中获取信息是很有用的。Bitbake将原始环境的一个副本保存到一个名为BB_ORIGENV的特殊变量中。
BB_ORIGENV变量返回一个可以使用标准数据存储操作符(如getVar())查询的数据存储对象。例如,datastore对象对于查找原始的DISPLAY 变量很有用。下面是一个例子:

     BB_ORIGENV - add example?

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

上面示例从原始执行环境返回BAR。默认情况下,BitBake会清理环境,只包括导出或在whitelist 中列出的内容,以确保构建环境是可复制的和一致的。

3.6. 变量标志

变量标志(varflags)帮助控制任务的功能和依赖关系。BitBake使用以下命令形式读取和写入数据存储中的varflags:

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

当使用varflags时,除了覆盖之外,同样的语法也适用。换句话说,你可以像设置变量一样设置、附加和前置varflags。
BitBake有一组定义好的varflags,可用于recipe和class。任务支持许多这些标志来控制任务的各种功能:

  • dirs:任务运行前应该创建的目录
  • cleandirs:任务运行前应该创建的空目录
  • noexec:将任务标记为空且不需要执行。noexec标志可用于将任务设置为依赖占位符,或禁用在特定recipe中其他地方定义但不需要的任务。
  • nostamp:告诉BitBake不要为任务生成戳记文件,这意味着任务应该始终执行。
  • fakeroot:通过将FAKEROOTENV中的变量添加到环境中,使任务在fakeroot环境中运行。
  • umask:The umask to run the task under
  • deptask:控制任务构建时的依赖关系
  • rdeptask:控制任务运行时的依赖关系
  • recrdeptask:控制任务递归运行时的依赖关系
  • depends:控制任务间的依赖关系
  • rdepends:控制任务间运行时的依赖关系
  • postfuncs:任务完成后要调用的函数列表
  • prefuncs:任务执行前要调用的函数列表
  • stamp-extra-info:附加到任务戳记的额外戳记信息。例如,OpenEmbedded使用这个标志来允许特定于机器的任务。
  • vardeps:指定要添加到变量依赖项中的以空格分隔的附加变量列表,以便计算其签名。在这个列表中添加变量是有用的,例如,当一个函数引用一个变量时,BitBake不允许自动确定该变量是否被引用。
  • vardepvalue:如果设置,则指示BitBake忽略变量的实际值,而在计算变量的签名时使用指定的值。
  • vardepsexclude:指定一个空格分隔的变量列表,为了计算变量的签名,这些变量应该被排除在变量的依赖项之外。
  • vardepvalueexclude:指定在计算变量签名时从变量值中排除的以管道分隔的字符串列表。

3.7. 事件

BitBake允许在recipe和类文件中安装事件处理程序。事件在操作期间的某些点被触发,例如针对给定的.bb的操作开始、给定任务的开始、任务失败、任务成功,等等。这样做的目的是简化诸如在构建失败时发送电子邮件通知之类的操作。
下面是一个示例事件处理程序,它打印事件的名称和文件变量的内容:

     addhandler myclass_eventhandler
     python myclass_eventhandler() {
         from bb.event import getName
         from bb import data
         print("The name of the Event is %s" % getName(e))
         print("The file we run for is %s" % data.getVar('FILE', e.data, True))
     }

该事件处理程序在每次触发事件时被调用。定义了一个全局变量“e”,“e.data”包含一个实例“bb.data”。使用getName(e)方法,可以获得被触发事件的名称。
在标准构建过程中,可能会发生以下常见事件:

  • bb.event.ConfigParsed()
  • bb.event.ParseStarted()
  • bb.event.ParseProgress()
  • bb.event.ParseCompleted()
  • bb.event.BuildStarted()
  • bb.build.TaskStarted()
  • bb.build.TaskInvalid()
  • bb.build.TaskFailedSilent()
  • bb.build.TaskFailed()
  • bb.build.TaskSucceeded()
  • bb.event.BuildCompleted()
  • bb.cooker.CookerExit()

下面是基于对服务器的特定请求而发生的其他事件的列表:

  • 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.8. 变量-类扩展机制

BitBake支持两个特性,可以方便地从单个recipe文件创建该recipe文件的多个版本,所有版本都可以构建。这些特性是通过BBCLASSEXTEND和BBVERSIONS变量实现的。
hint

这个类扩展机制的实现是极其特殊的。通常,recipe的PROVIDES、PN和DEPENDS变量需要由扩展类修改。

  • BBCLASSEXTEND:这个变量是一个用空格分隔的类列表,用于“扩展”每个变量的recipe。下面是使得当前recipe的第二个版本可用的示例。这第二个版本将继承“native”类:BBCLASSEXTEND = "native"
  • BBVERSIONS:此变量允许单个recipe从单个recipe文件构建项目的多个版本。你还可以为单个版本指定条件元数据(使用覆盖机制),或者为版本的可选命名范围指定条件元数据。下面是一个例子:
     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"

范围的名称默认为recipe的原始版本。例如,在OpenEmbedded中,菜谱文件foo_1.0.0+.bb创建的默认名称范围为1.0.0+。这很有用,因为范围名不仅被放置到覆盖中,而且还可以让元数据在变量中使用,该变量定义了在file://搜索路径(FILESPATH)中使用的基本recipe版本。

3.9. 依赖

为了考虑到多个并行执行的进程的有效操作,BitBake在任务级别处理依赖关系。BitBake支持一个健壮的方法来处理这些依赖关系。
本节描述几种类型的依赖机制。

3.9.1. .bb文件中的内部依赖

BitBake使用addtask指令来管理给定配方文件内部的依赖关系。可以使用addtask指令指示任务何时依赖于其他任务,或其他任务何时依赖于该recipe。下面是一个例子:

addtask printdate after do_fetch before do_build

在本例中,printdate任务取决于do_fetch任务的完成情况。同时,do_build依赖于printdate任务的完成。

3.9.2. 构建依赖

BitBake使用DEPENDS变量来管理构建时d的依赖关系。任务的“deptask”varflag表示DEPENDS中列出的每个项的任务,该任务必须在执行之前完成。下面是一个例子:

do_configure[deptask] = "do_populate_staging"

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

3.9.3. 运行时依赖

BitBake使用PACKAGES、RDEPENDS和RRECOMMENDS变量来管理运行时依赖关系。
PACKAGES变量列出运行时的包。每个包都可以有RDEPENDS和RRECOMMENDS运行时依赖关系。任务的“rdeptask”标志用于表示每个项目运行时依赖项的任务,在执行该任务之前必须完成该任务。

do_package_write[rdeptask] = "do_package"

在前面的示例中,在do_package_write可以执行之前,RDEPENDS中每个项的do_package任务必须已经完成。

3.9.4. 递归依赖

BitBake使用了“recrdeptask”标志来管理递归任务依赖关系。BitBake查看当前recipe的构建时和运行时依赖关系,查看任务的任务间依赖关系,然后为列出的任务添加依赖关系。一旦BitBake完成了这个任务,它就会递归地处理这些任务的依赖项。迭代传递持续进行,直到发现并添加所有依赖项。
你可能不仅希望使用BitBake查找这些任务的依赖项,还希望使用BitBake查找相关任务的构建时和运行时依赖项。如果是这种情况,你需要在任务列表中引用任务名称本身:

do_a[recrdeptask] = "do_a do_b"
3.9.5. 任务间的依赖关系

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

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

在本例中,目标quilt-native的do_populate_staging任务必须在do_patch任务执行之前完成。
“rdepends”标志以类似的方式工作,但目标在运行时名称空间而不是构建时依赖名称空间。

3.10. 使用Python访问数据存储

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

操作描述
d.getVar(“X”, expand=False)返回变量"X"的值,使用"expand=True"扩展该值
d.setVar(“X”, “value”)为变量"X"赋值"value"
d.appendVar(“X”, “value”)在变量"X"的末尾添加"value"
d.prependVar(“X”, “value”)在变量"X"的最前面添加"value"
d.delVar(“X”)从数据存储中删除变量"X"
d.getVarFlag(“X”, flag, expand=False)从变量"X"中获取已命名的flag,使用"expand=True"扩展这个flag
d.setVarFlag(“X”, flag, “value”)设置变量"X"的已命名的flag为"value"
d.appendVarFlag(“X”, flag, “value”)为"X"的已命名的flag追加"value"
d.prependVarFlag(“X”, flag, “value”)为变量"X"的已命名的flag最前面添加"value"
d.delVarFlag(“X”, flag)从数据存储中删除变量"X"的已命名的flag
d.setVarFlags(“X”, flagsdict)设置在flagsdict()参数中指定的标志。setVarFlags不清除以前的标志。可以将此操作看作addVarFlags。
d.getVarFlags(“X”)返回变量"X"标志的一个flagsdict
d.delVarFlags(“X”)删除变量"X"的全部标志

3.11. 任务校验和与Setscene

BitBake将校验和(或签名)与setscene一起使用,以确定是否需要运行某个任务。本节描述这个过程。为了帮助理解BitBake是如何做到这一点的,本节假设了一个基于OpenEmbedded元数据的示例。
此列表是手册中以前存在的内容的存放位置。部分或全部可能需要集成到组成本节的子节中。现在,我只是为每个变量提供了一个简短的注释式描述。

  • STAMP:创建戳记文件的基路径
  • STAMPCLEAN:同样的,创建戳记文件的基路径,不过可以使用通配符匹配到一组需要清理的文件
  • BB_STAMP_WHITELIST:列出当戳记策略为“whitelist”时要查看的戳记文件
  • BB_STAMP_POLICY:定义戳记文件用于比较时间戳的模式
  • BB_HASHCHECK_FUNCTION:指定在任务执行的“setscene”部分期间调用的函数的名称,以便验证任务哈希列表
  • BB_SETSCENE_VARIFY_FUNCTION:指定要调用的函数,该函数在主任务执行之前验证计划任务执行的列表
  • BB_SETSCENE_DEPVALID:指定一个BitBake调用的函数,该函数确定是否BitBake需要一个要被满足的setscene依赖
  • BB_TASKHASH:在正在执行的任务中,此变量保存当前启用的签名生成器返回的任务哈希

4. 文件下载支持

BitBake的fetch模块是一段独立的库代码,用于处理从远程系统下载源代码和文件的复杂问题。获取源代码是构建软件的基石之一。因此,这个模块构成了BitBake的一个重要部分。
当前的fetch模块称为“fetch2”,它指的是它是API的第二个主要版本。原始版本已经过时,并从代码库中删除了。因此,在本手册中,“fetch”都指“fetch2”。

4.1. 下载(抓取)

BitBake在获取源代码或文件时需要执行几个步骤。fetcher代码基按顺序处理两个不同的过程:从某处(缓存或其他地方)获取文件,然后以特定的方式将这些文件解压缩到特定的位置。获取和解压文件之后通常需要进行补丁。然而,这个模块不涉及补丁。
执行这个过程的第一部分——fetch——的代码如下所示:

     src_uri = (d.getVar('SRC_URI', True) or "").split()
     fetcher = bb.fetch2.Fetch(src_uri, d)
     fetcher.download()

这段代码设置了fetch类的一个实例。该实例使用来自SRC_URI变量的一个空格分隔的url列表,然后调用download方法来下载文件。
fetch类的实例化之后通常是:

     rootdir = l.getVar('WORKDIR', True)
     fetcher.unpack(rootdir)

这个代码解压由WORKDIR指定的下载文件。
hint

为了方便起见,这些示例中的命名与OpenEmbedded使用的变量匹配。

SRC_URI和WORKDIR变量没有编码到fetcher中。这些变量可以(也被)用不同的变量名调用。例如,在OpenEmbedded中,共享状态(sstate)代码使用fetch模块来获取sstate文件。
当download()方法被调用时,BitBake尝试通过以特定的搜索顺序查找源文件来实现url:

  • Pre-mirror Sites:BitBake首先使用pre-mirror来尝试查找源文件。这些位置使用PREMIRRORS变量定义。
  • Source URI:如果pre-mirror失败,BitBake使用原始URL(例如从SRC_URI)
  • Mirror Sites:如果抓取失败发生,BitBake接着使用由MIRRORS变量定义的mirror位置。

对于传递给获取器的每个URL,获取器调用处理特定URL类型的子模块。当你为SRC_URI变量提供url时,这种行为可能会造成一些混淆。考虑以下两个url:

     http://git.yoctoproject.org/git/poky;protocol=git
     git://git.yoctoproject.org/git/poky;protocol=http

在前一种情况下,URL被传递给wget抓取器,它不理解“git”。因此,后一种情况是正确的形式,因为Git获取器知道如何使用HTTP作为传输。
下面是一些常用的镜像定义的例子:

     PREMIRRORS ?= "\
         bzr://.*/.*   http://somemirror.org/sources/ \n \
         cvs://.*/.*   http://somemirror.org/sources/ \n \
         git://.*/.*   http://somemirror.org/sources/ \n \
         hg://.*/.*    http://somemirror.org/sources/ \n \
         osc://.*/.*   http://somemirror.org/sources/ \n \
         p4://.*/.*    http://somemirror.org/sources/ \n \
         svn://.*/.*   http://somemirror.org/sources/ \n"

     MIRRORS =+ "\
         ftp://.*/.*      http://somemirror.org/sources/ \n \
         http://.*/.*     http://somemirror.org/sources/ \n \
         https://.*/.*    http://somemirror.org/sources/ \n"      

需要注意的是,BitBake支持跨cross-URLs。可以将HTTP服务器上的Git存储库镜像为压缩文件。这就是前面示例中的git://映射的作用。
由于网络访问很慢,Bitbake维护了一个从网络下载文件的缓存。任何非本地的源文件(即从互联网下载的)都被放到下载目录中,该目录由DL_DIR变量指定。
文件完整性对于重新生成构建至关重要。对于非本地存档下载,fetcher代码可以验证sha256和md5校验和,以确保存档已被正确下载。你可以使用SRC_URI变量和适当的varflags来指定这些校验和,如下所示:

     SRC_URI[md5sum] = "value"
     SRC_URI[sha256sum] = "value"

你还可以将校验和指定为SRC_URI上的参数,如下所示:

SRC_URI = "http://example.com/foobar.tar.bz2;md5sum=4a8e0f237e961fd7785d19d07fdb994d"

如果存在多个url,可以像前面的示例那样直接指定校验和,也可以命名url。下面的语法展示了如何命名url:

     SRC_URI = "http://example.com/foobar.tar.bz2;name=foo"
     SRC_URI[foo.md5sum] = 4a8e0f237e961fd7785d19d07fdb994d

当一个文件被下载并且检查了它的校验和后,一个".done"的戳记被放在DL_DIR中。BitBake在后续构建过程中使用此戳记,以避免再次下载或比较文件的校验和。
hint

假设本地存储是安全的,不会损坏数据。如果情况不是这样,就会有更大的问题需要担心。

如果设置了BB_STRICT_CHECKSUM,任何没有校验和的下载都会触发错误消息。可以使用BB_NO_NETWORK变量使任何试图进行的网络访问出现致命错误,这对于检查镜像是否完整以及其他事情非常有用。

4.2. 解压

解压过程通常紧随下载之后。对于除Git url之外的所有url, BitBake使用通用的解包方法。
你可以在URL中指定一些参数来控制解压阶段的行为:

  • unpack:控制URL组件是否解压缩。如果设置为“1”(默认值),组件将被解压缩。如果设置为“0”,解压阶段将保持文件不受影响。当您希望将存档复制到其中而不希望解压缩时,此参数非常有用。
  • dos:应用于.zip和.jar文件,并指定是否对文本文件使用DOS行结束转换。
  • basepath:指定解包阶段在解包时从源路径中删除指定的目录。
  • subdir:将特定的URL解包到根目录中的指定子目录。

解包调用会用".Z", “.z”, “.gz”, “.xz”, “.zip”, “.jar”, “.ipk”, “.rpm”. “.srpm”, “.deb” and ".bz2"扩展以及各种压缩包扩展的组合自动解压和抽取文件。
正如前面提到的,Git fetcher有自己的解包方法,经过优化可以使用Git树。基本上,这种方法的工作原理是将树克隆到最终目录中。这个过程是使用引用完成的,因此只需要一个Git元数据的中心副本。

4.3. 抓取器

如前所述,URL前缀决定BitBake使用哪个fetcher子模块。每个子模块可以支持不同的URL参数,这些参数将在下面的部分中进行描述。

4.3.1. 本地文件抓取器(file://)

这个子模块处理以file://开头的url。您在URL中指定的文件名可以是文件的绝对路径或相对路径。如果文件名是相对的,那么使用FILESPATH变量的内容就像使用PATH查找可执行文件一样。如果失败,则使用FILESDIR查找适当的相对文件。
hint

不赞成使用FILESDIR,可以用FILESPATH替换。因为FILESDIR很可能被删除,所以您不应该在任何新代码中使用此变量。

如果找不到该文件,则假定在调用download()方法时DL_DIR中有该文件。
如果指定一个目录,整个目录将被解压缩。
下面是一些例子:

     SRC_URI = "file://relativefile.patch"
     SRC_URI = "file://relativefile.patch;this=ignored"
     SRC_URI = "file:///Users/ich/very_important_software"
4.3.2. CVS抓取器(cvs://)

这个子模块处理从CVS版本控制系统获取文件。您可以使用一些不同的变量配置它:

  • FETCHCMD_cvs:运行cvs命令时要使用的可执行文件的名称。这个名字通常是“cvs”。
  • SRCDATE:获取CVS源代码时要使用的日期。“now”的特殊值会在每个构建中更新checkout。
  • CVSDIR:指定保存临时checkout的位置。这个位置通常是DL_DIR/cvs。
  • CVS_PROXY_HOST:要使用的名字,在cvs命令中作为“proxy=”参数。
  • CVS_PROXY_PORT:要使用的端口号,在cvs命令中作为“proxyport=”参数。

除了标准的用户名和密码URL语法,你也可以配置fetcher的各种URL参数:
支持的参数如下:

  • “method”: 用于与cvs服务器通信的协议。默认情况下,这个协议是“pserver”。如果“method”设置为“ext”,BitBake检查“rsh”参数并设置CVS_RSH。您可以使用“dir”作为本地目录。
  • “module”:指定要下载的模块,你必须提供该参数
  • “tag”:描述应该为下载使用哪些CVS TAG。默认情况下,TAG是空的。
  • “date”:指定一个日期。如果没有指定“日期”,则使用配置的SRCDATE来checkout特定的日期。“now”特殊值导致在每个构建中更新checkout。
  • “localdir”:用于重命名模块。实际上,您正在重命名模块解压缩到的输出目录。您强制将模块置于相对于CVSDIR的特殊目录中。
  • “rsh”:与"method"参数结合使用
  • “scmdata”:当设置为"keep"时,使CVS元数据时在获取程序创建的tarball中进行维护。压缩文件被展开到工作目录中。默认情况下,CVS元数据被删除。
  • “fullpath”:控制结果checkout是在模块级(默认)还是在更深的路径上。
  • “norecurse”:使抓取器只checkout指定的目录,而不递归到任何子目录中。
  • “port”:CVS服务器连接的端口。

一些url的例子如下:

     SRC_URI = "cvs://CVSROOT;module=mymodule;tag=some-version;method=ext"
     SRC_URI = "cvs://CVSROOT;module=mymodule;date=20060126;localdir=usethat"
4.3.3. HTTP/FTP wget抓取器(http://,ftp://,https//)

这个获取器从web和FTP服务器获取文件。在内部,fetcher使用wget实用程序。
使用的可执行文件和参数由FETCHCMD_wget变量指定,该变量默认为合理的值。fetcher支持一个参数“downloadfilename”,它允许指定下载文件的名称。在处理多个具有相同名称的文件时,指定下载文件的名称对于避免DL_DIR中的冲突非常有用。
一些url的例子如下:

     SRC_URI = "http://oe.handhelds.org/not_there.aac"
     SRC_URI = "ftp://oe.handhelds.org/not_there_as_well.aac"
     SRC_URI = "ftp://you@oe.handheld.sorg/home/you/secret.plan"
4.3.4. 子版本(SVN)获取器(svn://)

这个fetcher子模块从Subversion源代码控制系统中获取代码。使用的可执行文件由FETCHCMD_svn指定,默认为“svn”。获取器的临时工作目录是由SVNDIR设置的,通常是DL_DIR/svn。
支持的参数如下:

  • “module”:要checkout svn模块的名字,这个参数必须提供。您可以将此参数视为所需存储库数据的顶级目录。
  • “protocol”:要使用的协议,默认为“svn”。其他选项是“svn+ssh”和“rsh”。对于“rsh”,也使用“rsh”参数。
  • “rev”:要checkout源码的修订版。
  • “date”:要checkout源码的日期。checkout特定的修订版通常比按日期更安全,因为它们不涉及时区(例如,它们更具有确定性)。
  • “scmdata”:当设置为"keep"时,使得".svn"目录在编译期间可以获得。默认情况下,这些目录会被移除。

下面是一些url的例子:

     SRC_URI = "svn://svn.oe.handhelds.org/svn;module=vip;proto=http;rev=667"
     SRC_URI = "svn://svn.oe.handhelds.org/svn/;module=opie;proto=svn+ssh;date=20060126"
4.3.5. GIT抓取器(git://)

这个抓取器子模块从Git源代码控制系统中获取代码。抓取器通过在GITDIR中创建远程文件的裸克隆来工作,它通常是DL_DIR/git。然后在解压阶段check out特定的树时,将这个裸克隆克隆到工作目录中。这是通过使用替代品和引用来实现的,以最小化磁盘上重复数据的数量,并加快解包过程。可以使用FETCHCMD_git设置所使用的可执行文件。
这个抓取器支持以下参数:

  • “protocol”:抓取文件使用的协议。当主机名被设置时默认是"git"。若没有设置,Git协议是"file"。你也可以使用"http",“https”,“ssh”,“rsync”。
  • “nocheckout”:当设置为"1"时,告诉抓取器在解压时不要checkout源码。为有一个自定义流程(要checkout代码)的URL设置这个选项,默认为"0"。
  • “rebaseable”:表示可以重定上游的Git存储库。如果修订可以与分支分离,则应该将此参数设置为“1”。在这种情况下,源镜像压缩是在每次修订时进行的,这会降低效率。重定上游Git存储库可能会导致当前修订从上游存储库中消失。这个选项提醒提取器小心地保留本地缓存以备将来使用。这个参数的默认值是“0”。
  • “nobranch”:告诉抓取器在设置为“1”时不要检查分支的SHA验证。默认值是“0”。为引用对标记有效的提交(而不是对分支有效)的recipe设置此选项。
  • “bareclone”:告诉抓取器在不checkout工作树的情况下将一个裸克隆克隆到目标目录中。只提供原始的Git元数据。此参数也意味着“nocheckout”参数。
  • “branch”:要克隆Git树的分支。若未设置,则假设为"master"。分支参数的数量与名称参数的数量必须匹配。
  • “rev”:为checkout使用的修订版,默认为"master"。
  • “tag”:指定用于checkout的标记。为了正确解析标签,BitBake必须访问网络。因此,标签通常不被使用。就Git而言,“tag”参数的行为实际上与“revision”参数相同。
  • “subpath”:限制checkout到这颗树的特殊子目录下。默认整棵树被checkout。
  • “destsuffix”:要放置checkout的路径的名称。默认情况下,路径是git/。

这有几个url的例子:

     SRC_URI = "git://git.oe.handhelds.org/git/vip.git;tag=version-1"
     SRC_URI = "git://git.oe.handhelds.org/git/vip.git;protocol=http"
4.3.6. 其他抓取器

其他的一些抓取器:

  • Bazaar (bzr://)
  • Perforce (p4://)
  • Git Submodules (gitsm://)
  • Trees using Git Annex (gitannex://)
  • Secure FTP (sftp://)
  • Secure Shell (ssh://)
  • Repo (repo://)
  • OSC (osc://)
  • Mercurial (hg://)

目前没有关于这些较少使用的fetcher子模块的文档。不过,您可能会发现这些代码很有帮助,而且可读性强。

4.4. 自动修订版

详细看 AUTOREV 和 SRCREV_FORMAT

5. 词汇表

Glossary链接

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值