1.. SPDX-License-Identifier: CC-BY-SA-2.0-UK 2 3Working With Licenses 4********************* 5 6As mentioned in the ":ref:`overview-manual/development-environment:licensing`" 7section in the Yocto Project Overview and Concepts Manual, open source 8projects are open to the public and they consequently have different 9licensing structures in place. This section describes the mechanism by 10which the :term:`OpenEmbedded Build System` 11tracks changes to 12licensing text and covers how to maintain open source license compliance 13during your project's lifecycle. The section also describes how to 14enable commercially licensed recipes, which by default are disabled. 15 16Tracking License Changes 17======================== 18 19The license of an upstream project might change in the future. In order 20to prevent these changes going unnoticed, the 21:term:`LIC_FILES_CHKSUM` 22variable tracks changes to the license text. The checksums are validated 23at the end of the configure step, and if the checksums do not match, the 24build will fail. 25 26Specifying the ``LIC_FILES_CHKSUM`` Variable 27-------------------------------------------- 28 29The :term:`LIC_FILES_CHKSUM` variable contains checksums of the license text 30in the source code for the recipe. Here is an example of how to 31specify :term:`LIC_FILES_CHKSUM`:: 32 33 LIC_FILES_CHKSUM = "file://COPYING;md5=xxxx \ 34 file://licfile1.txt;beginline=5;endline=29;md5=yyyy \ 35 file://licfile2.txt;endline=50;md5=zzzz \ 36 ..." 37 38.. note:: 39 40 - When using "beginline" and "endline", realize that line numbering 41 begins with one and not zero. Also, the included lines are 42 inclusive (i.e. lines five through and including 29 in the 43 previous example for ``licfile1.txt``). 44 45 - When a license check fails, the selected license text is included 46 as part of the QA message. Using this output, you can determine 47 the exact start and finish for the needed license text. 48 49The build system uses the :term:`S` 50variable as the default directory when searching files listed in 51:term:`LIC_FILES_CHKSUM`. The previous example employs the default 52directory. 53 54Consider this next example:: 55 56 LIC_FILES_CHKSUM = "file://src/ls.c;beginline=5;endline=16;\ 57 md5=bb14ed3c4cda583abc85401304b5cd4e" 58 LIC_FILES_CHKSUM = "file://${WORKDIR}/license.html;md5=5c94767cedb5d6987c902ac850ded2c6" 59 60The first line locates a file in ``${S}/src/ls.c`` and isolates lines 61five through 16 as license text. The second line refers to a file in 62:term:`WORKDIR`. 63 64Note that :term:`LIC_FILES_CHKSUM` variable is mandatory for all recipes, 65unless the :term:`LICENSE` variable is set to "CLOSED". 66 67Explanation of Syntax 68--------------------- 69 70As mentioned in the previous section, the :term:`LIC_FILES_CHKSUM` variable 71lists all the important files that contain the license text for the 72source code. It is possible to specify a checksum for an entire file, or 73a specific section of a file (specified by beginning and ending line 74numbers with the "beginline" and "endline" parameters, respectively). 75The latter is useful for source files with a license notice header, 76README documents, and so forth. If you do not use the "beginline" 77parameter, then it is assumed that the text begins on the first line of 78the file. Similarly, if you do not use the "endline" parameter, it is 79assumed that the license text ends with the last line of the file. 80 81The "md5" parameter stores the md5 checksum of the license text. If the 82license text changes in any way as compared to this parameter then a 83mismatch occurs. This mismatch triggers a build failure and notifies the 84developer. Notification allows the developer to review and address the 85license text changes. Also note that if a mismatch occurs during the 86build, the correct md5 checksum is placed in the build log and can be 87easily copied to the recipe. 88 89There is no limit to how many files you can specify using the 90:term:`LIC_FILES_CHKSUM` variable. Generally, however, every project 91requires a few specifications for license tracking. Many projects have a 92"COPYING" file that stores the license information for all the source 93code files. This practice allows you to just track the "COPYING" file as 94long as it is kept up to date. 95 96.. note:: 97 98 - If you specify an empty or invalid "md5" parameter, 99 :term:`BitBake` returns an md5 100 mis-match error and displays the correct "md5" parameter value 101 during the build. The correct parameter is also captured in the 102 build log. 103 104 - If the whole file contains only license text, you do not need to 105 use the "beginline" and "endline" parameters. 106 107Enabling Commercially Licensed Recipes 108====================================== 109 110By default, the OpenEmbedded build system disables components that have 111commercial or other special licensing requirements. Such requirements 112are defined on a recipe-by-recipe basis through the 113:term:`LICENSE_FLAGS` variable 114definition in the affected recipe. For instance, the 115``poky/meta/recipes-multimedia/gstreamer/gst-plugins-ugly`` recipe 116contains the following statement:: 117 118 LICENSE_FLAGS = "commercial" 119 120Here is a 121slightly more complicated example that contains both an explicit recipe 122name and version (after variable expansion):: 123 124 LICENSE_FLAGS = "license_${PN}_${PV}" 125 126It is possible to give more details about a specific license 127using flags on the :term:`LICENSE_FLAGS_DETAILS` variable:: 128 129 LICENSE_FLAGS_DETAILS[my-eula-license] = "For further details, see https://example.com/eula." 130 131If set, this will be displayed to the user if the license hasn't been accepted. 132 133In order for a component restricted by a 134:term:`LICENSE_FLAGS` definition to be enabled and included in an image, it 135needs to have a matching entry in the global 136:term:`LICENSE_FLAGS_ACCEPTED` 137variable, which is a variable typically defined in your ``local.conf`` 138file. For example, to enable the 139``poky/meta/recipes-multimedia/gstreamer/gst-plugins-ugly`` package, you 140could add either the string "commercial_gst-plugins-ugly" or the more 141general string "commercial" to :term:`LICENSE_FLAGS_ACCEPTED`. See the 142":ref:`dev-manual/licenses:license flag matching`" section for a full 143explanation of how :term:`LICENSE_FLAGS` matching works. Here is the 144example:: 145 146 LICENSE_FLAGS_ACCEPTED = "commercial_gst-plugins-ugly" 147 148Likewise, to additionally enable the package built from the recipe 149containing ``LICENSE_FLAGS = "license_${PN}_${PV}"``, and assuming that 150the actual recipe name was ``emgd_1.10.bb``, the following string would 151enable that package as well as the original ``gst-plugins-ugly`` 152package:: 153 154 LICENSE_FLAGS_ACCEPTED = "commercial_gst-plugins-ugly license_emgd_1.10" 155 156As a convenience, you do not need to specify the 157complete license string for every package. You can use 158an abbreviated form, which consists of just the first portion or 159portions of the license string before the initial underscore character 160or characters. A partial string will match any license that contains the 161given string as the first portion of its license. For example, the 162following value will also match both of the packages 163previously mentioned as well as any other packages that have licenses 164starting with "commercial" or "license":: 165 166 LICENSE_FLAGS_ACCEPTED = "commercial license" 167 168License Flag Matching 169--------------------- 170 171License flag matching allows you to control what recipes the 172OpenEmbedded build system includes in the build. Fundamentally, the 173build system attempts to match :term:`LICENSE_FLAGS` strings found in 174recipes against strings found in :term:`LICENSE_FLAGS_ACCEPTED`. 175A match causes the build system to include a recipe in the 176build, while failure to find a match causes the build system to exclude 177a recipe. 178 179In general, license flag matching is simple. However, understanding some 180concepts will help you correctly and effectively use matching. 181 182Before a flag defined by a particular recipe is tested against the 183entries of :term:`LICENSE_FLAGS_ACCEPTED`, the expanded 184string ``_${PN}`` is appended to the flag. This expansion makes each 185:term:`LICENSE_FLAGS` value recipe-specific. After expansion, the 186string is then matched against the entries. Thus, specifying 187``LICENSE_FLAGS = "commercial"`` in recipe "foo", for example, results 188in the string ``"commercial_foo"``. And, to create a match, that string 189must appear among the entries of :term:`LICENSE_FLAGS_ACCEPTED`. 190 191Judicious use of the :term:`LICENSE_FLAGS` strings and the contents of the 192:term:`LICENSE_FLAGS_ACCEPTED` variable allows you a lot of flexibility for 193including or excluding recipes based on licensing. For example, you can 194broaden the matching capabilities by using license flags string subsets 195in :term:`LICENSE_FLAGS_ACCEPTED`. 196 197.. note:: 198 199 When using a string subset, be sure to use the part of the expanded 200 string that precedes the appended underscore character (e.g. 201 ``usethispart_1.3``, ``usethispart_1.4``, and so forth). 202 203For example, simply specifying the string "commercial" in the 204:term:`LICENSE_FLAGS_ACCEPTED` variable matches any expanded 205:term:`LICENSE_FLAGS` definition that starts with the string 206"commercial" such as "commercial_foo" and "commercial_bar", which 207are the strings the build system automatically generates for 208hypothetical recipes named "foo" and "bar" assuming those recipes simply 209specify the following:: 210 211 LICENSE_FLAGS = "commercial" 212 213Thus, you can choose to exhaustively enumerate each license flag in the 214list and allow only specific recipes into the image, or you can use a 215string subset that causes a broader range of matches to allow a range of 216recipes into the image. 217 218This scheme works even if the :term:`LICENSE_FLAGS` string already has 219``_${PN}`` appended. For example, the build system turns the license 220flag "commercial_1.2_foo" into "commercial_1.2_foo_foo" and would match 221both the general "commercial" and the specific "commercial_1.2_foo" 222strings found in the :term:`LICENSE_FLAGS_ACCEPTED` variable, as expected. 223 224Here are some other scenarios: 225 226- You can specify a versioned string in the recipe such as 227 "commercial_foo_1.2" in a "foo" recipe. The build system expands this 228 string to "commercial_foo_1.2_foo". Combine this license flag with a 229 :term:`LICENSE_FLAGS_ACCEPTED` variable that has the string 230 "commercial" and you match the flag along with any other flag that 231 starts with the string "commercial". 232 233- Under the same circumstances, you can add "commercial_foo" in the 234 :term:`LICENSE_FLAGS_ACCEPTED` variable and the build system not only 235 matches "commercial_foo_1.2" but also matches any license flag with 236 the string "commercial_foo", regardless of the version. 237 238- You can be very specific and use both the package and version parts 239 in the :term:`LICENSE_FLAGS_ACCEPTED` list (e.g. 240 "commercial_foo_1.2") to specifically match a versioned recipe. 241 242Other Variables Related to Commercial Licenses 243---------------------------------------------- 244 245There are other helpful variables related to commercial license handling, 246defined in the 247``poky/meta/conf/distro/include/default-distrovars.inc`` file:: 248 249 COMMERCIAL_AUDIO_PLUGINS ?= "" 250 COMMERCIAL_VIDEO_PLUGINS ?= "" 251 252If you want to enable these components, you can do so by making sure you have 253statements similar to the following in your ``local.conf`` configuration file:: 254 255 COMMERCIAL_AUDIO_PLUGINS = "gst-plugins-ugly-mad \ 256 gst-plugins-ugly-mpegaudioparse" 257 COMMERCIAL_VIDEO_PLUGINS = "gst-plugins-ugly-mpeg2dec \ 258 gst-plugins-ugly-mpegstream gst-plugins-bad-mpegvideoparse" 259 LICENSE_FLAGS_ACCEPTED = "commercial_gst-plugins-ugly commercial_gst-plugins-bad commercial_qmmp" 260 261Of course, you could also create a matching list for those components using the 262more general "commercial" string in the :term:`LICENSE_FLAGS_ACCEPTED` variable, 263but that would also enable all the other packages with :term:`LICENSE_FLAGS` 264containing "commercial", which you may or may not want:: 265 266 LICENSE_FLAGS_ACCEPTED = "commercial" 267 268Specifying audio and video plugins as part of the 269:term:`COMMERCIAL_AUDIO_PLUGINS` and :term:`COMMERCIAL_VIDEO_PLUGINS` statements 270(along with :term:`LICENSE_FLAGS_ACCEPTED`) includes the plugins or 271components into built images, thus adding support for media formats or 272components. 273 274.. note:: 275 276 GStreamer "ugly" and "bad" plugins are actually available through 277 open source licenses. However, the "ugly" ones can be subject to software 278 patents in some countries, making it necessary to pay licensing fees 279 to distribute them. The "bad" ones are just deemed unreliable by the 280 GStreamer community and should therefore be used with care. 281 282Maintaining Open Source License Compliance During Your Product's Lifecycle 283========================================================================== 284 285One of the concerns for a development organization using open source 286software is how to maintain compliance with various open source 287licensing during the lifecycle of the product. While this section does 288not provide legal advice or comprehensively cover all scenarios, it does 289present methods that you can use to assist you in meeting the compliance 290requirements during a software release. 291 292With hundreds of different open source licenses that the Yocto Project 293tracks, it is difficult to know the requirements of each and every 294license. However, the requirements of the major FLOSS licenses can begin 295to be covered by assuming that there are three main areas of concern: 296 297- Source code must be provided. 298 299- License text for the software must be provided. 300 301- Compilation scripts and modifications to the source code must be 302 provided. 303 304There are other requirements beyond the scope of these three and the 305methods described in this section (e.g. the mechanism through which 306source code is distributed). 307 308As different organizations have different ways of releasing software, 309there can be multiple ways of meeting license obligations. At 310least, we describe here two methods for achieving compliance: 311 312- The first method is to use OpenEmbedded's ability to provide 313 the source code, provide a list of licenses, as well as 314 compilation scripts and source code modifications. 315 316 The remainder of this section describes supported methods to meet 317 the previously mentioned three requirements. 318 319- The second method is to generate a *Software Bill of Materials* 320 (:term:`SBoM`), as described in the ":doc:`/dev-manual/sbom`" section. 321 Not only do you generate :term:`SPDX` output which can be used meet 322 license compliance requirements (except for sharing the build system 323 and layers sources for the time being), but this output also includes 324 component version and patch information which can be used 325 for vulnerability assessment. 326 327Whatever method you choose, prior to releasing images, sources, 328and the build system, you should audit all artifacts to ensure 329completeness. 330 331.. note:: 332 333 The Yocto Project generates a license manifest during image creation 334 that is located in 335 ``${DEPLOY_DIR}/licenses/${SSTATE_PKGARCH}/<image-name>-<machine>.rootfs-<datestamp>/`` 336 to assist with any audits. 337 338Providing the Source Code 339------------------------- 340 341Compliance activities should begin before you generate the final image. 342The first thing you should look at is the requirement that tops the list 343for most compliance groups --- providing the source. The Yocto Project has 344a few ways of meeting this requirement. 345 346One of the easiest ways to meet this requirement is to provide the 347entire :term:`DL_DIR` used by the 348build. This method, however, has a few issues. The most obvious is the 349size of the directory since it includes all sources used in the build 350and not just the source used in the released image. It will include 351toolchain source, and other artifacts, which you would not generally 352release. However, the more serious issue for most companies is 353accidental release of proprietary software. The Yocto Project provides 354an :ref:`ref-classes-archiver` class to help avoid some of these concerns. 355 356Before you employ :term:`DL_DIR` or the :ref:`ref-classes-archiver` class, you 357need to decide how you choose to provide source. The source 358:ref:`ref-classes-archiver` class can generate tarballs and SRPMs and can 359create them with various levels of compliance in mind. 360 361One way of doing this (but certainly not the only way) is to release 362just the source as a tarball. You can do this by adding the following to 363the ``local.conf`` file found in the :term:`Build Directory`:: 364 365 INHERIT += "archiver" 366 ARCHIVER_MODE[src] = "original" 367 368During the creation of your 369image, the source from all recipes that deploy packages to the image is 370placed within subdirectories of ``DEPLOY_DIR/sources`` based on the 371:term:`LICENSE` for each recipe. 372Releasing the entire directory enables you to comply with requirements 373concerning providing the unmodified source. It is important to note that 374the size of the directory can get large. 375 376A way to help mitigate the size issue is to only release tarballs for 377licenses that require the release of source. Let us assume you are only 378concerned with GPL code as identified by running the following script: 379 380.. code-block:: shell 381 382 # Script to archive a subset of packages matching specific license(s) 383 # Source and license files are copied into sub folders of package folder 384 # Must be run from build folder 385 #!/bin/bash 386 src_release_dir="source-release" 387 mkdir -p $src_release_dir 388 for a in tmp/deploy/sources/*; do 389 for d in $a/*; do 390 # Get package name from path 391 p=`basename $d` 392 p=${p%-*} 393 p=${p%-*} 394 # Only archive GPL packages (update *GPL* regex for your license check) 395 numfiles=`ls tmp/deploy/licenses/$p/*GPL* 2> /dev/null | wc -l` 396 if [ $numfiles -ge 1 ]; then 397 echo Archiving $p 398 mkdir -p $src_release_dir/$p/source 399 cp $d/* $src_release_dir/$p/source 2> /dev/null 400 mkdir -p $src_release_dir/$p/license 401 cp tmp/deploy/licenses/$p/* $src_release_dir/$p/license 2> /dev/null 402 fi 403 done 404 done 405 406At this point, you 407could create a tarball from the ``gpl_source_release`` directory and 408provide that to the end user. This method would be a step toward 409achieving compliance with section 3a of GPLv2 and with section 6 of 410GPLv3. 411 412Providing License Text 413---------------------- 414 415One requirement that is often overlooked is inclusion of license text. 416This requirement also needs to be dealt with prior to generating the 417final image. Some licenses require the license text to accompany the 418binary. You can achieve this by adding the following to your 419``local.conf`` file:: 420 421 COPY_LIC_MANIFEST = "1" 422 COPY_LIC_DIRS = "1" 423 LICENSE_CREATE_PACKAGE = "1" 424 425Adding these statements to the 426configuration file ensures that the licenses collected during package 427generation are included on your image. 428 429.. note:: 430 431 Setting all three variables to "1" results in the image having two 432 copies of the same license file. One copy resides in 433 ``/usr/share/common-licenses`` and the other resides in 434 ``/usr/share/license``. 435 436 The reason for this behavior is because 437 :term:`COPY_LIC_DIRS` and 438 :term:`COPY_LIC_MANIFEST` 439 add a copy of the license when the image is built but do not offer a 440 path for adding licenses for newly installed packages to an image. 441 :term:`LICENSE_CREATE_PACKAGE` 442 adds a separate package and an upgrade path for adding licenses to an 443 image. 444 445As the source :ref:`ref-classes-archiver` class has already archived the 446original unmodified source that contains the license files, you would have 447already met the requirements for inclusion of the license information 448with source as defined by the GPL and other open source licenses. 449 450Providing Compilation Scripts and Source Code Modifications 451----------------------------------------------------------- 452 453At this point, we have addressed all we need prior to generating the 454image. The next two requirements are addressed during the final 455packaging of the release. 456 457By releasing the version of the OpenEmbedded build system and the layers 458used during the build, you will be providing both compilation scripts 459and the source code modifications in one step. 460 461If the deployment team has a :ref:`overview-manual/concepts:bsp layer` 462and a distro layer, and those 463those layers are used to patch, compile, package, or modify (in any way) 464any open source software included in your released images, you might be 465required to release those layers under section 3 of GPLv2 or section 1 466of GPLv3. One way of doing that is with a clean checkout of the version 467of the Yocto Project and layers used during your build. Here is an 468example: 469 470.. code-block:: shell 471 472 # We built using the dunfell branch of the poky repo 473 $ git clone -b dunfell git://git.yoctoproject.org/poky 474 $ cd poky 475 # We built using the release_branch for our layers 476 $ git clone -b release_branch git://git.mycompany.com/meta-my-bsp-layer 477 $ git clone -b release_branch git://git.mycompany.com/meta-my-software-layer 478 # clean up the .git repos 479 $ find . -name ".git" -type d -exec rm -rf {} \; 480 481One thing a development organization might want to consider for end-user 482convenience is to modify 483``meta-poky/conf/templates/default/bblayers.conf.sample`` to ensure that when 484the end user utilizes the released build system to build an image, the 485development organization's layers are included in the ``bblayers.conf`` file 486automatically:: 487 488 # POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf 489 # changes incompatibly 490 POKY_BBLAYERS_CONF_VERSION = "2" 491 492 BBPATH = "${TOPDIR}" 493 BBFILES ?= "" 494 495 BBLAYERS ?= " \ 496 ##OEROOT##/meta \ 497 ##OEROOT##/meta-poky \ 498 ##OEROOT##/meta-yocto-bsp \ 499 ##OEROOT##/meta-mylayer \ 500 " 501 502Creating and 503providing an archive of the :term:`Metadata` 504layers (recipes, configuration files, and so forth) enables you to meet 505your requirements to include the scripts to control compilation as well 506as any modifications to the original source. 507 508Compliance Limitations with Executables Built from Static Libraries 509------------------------------------------------------------------- 510 511When package A is added to an image via the :term:`RDEPENDS` or :term:`RRECOMMENDS` 512mechanisms as well as explicitly included in the image recipe with 513:term:`IMAGE_INSTALL`, and depends on a static linked library recipe B 514(``DEPENDS += "B"``), package B will neither appear in the generated license 515manifest nor in the generated source tarballs. This occurs as the 516:ref:`ref-classes-license` and :ref:`ref-classes-archiver` classes assume that 517only packages included via :term:`RDEPENDS` or :term:`RRECOMMENDS` 518end up in the image. 519 520As a result, potential obligations regarding license compliance for package B 521may not be met. 522 523The Yocto Project doesn't enable static libraries by default, in part because 524of this issue. Before a solution to this limitation is found, you need to 525keep in mind that if your root filesystem is built from static libraries, 526you will need to manually ensure that your deliveries are compliant 527with the licenses of these libraries. 528 529Copying Non Standard Licenses 530============================= 531 532Some packages, such as the linux-firmware package, have many licenses 533that are not in any way common. You can avoid adding a lot of these 534types of common license files, which are only applicable to a specific 535package, by using the 536:term:`NO_GENERIC_LICENSE` 537variable. Using this variable also avoids QA errors when you use a 538non-common, non-CLOSED license in a recipe. 539 540Here is an example that uses the ``LICENSE.Abilis.txt`` file as 541the license from the fetched source:: 542 543 NO_GENERIC_LICENSE[Firmware-Abilis] = "LICENSE.Abilis.txt" 544 545