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


说明
本文是博主学习BitBake英文版用户手册时做的记录,由于外语水平有限,难免会有一些翻译错误还望留言区指正。
BitBake User Manual


1. 概述

1.1. 介绍

BitBake是一个通用的任务执行引擎,并且支持shell和python,其主要服务于OpenEmbedded和Yocto,类似于GNU make,用于构建项目,差别主要在于以下几点:

  • BitBake根据用于建立任务的元数据(metadata)执行任务。 元数据存储在recipe(.bb)文件、related recipe “append” (.bbappend)文件、配置文件(.conf)、underlying include 文件(.inc)以及类文件(.bbclass)中。元数据提供给BitBake要执行的任务及其依赖关系。
  • BitBake包括一个fetcher库,用于从各种各样的地方(例如本地文件、源码控制系统或者某个网站)获取源码。
  • 每个要构建的单元的所有指令被称作 “recipe” 文件,其包含了该单元的全部信息(依赖关系,源码位置,校验数,描述,…)。
  • BitBake有一个client/server抽象,因此使用起来很灵活,既可以通过命令行的方式使用,也可以使用XML-RPC(一种远程调用机制)将其作为一个服务器使用,并且它有不同的用户接口。

1.2. 历史和目标

BitBake原先是OpenEmbedded项目的一部分,灵感来自于Gentoo Linux发行版的Portage包管理器。在2004年12月7日,OpenEmbedded项目团队成员Chris Larson将该项目单独分为两个部分:

  • BitBake, 一个通用的任务执行器
  • OpenEmbedded, 一个供BitBake使用的元数据集

现在,BitBake是OpenEmbedded项目的主要基础,该项目用于构建和维护Linux发行版,比如Angstrom发行版,它也被用作Yocto项目等Linux项目的构建工具。在BitBake之前,没有构建工具能够充分地满足嵌入式Linux发行版的需要。传统桌面Linux发行版使用的所有构建系统都缺乏重要的功能,嵌入式领域流行的基于Buildroot的特别系统都没有可伸缩性或可维护性。
BitBake的主要目标有如下几点:

  • 处理交叉编译
  • 处理包间的依赖关系(目标架构上构建时、本机架构上构建时和运行时的依赖关系)
  • 支持在给定包中运行任意数量的任务,包括但不限于获取上游源、解压缩源、打补丁、配置源等等
  • 对构建系统和目标系统都不固定Linux发行版
  • 对架构没有限制
  • 支持多个构建和目标操作系统(例如Cygwin、BSDs等等)
  • 自包含,而不是紧密集成到构建机器的根文件系统中
  • 处理目标体系结构、操作系统、发行版和机器上的符合条件的元数据
  • 易于使用这些工具来提供要操作的本地元数据和包
  • 易于使用BitBake在多个项目之间协作构建
  • 提供一种继承机制来在许多包之间共享公共元数据

随着时间的推移,显然需要进一步的要求:

  • 处理base recipe的变量(例如native、sdk 和 multilib)
  • 将元数据分割成layers,并允许layers增强或覆盖其他layers
  • 允许将一组给定的输入变量表示为任务的校验和。基于该校验和,允许使用预构建组件加速构建

1.3. 概念

BitBake是由Python编写的一个程序。在最高层,BitBake解释元数据,决定那个任务需要被运行以及执行那些任务。类似于GNU Make,BitBake控制软件怎样被构建。GNU Make 由makefiles来实现控制,同时BitBake使用 recipes。
BitBake扩展了像GNU Make简单工具的能力,允许定义更复杂的任务,例如组装Linux发行版。

1.3.1. Recipes

Recipes是最基本的元数据文件,后缀为.bb,其为BitBake提供了如下内容:

  • 关于包的描述信息(作者,主页,许可证,…)
  • recipe的版本
  • 存在的依赖关系(构建以及运行时的依赖关系)
  • 源码存放的位置及获取方式
  • 源码是否需要补丁,去哪找它,以及怎样使用
  • 怎样配置和编译源码
  • 在目标机哪去安装包或已创建的包
1.3.2. 配置文件(Configuration Files)

配置文件定义了用于管理构建过程的各种各样的配置变量,后缀为.conf。这些配置文件有这几个种类,它们分别定义了机器配置选项、发行版配置选项、编译优化选项、一般公共配置选项以及用户配置选项。主配置文件是单个bitbake.conf文件,其位于BitBake源码树的conf文件夹中。

1.3.3. 类(Classes)

