离线状态下自定义BitBake Recipe无法重构建的原因排查
我有一个如下所示的BitBake Recipe:
SUMMARY = "SomeLibrary" LICENSE = "Apache-2.0" LIC_FILES_CHKSUM = "file://LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57" SRC_URI += "git://gitlab.com/some_library/some-library.git;protocol=https;nobranch=1" SRCREV = "${PV}" S = "${WORKDIR}/git" inherit autotools pkgconfig
使用bitbake some-library可成功构建,且DL_DIR指向的downloads文件夹中存在git2/gitlab.com.some_library.some-library.git/目录和git2/gitlab.com.some_library.some-library.git.done文件。
我原本以为在无Recipe变更的情况下,执行bitbake -c cleansstate some-library && bitbake some-library时,BitBake无需再次下载资源,但离线或在local.conf中设置BB_NO_NETWORK="1"后,会出现如下错误:
Initialising tasks: 100% |################################################################| Time: 0:00:01 Sstate summary: Wanted 12 Found 4 Missed 8 Current 251 (33% match, 96% complete) NOTE: Executing Tasks ERROR: some-library-v2.3.0-r0 do_fetch: Bitbake Fetcher Error: NetworkAccess('https://gitlab.com/some_library/some-library.git', 'git -c core.fsyncobjectfiles=0 ls-remote "https://gitlab.com/some_library/some-library.git" ') ERROR: Logfile of failure stored in: /home/myusername/work/builddir/tmp/work/aarch64-poky-linux/some-library/v2.3.0-r0/temp/log.do_fetch.116252 ERROR: Task (/home/myusername/work/builddir/../../layers/meta-mymeta/recipes-core/some-library/some-library_v2.3.0.bb:do_fetch) failed with exit code '1' NOTE: Tasks Summary: Attempted 806 tasks of which 804 didn't need to be rerun and 1 failed. Summary: 1 task failed: /home/myusername/work/builddir/../../layers/meta-mymeta/recipes-core/some-library/some-library_v2.3.0.bb:do_fetch Summary: There was 1 ERROR message shown, returning a non-zero exit code.
令我困惑的是BitBake对自定义Recipe和官方Recipe的行为不同,比如can-utils的Recipe位于meta-openembedded/meta-oe/recipes-extended/socketcan/can-utils_git.bb,内容如下:
SUMMARY = "Linux CAN network development utilities" LICENSE = "GPLv2 & BSD-3-Clause" LIC_FILES_CHKSUM = "file://include/linux/can.h;endline=44;md5=a9e1169c6c9a114a61329e99f86fdd31" DEPENDS = "libsocketcan" SRC_URI = "git://github.com/linux-can/${BPN}.git;protocol=https;branch=master" SRCREV = "da65fdfe0d1986625ee00af0b56ae17ec132e700" PV = "2020.02.04" S = "${WORKDIR}/git" inherit autotools pkgconfig
该Recipe与我的结构类似,但设置BB_NO_NETWORK="1"后执行bitbake -c cleansstate can-utils && bitbake can-utils,结果显示所有任务均成功完成。我想知道:为何会出现这种情况?其他Recipe是如何避免该问题的?
核心差异:SRCREV的取值方式
你的自定义Recipe和官方can-utilsRecipe的关键区别在于SRCREV的定义:
- 官方
can-utils使用的是固定的Git提交哈希值:SRCREV = "da65fdfe0d1986625ee00af0b56ae17ec132e700" - 你的Recipe使用的是动态变量${PV}:
SRCREV = "${PV}"
为什么会触发网络访问?
BitBake的Git fetcher在处理SRCREV时,会根据取值类型做不同处理:
- 当
SRCREV是固定哈希值时,fetcher会直接检查DL_DIR中是否存在对应提交的本地Git仓库:- 如果仓库存在且包含该哈希,就不会触发网络请求,直接使用本地资源。
- 当
SRCREV是变量(比如${PV},对应版本号如v2.3.0)时,fetcher需要确认该版本标签对应的哈希值是否有效:- 即使本地已有仓库,BitBake也会尝试执行
git ls-remote命令去远程仓库验证标签与哈希的对应关系,确保资源一致性。 - 而当
BB_NO_NETWORK="1"时,这个网络验证操作被禁止,就会抛出NetworkAccess错误。
- 即使本地已有仓库,BitBake也会尝试执行
另外,你Recipe中使用的nobranch=1参数也会加剧这个问题:它告诉fetcher不跟踪分支,因此fetcher无法通过本地仓库确认标签的有效性,必须依赖远程查询。
如何解决?
方案1:将SRCREV设置为固定的Git提交哈希
找到你仓库中对应${PV}版本(比如v2.3.0)的Git提交哈希,替换掉SRCREV = "${PV}":
SRCREV = "abcdef1234567890abcdef1234567890abcdef12" # 替换为实际的提交哈希
这样BitBake会直接使用本地仓库中的对应提交,无需网络验证。
方案2:添加SRCREV_FORMAT(适用于多源场景)
如果你的Recipe需要保留版本号关联,可以添加SRCREV_FORMAT来明确指定SRCREV的验证方式,但本质上还是需要固定哈希:
SRCREV = "${PV}" SRCREV_FORMAT = "some-library" # 同时在文件中添加对应版本的哈希映射(通常在.inc文件或bbappend中) SRCREV_some-library = "abcdef1234567890abcdef1234567890abcdef12"
方案3:使用标签+分支参数替代nobranch=1
如果必须保留版本号作为SRCREV,可以去掉nobranch=1,并指定分支(比如main或master):
SRC_URI += "git://gitlab.com/some_library/some-library.git;protocol=https;branch=main"
这样fetcher可以通过本地分支的标签信息验证版本,减少网络依赖,但仍建议优先使用固定哈希。
为什么官方Recipe没问题?
官方Recipe都使用固定的SRCREV哈希值,这是Yocto项目的最佳实践:
- 确保构建的可重复性,避免远程仓库标签变更导致构建失败。
- 完全消除不必要的网络验证请求,支持离线构建。
内容的提问来源于stack exchange,提问作者Eternal

