Best Approach of Image Versioning in Yocto

best approach of image versioning in yocto

You are interested in os-release recipe. This gives provision to add version details to the image. This recipe installs a file /etc/os-release in the target.

If you are interested in adding custom fields based on your application or purpose of the image, you can add extra fields in OS_RELEASE_FIELDS variable in os-release.bbappend in your custom layer. For example,

OS_RELEASE_FIELDS += "BUILD_VERSION"
BUG_FIXED_VERSION = "1.0.0-B1"
BUILD_VERSION = "${BUG_FIXED_VERSION}"

This adds the build id into /etc/os-release and you can increment the versions based on bug fix or new delivery.

About yocto /etc/os-release versioning

Could it be you still have to tell Yocto to use the os-release recipe?

With a os-release.bbappend you can modify the recipe that is part of openembedded-core.
There are a few examples how to do at that webpage. A good one is e.g. the one used in meta-yoe.

But all this is just telling Yocto how to build the recipe. You still have to tell Yocto to add it to your image.

This can be done in the local.conf file or e.g. the recipes-images/images/your-image.bb file or in a packagegroup. The first solution is the quick and dirty one.

How to include git revision of image layer in boot output or /etc/issue?

Linux and U-Boot git hashes are the ones from the Linux/U-Boot git repository. This is how it is commonly done with OpenEmbedded. There is certainly a way to pass the git hash from OE to the U-Boot/Kernel build system, but I would not recommend doing that since it is not how it is commonly done.

As for the /etc/issue file, this typically gets generated in the meta/recipes-core/base-files/base-files_3.0.14.bb recipe. It should be fairly straight forward to add a bbappend to your layer and extend the task, e.g. something like this:

def get_layer_rev(d):
return bb.process.run('git rev-parse HEAD')

LAYER_REV="${@get_layer_rev(d)}"

do_install_basefilesissue_append() {
# Overwrite /etc/issue with a custom version of it
printf "${DISTRO_NAME} " > ${D}${sysconfdir}/issue
printf "${LAYER_REV}" >> ${D}${sysconfdir}/issue
}

How to handle distro versions in Yocto

Ubuntu and RedHat have a remote repositories. The systems have a internal list of installed packages. When you update the repository you get a new list of packages. You can then compare this list of installed packages against the new package list and install them. This is basically done with apt-get update && apt-get upgrade and the yum equivalent.

Yocto actually supports rpm and deb package format and their remote repositories. I am not familiar with opkg and if they have the option of a remote repository.

When I implemented a system I narrowed it down to the following options:

  • have a repository (deb and rpm definitely work here)
  • have a version package
  • using images

Version packages have the big disadvantages since you have to get your own logic on which packages to install. But you can require that version-1.deb needs software-v2.deb and tool-v1_5.deb. That works well with you own software but is a big manual overhead for the entire Yocto package stack.

Repository would be the usual way such as: apt-get update && apt-get -y upgrade. Works well and easy, but lacks also a risk free path to newer Yocto version.

The image way is more complicated and depends on your used hardware, size of image and transfer of the image. If you have a huge image and a slow network you might not want to do this. Basically you push your new image (or automatically pull it based on a version) d push it then to the device. The device dd's it to a secondary partition and then you flip the bootload to use the other partition. Depending on bootloader and/or hardware you can automatically flip back in case the partition you booted in is broken. Helpful for remote systems. Advantage is: you can also easily upgrade the entire OS without manually picking versions. And you can have (automatic) fail-over.

Yocto - git revision in the image name

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. 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.

I also had to add vardepsexclude attribute to the IMAGE_NAME variable. I tried to add vardepvalue flag to IMAGE_VERSION variable as well and in this particular case it did the same job as vardepsexclude. Mentioned Bitbake class uses both flags, but I think in my case using only one of them is enough.

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. The variable is set by a python script and is immediately expanded to prevent deterministic build warning:

layer.conf:

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

image-version.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.



Related Topics



Leave a reply



Submit