类文件包含了一些信息,这些信息对于元数据文件之间的共享是有用的,其后缀为.bbclass。目前BitBake源码树自带一个类元数据文件base.bbclass,位于classes文件夹下。这个文件是特殊的,因为它被所有recipe和class所包含。这个类包含了一些标准基本任务的定义,例如获取,解压,配置(默认为空),编译(运行现有的任意Makefile),安装(默认为空)以及打包(默认为空)。在项目开发过程中,这些任务经常被已添加的类覆盖或者扩展。

1.3.4. 层(Layers)

Layers允许你将彼此间不同类型的自定义隔离开。尽管将所有东西放在一个层中这种做法很诱人,但如果你将元数据组织为更多的模块,那么应对将来的改变就越简单。
为了阐述你可以怎样使用layers去将这些东西模块化,考虑可能用去支持一个特殊目标机的自定义。这些类型的自定义通常驻留在一个特殊的层中,而不是称为板级支持包(BSP)层的通用层。此外,机器自定义应该与recipe和元数据隔离,例如支持新的GUI环境。这种情况为您提供了两个层:一个用于机器配置,另一个用于GUI环境。但是,重要的是要理解,在GUI环境层中,BSP层仍然可以对recipes进行特定于机器的添加,而不会由于这些改变污染GUI层本身。你可以通过一个recipe,即一个BitBake append(.bbappend)文件实现上述内容。

1.3.5. 追加文件(Append Files)

Append文件扩展或者覆盖现有recipe文件的信息,其后缀为.bbappend。BitBake希望每个append文件都可以有一个对应的recipe文件。此外,append文件与对应的recipe文件必须使用相同的根文件名,它们只有后缀有差异(例如formfactor_0.0.bb与formfactor_0.0.bbappend)。
在你命名一个append文件的时候,通配符(%)是允许使用的,例如busybox_1.21.%.bbappend可以匹配任意busybox_1.21.x.bbappend文件。如果recipe更新为busybox_1.3.0.bb,那么这个append文件将不会匹配。但是,如果将append文件命名为busybox_1.%.bbappend,这时将可以匹配这个recipe文件。在最一般的情况下,将append文件命名为busybox_%.bbappend将匹配所有版本的recipe文件。

1.4. 安装BitBake

Cloning BitBake(推荐)
在选择版本的时候应该与你正在使用的元数据版本匹配,通常向后兼容而不是向前兼容,命令如下:

$ git clone git://git.openembedded.org/bitbake

这个命名会创建一个名为bitbake的目录,并将bitbake仓库放在该目录下,若不想将该目录命名为bitbake,而是想指定名称xxx,可以使用如下命令:

$ git clone git://git.openembedded.org/bitbake xxx

利用发行版的包管理系统安装(不推荐)

从源码仓库下载压缩包
以 BitBake 1.17.0为例,命令如下:

$ wget http://git.openembedded.org/bitbake/snapshot/bitbake-1.17.0.tar.gz
$ tar zxpvf bitbake-1.17.0.tar.gz

使用你的Build Checkout自带的BitBake
一般在一些大型的基于Bitbake的项目都会自带bitbake,例如(Poky或者Yocto Project)。

1.5. BitBake 命令

