简体   繁体   English

Yocto - 镜像名称中的 git 修订

[英]Yocto - git revision in the image name

By default Yocto adds build timestamp to the output image file name, but I would like to replace it by the revision of my integration Git repository (which references all my layers and configuration files).默认情况下,Yocto 将构建时间戳添加到 output 映像文件名,但我想用我的集成 Git 存储库的修订版替换它(它引用了我所有的层和配置文件)。 To achieve this, I put the following code to my image recipe:为此,我将以下代码放入我的图像配方中:

def get_image_version(d):
    import subprocess
    import os.path

    try:
        parentRepo = os.path.dirname(d.getVar("COREBASE", True))
        return subprocess.check_output(["git", "describe", "--tags", "--long", "--dirty"], cwd = parentRepo, stderr = subprocess.DEVNULL).strip().decode('UTF-8')
    except:
        return d.getVar("MACHINE", True) + "-" + d.getVar("DATETIME", True)


IMAGE_VERSION = "${@get_image_version(d)}"
IMAGE_NAME = "${IMAGE_BASENAME}-${IMAGE_VERSION}"
IMAGE_NAME[vardepsexclude] = "IMAGE_VERSION"

This code works properly until I change Git revision (eg by adding a new commit).此代码正常工作,直到我更改 Git 修订版(例如通过添加新提交)。 Then I receive the following error:然后我收到以下错误:

ERROR: When reparsing /home/ubuntu/yocto/poky/../mylayer/recipes-custom/images/core-image-minimal.bb.do_image_tar, the basehash value changed from 63e1e69797d2813a4c36297517478a28 to 9788d4bf2950a23d0f758e4508b0a894. The metadata is not deterministic and this needs to be fixed.

I understand this happens because the image recipe has already been parsed with older Git revision, but why constant changes of the build timestamp do not cause the same error?我知道发生这种情况是因为图像配方已经用旧的 Git 修订版解析,但为什么构建时间戳的不断变化不会导致相同的错误? How can I fix my code to overcome this problem?如何修复我的代码来克服这个问题?

The timestamp does not have this effect since its added to vardepsexclude: https://docs.yoctoproject.org/bitbake/bitbake-user-manual/bitbake-user-manual-metadata.html#variable-flags时间戳自从添加到 vardepsexclude 后没有此效果: https://docs.yoctoproject.org/bitbake/bitbake-user-manual/bitbake-user-manual-metadata.html#variable-flags

[vardepsexclude]: Specifies a space-separated list of variables that should be excluded from a variable's dependencies for the purposes of calculating its signature. [vardepsexclude]:指定一个以空格分隔的变量列表,这些变量应从变量的依赖项中排除,以便计算其签名。

You may need to add this in a couple of places, eg: https://git.yoctoproject.org/poky/tree/meta/classes/image-artifact-names.bbclass#n7您可能需要在几个地方添加它,例如: https://git.yoctoproject.org/poky/tree/meta/classes/image-artifact-names.bbclass#n7

IMAGE_VERSION_SUFFIX ?= "-${DATETIME}"
IMAGE_VERSION_SUFFIX[vardepsexclude] += "DATETIME SOURCE_DATE_EPOCH"
IMAGE_NAME ?= "${IMAGE_BASENAME}-${MACHINE}${IMAGE_VERSION_SUFFIX}"

After some research it turned out the problem was in this line经过一番研究,结果发现问题出在这一行

IMAGE_VERSION = "${@get_image_version(d)}"

because the function get_image_version() was called during parsing.因为在解析过程中调用了 function get_image_version get_image_version() I took inspiration from the source file in aehs29's post and moved the code to the anonymous Python function which is called after parsing.我从 aehs29 帖子中的源文件中获得灵感,并将代码移至匿名 Python function 中,该代码在解析后调用。

I also had to add vardepsexclude attribute to the IMAGE_NAME variable.我还必须将vardepsexclude属性添加到IMAGE_NAME变量。 I tried to add vardepvalue flag to IMAGE_VERSION variable as well and in this particular case it did the same job as vardepsexclude .我也尝试将vardepvalue标志添加到IMAGE_VERSION变量中,在这种特殊情况下,它的工作与vardepsexclude相同。 Mentioned Bitbake class uses both flags, but I think in my case using only one of them is enough.提到的 Bitbake class 使用这两个标志,但我认为在我的情况下只使用其中一个就足够了。

The final code is below:最终代码如下:

IMAGE_VERSION ?= "${MACHINE}-${DATETIME}"

IMAGE_NAME = "${IMAGE_BASENAME}-${IMAGE_VERSION}"
IMAGE_NAME[vardepsexclude] += "IMAGE_VERSION"

python () {
    import subprocess
    import os.path

    try:
        parentRepo = os.path.dirname(d.getVar("COREBASE", True))
        version = subprocess.check_output(["git", "describe", "--tags", "--long", "--dirty"], cwd = parentRepo, stderr = subprocess.DEVNULL).strip().decode('UTF-8')
        d.setVar("IMAGE_VERSION", version)

    except:
        bb.warning("Could not get Git revision, image will have default name.")
}

EDIT: After some research I realized it's better to define a global variable in layer.conf file of the layer containing the recipes referencing the variable.编辑:经过一些研究,我意识到最好在layer.conf文件中定义一个全局变量,该文件包含引用该变量的配方。 The variable is set by a python script and is immediately expanded to prevent deterministic build warning:该变量由 python 脚本设置,并立即展开以防止确定性构建警告:

layer.conf:层.conf:

require conf/image-version.py.inc
IMAGE_VERSION := "${@get_image_version(d)}"

image-version.py.inc:图像版本.py.inc:

def get_image_version(d):
    import subprocess
    import os.path

    try:
        parentRepo = os.path.dirname(d.getVar("COREBASE", True))
        return subprocess.check_output(["git", "describe", "--tags", "--long", "--dirty"], cwd = parentRepo, stderr = subprocess.DEVNULL).strip().decode('UTF-8')
    except:
        bb.warn("Could not determine image version. Default naming schema will be used.")
        return d.getVar("MACHINE", True) + "-" + d.getVar("DATETIME", True)

I think this is cleaner approach which fits BitBake build system better.我认为这是更干净的方法,更适合 BitBake 构建系统。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM