Understanding licenses in a Yocto Project build

Introduction

A modern piece of software usually involves a number of parts that you did not write yourself. This could be libraries or tools for example. Many of those are available under so-called Open Source Licenses, like MIT, BSD or the GPL. But even if you are usually allowed to use software under these licenses for free, as without financial compensation, it does not mean that you are free to do whatever you want. Especially once you are distributing your resulting software product, a number of obligations apply.

This tutorial will guide you through the mechanisms that the Yocto Project® offers in order to understand the licenses that are involved in your build, and outline some considerations and means that you can apply in order to archieve license compliance.

Prerequisites

To follow this tutorial, it is helpful to have a finished Yocto Project® build that you can inspect. As an example for the Raspberry Pi 3, you can follow the tutorial at Preparing the Yocto Project environment from scratch. In that case the MACHINE variable is raspberrypi3. If you use a build for another board, the MACHINE variable differs accordingly.

Inspecting the used licenses

The most basic step in understanding your licensing situation is to see which licenses actually do apply to your build. This is something that the Yocto Project® already gives you without additional effort.

In your build directory, look at the tmp/deploy/licenses subdirectory. Here you will find an exhaustive list of all artifacts generated in this build context and their licensing information. The license of most artifacts will not vary across different MACHINE selections, so the content of this directory is not split up by MACHINE, build date or other determinants. Images are a special case then, as they are MACHINE-specific and also often vary over build iterations, so they follow the additional naming convention $IMAGE_NAME-$MACHINE-$DATE. As we are mostly interested in the licenses involved in one specific image, we can inspect such like for example:

$ tree tmp/deploy/licenses/core-image-minimal-raspberrypi3-20220408092057/
tmp/deploy/licenses/core-image-minimal-raspberrypi3-20220408092057/
├── image_license.manifest
├── license.manifest
└── package.manifest

There are two files with the term license in the name. Looking at those shows the following information:

  • image_license.manifest: the licenses for all deployed packages. These are mostly things that are needed to boot the device, but live outside the root filesystem. In the case of the Raspberry Pi 3, these are bootfiles, linux-raspberrypi(the Linux kernel), rpi-config, rpi-u-boot-scr and u-boot (the bootloader). The file includes an exhaustive mapping of file to license, recipe and version. Example extract for the u-boot recipe:
    RECIPE NAME: u-boot
    VERSION: 2020.01
    LICENSE: GPLv2+
    FILES: u-boot-initial-env-raspberrypi3-2020.01-r0 fw_env.config-raspberrypi3-2020.01-r0 fw_env.config.default u-boot-raspberrypi3-2020.01-r0.bin uboot.env
    
  • licenses.manifest: the licenses of all packages included in the image. Those are not broken down on a file level, but also include a mapping of package to license, recipe and version. Example extract for the bash package:
    PACKAGE NAME: bash
    PACKAGE VERSION: 5.0
    RECIPE NAME: bash
    LICENSE: GPLv3+
    

The package.manifest file is not relevant in the context of this tutorial.

So by inspecting those files we can get reliable information on the licenses involved in the software artifact that we are deploying.

Adjusting the allowed licenses for your build

You might want to restrict your build from using specific licenses, and allow some others. By default, a Yocto Project® build does include software under commercial licenses.

As you will want to apply licensing-related setting to all of your build, they must be put into a .conf (e.g. “configuration”) file, such as your products DISTRO.conf or local.conf. Usually the DISTRO is a good place is it makes sure this setting is under version control and therefore reproducible, but under some circumstances a more transient setting in local.conf can be appropriate too.

This does not work when put into the recipe of the image that you are building. The reason is that it is only locally visible in the context of the recipe then and can not affect any other recipe.

In a product that you are shipping, you will maybe want to allow certain commercial things to be added to your build, such as the Mender Monitor add-on. This can be done by adding

LICENSE_FLAGS_WHITELIST += "commercial_mender-monitor"

to the configuration file.

On the opposite end, there are cases where you want to avoid software under specific open source licenses being added to your build. As an example, you can exclude any AGPL-3.0-licensed package by adding

INCOMPATIBLE_LICENSE = "AGPL-3.0"

to the configuration file. This affects the whole build dependencies and not only the packages that you actively added.

Note: removing software can break dependencies, especially when core recipes are involved.

As an example, you can try and remove the GPL-3.0-license. This will not work without supplying replacements for a number of packages in the most cases.

Correctly specifying LICENSE for your own recipes

In order for the tracking mechanism to function properly, all recipes are required to provide license information. This information consists of two parts.

  • naming the applicable license. This is done by setting the LICENSE variable in the recipe, for example like

    LICENSE = "MIT"
    

    The standard licenses are included in poky in the meta/files/common-licenses directory. The file names should be used as license strings. More information also relating to SPDX is provided in the variable reference

  • tracking the license of your sources. The tracking in itself does not convey any information about the actual license, but makes sure that it does not change unnoticed between builds. This is archieved by supplying at least one, but often multiple locations and checksums of license statements in the sources to the LIC_FILES_CHECKSUM variable. An example taken from the Yocto Project® documentation demonstrates various mechanims:

    LIC_FILES_CHKSUM = "file://COPYING;md5=xxxx \
      file://licfile1.txt;beginline=5;endline=29;md5=yyyy \
      file://licfile2.txt;endline=50;md5=zzzz \
      ..."
    

    Checksumming the license notes in the sources has the desired effect of mismatching and therefore stopping the build whenever a change in those notes happens. Then the note and license can be inspected to verify that the assumed license information is still correct.

    For more information on this, please see the Yoctp Project® Dev Manual

CLOSED is not commercial/proprietary!
A common misconception is that setting LICENSE = "CLOSED" means the recipe in question is closed source, respectively proprietary. This is not the actual case: the license value CLOSED has the meaning “do not care about the license of this recipe”. This effectively disables all license tracking for this recipe and should be avoided.

The correct way to set a proprietary, nonstandard license is

LICENSE = "Proprietary"

This often correlates with being commercial, which is expressed by the flag

LICENSE_FLAGS = "commercial"

The commercial flag is automatically expanded with the recipe name, and can then be matched, therefore allowed for the build, as outlined in the first paragraph.

Conclusion

In this tutorial we went through the basics for understanding and adjusting the licenses involved in a image build using the Yocto Project®, as well as properly declaring license information for your own recipes.

For further reading please visit


If this tutorial was useful to you, please press like, or leave a thank you note to the contributor who put valuable time into this and made it available to you. It will be much appreciated!