1.5.1. 用法&语法
$ bitbake -h
     Usage: bitbake [options] [recipename/target recipe:do_task ...]

         Executes the specified task (default is 'build') for a given set of target recipes (.bb files).
         It is assumed there is a conf/bblayers.conf available in cwd or in BBPATH which
         will provide the layer, BBFILES and other configuration information.

     Options:
       --version             show program's version number and exit
       -h, --help            show this help message and exit
       -b BUILDFILE, --buildfile=BUILDFILE
                             Execute tasks from a specific .bb recipe directly.
                             WARNING: Does not handle any dependencies from other
                             recipes.
       -k, --continue        Continue as much as possible after an error. While the
                             target that failed and anything depending on it cannot
                             be built, as much as possible will be built before
                             stopping.
       -a, --tryaltconfigs   Continue with builds by trying to use alternative
                             providers where possible.
       -f, --force           Force the specified targets/task to run (invalidating
                             any existing stamp file).
       -c CMD, --cmd=CMD     Specify the task to execute. The exact options
                             available depend on the metadata. Some examples might
                             be 'compile' or 'populate_sysroot' or 'listtasks' may
                             give a list of the tasks available.
       -C INVALIDATE_STAMP, --clear-stamp=INVALIDATE_STAMP
                             Invalidate the stamp for the specified task such as
                             'compile' and then run the default task for the
                             specified target(s).
       -r PREFILE, --read=PREFILE
                             Read the specified file before bitbake.conf.
       -R POSTFILE, --postread=POSTFILE
                             Read the specified file after bitbake.conf.
       -v, --verbose         Output more log message data to the terminal.
       -D, --debug           Increase the debug level. You can specify this more
                             than once.
       -n, --dry-run         Don't execute, just go through the motions.
       -S SIGNATURE_HANDLER, --dump-signatures=SIGNATURE_HANDLER
                             Dump out the signature construction information, with
                             no task execution. The SIGNATURE_HANDLER parameter is
                             passed to the handler. Two common values are none and
                             printdiff but the handler may define more/less. none
                             means only dump the signature, printdiff means compare
                             the dumped signature with the cached one.
       -p, --parse-only      Quit after parsing the BB recipes.
       -s, --show-versions   Show current and preferred versions of all recipes.
       -e, --environment     Show the global or per-recipe environment complete
                             with information about where variables were
                             set/changed.
       -g, --graphviz        Save dependency tree information for the specified
                             targets in the dot syntax.
       -I EXTRA_ASSUME_PROVIDED, --ignore-deps=EXTRA_ASSUME_PROVIDED
                             Assume these dependencies don't exist and are already
                             provided (equivalent to ASSUME_PROVIDED). Useful to
                             make dependency graphs more appealing
       -l DEBUG_DOMAINS, --log-domains=DEBUG_DOMAINS
                             Show debug logging for the specified logging domains
       -P, --profile         Profile the command and save reports.
       -u UI, --ui=UI        The user interface to use (depexp, goggle, hob, knotty
                             or ncurses - default knotty).
       -t SERVERTYPE, --servertype=SERVERTYPE
                             Choose which server type to use (process or xmlrpc -
                             default process).
       --token=XMLRPCTOKEN   Specify the connection token to be used when
                             connecting to a remote server.
       --revisions-changed   Set the exit code depending on whether upstream
                             floating revisions have changed or not.
       --server-only         Run bitbake without a UI, only starting a server
                             (cooker) process.
       -B BIND, --bind=BIND  The name/address for the bitbake server to bind to.
       --no-setscene         Do not run any setscene tasks. sstate will be ignored
                             and everything needed, built.
       --remote-server=REMOTE_SERVER
                             Connect to the specified server.
       -m, --kill-server     Terminate the remote server.
       --observe-only        Connect to a server as an observing-only client.
       --status-only         Check the status of the remote bitbake server.
       -w WRITEEVENTLOG, --write-log=WRITEEVENTLOG
                             Writes the event log of the build to a bitbake event
                             json file. Use '' (empty string) to assign the name
                             automatically.
1.5.2. 实例
1.5.2.1. 对单个Recipe执行任务

在确定了一个recipe文件后,即可使用BitBake去解析它,同时执行这个确定的任务。如果没有明确任务,BitBake执行默认的任务,即构建。BitBake会遵循任务间的依赖关系,下面一个命令会运行一个默认任务(构建recipe文件):

$ bitbake -b foo_1.0.bb

下面这个命令在foo.bb文件上执行清理命令:

 $ bitbake -b foo.bb -c clean

"-b"选项用于指定要构建的recipe文件,一般用于调试单个文件,不会处理recipe文件之间的依赖关系;“-c”用于指定执行的任务,默认是构建。

1.5.2.2. 对一组Recipe执行任务

在不使用“-b”时,bitbake命令只接受一个“PROVIDES”。默认情况下,一个recipe文件一般会提供它的包名,如下所示:

$ bitbake foo

下面的例子提供了包名,并且只执行清理任务:

$ bitbake -c clean foo
1.5.2.3. 生成依赖图

BitBake能使用dot语法生成依赖图,通过dot工具Graphviz可以将其转化为图。在生成依赖图时,BitBake会在当前目录下写四个文件:

  • package-depends.dot:展示运行时的依赖关系
  • pn-depends.dot:展示构建时的依赖关系
  • task-depends.dot:展示任务间的依赖关系
  • pn-buildlist:展示要构建目标的一个列表

要停止依赖于公共依赖,使用“-I”依赖选项,BitBake将会把它们从图中省略。省略这些信息可以生成更可读的图表。这样,你就可以从图DEPENDS中删除继承类,比如base.bbclass。下面是两个创建依赖图的例子,第二个从图中忽略了对OpenEmbedded的公共依赖:

