Yocto Sergio Training
Yocto Sergio Training
Sergio Prado
sergio.prado@e-labworks.com
https://www.linkedin.com/in/sprado
ABOUT THIS DOCUMENT
Yocto Project v1.1.1 training slides.
The most current version of the slides is available on the Embedded Labworks
website.
https://e-labworks.com/training/en/ypr/slides
Active in the embedded systems community in Brazil, one of the creators of the
Embarcados website and blogger.
https://sergioprado.blog
Free and open source software contributor, including projects like Buildroot, Yocto
Project and the Linux kernel.
TRAINING SCHEDULE
DAY 1: Introduction to the Yocto Project, first steps with Poky, overview of the
OpenEmbedded build system and the BitBake tool, introduction to the concept of
layers and recipes.
DAY 3: Development of BSP layers, generation and use of SDKs, additional tools and
resources.
HARDWARE: COLIBRI IMX6 + ASTER + IPÊ BOARD
PREREQUISITES
Basic knowledge of GNU/Linux command line tools (cat, echo, vim, grep, find, etc).
Help...
Participate!
YOCTO PROJECT
Bootloader: basic hardware initialization, loads and runs the Linux kernel.
Toolchain: set of tools to build operating system artifacts (bootloader, kernel, rootfs).
WORKING WITH EMBEDDED LINUX
We can adopt 3 different approaches when developing an embedded Linux system:
Use a third-party Linux distribution.
There are also several open source options, including Android, Debian, Ubuntu,
Fedora IoT, etc.
Some features are difficult to implement (remote update, secure boot, etc).
Provides a set of tools that automate the build of all operating system components
(toolchain, bootloader, kernel, rootfs).
Facilitates configuring, extending and maintaining the Linux system over time.
ADVANTAGES OF A BUILD SYSTEM
Flexibility, providing full control over all operating system components.
Greater control over the use of hardware resources (CPU, memory, storage, power,
etc).
Configuration files and other metadata used to create the Linux distribution can be
versioned, making it easier to control and maintain the operating system over time.
OPEN SOURCE BUILD SYSTEMS
Buildroot, developed by the community:
https://www.buildroot.org
OpenEmbedded (used by the Yocto Project), more flexible and also more complex:
https://www.openembedded.org
WHAT IS THE YOCTO PROJECT?
Collaborative project that provides a set of tools to help create custom Linux
distributions for embedded devices.
https://www.yoctoproject.org
Under the governance of the Linux Foundation, ensuring the project's independence
from any member of the organization.
YOCTO PROJECT MEMBERS
PROJECTS
These are some of the projects that are part of the Yocto Project:
Openembedded-Core
BitBake
Poky
Matchbox
AutoBuilder
Toaster
Patches to fix critical bugs and security flaws are applied also in a previous version
and LTS versions.
Provides facilities to maintain and extend the system via the layers mechanism.
Supported by major hardware architectures (ARM, MIPS, x86, PPC) and SoC/SoM
manufacturers.
It is a de facto standard for BSP development.
Can generate Linux distributions for QEMU and some reference platforms
(Beaglebone, EdgeRouter, x86-64, etc).
Reference Manual:
https://docs.yoctoproject.org/ref-manual/index.html
DOCUMENTATION
Yocto Project Development Manual:
https://docs.yoctoproject.org/dev-manual/index.html
BitBake Documentation:
https://docs.yoctoproject.org/bitbake.html
Feel free to refer to this documentation during the training, particularly the Yocto
Project's Reference Manual.
https://docs.yoctoproject.org/ref-manual/index.html
YOCTO PROJECT
INTRODUCTION TO POKY
POKY
The Yocto Project community is responsible for maintaining several projects,
including Poky.
With Poky, it's possible to build a custom Linux distribution for hardware platforms
officially supported by the project (QEMU, Beaglebone, EdgeRouter, etc).
In this section, we will have a brief introduction on how to use Poky to build a custom
Linux distribution.
THE BUILD MACHINE
Good processing capacity (e.g. Intel Core i7, 4+ CPUs) is a requirement, with lots of
memory (16Gb+) and disk space (100Gb+, SSD).
There are some software prerequisites, including gcc, git, python, tar and make.
This command will clone the master branch of Poky, not recommended as it is a
development branch.
This script will configure the build environment in the current terminal, creating by
default a directory called build with the configuration files needed to build an image.
Optionally, you can pass the name of the build directory when sourcing the
configuration script:
$ source poky/oe-init-build-env build-test
THE BUILD DIRECTORY
$ tree build/
build/
└── conf
├── bblayers.conf
├── local.conf
└── templateconf.cfg
THE BUILD DIRECTORY
By default, the entire build process will happen inside the build directory.
The build directory is created with some configuration files, including bblayers.conf
and local.conf.
The bblayers.conf file allows to configure the layers that will be used to build the
image.
The local.conf file allows to define global configuration variables that will be used to
customize the build.
BBLAYERS.CONF
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"
BBPATH = "${TOPDIR}"
BBFILES ?= ""
BBLAYERS ?= " \
/opt/labs/ex/layers/poky/meta \
/opt/labs/ex/layers/poky/meta-poky \
/opt/labs/ex/layers/poky/meta-yocto-bsp \
"
LOCAL.CONF
# Machine Selection
MACHINE ??= "qemuarm"
...
VARIABLES IN LOCAL.CONF
Variable Description
MACHINE Target platform
DISTRO Distribution name
DL_DIR Download directory
SSTATE_DIR Shared-state caches directory
TMPDIR Build directory
PACKAGE_CLASSES Packaging Format (rpm, deb, ipk)
CORE_IMAGE_EXTRA_INSTALL Additional packages to install
EXTRA_IMAGE_FEATURES Image features to enable
BUILDING THE IMAGE
With bblayers.conf and local.conf configured, just start the build process:
$ bitbake core-image-minimal
And then use the runqemu script to run the generated image:
$ runqemu qemuarm
QEMU
LAB 1
Classes (.bbclass).
They have this name because they contain the "recipe" to process a certain software
component.
A list of the main variables that can be used to write a recipe is available in the Yocto
Project's reference guide.
https://docs.yoctoproject.org/ref-manual/varlocality.html#recipes
APPEND FILES
Append files have the .bbappend extension and make it possible to modify the
behavior of a recipe without changing its implementation.
The contents of an append file are concatenated at the end of the corresponding
recipe, making it possible to redefine tasks and variables and change the behavior of
the original recipe.
Append files encourage reuse and make it easier to maintain metadata in the Yocto
Project.
CLASSES
Classes are files with the .bbclass extension, used to abstract common functionalities
shared by recipes and other metadata.
Examples of classes:
autotools.bbclass: tasks to build software based on Autotools.
See the Yocto Project reference guide for a list of existing classes.
https://docs.yoctoproject.org/ref-manual/classes.html
CONFIGURATION FILES
Configuration files have the .conf extension and contain the definition of variables
that will parameterize the build system.
Among other things, it allows to define information about the hardware architecture
and platform, image organization and content, distribution policies, etc.
Only variable definitions and include directives are allowed in configuration files.
Common variables that can be used in configuration files are documented in the
Yocto Project's reference guide.
https://docs.yoctoproject.org/ref-manual/varlocality.html#configuration
LAYERS
Metadata (recipes, classes and configuration files) are organized into layers in the
build system.
In the Yocto Project, a Linux system is generated by combining two or more layers
with the required metadata.
POKY LAYERS
$ tree -L 1 poky/
poky/
├── bitbake
├── contrib
├── documentation
├── LICENSE
├── LICENSE.GPL-2.0-only
├── LICENSE.MIT
├── MAINTAINERS.md
├── Makefile
├── MEMORIAM
├── meta
├── meta-poky
├── meta-selftest
├── meta-skeleton
├── meta-yocto-bsp
├── oe-init-build-env
├── README.hardware.md -> meta-yocto-bsp/README.hardware.md
├── README.md -> README.poky.md
├── README.OE-Core.md
├── README.poky.md -> meta-poky/README.poky.md
├── README.qemu.md
└── scripts
TYPES OF LAYERS
We can classify layers into three types, which can be combined to generate the image
of the operating system:
BSP (Board Support Package) layers.
Recipes for compiling the bootloader (e.g. U-Boot) and the Linux kernel.
Recipes for compiling software for specific hardware features (GPU, security, etc).
The main variables that can be used in the distribution context are documented in
the Yocto Project's reference guide.
https://docs.yoctoproject.org/ref-manual/varlocality.html#distribution-distro
META-POKY
$ tree meta-poky/
meta-poky/
├── classes
│ └── poky-sanity.bbclass
├── conf
│ ├── bblayers.conf.sample
│ ├── conf-notes.txt
│ ├── distro
│ │ ├── include
│ │ ├── poky-altcfg.conf
│ │ ├── poky-bleeding.conf
│ │ ├── poky.conf
│ │ └── poky-tiny.conf
│ ├── layer.conf
│ ├── local.conf.sample
│ ├── local.conf.sample.extended
│ └── site.conf.sample
├── README.poky.md
└── recipes-core
├── busybox
│ ├── busybox
│ └── busybox_%.bbappend
...
META-LUNEOS
$ tree meta-luneos/
meta-luneos/
├── classes
├── conf
│ ├── distro
│ │ ├── include
│ │ └── luneos.conf
│ └── layer.conf
├── COPYING.MIT
├── lib
├── licenses
├── README
├── recipes-android
├── recipes-benchmark
├── recipes-connectivity
├── recipes-containers
├── recipes-core
├── recipes-devtools
├── recipes-extended
├── recipes-graphics
├── recipes-kernel
├── recipes-luneos
...
SOFTWARE LAYERS
Software layers provide additional recipes that might compose the final image.
Product-specific applications.
OPENEMBEDDED-CORE
$ tree -L 1 meta
meta
├── classes
├── conf
├── COPYING.MIT
├── files
├── lib
├── recipes-bsp
├── recipes-connectivity
├── recipes-core
├── recipes-devtools
├── recipes-example
├── recipes-extended
├── recipes-gnome
├── recipes-graphics
├── recipes-kernel
├── recipes-multimedia
├── recipes-rt
├── recipes-sato
├── recipes-support
├── recipes.txt
└── site
META-QT5
$ tree -L 2 meta-qt5/
meta-qt5/
├── classes
│ ├── cmake_qt5.bbclass
│ ├── populate_sdk_qt5_base.bbclass
│ ├── populate_sdk_qt5.bbclass
│ ├── qmake5_base.bbclass
│ ├── qmake5.bbclass
│ └── qmake5_paths.bbclass
├── conf
│ └── layer.conf
...
└── recipes-qt
├── demo-extrafiles
├── examples
├── maliit
├── meta
├── packagegroups
├── qmllive
├── qsiv
├── qt5
├── qtchooser
...
LAYER INDEX
The Yocto Project maintains a selected list of layers officially supported by the
project.
https://www.yoctoproject.org/software-overview/layers/
Be aware that hardware manufacturers, vendors and software providers might not
list their layers in these databases.
BITBAKE
The BitBake tool has the following syntax:
$ bitbake [options] [recipename/target recipe:do_task ...]
For example, the command below will process the BusyBox recipe:
$ bitbake busybox
By default, it will run the build task, which depends on all other "normal" tasks
needed to process the recipe.
$ bitbake -c build busybox
RECIPE TASKS
The -c option can be used to execute a specific task:
$ bitbake -c fetch busybox
The -k option causes bitbake to continue executing tasks (as far as it can go), even in
case of errors:
$ bitbake -k busybox
To clean the build output and the build caches, execute the cleansstate task:
$ bitbake -c cleansstate busybox
To clean the build output, the build caches, and the downloaded source code,
execute the cleanall task:
$ bitbake -c cleanall busybox
BITBAKE INTERNALS
Bitbake's objective is to execute tasks described in recipes.
But how do all metadata are identified and parsed, so tasks are executed until the
final operating system image is generated?
bitbake.conf file, which contains the basic and global settings that affect all
recipes and tasks that will be executed.
BITBAKE.CONF
The bitbake.conf file will include several other configuration files, including:
User local files (site.conf, local.conf, etc).
After reading the configuration files, BitBake will inherit several classes, including the
base.bbclass, which defines a set of tasks that will be inherited by all recipes.
The entire process of reading the metadata can be visualized with the -e parameter.
INCLUDE HISTORY
$ bitbake -e
#
# INCLUDE HISTORY:
#
# /opt/labs/ex/build-qemu/conf/bblayers.conf
# /opt/labs/ex/layers/poky/meta/conf/layer.conf
# /opt/labs/ex/layers/poky/meta-poky/conf/layer.conf
# /opt/labs/ex/layers/poky/meta-yocto-bsp/conf/layer.conf
# conf/bitbake.conf includes:
# /opt/labs/ex/layers/poky/meta/conf/abi_version.conf
# conf/site.conf
# conf/auto.conf
# /opt/labs/ex/build-qemu/conf/local.conf
# /opt/labs/ex/layers/poky/meta/conf/multiconfig/default.conf
# /opt/labs/ex/layers/poky/meta/conf/machine/qemuarm.conf includes:
# /opt/labs/ex/layers/poky/meta/conf/machine/include/arm/armv7a/tune-cortexa15.inc includes:
# /opt/labs/ex/layers/poky/meta/conf/machine/include/arm/arch-armv7ve.inc includes:
# /opt/labs/ex/layers/poky/meta/conf/machine/include/arm/arch-armv7a.inc includes:
# /opt/labs/ex/layers/poky/meta/conf/machine/include/arm/arch-armv6.inc includes:
# /opt/labs/ex/layers/poky/meta/conf/machine/include/arm/arch-armv5-dsp.inc includes:
# /opt/labs/ex/layers/poky/meta/conf/machine/include/arm/arch-armv5.inc includes:
# /opt/labs/ex/layers/poky/meta/conf/machine/include/arm/arch-armv4.inc includes:
...
TASKS DEPENDENCIES
When reading the configuration files, the BBFILES variable will be populated with a
list of available recipes and append files.
Recipes and append files will be parsed, one by one, and a list of tasks will be defined
for each recipe, including dependencies between them.
Finally, BitBake executes the build task of the recipe, which causes all its
dependencies to run, until the final operating system image is generated.
The generated file can be converted to an image or opened with a dot file reader:
$ dot -Tps task-depends.dot -o task-depends.ps
$ xdot task-depends.dot
BitBake is also able to display the dependency graph with a graphical tool (Task
Dependency Explorer):
$ bitbake -g core-image-minimal -u taskexp
DEPENDENCY GRAPH
TASK DEPENDENCY EXPLORER
LAB 2
LAYERS
LAYERS
OpenEmbedded/Yocto Project supports organizing build system metadata into
layers.
The layer directory can have any name, but the default is to start with meta-.
A distribution built with the Yocto Project will use these and other community-
provided and project-specific layers.
CREATING A LAYER
First create a directory for the layer:
$ mkdir meta-labworks
Inside the layer directory, create the layer configuration file (conf/layer.conf):
$ cd meta-labworks
$ mkdir conf
$ vim conf/layer.conf
The content of this file is similar to other layer configuration files, so we can just
copy/paste and change it as needed.
LAYER.CONF
BBPATH .= ":${LAYERDIR}"
BBFILES += " \
${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend \
"
BBFILE_COLLECTIONS += "meta-labworks"
BBFILE_PATTERN_meta-labworks = "^${LAYERDIR}/"
BBFILE_PRIORITY_meta-labworks = "6"
LAYERVERSION_meta-labworks = "1"
LAYERDEPENDS_meta-labworks = "core"
LAYERSERIES_COMPAT_meta-labworks = "kirkstone"
LAYER.CONF VARIABLES
The BBPATH variable must be set so that BitBake can find the files provided by the
layer (configuration files, classes, etc).
BBPATH .= ":${LAYERDIR}"
The BBFILES variable must include the paths of recipes provided by the layer:
BBFILES += " \
${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend \
"
The BBFILE_PRIORITY variable defines the layer priority, useful for example in
situations where the same recipe appears in more than one layer.
BBFILE_PRIORITY_meta-labworks = "6"
LAYER.CONF VARIABLES
The LAYERVERSION variable defines the layer version.
LAYERVERSION_meta-labworks = "2"
The LAYERSERIES_COMPAT variable allows to set the layer's compatibility with Yocto
Project releases.
LAYERSERIES_COMPAT_meta-labworks = "kirkstone"
ADDING METADATA TO LAYERS
After creating the configuration file, the next step is to add metadata to the layer:
If the layer has recipes, these are usually added in subdirectories starting with
recipes-.
If it's a distribution layer, then distro configuration files are defined in conf/distro/.
If it's a BSP layer, then machine configuration files are defined in conf/machine/.
It's common to have a license file (eg COPYING.MIT), in addition to a README file
describing the layer contents, dependencies, maintainer, how to contribute, usage
instructions, etc.
META-LABWORKS
$ tree meta-labworks/
meta-labworks/
├── conf
│ └── layer.conf
├── COPYING.MIT
└── README
ENABLING THE LAYER
To enable the layer, just add it to the BBLAYERS variable in conf/bblayers.conf:
BBLAYERS ?= " \
/home/sprado/yocto/poky/meta \
/home/sprado/yocto/poky/meta-yocto \
/home/sprado/yocto/poky/meta-yocto-bsp \
/home/sprado/yocto/poky/meta-labworks \
"
BITBAKE-LAYERS
$ bitbake-layers -h
usage: bitbake-layers [-d] [-q] [-F] [--color COLOR] [-h] <subcommand> ...
...
subcommands:
<subcommand>
add-layer Add one or more layers to bblayers.conf.
remove-layer Remove one or more layers from bblayers.conf.
flatten flatten layer configuration into a separate output directory.
show-layers show current configured layers.
show-overlayed list overlayed recipes (where the same recipe exists in another layer)
show-recipes list available recipes, showing the layer they are provided by
show-appends list bbappend files and recipe files they apply to
show-cross-depends Show dependencies between recipes that cross layer boundaries.
layerindex-fetch Fetches a layer from a layer index along with its dependent layers
layerindex-show-depends
Find layer dependencies from layer index.
create-layer Create a basic layer
$ tree ../layers/meta-labworks/
../layers/meta-labworks/
├── conf
│ └── layer.conf
├── COPYING.MIT
├── README
└── recipes-example
└── example
└── example_0.1.bb
$ bitbake-layers show-layers
layer path priority
==========================================================================
meta /opt/labs/ex/layers/poky/meta 5
meta-poky /opt/labs/ex/layers/poky/meta-poky 5
meta-yocto-bsp /opt/labs/ex/layers/poky/meta-yocto-bsp 5
meta-labworks /opt/labs/ex/layers/meta-labworks 10
DYNAMIC LAYERS
To use a layer with metadata that depends on another layer (e.g. append files), it is
required to download all dependencies for the layer to work.
For example, a user of a BSP layer that contains append files for graphical
applications will need to download the layer that contains the graphical
application recipes (even if it's not required), or BitBake will complain.
In this case, the dynamic layers functionality can be used to enable conditional
processing of metadata.
$ tree -L 2 meta-oe/dynamic-layers/perl-layer/recipes-core/
meta-oe/dynamic-layers/perl-layer/recipes-core/
└── packagegroups
└── packagegroup-meta-oe.bbappend
# meta-oe/conf/layer.conf
...
BBFILES_DYNAMIC += " \
meta-python:${LAYERDIR}/dynamic-layers/meta-python/recipes-*/*/*.bb \
perl-layer:${LAYERDIR}/dynamic-layers/perl-layer/recipes-*/*/*.bb \
"
...
COMPATIBILITY PROGRAM
When creating a layer to use with the Yocto Project, it's beneficial to ensure that the
layer is compliant with the project's standards:
Ensures a minimum quality standard defined by the community, including
interoperability with other layers.
More information about this process is available at Making Sure Your Layer is
Compatible With Yocto Project.
YOCTO-CHECK-LAYER
$ yocto-check-layer --without-software-layer-signature-check meta-labworks/
INFO: Detected layers:
INFO: meta-training: LayerType.SOFTWARE, /opt/labs/ex/layers/meta-training
INFO:
INFO: Setting up for meta-training(LayerType.SOFTWARE), /opt/labs/ex/layers/meta-training
INFO: Getting initial bitbake variables ...
INFO: Getting initial signatures ...
INFO: Adding layer meta-training
INFO: Starting to analyze: meta-training
INFO: ----------------------------------------------------------------------
INFO: skipped "BSPCheckLayer: Layer meta-training isn't BSP one."
INFO: test_layerseries_compat (common.CommonCheckLayer)
INFO: ... ok
INFO: test_parse (common.CommonCheckLayer)
INFO: ... ok
...
INFO: Ran 7 tests in 435.104s
INFO: OK
INFO: (skipped=3)
INFO:
INFO: Summary of results:
INFO:
INFO: meta-training ... PASS
LAB 3
CREATING LAYERS
YOCTO PROJECT
INTRODUCTION TO RECIPES
RECIPES
Recipes are files with the .bb extension, processed by the BitBake tool to generate the
various software components of the operating system.
libpng_1.6.37.bb
mmc-utils_git.bb
Packages contain files generated during recipe processing, aggregated by type (-dbg
for debug files, -doc for documentation, etc).
The bitbake-layers command can help search for existing recipes in the layers
enabled in bblayers.conf:
$ bitbake-layers show-recipes | grep "busybox:" -A 1
busybox:
meta 1.35.0
If you need to create a new recipe, other recipes can be used as a starting point.
Also, some tools can help creating recipes, like recipetool and devtool. We will study
these tools later in the training.
STRUCTURE OF A RECIPE
A recipe basically contains the definition of tasks and variables.
Tasks contain instructions to process a recipe (download the source code, unpack,
apply patches, configure, compile, install, package, etc).
Variables allow to parameterize and configure the behavior of tasks (source code
location, patches to be applied, dependencies, compilation flags, etc).
SETSERIAL_2.17.BB
SUMMARY = "Controls the configuration of serial ports"
DESCRIPTION = "setserial is a program designed to set and/or report the configuration information ass
HOMEPAGE = "http://setserial.sourceforge.net"
AUTHOR = "Theodore Ts'o <tytso@mit.edu>"
SECTION = "console/utils"
LICENSE = "GPLv2.0"
LIC_FILES_CHKSUM = "file://version.h;beginline=1;endline=6;md5=2e7c59cb9e57e356ae81f50f4e4dfd99"
PR = "r3"
DEPENDS += "groff-native"
inherit autotools-brokensep
SRC_URI = "${SOURCEFORGE_MIRROR}/setserial/${BPN}-${PV}.tar.gz \
file://add_stdlib.patch \
file://ldflags.patch \
"
SRC_URI[md5sum] = "c4867d72c41564318e0107745eb7a0f2"
SRC_URI[sha256sum] = "7e4487d320ac31558563424189435d396ddf77953bb23111a17a3d1487b5794a"
do_install() {
install -d ${D}${bindir}
TASKS
Task is a step in processing a recipe (downloading source code, applying patches,
configuring, compiling, etc).
By default, all recipes automatically inherit some classes when BitBake is parsing the
metadata, including the base.bbclass class.
These classes define some common tasks in all recipes (do_fetch, do_unpack,
do_patch, do_configure, do_compile, etc).
TASKS IN AN EMPTY RECIPE
$ cat ../layers/meta-labworks/recipes-test/empty-recipe/empty-recipe_1.0.bb
LICENSE = "CLOSED"
The most commonly used classes are documented in the Reference Manual:
https://docs.yoctoproject.org/ref-manual/classes.html
IMPLEMENTING TASKS
A recipe can change existing tasks or even implement custom ones.
Before implementing a task, make sure that a class with the necessary logic for
processing the recipe doesn't already exist.
SHELL SCRIPT VS PYTHON
Tasks are typically implemented in Shell Script:
do_install() {
install -d ${D}${bindir}
install -m 0755 main ${D}${bindir}
}
New tasks don't run by default, but can be executed manually with the -c parameter:
$ bitbake myrecipe -c mkimage
For a new task to run automatically while processing a recipe, it must be added to
the task dependency chain:
addtask mkimage after do_compile before do_install
VARIABLES
Variables are used to parameterize and define the behavior of tasks during recipe
processing. Examples:
The do_fetch task uses the SRC_URI variable to identify the location of the source
code.
The do_patch task uses the SRC_URI variable to identify the patches that must be
applied to the source code.
The source code can be obtained from a variety of sources, including HTTP, FTP, GIT,
SVN, etc.
See the BitBake documentation for a complete list of supported protocols.
The source code is downloaded to the directory pointed to by the DL_DIR variable.
DO_FETCH
If the source code is downloaded from a remote server without using a version
control system (VCS), it's mandatory to provide the hash of the file being
downloaded.
SRC_URI = "http://www.libsdl.org/release/SDL2-${PV}.tar.gz"
SRC_URI[sha256sum] = "65be9ff6004034b5b2ce9927b5a4db1814930f169c4b2dae0a1e4697075f287b"
If the source code is available in a VCS repository, it's mandatory to define the
variable SRCREV and optionally PV.
SRC_URI = "git://git.yoctoproject.org/${BPN};branch=master"
SRCREV = "7ad885912efb2131e80914e964d5e635b0d07b40"
PV = "0.3+git${SRCPV}"
DO_UNPACK
The source code will be unpacked into the directory defined by the S variable.
If the source code is downloaded from a VCS repository, it's necessary to set the S
variable.
SRC_URI = "git://anongit.freedesktop.org/git/xorg/lib/${XORG_PN};protocol=https"
S = "${WORKDIR}/git"
A recipe can have local files (e.g. patches), provided in the SCR_URI variable through
the file protocol.
SRC_URI = "http://www.mirrorservice.org/sites/lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof_${PV}.
file://lsof-remove-host-information.patch"
DO_UNPACK
These files are stored along with the metadata in the recipe directory, and BitBake
uses the FILESPATH variable to search for them.
$ tree poky/meta/recipes-extended/lsof/
poky/meta/recipes-extended/lsof/
├── files
│ └── lsof-remove-host-information.patch
└── lsof_4.91.bb
$ bitbake lsof -e | grep ^FILESPATH=
During the execution of the do_unpack task, these files are copied to the recipe's
working directory (WORKDIR).
DO_PATCH
All files defined in the SRC_URI variable with .patch or .diff extensions are treated as
patches.
By default, the -p1 option will be used to apply patches (this behavior can be
changed with the striplevel option).
SRC_URI += "file://0002-llvm-allow-env-override-of-exe-path.patch;striplevel=2"
The patchdir option allows applying the patch from a specific directory.
SRC_URI += "file://0001-Workaround-for-GCC-11-uninit-variable-warnings-946.patch;patchdir=src"
DO_POPULATE_LIC
The do_populate_lic task is responsible for managing the license of the software.
The recipe must also contain the LIC_FILES_CHKSUM variable to ensure that the
license file has not been changed.
LIC_FILES_CHKSUM = "file://LICENSE;md5=44bc22578be94b6536c8bdc3a01e5db9"
DO_CONFIGURE
It's common for applications to have a software configuration mechanism before
starting the build (e.g. Autotools and CMake).
Usually, the implementation of this task is inherited from a class. For example, to
compile software based on Autotools:
inherit autotools
In the case of Autotools, the EXTRA_OECONF variable can be used to pass extra
options to the configuration script.
EXTRA_OECONF = "--enable-debug"
Check the documentation of the class being used for more information.
DO_COMPILE
Similar to the configure task, the implementation of the compile task is usually
inherited from a class.
It's also possible to customize the install task by appending extra commands to it:
do_install:append() {
install -d ${D}/${libdir}/pkgconfig
install -m 0644 ${B}/src/libgcrypt.pc ${D}/${libdir}/pkgconfig/
}
For this, the software artifacts generated during the build are divided into directories
in ${WORKDIR}/packages-split.
$ ls -1 tmp/work/cortexa9t2hf-neon-poky-linux-gnueabi/libpcap/1.10.1-r0/packages-split/
libpcap
libpcap-dbg
libpcap-dev
libpcap-doc
libpcap-locale
libpcap-src
libpcap-staticdev
DO_PACKAGE
The FILES variable is used to define where each software artifact should go:
$ bitbake libpng -e | grep ^FILES\:
FILES:libpng="/usr/bin/* /usr/sbin/* /usr/libexec/* /usr/lib/lib*.so.* /etc /com /var /bin/* /sbin/* /
FILES:libpng-dev="/usr/include /lib/lib*.so /usr/lib/lib*.so /usr/lib/*.la /usr/lib/*.o"
FILES:libpng-doc="/usr/share/doc /usr/share/man /usr/share/info /usr/share/gtk-doc /usr/share/gnome/he
FILES:libpng-locale="/usr/share/locale"
FILES:libpng-src=""
FILES:libpng-staticdev="/usr/lib/*.a /lib/*.a /usr/lib/libpng/*.a"
FILES:libpng-tools="/usr/bin/png-fix-itxt /usr/bin/pngfix /usr/bin/pngcp"
After splitting software artifacts into directories, final installation packages are generated
in ${WORKDIR}/deploy-<package-format>.
$ ls tmp/work/cortexa9t2hf-neon-poky-linux-gnueabi/libpcap/1.10.1-r0/deploy-rpms/cortexa9t2hf_neon/
libpcap1-1.10.1-r0.cortexa9t2hf_neon.rpm libpcap-dev-1.10.1-r0.cortexa9t2hf_neon.rpm
libpcap-src-1.10.1-r0.cortexa9t2hf_neon.rpm libpcap-dbg-1.10.1-r0.cortexa9t2hf_neon.rpm
libpcap-doc-1.10.1-r0.cortexa9t2hf_neon.rpm libpcap-staticdev-1.10.1-r0.cortexa9t2hf_neon.rpm
WORKING DIRECTORY
$ ls -1 tmp/work/core2-64-poky-linux/libpcap/1.10.1-r0/
build
configure.sstate
debugsources.list
deploy-rpms
deploy-source-date-epoch
image
libpcap-1.10.1
libpcap.spec
license-destdir
package
packages-split
pkgdata
pkgdata-pdata-input
pkgdata-sysroot
pseudo
recipe-sysroot
recipe-sysroot-native
source-date-epoch
sysroot-destdir
temp
LOGS
$ ls tmp/work/core2-64-poky-linux/libpcap/1.10.1-r0/temp/
depsig.do_deploy_source_date_epoch run.do_unpack
depsig.do_deploy_source_date_epoch.2949190 run.do_unpack.2949177
depsig.do_package run.emit_pkgdata.3006016
depsig.do_package.3006016 run.extend_recipe_sysroot.2947221
depsig.do_packagedata run.extend_recipe_sysroot.2949182
depsig.do_packagedata.3006753 run.extend_recipe_sysroot.3001129
depsig.do_package_qa run.extend_recipe_sysroot.3001312
depsig.do_package_qa.3006796 run.extend_recipe_sysroot.3005808
depsig.do_package_write_rpm run.extend_recipe_sysroot.3006016
depsig.do_package_write_rpm.3006795 run.extend_recipe_sysroot.3006017
depsig.do_populate_lic run.extend_recipe_sysroot.3006795
depsig.do_populate_lic.2949191 run.extend_recipe_sysroot.3006796
depsig.do_populate_sysroot run.fixup_perms.3006016
depsig.do_populate_sysroot.3006017 run.package_convert_pr_autoinc.3006016
log.do_compile run.packagedata_translate_pr_autoinc.3006753
log.do_compile.3005561 run.package_depchains.3006016
log.do_configure run.package_do_filedeps.3006016
log.do_configure.3001312 run.package_do_pkgconfig.3006016
log.do_deploy_source_date_epoch run.package_do_shlibs.3006016
log.do_deploy_source_date_epoch.2949190 run.package_do_split_locales.3006016
log.do_fetch run.package_fixsymlinks.3006016
log.do_fetch.2947221 run.package_get_auto_pr.3006753
log.do install run.package name hook.3006016
RECIPE TEMPLATE
DESCRIPTION = ""
HOMEPAGE = ""
SECTION = ""
LICENSE = ""
LIC_FILES_CHKSUM = ""
SRC_URI = ""
SRC_URI[sha256sum] = ""
DEPENDS = ""
inherit <some_class>
EXAMPLE 1: HELLO.C
DESCRIPTION = "Hello World application"
HOMEPAGE = "git://mygitserver.com/hello.git"
SECTION = "tests"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=7363621101019373746565758497289305"
SRC_URI = "git://mygitserver.com/hello.git;protocol=https;branch=main"
SRCREV = "6a4be9e9946df310d9402f995f371c7deb8c27ba"
S = "${WORKDIR}/git"
TARGET_CC_ARCH += "${LDFLAGS}"
do_compile() {
${CC} hello.c -o hello
}
do_install() {
install -d ${D}${bindir}
install -m 0755 hello ${D}${bindir}
}
EXAMPLE 2: AUTOTOOLS
SUMMARY = "GNU Hello World application"
HOMEPAGE = "https://hello.gnu.org"
SECTION = "tests"
LICENSE = "GPL-2.0-or-later"
LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe"
SRC_URI = "${GNU_MIRROR}/hello/hello-${PV}.tar.gz"
SRC_URI[sha256sum] = "d21b2d1fd78c1efbe1f2c16dae1cb23f8fd231dcf891465b8debe636a9054b0c"
DEPENDS = "zlib"
inherit autotools
EXTRA_OECONF = "--enable-debug"
EXAMPLE 3: AUTOTOOLS
SUMMARY = "X11 Code Viewer"
DESCRIPTION = "Allow viewing of X11 code in a fancy way which allows easier \
and more productive X11 programming"
AUTHOR = "John Bazz <john.bazz@example.org>"
HOMEPAGE = "http://www.example.org/xcv/"
SECTION = "x11/applications"
LICENSE = "GPL-2.0"
DEPENDS = "libsm libx11 libxext libxaw"
PV = "0.9+git${SRCPV}"
# upstream does not yet publish any release so we have to fetch last working version from GIT
SRCREV = "6a5e79ae8a0f4a273a603b2df1742972510d3d8f"
SRC_URI = "git://xcv.example.org/xcv;protocol=http \
file://toolbar-resize-fix.patch"
S = "${WORKDIR}/xcv/"
inherit autotools
do_configure:prepend() {
rm ${S}/aclocal.m4
}
do install() {
OPENEMBEDDED STYLE GUIDE
There is an official OpenEmbedded style guide for metadata development.
https://www.openembedded.org/wiki/Styleguide
The style guide standardizes code formatting, the organization of variables, task
declaration order, among other things.
The idea is to follow the same coding standard, making it easier to read and maintain
BitBake metadata.
LAB 4
DEVELOPING RECIPES
YOCTO PROJECT
During parsing, assignments to the same variable might happen in different places in
the parsed metadata.
For this reason, it is important to know the BitBake syntax when assigning a value to
a variable.
VARIABLE ASSIGNMENT
The = operator performs the assignment at the moment it finds the assignment (hard
assignment).
VAR = "value"
The ?= operator performs the assignment at the moment it finds the assignment, in
case the variable is not yet defined (soft assignment).
VAR ?= "value"
The ??= operator performs the assignment at the end of the parsing, in case the
variable is not yet defined (weak assignment).
VAR ??= "value"
VARIABLE EXPANSION
The ${} operator makes it possible to expand a variable inside another variable.
Using the = operator, the expansion only happens when the variable is used:
VAR1 = "A"
VAR2 = "${VAR1} B"
VAR1 = "C"
Use the operators ".=" and "=." to concatenate without adding spaces:
VAR = "1"
VAR =. "0 "
VAR .= " 2"
APPEND AND PREPEND
Concatenation can also be done by adding :append and :prepend to variables.
VAR = "1"
VAR:prepend = "0 "
VAR:append = " 2"
But unlike the .= and =. operators, the assignment happens only at the end of the
parsing process.
REMOVING
To remove a value from a variable, simply add :remove to the variable name:
VAR = "1 2 1 3"
VAR:remove = "1"
Before this release, the _ character was used for conditional assignments.
VAR_mx6 = "1"
VAR_append_mx6 = " 2"
More information about this change is available in the Yocto Project's Release
Migration Guide.
APPEND FILES
Append files have the .bbappend extension and make it possible to modify the
behavior of a recipe without changing its original implementation.
It can be used to apply patches, customize build flags, install additional files, and so
on, making the maintenance of the metadata quite flexible.
The way it works is very simple: the content of an append file is concatenated at the
end of the recipe, making it possible to redefine tasks and variables, and
consequently change the behavior of the original recipe.
CREATING APPEND FILES
Suppose you want to change the behavior of the json-c recipe available in the
OpenEmbedded-Core layer:
$ ls poky/meta/recipes-devtools/json-c/json-c_0.15.bb
The first step is to create the same directory structure in your layer:
$ mkdir -p meta-labworks/recipes-devtools/json-c/
And implement the append file inside of it (the % character indicates that the append
file is valid for any version of the recipe):
$ vim meta-labworks/recipes-devtools/json-c/json-c_%.bbappend
CONTENT OF AN APPEND FILE
In an append file it's possible to:
Define new tasks, redefine existing tasks, concatenate commands to tasks.
Assign values to variables, define new variables, redefine existing variables.
IMX_PATCH = " \
file://0001-add-conf-for-multichannel-support-in-imx.patch \
file://0005-add-ak4458-conf-for-multichannel-support.patch \
file://0006-add-conf-for-iMX-XCVR-sound-card.patch \
"
SRC_URI:append:imx-nxp-bsp = "${IMX_PATCH}"
PACKAGE_ARCH:imx-nxp-bsp = "${MACHINE_SOCARCH}"
EXAMPLE 2: IPROUTE2_%.BBAPPEND
do_install:append () {
install -d ${D}/usr/include/tc
cp -a ${B}/include ${D}/usr/include
cp -a ${B}/tc/*.h ${D}/usr/include/tc
}
EXAMPLE 3: MTD-UTILS_%.BBAPPEND
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI:append = " file://ubihealthd.service"
inherit systemd
SYSTEMD_PACKAGES = "${PN}"
SYSTEMD_SERVICE:${PN} = "ubihealthd.service"
SYSTEMD_AUTO_ENABLE = "disable"
do_install:append() {
install -d ${D}${systemd_unitdir}/system
install -m 0644 ${WORKDIR}/ubihealthd.service ${D}${systemd_unitdir}/system/
sed -i -e 's,@SBINDIR@,${sbindir},g' \
-e 's,@SYSCONFDIR@,${sysconfdir},g' \
${D}${systemd_unitdir}/system/*.service
}
LISTING APPEND FILES
The bitbake-layers command can be used to list existing append files:
$ bitbake-layers show-appends
alsa-lib_1.2.1.2.bb:
/opt/labs/ex/layers/meta-freescale/recipes-multimedia/alsa/alsa-lib_%.bbappend
alsa-state.bb:
/opt/labs/ex/layers/meta-freescale-3rdparty/recipes-bsp/alsa-state/alsa-state.bbappend
/opt/labs/ex/layers/meta-freescale/recipes-bsp/alsa-state/alsa-state.bbappend
/opt/labs/ex/layers/meta-toradex-nxp/recipes-bsp/alsa-state/alsa-state.bbappend
base-files_3.0.14.bb:
/opt/labs/ex/layers/meta-lmp/meta-lmp-base/recipes-core/base-files/base-files_%.bbappend
/opt/labs/ex/layers/meta-toradex-torizon/recipes-core/base-files/base-files_%.bbappend
base-passwd_3.5.29.bb:
/opt/labs/ex/layers/meta-toradex-torizon/recipes-core/base-passwd/base-passwd_3.5.29.bbappend
bind_9.11.32.bb:
/opt/labs/ex/layers/meta-virtualization/recipes-core/bind/bind_%.bbappend
busybox_1.31.1.bb:
/opt/labs/ex/layers/meta-yocto/meta-poky/recipes-core/busybox/busybox_%.bbappend
/opt/labs/ex/layers/meta-virtualization/recipes-core/busybox/busybox_%.bbappend
/opt/labs/ex/layers/meta-security/recipes-core/busybox/busybox_%.bbappend
/opt/labs/ex/layers/meta-lmp/meta-lmp-base/recipes-core/busybox/busybox_%.bbappend
...
INCLUDE AND REQUIRE
BitBake allows recipes to include files with the include and require directives.
include: if the file is not found, recipe processing continues normally.
require: if the file is not found, an error will occur while processing the recipe.
A common use case of these directives is to split the recipe implementation into two
files, to make maintenance easier or support multiple versions.
Version-dependent metadata (ex: libmodbus_3.0.6.bb)
$ cat meta-openembedded/meta-oe/recipes-extended/libmodbus/libmodbus_3.0.6.bb
require libmodbus.inc
SRC_URI[md5sum] = "c80f88b6ca19cabc4ceffc195ca07771"
SRC_URI[sha256sum] = "046d63f10f755e2160dc56ef681e5f5ad3862a57c1955fd82e0ce036b69471b6"
VARIABLE FLAGS
Variable flags (varflags) is a BitBake feature for associating extra information with
variables and tasks.
In the example below, the variable FOO has two flags, a and b, with values 123 and
456 respectively.
FOO[a] = "123"
FOO[b] = "456"
Some interesting varflags use cases include enabling software functionality (via
PACKAGECONFIG) and controlling the execution of tasks.
do_configure[noexec] = "1"
...
liburi-perl-native :5.08-r0
libusb1 :1.0.24-r0
libusb1-native :1.0.24-r0
libuv :1.42.0-r0
libuv-native :1.42.0-r0
libva :2.12.0-r0
libva-initial :2.12.0-r0
libva-utils :2.12.0-r0
libvorbis :1.3.7-r0
libwebp :1.2.1-r0
libwpe :1.10.1-r0
libx11 1:1.7.2-r0
libx11-native 1:1.7.2-r0
libxau 1:1.0.9-r0
libxau-native 1:1.0.9-r0
libxcb :1.14-r0
libxcb-native :1.14-r0
libxcomposite 1:0.4.5-r0
libxcomposite-native 1:0.4.5-r0
VERSIONS AND PRIORITIES
If there is more than one version of the same recipe, by default BitBake selects the
most recent recipe.
If recipes are in layers with different priorities (BBFILE_PRIORITY), the recipe in the
highest priority layer is selected.
When in doubt about which version is being selected, check PV with bitbake -e:
$ bitbake busybox -e | grep ^PV=
PV="1.34.1"
INSPECTING VERSIONS
The bitbake-layers command can be used to show recipes available in multiple
layers:
$ bitbake-layers show-overlayed
podman:
meta-toradex-torizon 3.4.1+gitAUTOINC+a6493ae690
meta-virtualization 2.0.1+gitAUTOINC+a11c4ead10
python3-colorama:
meta-virtualization 0.3.9
meta-python 0.4.3
python3-docker:
meta-lmp-base 4.2.1
meta-virtualization 4.2.0
python3-docker-compose:
meta-lmp-base 1.26.0
meta-virtualization 1.25.4
python3-scapy:
meta-security 2.4.3
meta-python 0.25
python3-websocket-client:
meta-virtualization 0.57.0
meta-python 0.56.0
...
DEBUGGING RECIPES
Several techniques can be used to debug problems in recipes:
Recipe processing logs analysis.
Variable inspection.
The Debugging Tools and Techniques section of the Yocto Project's development
manual has detailed information on debugging recipes.
RECIPE PROCESSING LOGS
In case of errors processing a recipe, check the logs generated in ${WORKDIR}/temp:
$ ls -1 temp/log.*
temp/log.do_cleansstate
temp/log.do_cleansstate.2772038
temp/log.do_compile
temp/log.do_compile.2779663
temp/log.do_configure
temp/log.do_configure.2778094
...
$ ls -1 temp/run.*
temp/run.do_configure
temp/run.do_configure.2778094
temp/run.do_fetch
temp/run.do_fetch.2776775
temp/run.do_patch
temp/run.do_patch.2776970
...
BITBAKE LOGS
General BitBake issues can be viewed with the -D parameter, which can be set
multiple times to increase the debug level.
If the task has already executed, running again won't have any effect. To force the
task to run, its build cache should be removed.
$ bitbake unzip -c cleansstate && bitbake unzip
In the devshell terminal, all environment variables needed for cross-compilation are
defined, making it possible to directly use compilation commands (make, cmake,
autotools, etc).
$ echo $CC
x86_64-poky-linux-gcc -m64 -march=core2 -mtune=core2 -msse3 -mfpmath=sse -fstack-protector-strong
For example, the recipe is processed, but the generated packages do not contain the
expected artifacts.
OpenEmbedded pkgdata tool - queries the pkgdata files written out during do_package
options:
-h, --help show this help message and exit
-d, --debug Enable debug output
-p PKGDATA_DIR, --pkgdata-dir PKGDATA_DIR
Path to pkgdata directory (determined automatically if not specified)
subcommands:
lookup-pkg Translate between recipe-space package names and runtime package names
list-pkgs List packages
list-pkg-files List files within a package
lookup-recipe Find recipe producing one or more packages
package-info Show version, recipe and size information for one or more packages
find-path Find package providing a target path
read-value Read any pkgdata value for one or more packages
glob Expand package name glob expression
Use oe-pkgdata-util <subcommand> --help to get help on a specific command
OE-PKGDATA-UTIL
$ oe-pkgdata-util list-pkgs lsof*
lsof
lsof-dbg
lsof-dev
lsof-doc
lsof-src
When processing a recipe, the build system will perform several checks to avoid
common problems and report them to the user.
Some checks just generate warning messages, but the execution completes
successfully.
A list of all existing QA checks is documented in the Yocto Project's Reference Manual:
https://docs.yoctoproject.org/ref-manual/qa-checks.html
If it's not possible or practical to solve a QA problem, the INSANE_SKIP variable can
be used to disable the check.
INSANE_SKIP:${PN} = "installed-vs-shipped"
LAB 5
CUSTOMIZING RECIPES
YOCTO PROJECT
IMAGE CUSTOMIZATION
CUSTOMIZING IMAGES
During the development of a Linux distribution with the Yocto Project, it will be
necessary to customize the final rootfs image, for several reasons:
Add or remove software components (packages).
Modify the size, format and type of the final image (ext4, f2fs, btrfs, etc).
And so on!
WHERE TO CUSTOMIZE?
An image can be customized in different places:
Changes can be made in the local.conf file.
For this reason, the local.conf file can be used for simple modifications and
prototyping, but changing it is not a recommended approach for production images
customization.
IMAGE RECIPES
Image recipes allow for greater flexibility and control in customizing the final
operating system image.
Other parameters for generating the final image (format, type, size, etc.).
IMAGE RECIPES
Usually, image recipes are stored in a directory called images. Example:
$ ls poky/meta/recipes-core/images/
build-appliance-image core-image-minimal-initramfs.bb
build-appliance-image_15.0.0.bb core-image-minimal-mtdutils.bb
core-image-base.bb core-image-ptest-all.bb
core-image-minimal.bb core-image-ptest-fast.bb
core-image-minimal-dev.bb core-image-tiny-initramfs.bb
It is very common to create new image recipes when working with the Yocto Project.
CORE-IMAGE-MINIMAL.BB
SUMMARY = "A small image just capable of allowing a device to boot."
LICENSE = "MIT"
inherit core-image
IMAGE_ROOTFS_SIZE ?= "8192"
IMAGE_ROOTFS_EXTRA_SPACE:append = "${@bb.utils.contains("DISTRO_FEATURES", "systemd", " + 4096", "",
CREATING IMAGE RECIPES
When creating an image recipe, we can build on top of existing recipes.
We can simply copy an existing image recipe to our layer and customize it.
After creating the image recipe, image-specific variables can be used to customize
the image, like IMAGE_INSTALL, CORE_IMAGE_EXTRA_INSTALL and IMAGE_FEATURES.
CORE-IMAGE-MINIMAL-MTDUTILS.BB
require core-image-minimal.bb
DESCRIPTION = "Small image capable of booting a device with support for the \
Minimal MTD Utilities, which let the user interact with the MTD subsystem in \
the kernel to perform operations on flash devices."
IMAGE_INSTALL += "mtd-utils"
ADDING PACKAGES
The IMAGE_INSTALL and CORE_IMAGE_EXTRA_INSTALL variables can be used in an
image recipe to add packages to the image.
IMAGE_INSTALL += "mtd-utils"
These variables must be set to the package name, not the recipe name!
Remember that one recipe can generate multiple packages, and the generated
packages will not necessarily have the same name used in the recipe!
RECIPES VS PACKAGES
$ bitbake pcre
...
NOTE: Tasks Summary: Attempted 717 tasks of which 717 didn't need to be rerun and all succeeded.
$ bitbake core-image-minimal
...
ERROR: Nothing RPROVIDES 'pcre' (but /opt/labs/ex/layers/poky/meta/recipes-core/images/core-image-min
NOTE: Runtime target 'pcre' is unbuildable, removing...
Missing or unbuildable dependency chain was: ['pcre']
ERROR: Required build target 'core-image-minimal' has no buildable providers.
Missing or unbuildable dependency chain was: ['core-image-minimal', 'pcre']
A packagegroup is nothing more than a recipe that inherits the packagegroup class
to group packages with common functionality.
PACKAGEGROUPS RECIPES
Typically, packagegroups are located in a directory called packagegroups:
$ ls poky/meta/recipes-core/packagegroups/
nativesdk-packagegroup-sdk-host.bb
packagegroup-base.bb
packagegroup-core-boot.bb
packagegroup-core-buildessential.bb
packagegroup-core-eclipse-debug.bb
packagegroup-core-nfs.bb
packagegroup-core-sdk.bb
packagegroup-core-ssh-dropbear.bb
packagegroup-core-ssh-openssh.bb
packagegroup-core-standalone-sdk-target.bb
packagegroup-core-tools-debug.bb
packagegroup-core-tools-profile.bb
packagegroup-core-tools-testapps.bb
packagegroup-cross-canadian.bb
packagegroup-go-cross-canadian.bb
packagegroup-go-sdk-target.bb
packagegroup-rust-cross-canadian.bb
packagegroup-self-hosted.bb
PACKAGEGROUP-CORE-ECLIPSE-DEBUG.BB
SUMMARY = "Remote debugging tools for Eclipse integration"
inherit packagegroup
RDEPENDS:${PN} = "\
gdbserver \
tcf-agent \
openssh-sftp-server \
"
USING PACKAGEGROUPS
A packagegroup can be added to an image using the IMAGE_INSTALL and
CORE_IMAGE_EXTRA_INSTALL variables.
While others will directly change the content of the generated image.
IMAGE_FEATURES = "read-only-rootfs"
The NO_RECOMMENDATIONS variable allows removing from the image all packages
that were installed through the RRECOMMENDS variable.
ADDING USERS AND GROUPS
The useradd and extrausers classes can be used to add users and groups to the
generated image.
It's recommended to use the useradd class when the user/group to be created is
associated with a package installed in the image.
https://docs.yoctoproject.org/ref-manual/classes.html#useradd-bbclass
It's recommended to use the extrausers class when the user/group is global to the
image, and not associated with any specific program or package.
https://docs.yoctoproject.org/ref-manual/classes.html#extrausers-bbclass
EXAMPLE: USERADD
inherit useradd
USERADD_PACKAGES = "${PN}"
do_install:append () {
install -d -m 755 ${D}${datadir}/user1
install -d -m 755 ${D}${datadir}/user2
This may be necessary if you want to apply global permission settings on the image
(settings associated with an application should be made in the corresponding
recipe).
...
# Fixup locales
${datadir}/locale 0755 root root true 0644 root root
...
ADDING FILES
A common need when customizing images is the addition of files (blobs, shell scripts,
configuration files, etc).
If the file is related to a certain software, we can change the corresponding recipe to
add it to the image.
In case the file is not associated with any software, we can create a specific recipe to
add it to the image.
EXAMPLE: ADDING FILES
DESCRIPTION = "Some closed source library from hell"
LICENSE = "CLOSED"
SRC_URI = "http://hell.com/mylib.so;unpack=false"
SRC_URI[sha256sum] = "2ea483c3c4ce87f4a3c851077c3b8ea8e7d5539 8bfb56fa3b0765e65085617bd"
do_install() {
install -d ${D}${libdir}
install -m 0755 ${WORKDIR}/mylib.so ${D}${libdir}
}
FILES_${PN} = "${libdir}/mylib.so"
POST-INSTALL SCRIPTS
Packages may contain post-install scripts, which allow the execution of commands
during their installation (during rootfs generation or at runtime).
They are useful to prepare the root filesystem for a certain package (create
directories and temporary files, set permissions, change configuration files, etc).
There is also support for pre-install, pre-uninstall, and post-uninstall scripts through
the pkg_preinst, pkg_prerm and pkg_postrm functions, respectively.
EXAMPLE: POST-INSTALL SCRIPTS
$ cat meta-openembedded/meta-oe/recipes-shells/zsh/zsh_5.8.bb
...
pkg_postinst:${PN} () {
touch $D${sysconfdir}/shells
grep -q "bin/zsh" $D${sysconfdir}/shells || echo /bin/zsh >> $D${sysconfdir}/shells
grep -q "bin/sh" $D${sysconfdir}/shells || echo /bin/sh >> $D${sysconfdir}/shells
}
$ cat poky/meta/recipes-connectivity/avahi/avahi_0.8.bb
...
pkg_postinst:avahi-daemon () {
if [ -z "$D" ]; then
killall -q -HUP dbus-daemon || true
fi
}
POST-INSTALL ON BOOT
Sometimes it is necessary to delay running a post-installation script until the device
first boots.
It might be useful when it's required to run the post-installation script directly on the
target.
The functions added to this variable are executed at the end of the rootfs generation
process.
For example, the code below is intended to change the password of the admin user:
run_set_admin_pass () {
sed 's%^admin:[^:]*:%admin:$6$3WWbKfr1$4vblknvGr6FcDe:\
%' ${IMAGE_ROOTFS}/etc/shadow \
${IMAGE_ROOTFS}/etc/shadow.new;
mv ${IMAGE_ROOTFS}/etc/shadow.new \
${IMAGE_ROOTFS}/etc/shadow ;"
}
ROOTFS_POSTPROCESS_COMMAND += " run_set_admin_pass ; "
CHANGING THE IMAGE FORMAT
The IMAGE_FSTYPES variable can be used to change the rootfs image format.
IMAGE_FSTYPES = "ext4"
A list of existing image types is available in the Yocto Project reference guide.
https://docs.yoctoproject.org/ref-manual/variables.html#term-IMAGE_TYPES
The IMAGE_CMD variable can be used to define custom image formats (see
poky/meta/classes/image_types.bbclass for more examples):
IMAGE_CMD:jffs2 = "mkfs.jffs2 --root=${IMAGE_ROOTFS} --faketime \
--output=${IMGDEPLOYDIR}/${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.jffs2 \
${EXTRA_IMAGECMD}"
CHANGING THE IMAGE SIZE
The IMAGE_ROOTFS_SIZE variable can be used to set the final rootfs size (in KBs).
IMAGE_ROOTFS_SIZE = "1048576"
To have more control over package selection, build options and other low-level
settings, a custom distribution can be created.
poky/meta/conf/distro/defaultsetup.conf
To use the distribution, the DISTRO variable needs to be defined in local.conf with the
same name as the distro configuration file.
DISTRO VARIABLES
Variable Description
DISTRO Distribution name
DISTRO_NAME Long distribution name
DISTRO_VERSION Distribution Version
TCMODE Toolchain
TCLIBC C library (glibc, musl, newlib, baremetal)
INIT_MANAGER Init system (sysvinit, systemd, mdev-busybox)
DISTRO VARIABLES
Variable Description
DISTRO_EXTRA_RDEPENDS Add packages to the image
DISTRO_EXTRA_RRECOMMENDS Add packages to the image (if they exist)
PREFERRED_VERSION Set/force a Package Version
PACKAGE_CLASSES Package type to be used
DISTROOVERRIDES Distribution-specific overrides
MIRRORS/PREMIRRORS Alternative sources for source code download
DISTRO FEATURES
Distro features allow to control the software installed in the image:
Enable the installation of additional packages.
Distro features are defined in distro configuration files via the DISTRO_FEATURES
variable:
DISTRO_FEATURES = "opengl ppp ipv6 usrmerge"
The complete list of distro features is documented in the Yocto Project's Reference
Manual.
https://docs.yoctoproject.org/ref-manual/features.html#distro-features
PACKAGEGROUP-CORE-FULL-CMDLINE.BB
SUMMARY = "Standard full-featured Linux system"
DESCRIPTION = "Package group bringing in packages needed for a more traditional full-featured Linux s
PR = "r6"
inherit packagegroup
...
RDEPENDS:packagegroup-core-full-cmdline-sys-services = "\
at \
cronie \
logrotate \
${@bb.utils.contains('DISTRO_FEATURES', 'nfs', 'nfs-utils rpcbind', '', d)} \
"
LIBPCAP_1.10.1.BB
SUMMARY = "Interface for user-level network packet capture"
DESCRIPTION = "Libpcap provides a portable framework for low-level network \
monitoring. Libpcap can provide network statistics collection, \
security monitoring and network debugging."
...
...
RUNTIME PACKAGE MANAGEMENT
With the Yocto Project, it's possible to build an image with package management
support.
On the target, package management tools are installed to make it possible to:
Install and remove packages from the image at runtime.
Some additional variables can be defined to configure the package server location
(PACKAGE_FEED_URIS, PACKAGE_FEED_ARCHS, etc).
On the host, each time packages are changed, it is necessary to regenerate the
package index with the command below:
$ bitbake package-index
When initializing the build directory, the environment variable TEMPLATECONF can
be used to define the location of the template files:
$ export TEMPLATECONF=$PWD/layers/meta-labworks/conf
$ source layers/poky/oe-init-build-env build-test
TIPS FOR CUSTOMIZATION
Use local.conf for testing and prototyping, but concentrate changes in a separate
layer, using image recipes and distro configuration files for production images
customizations.
It is recommended to create a distribution with the settings and policies that will
serve as the basis for your products.
MANAGING LAYERS
Try to organize the metadata in layers to make it easier to maintain:
Separate BSP, distro and software metadata into different layers.
CUSTOMIZING IMAGES
YOCTO PROJECT
BSP DEVELOPMENT
BSP LAYER
BSP (Board Support Package) is a term used to refer to all the source code necessary
for a hardware platform to support a certain operating system (in our case, the Linux
kernel).
To support a new hardware platform in the Yocto Project, a BSP layer is required.
Classes for the target platform (e.g. logic to generate a custom image format).
META-YOCTO-BSP
$ tree -L 3 poky/meta-yocto-bsp/
poky/meta-yocto-bsp/
├── conf
│ ├── layer.conf
│ └── machine
│ ├── beaglebone-yocto.conf
│ ├── edgerouter.conf
│ ├── genericx86-64.conf
│ ├── genericx86.conf
│ └── include
├── lib
│ └── oeqa
│ ├── controllers
│ └── selftest
├── README.hardware.md
├── recipes-bsp
│ ├── formfactor
│ │ ├── formfactor
│ │ └── formfactor_0.0.bbappend
│ └── gma500-gfx-check
│ ├── gma500-gfx-check
│ └── gma500-gfx-check_1.0.bb
├── recipes-graphics
│ └── xorg-xserver
CREATING A BSP LAYER
Before creating a BSP layer, check if there isn't already an implementation available
for the target platform.
It's very common for vendors and hardware manufacturers to support the Yocto
Project by providing a BSP layer for their products.
The BSP Development Guide has a lot of information on how to create and maintain
BSP layers for the Yocto Project.
https://docs.yoctoproject.org/bsp-guide/index.html
STRUCTURE OF A BSP LAYER
$ tree meta-labworks-bsp
meta-labworks-bsp
├── classes
├── conf
│ ├── layer.conf
│ └── machine
│ └── my-machine.conf
├── recipes-bsp
│ └── u-boot
├── recipes-core
├── recipes-graphics
└── recipes-kernel
└── linux
MACHINE CONFIGURATION FILE
One of the main tasks when developing a BSP layer is implementing the machine
configuration file.
In this file, we must define all the necessary information about the hardware,
including:
Hardware architecture and compiler optimization options.
Most of the time, we can create a machine configuration file based on other
implementations for the same SoC.
CPU ARCHITECTURE
In the machine configuration file, the CPU architecture is usually defined by including
a file that contains the settings for a particular hardware platform.
require conf/machine/include/tune-cortexa9.inc
In these files, some variables like TARGET_ARCH, DEFAULTTUNE and TUNE_ARCH are
set so that the build system knows the hardware architecture. This way:
A toolchain optimized for the target platform is generated.
MACHINEOVERRIDES =. "qemuall:"
This feature allows the use of conditional assignment per architecture or machine in
other metadata.
SRC_URI:append:mx6 = " file://fix-imx6-bug.patch"
BOOTLOADER AND KERNEL
In the machine configuration file, we also need to define bootloader and kernel
recipes that will be used to generate the Linux distribution for the target platform.
To use these variables, we need to understand how the PROVIDES mechanism and
BitBake virtual packages work.
PROVIDES
An specific software artifact (e.g. a kernel image) might be provided by more than
one recipe.
For a recipe to indicate that it provides a certain software artifact, there is the
concept of virtual package.
For example, a kernel recipe will use the PROVIDES variable to indicate that it
provides the Linux kernel virtual package:
PROVIDES += "virtual/kernel"
Enabling a machine feature might result in adding additional packages to the image
and/or changing the way some software is compiled.
PR = "r13"
...
RRECOMMENDS:${PN} = "\
${MACHINE_EXTRA_RRECOMMENDS} \
${@bb.utils.contains("MACHINE_FEATURES", "usbhost", "usbutils", "", d)} \
${@bb.utils.contains("MACHINE_FEATURES", "alsa", "alsa-utils-alsamixer", "", d)} \
${@bb.utils.contains("MACHINE_FEATURES", "usbgadget", "kernel-module-g-ether kernel-module-g-seri
\
${@bb.utils.contains("DISTRO_FEATURES", "bluetooth", "bluez5", "", d)} \
${@bb.utils.contains("DISTRO_FEATURES", "wifi", "iw wpa-supplicant", "", d)} \
\
tzdata \
\
cpufrequtils \
htop \
"
...
EXAMPLE: MATCHBOX-PANEL-2_2.11.BB
SUMMARY = "Simple GTK+ based panel for handheld devices"
DESCRIPTION = "A flexible always present 'window bar' for holding application \
launchers and small 'applet' style applications"
HOMEPAGE = "http://matchbox-project.org"
BUGTRACKER = "http://bugzilla.yoctoproject.org/"
...
...
...
MACHINE FEATURES VS DISTRO FEATURES
Machine features and distro features work together to add support for certain
functionality in the Linux distribution.
Some features will only be enabled if they are in both variables (DISTRO_FEATURES
and MACHINE_FEATURES).
...
RRECOMMENDS:${PN} = "\
kernel-module-pxaficp-ir \
kernel-module-irda \
kernel-module-ircomm \
kernel-module-ircomm-tty \
kernel-module-irlan \
${@bb.utils.contains('DISTRO_FEATURES', 'ppp', 'kernel-module-irnet', '',d)} \
kernel-module-irport \
kernel-module-irtty \
kernel-module-irtty-sir \
kernel-module-sir-dev \
${@bb.utils.contains('COMBINED_FEATURES', 'usbhost', 'kernel-module-ir-usb', '',d)} "
...
MACHINE: BEAGLEBONE-YOCTO.CONF
#@TYPE: Machine
#@NAME: Beaglebone-yocto machine
#@DESCRIPTION: Reference machine configuration for http://beagleboard.org/bone and http://beagleboard
PREFERRED_PROVIDER_virtual/xserver ?= "xserver-xorg"
XSERVER ?= "xserver-xorg \
xf86-video-modesetting \
"
EXTRA_IMAGEDEPENDS += "virtual/bootloader"
DEFAULTTUNE ?= "cortexa8hf-neon"
include conf/machine/include/arm/armv7a/tune-cortexa8.inc
include conf/machine/include/imx-base.inc
include conf/machine/include/arm/armv7a/tune-cortexa9.inc
IMX_DEFAULT_BOOTLOADER = "u-boot-toradex"
PREFERRED_PROVIDER_u-boot-default-script = "u-boot-script-toradex"
UBOOT_SUFFIX = "img"
SPL_BINARY = "SPL"
UBOOT_CONFIG ??= "spl"
UBOOT_CONFIG[spl] = "colibri_imx6_defconfig,,u-boot.img"
UBOOT_MAKE_TARGET = ""
UBOOT ENTRYPOINT:use-mainline-bsp = "0x10008000"
ENABLING THE MACHINE
To enable the machine, first add its layer to the bblayers.conf file:
BBLAYERS ?= "\
/opt/labs/ex/layers/poky/meta \
/opt/labs/ex/layers/poky/meta-poky \
/opt/labs/ex/layers/poky/meta-yocto-bsp \
/opt/labs/ex/layers/meta-labworks \
/opt/labs/ex/layers/meta-labworks-bsp \
"
And set the MACHINE variable in local.conf with the name used in the machine
configuration file.
MACHINE ??= "colibri-imx6"
CREATING BSP RECIPES
A BSP layer will probably need some recipes, at least for compiling the bootloader
and the Linux kernel.
Creating a recipe for a BSP layer is no different from other layers (the only detail is
that there are some specific BSP-related classes that we can use).
To compile U-Boot, it's necessary to include the file recipes-bsp/u-boot/u-boot.inc
in the recipe (currently, there is no class to compile U-Boot).
To compile the Linux kernel, the kernel class can be inherited. Optionally, the
kernel-yocto class can also be inherited to benefit from additional features such
as the Kernel Advanced Metadata.
require recipes-bsp/u-boot/u-boot.inc
PV = "2020.07+git${SRCPV}"
SRC_URI = " \
git://git.toradex.com/u-boot-toradex.git;branch=${SRCBRANCH} \
file://fw_env.config \
"
SRCBRANCH = "toradex_2020.07"
SRCREV = "ab862daf5d5a2eebf305c5c125f0463b0ff34161"
UBOOT_INITIAL_ENV = "u-boot-initial-env"
PROVIDES += "u-boot"
B = "${WORKDIR}/build"
S = "${WORKDIR}/git"
EXAMPLE: LINUX-YOCTO-CUSTOM.BB
inherit kernel
require recipes-kernel/linux/linux-yocto.inc
LINUX_VERSION ?= "4.2"
LINUX_VERSION_EXTENSION:append = "-custom"
PV = "${LINUX_VERSION}+git${SRCPV}"
inherit module
SRC_URI = "file://Makefile \
file://hello.c \
file://COPYING \
"
S = "${WORKDIR}"
RPROVIDES:${PN} += "kernel-module-hello"
EXTENDING A BSP
Many vendors provide Yocto Project based BSPs ready to use with their hardware
platforms.
In this case, instead of creating a BSP layer from scratch, we can simply extend the
vendor's BSP.
Use patch files to apply changes software components (bootloader, kernel, etc).
CONFIGURING THE KERNEL
A common need for BSP customization is changing the kernel configuration.
The kernel configuration menu can be opened directly with BitBake executing the
menuconfig task.
$ bitbake virtual/kernel -c menuconfig
The configuration is done directly in the kernel build directory, so you can just
recompile the kernel to test the changes.
However, the configuration will not be persistent, and may be lost in an eventual
cleanup of the kernel build directory.
CONFIGURING THE KERNEL
For more control, customizations in the kernel configuration can be saved along with
the metadata in a BSP layer.
Then an append file for the kernel recipe can be created to add the defconfig file to
the SRC_URI variable.
OVERRIDING THE CONFIGURATION
$ tree recipes-kernel/
recipes-kernel
└── linux
├── files
│ └── defconfig
└── linux-toradex_%.bbappend
$ cat recipes-kernel/linux/linux-toradex_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI += "file://defconfig"
CONFIGURATION FRAGMENTS
Configuration fragments allow to define parts of the kernel configuration in files with
the .cfg extension.
An append file for the kernel recipe can be created to add the configuration
fragments to the SRC_URI variable.
CONFIGURATION FRAGMENTS
$ tree recipes-kernel/
recipes-kernel
└── linux
├── files
│ └── ntfs.cfg
└── linux-yocto_%.bbappend
$ cat recipes-kernel/linux/files/ntfs.cfg
CONFIG_NTFS_FS=y
$ cat recipes-kernel/linux/linux-yocto_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI += "file://ntfs.cfg"
PATCHING THE KERNEL
Keeping some kernel patches in the BSP layer might be necessary when we choose to
not maintain a custom kernel repository.
To apply kernel patches we can follow the same process that we have already studied
in the training.
Important: if the amount of kernel patches in the BSP layer starts to grow (5+), it's
time to think about forking the kernel or even upstreaming the work!
This also applies to U-Boot patches.
PATCHING THE KERNEL
$ tree recipes-kernel/
recipes-kernel/
└── linux
├── files
│ └── 0001-fixbug.patch
└── linux-toradex_%.bbappend
$ cat recipes-kernel/linux/linux-toradex_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI += "file://0001-fixbug.patch"
ADVANCED METADATA
Another way to configure the kernel is through a feature called Advanced Metadata.
The idea is to organize patches and kernel configuration fragments into features,
which can be enabled as needed.
A kernel feature is described in a file with the .scc extension and can be enabled
through the SRC_URI or KERNEL_FEATURES variables.
Complete documentation about this feature is available in the Yocto Project's Kernel
Development Manual.
https://docs.yoctoproject.org/kernel-dev/advanced.html
EXAMPLE: ADVANCED METADATA
$ tree meta-labworks/recipes-kernel/linux/
meta-labworks/recipes-kernel/linux/
├── files
│ ├── 0001-fix-tpm2-bug.patch
│ ├── tpm2.cfg
│ └── tpm2.scc
└── linux-yocto_%.bbappend
$ cat meta-labworks/recipes-kernel/linux/files/tpm2.scc
define KFEATURE_DESCRIPTION "Enable TPM 2.0"
kconf hardware tpm2.cfg
patch 0001-fix-tpm2-bug.patch
$ cat meta-labworks/recipes-kernel/linux/files/tpm2.cfg
CONFIG_HW_RANDOM_TPM=y
CONFIG_TCG_TPM=y
CONFIG_TCG_TIS_CORE=y
CONFIG_TCG_TIS=y
$ cat meta-labworks/recipes-kernel/linux/linux-yocto_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI:append = " file://tpm2.scc"
LAB 7
The build system is an integration tool focused on helping with building and
maintaining the software artifacts of the operating system.
It might not be very effective as an application development tool
(write/compile/deploy/test workflow).
For this reason, build systems usually provide developers with a set of development
tools, which are generically called SDK.
SDK
An SDK (Software Development Kit) provides an infrastructure of tools, libraries and
utilities that enable the development of applications for a specific target platform.
Binaries with debugging symbols (useful for debugging and resolving symbols).
The sysroot content is usually based on the rootfs of an image generated for the
target.
SCRIPTS AND OTHER TOOLS
An SDK may contain configuration scripts and other additional tools.
The generated SDK will be a self-contained installation script that can be executed on
development machines.
META-TOOLCHAIN
A generic SDK with a basic sysroot can be generated by processing the meta-
toolchain recipe.
$ bitbake meta-toolchain
This SDK can be used for bare-metal development (bootloader, kernel) or to compile
simple applications.
META-TOOLCHAIN: INSTALLING
$ tmp/deploy/sdk/poky-glibc-x86_64-meta-toolchain-cortexa9t2hf-neon-colibri-imx6-training-toolchain-4
Poky (Yocto Project Reference Distro) SDK installer version 4.0.1
=================================================================
Enter target directory for SDK (default: /opt/poky/4.0.1):
You are about to install the SDK to "/opt/poky/4.0.1". Proceed [Y/n]? y
[sudo] password for sprado:
Extracting SDK..............................................done
Setting it up...done
SDK has been successfully set up and is ready to be used.
Each time you wish to use the SDK in a new shell session, you need to source the environment setup sc
$ . /opt/poky/4.0.1/environment-setup-cortexa9t2hf-neon-poky-linux-gnueabi
$ ls -l /opt/poky/4.0.1/
total 36
-rw-r--r-- 1 root root 4084 jul 13 11:21 environment-setup-cortexa9t2hf-neon-poky-linux-gnueabi
-rw-r--r-- 1 root root 22387 jul 13 11:21 site-config-cortexa9t2hf-neon-poky-linux-gnueabi
drwxr-xr-x 4 root root 4096 jul 13 11:20 sysroots
-rw-r--r-- 1 root root 90 jul 13 11:21 version-cortexa9t2hf-neon-poky-linux-gnueabi
META-TOOLCHAIN: USING
$ source /opt/poky/4.0.1/environment-setup-cortexa9t2hf-neon-poky-linux-gnueabi
$ echo $CC
arm-poky-linux-gnueabi-gcc -mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a9 -fstack-protector-stro
$ $CC --version
arm-poky-linux-gnueabi-gcc (GCC) 11.3.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ cat main.c
int main(void){return 0;}
$ file main
main: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /li
POPULATE_SDK
A complete SDK with a sysroot based on an image can be generated by processing
the populate_sdk task:
$ bitbake core-image-minimal -c populate_sdk
This SDK can be used for the development of bare-metal code and Linux applications,
making it possible to link with any library installed in the system image.
POPULATE_SDK: INSTALLING
$ tmp/deploy/sdk/poky-glibc-x86_64-core-image-minimal-cortexa9t2hf-neon-colibri-imx6-training-toolcha
Poky (Yocto Project Reference Distro) SDK installer version 4.0.1
=================================================================
Enter target directory for SDK (default: /opt/poky/4.0.1): y
You are about to install the SDK to "/opt/labs/ex/build/y". Proceed [Y/n]? y
Extracting SDK................................................................................done
Setting it up...done
SDK has been successfully set up and is ready to be used.
Each time you wish to use the SDK in a new shell session, you need to source the environment setup sc
$ . /opt/labs/ex/build/y/environment-setup-cortexa9t2hf-neon-poky-linux-gnueabi
$ ls -l /opt/poky/4.0.1/
total 36
-rw-r--r-- 1 root root 4084 jul 13 11:21 environment-setup-cortexa9t2hf-neon-poky-linux-gnueabi
-rw-r--r-- 1 root root 22387 jul 13 11:21 site-config-cortexa9t2hf-neon-poky-linux-gnueabi
drwxr-xr-x 4 root root 4096 jul 13 11:20 sysroots
-rw-r--r-- 1 root root 90 jul 13 11:21 version-cortexa9t2hf-neon-poky-linux-gnueabi
POPULATE_SDK: USING
$ source /opt/poky/4.0.1/environment-setup-cortexa9t2hf-neon-poky-linux-gnueabi
$ echo $CC
arm-poky-linux-gnueabi-gcc -mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a9 -fstack-protector-stro
$ $CC --version
arm-poky-linux-gnueabi-gcc (GCC) 11.3.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ cat main.c
int main(void){return 0;}
$ file main
main: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /li
POPULATE_SDK: AUTOTOOLS
$ ls
configure.ac hello.c Makefile.am
$ cat hello.c
#include <stdio.h>
int main(void) { printf("Hello World!\n"); }
$ cat configure.ac
AC_INIT(hello,0.1)
AM_INIT_AUTOMAKE([foreign])
AC_PROG_CC
AC_CONFIG_FILES(Makefile)
AC_OUTPUT
$ cat Makefile.am
bin_PROGRAMS = hello
hello_SOURCES = hello.c
POPULATE_SDK: AUTOTOOLS
$ source /opt/poky/4.0.1/environment-setup-cortexa9t2hf-neon-poky-linux-gnueabi
$ autoreconf
$ ls
aclocal.m4 autom4te.cache compile configure configure.ac depcomp
hello.c install-sh Makefile.am Makefile.in missing
$ ./configure ${CONFIGURE_FLAGS}
$ echo $CONFIGURE_FLAGS
--target=arm-poky-linux-gnueabi --host=arm-poky-linux-gnueabi --build=x86_64-linux
--with-libtool-sysroot=/opt/poky/4.0.1/sysroots/cortexa9t2hf-neon-poky-linux-gnueabi
$ make
This SDK is called Extensible SDK (eSDK) and extends the functionality of a normal SDK,
allowing to customize and manipulate the operating system image through the devtool
tool.
POPULATE_SDK_EXT: INSTALLING
$ tmp/deploy/sdk/poky-glibc-x86_64-core-image-training-cortexa9t2hf-neon-colibri-imx6-training-toolch
Poky (Yocto Project Reference Distro) Extensible SDK installer version 4.0.1
============================================================================
Enter target directory for SDK (default: ~/poky_sdk):
You are about to install the SDK to "/home/sprado/poky_sdk". Proceed [Y/n]?
Extracting SDK.......................................................done
Setting it up...
Extracting buildtools...
Preparing build system...done
SDK has been successfully set up and is ready to be used.
Each time you wish to use the SDK in a new shell session, you need to source the environment setup sc
$ . /home/sprado/poky_sdk/environment-setup-cortexa9t2hf-neon-poky-linux-gnueabi
$ ls /home/sprado/poky_sdk/
bitbake-cookerdaemon.log preparing_build_system.log
buildtools site-config-cortexa9t2hf-neon-poky-linux-gnue
cache sstate-cache
conf sysroots
downloads tmp
environment-setup-cortexa9t2hf-neon-poky-linux-gnueabi version-cortexa9t2hf-neon-poky-linux-gnueabi
layers workspace
POPULATE_SDK_EXT: USING
$ source ~/poky_sdk/environment-setup-cortexa9t2hf-neon-poky-linux-gnueabi
SDK environment now set up; additionally you may now run devtool to perform development tasks.
Run devtool --help for further details.
$ echo $CC
arm-poky-linux-gnueabi-gcc -mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a9 -fstack-protector-stro
$ $CC --version
arm-poky-linux-gnueabi-gcc (GCC) 11.3.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ cat main.c
int main(void){return 0;}
$ file main
main: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib
DEVTOOL
The big difference between the SDK generated with the populate_sdk task and the
SDK generated with the populate_sdk_ext task is the support for the devtool tool.
This tool provides a set of functionality to help develop and integrate software into
an image generated with OpenEmbedded/Yocto Project.
It has a Git-like design, with sub-commands for each of the supported features.
devtool is not only limited to the SDK and can be used in the Yocto Project build
environment.
INTERESTING COMMANDS
devtool add: creates a recipe from an application's source code.
devtool finish: integrates the generated metadata (recipes, appends, etc) into a layer.
$ tree -L 3 workspace/
workspace/
├── appends
│ └── fping_4.4.bbappend
├── conf
│ └── layer.conf
├── README
├── recipes
│ └── fping
│ └── fping_4.4.bb
└── sources
└── fping
├── aclocal.m4
├── CHANGELOG.md
├── ci
├── compile
├── ...
└── src
GENERATED REVENUE: FPING_4.4.BB
# Recipe created by recipetool
# This is the basis of a recipe and may need further editing in order to be fully functional.
# (Feel free to remove these comments when editing.)
# WARNING: the following LICENSE and LIC_FILES_CHKSUM values are best guesses - it is
# your responsibility to verify that the values are complete and correct.
#
# The following license files were not able to be identified and are
# represented as "Unknown" below, you will need to check them yourself:
# COPYING
LICENSE = "Unknown"
LIC_FILES_CHKSUM = "file://COPYING;md5=c6170fbadddfcd74f011515291d96901"
SRC_URI = "http://www.fping.org/dist/fping-${PV}.tar.gz"
SRC_URI[md5sum] = "10e50c164ddff6941eff5fef41c21e3d"
SRC_URI[sha1sum] = "8be8be5b8dc5c0dd3505db79b8fe1438fe4ef590"
SRC_URI[sha256sum] = "9f854b65a52dc7b1749d6743e35d0a6268179d1a724267339fc9a066b2b72d11"
SRC_URI[sha384sum] = "1647b4cf07d751961fbe37bde12292dbc3820e396fe37271d088168a605588a7b4def9f14ac6978
SRC_URI[sha512sum] = "8c9ff78edee10ce8e02a0d6189d4a2d91cc60954740c15730f8f1a17d037ee9f565828fa0dcd47a
# NOTE: if this software is not capable of being built in a separate build directory
# from the source, you should replace autotools with autotools-brokensep in the
# inherit line
inherit autotools
DEVTOOL EDIT-RECIPE
$ devtool edit-recipe fping
SRC_URI = "http://www.fping.org/dist/fping-${PV}.tar.gz"
-SRC_URI[md5sum] = "10e50c164ddff6941eff5fef41c21e3d"
-SRC_URI[sha1sum] = "8be8be5b8dc5c0dd3505db79b8fe1438fe4ef590"
SRC_URI[sha256sum] = "9f854b65a52dc7b1749d6743e35d0a6268179d1a724267339fc9a066b2b72d11"
-SRC_URI[sha384sum] = "1647b4cf07d751961fbe37bde12292dbc3820e396fe37271d088168a605588a7b4def9f14ac697
-SRC_URI[sha512sum] = "8c9ff78edee10ce8e02a0d6189d4a2d91cc60954740c15730f8f1a17d037ee9f565828fa0dcd47
# NOTE: if this software is not capable of being built in a separate build directory
# from the source, you should replace autotools with autotools-brokensep in the
DEVTOOL BUILD/DEPLOY-TARGET
$ devtool build fping
...
NOTE: fping: compiling from external source tree /home/sprado/poky_sdk/workspace/sources/fping
NOTE: Tasks Summary: Attempted 621 tasks of which 595 didn't need to be rerun and all succeeded.
# fping --version
fping: Version 4.4
fping: comments to david@schweikert.ch
DEVTOOL FINISH
$ devtool finish --force --remove-work fping meta-labworks
...
INFO: No patches or files need updating
INFO: Moving recipe file to /home/sprado/poky_sdk/layers/meta-labworks/recipes-fping/fping
INFO: -r argument used on fping, removing source tree. You will lose any unsaved work
$ tree layers/meta-labworks/recipes-fping/
layers/meta-labworks/recipes-fping/
└── fping
└── fping_4.4.bb
DEVTOOL UPGRADE
$ devtool upgrade --version 5.0 fping
...
INFO: Rebasing devtool onto d6ab87c90bc0b5b542db1c302edf2f15cc6df490
INFO: Upgraded source extracted to /home/sprado/poky_sdk/workspace/sources/fping
INFO: New recipe is /home/sprado/poky_sdk/workspace/recipes/fping/fping_5.0.bb
# fping --version
fping: Version 5.0
$ ls layers/meta-labworks/recipes-fping/fping/
fping_5.0.bb
DEVTOOL MODIFY
$ devtool modify fping
INFO: Source tree extracted to /home/sprado/poky_sdk/workspace/sources/fping
INFO: Recipe fping now set up to build from /home/sprado/poky_sdk/workspace/sources/fping
$ cd workspace/sources/fping
$ vim src/fping.c && git commit -s -m "change version message"
# fping --version
fping: Version 5.0 (test)
$ tree layers/meta-labworks/recipes-fping/
layers/meta-labworks/recipes-fping/
└── fping
├── fping
│ └── 0001-change-version-message.patch
└── fping_5.0.bb
DEVTOOL --HELP
$ devtool --help
usage: devtool [--basepath BASEPATH] [--bbpath BBPATH] [-d] [-q] [--color COLOR] [-h] <subcommand> .
options:
--basepath BASEPATH Base directory of SDK / build directory
--bbpath BBPATH Explicitly specify the BBPATH, rather than getting it from the metadata
-d, --debug Enable debug output
-q, --quiet Print only errors
--color COLOR Colorize output (where COLOR is auto, always, never)
-h, --help show this help message and exit
subcommands:
Beginning work on a recipe:
add Add a new recipe
modify Modify the source for an existing recipe
upgrade Upgrade an existing recipe
Getting information:
status Show workspace status
search Search available recipes
latest-version Report the latest version of an existing recipe
check-upgrade-status Report upgradability for multiple (or all) recipes
Working on a recipe in the workspace:
SDK VS ESDK
Feature SDK (populate_sdk) eSDK (populate_sdk_ext)
Toolchain Yes Yes
Debugger Yes Yes
Size 100+ MBytes 1+ GBytes
devtool No Yes
Compile Images No Yes
Upgradable No Yes
Manageable sysroot No Yes
Construction Packages Shared State
LAB 8
Build history.
Toaster.
A warning message is displayed if the license declared in the LICENSE variable is not
found.
COMMON-LICENSES
$ ls poky/meta/files/common-licenses/
0BSD DRL-1.0 NLOD-2.0
AAL DSDP NLPL
Abstyles DSSSL Nokia
Adobe dvipdfm NOSL
Adobe-2006 ECL-1.0 Noweb
Adobe-Glyph ECL-2.0 NPL-1.0
ADSL eCos-2.0 NPL-1.1
AFL-1.1 EDL-1.0 NPOSL-3.0
AFL-1.2 EFL-1.0 NRL
AFL-2.0 EFL-2.0 NTP
AFL-2.1 eGenix NTP-0
AFL-3.0 Entessa OASIS
Afmparse EPICS OCCT-PL
AGPL-1.0-only EPL-1.0 OCLC-2.0
AGPL-1.0-or-later EPL-2.0 ODbL-1.0
AGPL-3.0-only ErlPL-1.1 ODC-By-1.0
AGPL-3.0-or-later etalab-2.0 OFL-1.0
Aladdin EUDatagrid OFL-1.0-no-RFN
AMDPLPA EUPL-1.0 OFL-1.0-RFN
AML EUPL-1.1 OFL-1.1
...
LICENSES.CONF
$ cat meta/conf/licenses.conf
# Standards are great! Everyone has their own. In an effort to standardize licensing
# names, common-licenses will use the SPDX standard license names. In order to not
# break the non-standardized license names that we find in LICENSE, we'll set
# up a bunch of VarFlags to accommodate non-SPDX license names.
#
# We should really discuss standardizing this field, but that's a longer term goal.
# For now, we can do this and it should grab the most common LICENSE naming variations.
#
# We should NEVER have a GPL/LGPL without a version!!!!
# Any mapping to MPL/LGPL/GPL should be fixed
# AGPL variations
SPDXLICENSEMAP[AGPL-3] = "AGPL-3.0-only"
SPDXLICENSEMAP[AGPL-3+] = "AGPL-3.0-or-later"
SPDXLICENSEMAP[AGPLv3] = "AGPL-3.0-only"
SPDXLICENSEMAP[AGPLv3+] = "AGPL-3.0-or-later"
SPDXLICENSEMAP[AGPLv3.0] = "AGPL-3.0-only"
SPDXLICENSEMAP[AGPLv3.0+] = "AGPL-3.0-or-later"
SPDXLICENSEMAP[AGPL-3.0] = "AGPL-3.0-only"
SPDXLICENSEMAP[AGPL-3.0+] = "AGPL-3.0-or-later"
# BSD variations
SPDXLICENSEMAP[BSD-0-Clause] = "0BSD"
DISABLING A LICENSE
During the development of a product, it may be necessary to avoid using software
under a certain license.
For example, the GPLv3 license has a clause to prevent what is commonly called
Tivoization (hardware restrictions that prevent the user from updating the software
on the device).
This license requirement may be prohibitive for some commercial products.
For these cases, the INCOMPATIBLE_LICENSE variable can be used to prevent the
usage of software with certain licenses.
INCOMPATIBLE_LICENSE = "GPL-3.0* LGPL-3.0* AGPL-3.0*"
PROPRIETARY AND COMMERCIAL SOFTWARE
Recipes can use the CLOSED value to define that a software is proprietary.
LICENSE = "CLOSED"
Commercial or special software licenses can be specified in the recipe using the
LICENSE_FLAGS variable.
LICENSE_FLAGS = "commercial"
For BitBake to process recipes with such special licenses, it's necessary to set the
LICENSE_FLAGS_ACCEPTED variable.
LICENSE_FLAGS_ACCEPTED = "commercial"
LICENSE COMPLIANCE
One of the concerns in a project that uses free software is compliance with software
licenses.
While each license has its own "requirements", there are typically three things a
developer should be concerned about:
Availability of the original source code and any changes made to it.
The Yocto Project is able to help with these requirements to ensure compliance with
software licenses.
DISTRIBUTING THE SOURCE CODE
The archiver class and the ARCHIVER_MODE variable can be used to generate a
directory with the source code of the software components used in the distribution:
INHERIT += "archiver"
ARCHIVER_MODE[src] = "original"
At the end of the image generation, the sources in tarball format and their respective
patches will be available in tmp/deploy/sources.
However, some licenses require the license text to be distributed in the image along
with the generated artifacts (library, executable, etc).
# ls /usr/share/common-licenses/busybox/
LICENSE.0 LICENSE.1 generic_GPLv2 generic_bzip2-1.0.4 recipeinfo
DISTRIBUTING THE BUILD SCRIPTS
To provide the build scripts, just give the user the necessary commands to download
the correct versions of the layers and configure the build directory:
To share the sstate cache directory between multiple developers or machines, the
NFS protocol is recommended.
BUILD HISTORY
During the development of a Linux distribution with the Yocto Project, any change in
the metadata can impact the generated image, causing possible regressions.
The build history is a tool that makes it possible to analyze and track changes in the
build output, identifying possible unwanted changes.
Keep in mind that the build history may slightly increase the build time and disk
usage.
BUILD HISTORY DIRECTORY
The build history is stored by default in buildhistory/.
Information about generated images is stored buildhistory/images/.
The build history directory can be changed via the BUILDHISTORY_DIR variable.
BUILDHISTORY_DIR ?= "${TOPDIR}/buildhistory"
BUILDHISTORY DIRECTORY
$ tree buildhistory/
buildhistory/
├── images
│ └── qemux86_64
│ └── glibc
│ └── core-image-minimal
│ ├── build-id.txt
│ ├── depends.dot
│ ├── depends-nokernel.dot
│ ├── depends-nokernel-nolibc.dot
│ ├── depends-nokernel-nolibc-noupdate.dot
│ ├── depends-nokernel-nolibc-noupdate-nomodules.dot
│ ├── files-in-image.txt
│ ├── image-files
│ │ └── etc
│ │ ├── group
│ │ └── passwd
│ ├── image-info.txt
│ ├── installed-package-info.txt
│ ├── installed-package-names.txt
│ ├── installed-package-sizes.txt
│ └── installed-packages.txt
├── metadata-revs
└── packages
ANALYZING THE BUILD HISTORY
The build history can be analyzed directly with Git.
$ git log
$ git show HEAD
Alternatively, the buildhistory-diff tool can be used, which has a simpler and easy to
understand output:
$ buildhistory-diff -a HEAD^
It has features similar to the devtool tool, but is more focused on creating and
changing recipes.
options:
-d, --debug Enable debug output
-q, --quiet Print only errors
--color COLOR Colorize output (where COLOR is auto, always, never)
-h, --help show this help message and exit
subcommands:
create Create a new recipe
appendfile Create/update a bbappend to replace a target file
appendsrcfiles Create/update a bbappend to add or replace source files
appendsrcfile Create/update a bbappend to add or replace a source file
edit Edit the recipe and appends for the specified target. This obeys $VISUAL if set, o
setvar Set a variable within a recipe
newappend Create a bbappend for the specified target in the specified layer
Use recipetool <subcommand> --help to get help on a specific command
TOASTER
Toaster is a web interface to the Yocto Project’s OpenEmbedded Build System.
https://docs.yoctoproject.org/toaster-manual/intro.html
With a simple and easy-to-use interface, Toaster provides two main functionalities:
Collect and display information about the build process.
Instructions on how to configure and use CROPS are documented in the Yocto Project
development manual.
AUTOBUILDER
Autobuilder is an automation tool maintained by the Yocto Project.
https://autobuilder.yoctoproject.org/
FINAL CONSIDERATIONS
LINKS
Yocto Project website:
https://www.yoctoproject.org/
OpenEmbedded website:
http://www.openembedded.org/wiki/Main_Page
THANKS!