15 使用 Multiconfig 为多个目标构建镜像
可以用一条 bitbake 命令,为不同目标构建多个镜像或软件包,每个镜像或
软件包采用不同配置。这种多配置构建也称为 "multiconfig",本节沿用这一术语。
本节介绍如何设置多配置构建,以及如何处理不同 multiconfig 之间的跨构建依赖。
15 设置并运行多配置构建
进行多配置构建时,必须在 Build Directory 或层的配置目录中,使用 并列的 configuration file 分别定义每个目标的配置,并遵循规定的 文件层级。此外,还必须在 build/conf/local.conf 中启用 多配置构建。
按以下步骤设置和执行:
创建独立配置文件: 为每个构建目标,即每个 multiconfig,创建一个 Configuration File。配置内容取决于具体实现,通常会定义 MACHINE 和 BitBake 构建使用的临时目录 TMPDIR。
备注
能否共享 TMPDIR,取决于配置之间的相同点和差异。只要其他配置 一致,多个 MACHINE 目标可以共享同一个 TMPDIR;不同 DISTRO 设置则需要独立的 TMPDIR。
例如,同一个 MACHINE "qemux86" 分别使用 "poky" 和 "poky-lsb" 两个发行版构建时,必须使用两个不同的 TMPDIR。
一般而言,强烈建议不同 multiconfig 使用独立 TMPDIR。
配置文件必须放在当前 Build Directory 的
conf/multiconfig子目录中,或者 Layer 的conf/multiconfig目录中。下例为 "x86" 和 "arm" 两个 multiconfig 定义配置文件:
与其他配置文件类似,使用通常的 BBPATH 搜索路径定位 multiconfig 文件。
以下
qemux86.confconfiguration file 展示了qemux86目标所需的最少语句,临时构建目录为tmp-qemux86:MACHINE = "qemux86" TMPDIR .= "-${BB_CURRENT_MC}"
BitBake 将 BB_CURRENT_MC 展开为当前使用的 multiconfig 名称。 将其追加到 TMPDIR,可以使 TMPDIR 定义的任何变化自动 影响各 multiconfig 的临时目录。
向本地配置文件添加 BitBake 多配置变量: 在 build/conf/local.conf 中使用 BBMULTICONFIG 指定各 multiconfig。延续上图示例,需要指定两个配置文件以启用 "x86" 和 "arm":
BBMULTICONFIG = "x86 arm"
备注
默认配置始终存在,名称为 "",即空字符串,由 build/conf/local.conf 中的变量定义。因此,上例实际 是在 "" 之外增加了 "arm" 和 "x86" 两种配置。
启动 BitBake: 使用以下命令形式启动多配置构建:
$ bitbake [mc:multiconfigname:]target [[[mc:multiconfigname:]target] ... ]
本节示例的命令如下:
$ bitbake mc:x86:core-image-minimal mc:arm:core-image-sato mc::core-image-base
该命令构建:
通过
x86.conf配置的core-image-minimal镜像通过
arm.conf配置的core-image-sato镜像通过 build/conf/local.conf 配置的
core-image-base
备注
Yocto Project 6.1(Blacksail)发行版的多配置构建支持不包含共享 状态(sstate)优化。因此,如果某个对象在两个不同 TMPDIR 等 位置使用两次,构建只会在开始时使用已有共享状态缓存,否则就从头构建该对象。
15 启用多配置构建依赖
多配置构建中,不同目标之间有时存在依赖。例如,为 "x86" multiconfig 构建
core-image-sato 镜像前,需要先生成 "arm" multiconfig 的根文件系统。
其本质是 core-image-sato 配方的 do_image 任务依赖
core-image-minimal 配方的 do_rootfs 任务完成。
要启用这种依赖,必须在配方中按以下格式声明:
task_or_package[mcdepends] = "mc:from_multiconfig:to_multiconfig:recipe_name:task_on_which_to_depend"
以前述场景为例,需要向构建 core-image-sato 的配方添加:
do_image[mcdepends] = "mc:x86:arm:core-image-minimal:do_rootfs"
本例的 from_multiconfig 是 "x86",to_multiconfig 是 "arm"。配方的
do_image 依赖 "arm" multiconfig 中 core-image-minimal
配方的 do_rootfs。
设置依赖后,可如下构建 "x86" multiconfig:
$ bitbake mc:x86:core-image-sato
此命令执行创建 "x86" 的 core-image-sato 镜像所需的全部任务。由于上述
依赖,BitBake 也会执行 "arm" 构建,直到完成 do_rootfs。
让配方依赖另一个构建的根文件系统,可能看起来用途不大。可以将
core-image-sato 中的语句改为:
do_image[mcdepends] = "mc:x86:arm:core-image-minimal:do_image"
这时,由于 "x86" 构建的依赖,BitBake 必须创建 "arm" 的
core-image-minimal 镜像。
因为 "x86" 和 "arm" 都已启用并具有独立配置文件,BitBake 会将各构建产物 放在相应临时构建目录,即 TMPDIR 中。
15 推荐实践
除
bitbake.conf的默认值外,TMPDIR 只由用户在 build/conf/local.conf 中设置。这意味着 不应 在 机器或发行版 configuration file 中以任何方式修改它。multiconfig 应指定 TMPDIR,并通过 BB_CURRENT_MC 追加 multiconfig 名称。
将某个 multiconfig 构建输出转移到另一个配置的配方,应使用
do_task[mcdepends]触发组件构建,再在 do_install 和 do_deploy 中,依据 TMPDIR 确定部署产物位置并转移 到当前配置。do_install 和 do_deploy 应类似如下:
do_install() { install -m 0644 ${TMPDIR}-<multiconfig>/tmp/deploy/images/<machine>/somefile ${D}/some/path } do_deploy() { install -m 0644 ${TMPDIR}-<multiconfig>/tmp/deploy/images/<machine>/somefile ${DEPLOYDIR}/somefile }上例中:
<multiconfig>是 multiconfig configuration file 设置的 名称,见前文 设置并运行多配置构建。<machine>必须是构建和部署somefile所用的 MACHINE。 如果 multiconfig configuration file 覆盖了机器设置,这个值 可能与当前 MACHINE 不同。
不依赖标准 C 库等默认依赖的固件配方,可以将 INHIBIT_DEFAULT_DEPS 设为
1。
15 常见用例:同时构建裸机固件和 Linux
一种常见用法是将默认配置用于常规 Linux 构建,另用一个或多个 multiconfig 构建裸机固件等特殊组件。它也适用于微控制器与运行 Linux 的主处理器协同 工作的场景。本节说明如何通过多配置构建实现这些需求。
15 为裸机固件添加 multiconfig 配置文件和配方
如 设置并运行多配置构建 所述,每个 multiconfig 都需要独立 Configuration File。此外,本例 为裸机固件构建配置定义独立 TMPDIR。
例如,新建 conf/multiconfig/baremetal-firmware.conf,内容如下:
TMPDIR .= "-${BB_CURRENT_MC}"
TCLIBC = "newlib"
此文件配置独立的 TMPDIR,保存使用 newlib 工具链编译的二进制文件,见 TCLIBC。
然后创建 my-firmware.bb 配方,定义裸机固件的构建方式。配方应提供足够
信息,让 OpenEmbedded build system 正确使用工具链编译固件。具体
构建任务因固件而异,但配方应定义 deploy 任务,将输出
部署到 DEPLOYDIR。下文假定输出文件名为 my-firmware.elf。
15 构建固件
可以用以下 BitBake 命令构建固件:
$ bitbake mc:baremetal-firmware:my-firmware
不过,我们希望启动常规 Linux 构建时自动构建 my-firmware。
Linux 构建中的配方可以通过 mcdepend 触发 my-firmware 构建。例如,
Linux 构建需要组装一种使用该配方输出的“特殊”固件,称为
my-parent-firmware.bb。在其中指定依赖:
do_compile[mcdepends] = "mc::baremetal-firmware:my-firmware:do_deploy"
这样就能确保 my-parent-firmware 的 do_compile 被触发时,
my-firmware 的 do_deploy 已成功完成。
15 使用 my-firmware 的输出
my-firmware 配方部署 my-firmware.elf 后,需要使用该输出。可以根据
Yocto Project 默认变量作出一组约定,以找到二进制文件进行打包。
首先在 my-parent-firmware.bb 中设置:
FIRMWARE_FILE ??= "${TMPDIR}-baremetal-firmware/deploy/images/<machine>/my-firmware.elf"
FIRMWARE_FILE[vardepsexclude] += "TMPDIR"
第一条赋值保存 my-firmware.bb 构建并部署的固件路径;第二条将
TMPDIR 排除在 FIRMWARE_FILE 的依赖之外。这意味着修改
TMPDIR,例如更换构建主机,不会使
共享状态缓存 失效。
<machine> 应替换为 baremetal-firmware 配置中构建所用的 MACHINE。
随后向 my-parent-firmware 添加 do_install 任务:
do_install() {
install -Dm 0644 ${FIRMWARE_FILE} ${D}/lib/firmware/my-firmware.elf
}
这样便可将固件二进制文件转移并打包到 Linux 配置及根文件系统中。