$ bitbake -g foo
$ bitbake -g -I virtual/kernel -I eglibc foo

2. 执行

运行BitBake的主要目的是生成某种输出,比如一个简单的安装包、一个内核、一个软件开发工具包,甚至是一个完整的、特定板的、可启动的Linux镜像,包括引导加载程序、内核和根文件系统。当然,您可以使用选项执行bitbake命令,使其执行单个任务、编译单个recipe文件、捕获或清除数据,或者简单地返回关于执行环境的信息。
这一章节描述在你使用BitBake创建镜像时的一个从开始到结束的执行过程。执行过程使用下面的命令启动:

$ bitbake target

关于多线程执行:
在执行BitBake之前,你应该在项目的local.conf配置文件中设置BB_NUMBER_THREADS变量,来利用构建主机上可用的并行线程执行。
要确定此值的一种常见方法是运行以下命令:

$ grep processor /proc/cpuinfo

这个命令返回考虑到多线程的处理器数量。因此,多线程的四核构建主机最有可能显示8个处理器,这是你之后要分配给BB_NUMBER_THREADS的值。
一个可能更简单的方法是使用Linux发行版(例如Debian或者Ubuntu)的ncpus命令。

2.1. 解析基本的配置元数据

BitBake做的第一件事是解析基本配置元数据。基本配置元数据包括你的项目的bblayers .conf文件(用于确定BitBake需要识别哪些层)、所有必要的layer.conf文件(每层一个)和bitbake.conf文件。数据本身有各种类型:

  • Recipes: 特定软件的一些细节
  • Class Data: 公共构建信息的一个抽象(例如怎样构建一个Linux内核)
  • Configuration Data:特定机器的设置,策略决策和其他。相当于粘合剂将所有东西绑定在一块

layer.conf文件用于建立关键变量,例如BBPATH和BBFILES。BBPATH被用于搜索conf和classes文件夹下的所有配置文件和类文件。BBFILES被用于定位 recipe和recipe append文件。若没有bblayers.conf文件,那么默认用户在环境变量中设置了BBPATH和BBFILES。
接着,通过BBPATH定位到bitbake.conf文件。这个文件也有可能通过使用include或者require之间包含其他配置文件。
在解析配置文件之前,BitBake会查看某些变量,包括:BB_ENV_WHITELIST,BB_ENV_EXTRAWHITE,BB_PRESERVE_ENV,BB_ORIGENV,BITBAKE_UI。前四个变量与BitBake在任务执行期间怎样对待环境变量相关。默认情况下,BitBake清除环境变量并且提供对shell执行环境的严格控制。但是,通过使用这前四个变量,你可以对执行任务期间shell中BitBake允许使用的环境变量进行控制。
基本配置元数据是全局的,因此它可以影响全部的recipe和被执行的任务。
BitBake先从当前工作目录中搜索一个可选的conf/bblayers.conf配置文件。这个文件应该包含一个BBLAYERS变量,它是一个以空格分隔的“layer”目录列表。回想一下,如果BitBake找不到bblayers.conf文件,则假定用户已经在环境变量中直接设置了BBPATH和BBFILES变量。
对于这个列表中的每个目录(层),都有一个conf/layer.conf文件,并被解析,同时将LAYERDIR变量设置为该层所在的目录。其思想是,这些文件自动为给定的构建目录正确地设置BBPATH和其他变量。
BitBake期望在用户指定的BBPATH中找到conf/bitbake.conf文件。该配置文件通常包含用于拉入任何其他元数据的指令,比如特定于体系结构、机器、本地环境变量等。
在BitBake配置文件中只允许变量定义和包含指令。一些变量直接影响BitBake的行为。根据前面提到的环境变量或在配置文件中设置的环境变量,可能已经在环境中设置了这些变量。
解析配置文件之后,BitBake使用它的基本继承机制(通过类文件)来继承一些标准类。当遇到负责获取该类的继承指令时,BitBake解析该类。
base.bbclass文件总是包含在内。在配置中使用INHERIT变量指定的其他类也会被包含。BitBake在BBPATH路径下的classes子目录中搜索类文件,方法与配置文件相同。
要了解执行环境中使用的配置文件和类文件,一个好方法是运行以下BitBake命令:

$ bitbake -e > mybb.log

之后你可以在mybb.log文件中看到许多在你执行环境下的配置文件及类文件。

