在我们基于 yocto 的嵌入式应用程序中,我们现在有几个 Golang 二进制文件,它们可能会变得非常大。例如,docker(来自meta-virtualization
)和相关二进制文件如果不压缩,则重达几百兆字节。因此,我们创建了使用 upx 压缩这些二进制文件的配方。例如,这是我们的docker-ce_git.bbappend
:
do_install_append() {
/usr/bin/upx --brute ${D}/${bindir}/docker
/usr/bin/upx --brute ${D}/${bindir}/dockerd
/usr/bin/upx --brute ${D}/${bindir}/docker-proxy
}
这导致烘焙过程中出现以下错误:
ERROR: docker-ce-19.03.2-ce+git6a30dfca03664a0b6bf0646a7d389ee7d0318e6e-r0 do_package: QA Issue: File '/usr/bin/docker' from docker-ce was already stripped, this will prevent future debugging! [already-stripped]
ERROR: docker-ce-19.03.2-ce+git6a30dfca03664a0b6bf0646a7d389ee7d0318e6e-r0 do_package: QA Issue: File '/usr/bin/docker-proxy' from docker-ce was already stripped, this will prevent future debugging! [already-stripped]
ERROR: docker-ce-19.03.2-ce+git6a30dfca03664a0b6bf0646a7d389ee7d0318e6e-r0 do_package: QA Issue: File '/usr/bin/dockerd' from docker-ce was already stripped, this will prevent future debugging! [already-stripped]
好的,这很有道理。如果我们想创建调试版本,我们就不会删除这些二进制文件。
但:我们如何正确地进行条件剥离?我猜测存在某种仅针对非调试版本执行的剥离阶段,我们可以用它do_strip_append()
或类似的东西附加它,但到目前为止,我在文档中搜索却一无所获。
答案1
我找到了一种解决这个问题的办法。你可以将自己附加到图像生成中,而不是将自己附加到与包相关的配方中。由于我们将其用作core-image-minimal
目标,因此我创建了一个core-image-minimal.bbappend
包含以下内容的:
ROOTFS_POSTPROCESS_COMMAND += "compress_docker_binaries;"
# Need to run in bash because pysh has no job control
compress_docker_binaries() {
/bin/bash -x -c '
set -e
files=(containerd containerd-shim containerd-ctr docker dockerd \
docker-proxy runc)
for (( i=0; i<${#files[@]}; i++ )); do
/usr/bin/upx --brute "$0/$1/${files[${i}]}" &
pids[${i}]=$!
done;
for pid in ${pids[@]}; do
wait ${pid}
done
' "${IMAGE_ROOTFS}" "${bindir}"
}
通过附加compress_docker_binaries
到ROOTFS_POSTPROCESS_COMMAND
,我们确保在提取任何调试符号后文件也被压缩。
这个解决方案有一些缺点:
- 您不需要附加到实际的包装配方,而是附加到更通用的图像配方。
- 您仍然可以
.bbappend
使用单独的函数将文件保存在单独的目录中。但是,yocto 将按顺序执行它们,尽管在这种情况下您可以并行运行upx
二进制文件。 - 或者,您可以强制作业并行运行(就像我使用小 bash hack 所做的那样(pysh 没有作业控制)),但所有内容都必须放在一个文件中。它还会对并行运行的作业数量进行硬编码。