注意:
你需要知道BitBake是如何解析花括号的,如果recipe文件在函数中使用右花括号,并且字符没有前导空格,则BitBake会产生解析错误。如果在shell函数中使用一对大括号,那么右大括号不能位于没有前导空格的行首。下面是一个例子:

	fakeroot create_shar() {
         cat << "EOF" > ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
     usage()
     {
       echo "test"
       ###### The following "}" at the start of the line causes a parsing error ######
     }
     EOF
     }
               
     fakeroot create_shar() {
         cat << "EOF" > ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
     usage()
     {
       echo "test"
       ######The following "}" with a leading space at the start of the line avoids the error ######
      }
     EOF
     }

2.2. 定位解析Recipes

在配置阶段,BitBake将设置BBFILES。BitBake现在使用它构造要解析的recipe列表,以及要应用的任何append文件(.bbappend)。BBFILES是一个以空格分割的可获得文件的列表,且支持通配符,例如:

BBFILES = "/path/to/bbfiles/*.bb /path/to/appends/*.bbappend"

BitBake解析每个由BBFILES定位到的recipe及append文件,并将各个变量的值存入datastore中。

注意

append文件以它们在BBFILES中出现的顺序被应用。

对于每个文件,先对基本配置做一个拷贝,然后逐行解析recipe。任何继承语句都会导致BitBake使用BBPATH作为搜索路径来查找并解析类文件(.bbclass)。最后,BitBake按顺序解析在BBFILES中找到的所有append文件。
一种常见的习惯是使用recipe文件名来定义元数据片段。例如,在bitbake.conf中,使用recipe名称和版本号来设置变量PN和PV:

 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'}"

在这个例子中,一个名称为"something_1.2.3.bb"的recipe将会设置PN为"something",PV为“1.2.3”。
在完成对recipe的解析之后,BitBake有了recipe定义的一系列任务、一组由键和值组成的数据以及关于这些任务的依赖信息。
BitBake不需要所有这些信息。它只需要信息的一个小子集就可以做出关于recipe的决策。因此,BitBake只缓存它感兴趣的值,而不存储其余的信息。实验表明,重新解析元数据要比尝试将其写入磁盘然后重新加载更快。
在可能的情况下,后续的BitBake命令会重用recipe信息的缓存。这个缓存的有效性是通过首先计算基本配置数据的校验和(参见BB_HASHCONFIG_WHITELIST),然后检查校验和是否匹配来确定的。如果校验和与缓存中的内容匹配,并且recipe和类文件没有更改,Bitbake就可以使用缓存。BitBake会重新加载缓存的recipe信息,而不是从头开始解析。
recipe文件集合允许用户拥有包含相同包的.bb文件的多个存储库。For example, one could easily use them to make one’s own local copy of an upstream repository, but with custom modifications that one does not want upstream.这有一个例子:

	BBFILES = "/stuff/openembedded/*/*.bb /stuff/openembedded.modified/*/*.bb"
    BBFILE_COLLECTIONS = "upstream local"
    BBFILE_PATTERN_upstream = "^/stuff/openembedded/"
    BBFILE_PATTERN_local = "^/stuff/openembedded.modified/"
    BBFILE_PRIORITY_upstream = "5"
    BBFILE_PRIORITY_local = "10"

Hint

层机制现在是collecting code的首选方法。虽然保留了collecting code,但它的主要用途是设置层的优先级和处理层之间的重叠(冲突)。

2.3. 提供者

假设已经指示BitBake执行一个目标,并且所有的recipe文件都已解析,BitBake开始计算如何构建目标。BitBake查看每个recipe的PROVIDES列表。PROVIDES列表是可以知道recipe的名称列表。每个recipe的PROVIDES列表是通过recipe的PN变量隐式地,以及recipe的PROVIDES变量显式地创建,后者是可选的。
当recipe使用PROVIDES时,除了隐式PN名称之外,该recipe的功能还可以在替代名称或者名称列表中找到。例如,假设有一个名为keyboard_1.0.bb的recipe包含以下内容:

PROVIDES += "fullkeyboard"

此时,PROVIDES列表会隐式的变为"keyboard",并且显式地变为"fullkeyboard"。结果就是,keyboard_1.0.bb的功能可以用两种不同的名字找到。

2.4. 首选项

“PROVIDES”列表只是找出目标recipe解决方案的一部分。因为目标可能有多个提供者,BitBake需要通过确定提供者首选项来对提供者进行优先级排序。
目标具有多个提供者的常见示例是“virtual/kernel”,它位于每个内核recipe的PROVIDES列表中。每台机器通常通过在机器配置文件中使用类似如下行来选择最好的内核提供程序:

PREFERRED_PROVIDER_virtual/kernel = "linux-yocto"

默认的PREFERRED_PROVIDER是与目标名称相同的提供程序。Bitbake通过这个程序迭代需要构建和解析的每个目标及其依赖关系。
一个给定的提供程序可能存在多个版本,这使得理解如何选择提供程序变得复杂。BitBake默认为提供商的最高版本。版本比较的方法与Debian相同。你可以使用PREFERRED_VERSION变量来指定特定的版本。你可以使用DEFAULT_PREFERENCE变量来影响顺序。
默认情况下,文件的首选项为“0”。将DEFAULT_PREFERENCE设置为“-1”将导致recipe不可能被使用,除非它被显式引用。将DEFAULT_PREFERENCE设置为“1”使得该recipe可能会被使用。PREFERRED_VERSION覆盖所有DEFAULT_PREFERENCE设置。DEFAULT_PREFERENCE通常用于标记较新的和不稳定的recipe版本,直到它们经过了充分的测试,被认为是稳定的。
如果一个recipe有多个“版本”,BitBake默认选择最新版本,除非另有说明。如果所讨论的recipe的DEFAULT_PREFERENCE设置低于其他recipe(默认值为0),那么它将不会被选中。这允许维护菜谱文件存储库的人员指定他们对所选默认版本的首选项。此外,用户可以指定他们的首选版本。
如果第一个recipe命名为a_1.1.bb,那么PN变量将被设置为“a”,PV变量将被设置为1.1。因此,如果一个名为a_1.2.bb的recipe存在,BitBake默认选择1.2。但是,如果你在BitBake解析的.conf文件中定义了下面这个变量,你可以改变这个参数:

 PREFERRED_VERSION_a = "1.1"

Hint

Recipe通常提供两个版本——稳定的、编号的(首选的)版本,和从源代码存储库自动导出的版本,后者被认为更“前沿”,但只能显式地选择。例如,在OpenEmbedded代码中,有一个BusyBox的标准版本recipe文件busybox_1.22.1.bb,但是也有一个基于git的版本busybox_git.bb,它显式地包含 DEFAULT_PREFERENCE = " -1 "。为了确保有编号的稳定版本总是首选,除非开发人员显式地选择否则默认使用带有编号的版本。

2.5. 依赖

每个目标BitBake构建包含多个任务,如获取、解包、修补、配置和编译。为了在多核系统上获得最佳性能,BitBake将每个任务视为具有自己依赖集的独立实体。
依赖关系是通过几个变量定义的。在基本的层次上,知道BitBake在计算依赖关系时使用DEPENDS和RDEPENDS变量就足够了。

2.6. 任务列表

根据提供者的生成列表及依赖信息,BitBake现在可以精确的计算它需要执行什么任务以及以何种顺序运行它们。
构建开始时,BitBake将复制线程,直到达到BB_NUMBER_THREADS变量中设置的限制值。只要有任务准备运行,且这些任务的依赖关系被满足,且没有超过线程阈值,BitBake就会继续拷贝线程。
值得注意的是,通过正确设置BB_NUMBER_THREADS变量,可以大大加快构建时间。
当每个任务完成时,时间戳被写入到STAMP变量指定的目录中。在随后的运行中,BitBake会查看tmp/ stamps中的构建目录,并且不会重新运行已经完成的任务,除非发现时间戳无效。目前,仅针对每个recipe文件考虑无效的时间戳。例如,如果配置戳的时间戳大于给定目标的编译时间戳,则编译任务将重新运行。但是,再次运行编译任务对依赖于该目标的其他提供程序没有影响。
戳的确切格式是可以部分配置的。在BitBake的最新版本中,hash被附加到戳记上,这样如果配置发生变化,戳记就会失效,任务会自动重新运行。使用的哈希或签名由配置的签名策略管理。还可以使用“stamp-extra-info”任务标志向戳记追加额外的元数据。例如,OpenEmbedded使用这个标志使一些任务机器特定化。

注意
一些任务被标记为“nostamp”任务。运行这些任务时不会创建时间戳文件。因此,总是会重新运行“nostamp”任务。

2.7. 执行任务

任务可能是一个shell任务也有可能是一个python任务,Bitbake会将一个shell脚本写到 T / r u n . d o t a s k n a m e . p i d 中 , 然 后 执 行 这 个 脚 本 。 这 个 生 成 的 脚 本 包 含 全 部 的 导 出 变 量 以 及 s h e l l 函 数 ( 其 变 量 已 全 部 展 开 ) s h e l l 脚 本 的 输 出 会 写 入 {T}/run.do_taskname.pid中,然后执行这个脚本。这个生成的脚本包含全部的导出变量以及shell函数(其变量已全部展开)shell脚本的输出会写入 T/run.dotaskname.pidshellshell{T}/log.do_taskname.pid中。查看运行文件中的扩展shell函数和日志文件中的输出是一种有用的调试技术。
对于Python任务,BitBake在内部执行任务并将信息记录到控制终端。BitBake的未来版本将以类似于处理shell任务的方式将函数写入文件。日志记录的处理方式也类似于shell任务。
BitBake运行任务的顺序由其任务调度程序控制。配置调度程序并为特定用例定义自定义实现是可能的。有关更多信息,请参见控制这些行为的这些变量:BB_SCHEDULER,BB_SCHEDULERS。
可以在任务的主函数之前或之后运行函数。这是使用列出要运行的函数的任务的“prefuncs”和“postfuncs”标志来完成的。

2.8. 校验和(签名)

校验和是任务输入的唯一签名。任务的签名可用于确定是否需要运行任务。由于触发运行任务的是任务输入中的更改,所以BitBake需要检测给定任务的所有输入。对于shell任务,这是相当容易的,因为BitBake为每个任务生成一个“运行”shell脚本,并且可以创建一个校验和,让您了解任务的数据何时发生变化。
为了使问题复杂化,一些东西不应该包含在校验和中。首先,有给定任务的实际指定构建路径—工作目录。工作目录是否更改并不重要,因为它不应该影响目标包的输出。排除工作目录的简单方法是将其设置为某个固定值,并为“run”脚本创建校验和。BitBake做得更好,它使用BB_HASHBASE_WHITELIST变量来定义在生成签名时不应该包含的变量列表。
另一个问题来自运行脚本包含可能被调用也可能不会被调用的函数。增量构建解决方案包含找出shell函数之间依赖关系的代码。这段代码用于将“运行”脚本精简到最小集,从而缓解了这个问题,并提高了“运行”脚本的可读性。
到目前为止,我们已经有了shell脚本的解决方案。那么Python任务呢?即使这些任务比较困难,也可以采用同样的方法。这个过程需要弄清楚Python函数访问什么变量,调用什么函数。同样,增量构建解决方案包含的代码首先计算出变量和函数依赖关系,然后为用作任务输入的数据创建校验和。
与工作目录情况类似,存在应该忽略依赖关系的情况。对于这些情况,您可以使用如下代码行指示构建过程忽略依赖项:

PACKAGE_ARCHS[vardepsexclude] = "MACHINE"

这个例子确保了PACKAGE_ARCHS变量不依赖于MACHINE的值,即使它的确引用了MACHINE的值。
同样,在某些情况下,我们需要添加BitBake无法找到的依赖项。你可以使用如下的代码来完成这个任务:

PACKAGE_ARCHS [vardeps] = "MACHINE"

这个示例显式地添加了MACHINE变量作为PACKAGE_ARCHS的依赖项。
例如,考虑一个内联Python的情况,BitBake不能计算出依赖关系。在调试模式下运行时(即使用-DDD), BitBake会在发现某些无法确定依赖关系的内容时产生输出。
到目前为止,本节的讨论仅限于对任务的直接输入。基于直接输入的信息在代码中称为“basehash”。然而,任务的间接输入仍然存在问题——已经构建并出现在构建目录中的内容。特定任务的校验和(或签名)需要添加该特定任务所依赖的所有任务的哈希值。选择要添加的依赖项是一个策略决策。但是,其效果是生成一个主校验和,该校验和由basehash和任务依赖项的哈希组成。
在代码级别,可以通过多种方式影响基散列和依赖任务的散列。在BitBake配置文件中,我们可以给BitBake一些额外的信息来帮助它构造基哈希。下面的语句会有效地产生一列全局变量依赖关系排除—这些变量从未包含在任何校验和中。这个例子使用了来自OpenEmbedded的变量来帮助说明这个概念:

BB_HASHBASE_WHITELIST ?= "TMPDIR FILE PATH PWD BB_TASKHASH BBPATH DL_DIR \
         SSTATE_DIR THISDIR FILESEXTRAPATHS FILE_DIRNAME HOME LOGNAME SHELL TERM \
         USER FILESPATH STAGING_DIR_HOST STAGING_DIR_TARGET COREBASE PRSERV_HOST \
         PRSERV_DUMPDIR PRSERV_DUMPFILE PRSERV_LOCKDOWN PARALLEL_MAKE \
         CCACHE_DIR EXTERNAL_TOOLCHAIN CCACHE CCACHE_DISABLE LICENSE_PATH SDKPKGSUFFIX"

前面的例子排除了工作目录,这是TMPDIR的一部分。
确定通过依赖链包含哪些依赖任务散列的规则更为复杂,通常使用Python函数来完成。 meta/lib/oe/sstatesig.py 中的代码展示了两个这样的示例,还演示了如果需要,如何将自己的策略插入到系统中。这个文件定义了OpenEmbedded核心使用的两个基本签名生成器:“OEBasic”和“OEBasicHash”。默认情况下,BitBake中启用了一个虚拟的“noop”签名处理程序。这意味着行为与以前的版本没有改变。在默认情况下,OE-Core通过在bitbake.conf文件中的设置使用“OEBasicHash”签名处理器:

BB_SIGNATURE_HANDLER ?= "OEBasicHash"

“OEBasicHash”BB_SIGNATURE_HANDLER与“OEBasic”版本相同,只是将任务散列添加到戳文件中。这会导致全部元数据改变任务哈希,自动造成任务再次运行。这样就不需要增加PR值,并且对元数据的更改会在构建过程中自动发生变化。
还值得注意的是,这些签名生成器的最终结果是使一些依赖项和散列信息对构建可用。这些信息包括:

  • BB_BASEHASH_task-< taskname > : recipe中每个任务的基哈希
  • BB_BASEHASH_< filename:taskname >: 每个依赖任务的基哈希
  • BBHASHDEPS_< filename:taskname >: 每个任务的依赖任务
  • BB_TASKHASH: 当前运行任务的哈希

值得注意的是,BitBake的“-S”选项允许您调试BitBake对签名的处理。传递给-S的选项允许使用不同的调试模式,可以使用BitBake自己的调试函数,也可以使用元数据/签名处理程序本身中定义的调试函数。传递的最简单参数是“none”,它会导致将一组签名信息写入到指定目标相对应的STAMP_DIR中。另一个当前可用的参数是“printdiff”,它导致BitBake试图建立最接近的签名匹配(例如在sstate缓存中),然后在匹配项上运行bitbaker-diffsigs,以确定这两个戳记树发散处的戳记和增量。

hint
在BitBake未来的版本中,有可能提供其他由“-S”选项触发的签名处理程序。

2.9. Setscene

setscene进程使BitBake能够处理“预构建”的工件。处理和重用这些工件的能力使BitBake不必每次都从头构建东西。相反,如果可能的话,BitBake可以使用现有的构建工件。
BitBake需要可靠的数据来指示工件是否兼容。签名(在前一节中描述)提供了一种表示工件是否兼容的理想方法。如果签名相同,则可以重用对象。
如果对象可以重用,那么问题就变成了如何用预构建的构件替换给定的任务或一组任务。BitBake通过“setscene”流程解决了这个问题。
当BitBake被要求构建一个给定的目标时,在构建任何内容之前,它首先会询问缓存的信息对于它正在构建的任何目标或任何中间目标是否可用。如果缓存的信息可用,BitBake将使用该信息而不是运行主任务。
BitBake首先调用由BB_HASHCHECK_FUNCTION变量定义的函数,该函数带有任务列表和需要构建的相应散列。这个函数被设计为快速并返回一个任务列表,它相信可以从中获得工件。
接下来,对于作为可能性返回的每个任务,BitBake执行可能工作覆盖的任务的setscene版本。任务的Setscene版本将字符串"_setscene"附加到任务名称中。例如,名为xxx的任务有一个名为xxx_setscene的setscene任务。该任务的setscene版本执行,并会提供返回成功或失败的必要工件。
正如前面提到的,一个工件可以覆盖多个任务。例如,如果您已经有已编译的二进制文件,那么获取编译器是毫无意义的。为了处理这个问题,BitBake为每个成功的setscene任务调用BB_SETSCENE_DEPVALID函数,以知道它是否需要获得该任务的依赖项。
最后,在所有的setscene任务执行完毕后,BitBake调用BB_SETSCENE_VERIFY_FUNCTION中列出的函数,该函数包含BitBake认为已经“覆盖”的任务列表。然后元数据可以确保这个列表是正确的,并可以通知BitBake它希望运行特定的任务,而不管setscene的结果如何。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值