Embedded Linux Projects Using Yocto Project Cookbook - Sample Chapter
Embedded Linux Projects Using Yocto Project Cookbook - Sample Chapter
ee
This book begins with the installation of a professional embedded Yocto setup, then advises you on
best practices, and finally explains how to quickly get hands on with the Freescale ARM ecosystem and
community layer, using the affordable and open source Wandboard embedded board.
The embedded Linux world is standardizing around Yocto Project as the best integration framework
to create reliable embedded Linux products. Yocto Project effectively shortens the time it takes to
develop and maintain an embedded Linux product, and it increases its reliability and robustness by
using proven and tested components.
Sa
pl
e
and problems
$ 49.99 US
32.99 UK
P U B L I S H I N G
Alex Gonzlez
P U B L I S H I N G
Alex Gonzlez
Linux is quick to adapt to new technologies and it's the place where innovation
happens first
It is robust, and the development community is quick to react to problems
It is secure, and vulnerabilities are discovered and dealt with in a much quicker
way than in competing proprietary products
It is open, which means your company is able to own, modify, and understand
the technology
Finally, Linux is free
Yocto is secure, as it uses recent sources and provides the means to quickly apply
security vulnerabilities to your products
It is robust, as it is used by a large community, which is quick to react to
problems
It is open, so your company can own the technology, understand it, and make it
fit for specific needs
It is free
With the Yocto Project's 6-month stable release process, package management updates,
and flexibility, you will be able to focus on your embedded application, knowing that you
are building it on top of a trusted system. You will speed up your development cycles and
produce outstanding products.
But Yocto is a new technology, and developers need to adapt to it. This books aims to
provide a practical guide for readers with basic knowledge of Linux and Yocto to develop
a production-ready industrial system based on the ARM architecture.
Installing Poky
Sharing downloads
Introduction
The Yocto project (http://www.yoctoproject.org/) is an embedded Linux distribution
builder that makes use of several other open source projects.
The Yocto project provides a reference build system for embedded Linux, called Poky, which
has the BitBake and OpenEmbedded-Core (OE-Core) projects at its base. The purpose of
Poky is to build the components needed for an embedded Linux product, namely:
A bootloader image
With these, the Yocto project covers the needs of both system and application developers.
When the Yocto project is used as an integration environment for bootloaders, the Linux
kernel, and user space applications, we refer to it as system development.
For application development, the Yocto project builds SDKs that enable the development of
applications independently of the Yocto build system.
The Yocto project makes a new release every six months. The latest release at the time of this
writing is Yocto 1.7.1 Dizzy, and all the examples in this book refer to the 1.7.1 release.
A Yocto release comprises the following components:
A build appliance; that is, a VMware image of a host system ready to use Yocto
Prebuilt toolchains
Prebuilt images
Chapter 1
Getting ready
The recommended way to develop an embedded Linux system is using a native Linux
workstation. Development work using virtual machines is discouraged, although they may
be used for demo and test purposes.
Yocto builds all the components mentioned before from scratch, including the cross-compilation
toolchain and the native tools it needs, so the Yocto build process is demanding in terms of
processing power and both hard drive space and I/O.
Although Yocto will work fine on machines with lower specifications, for professional
developer's workstations, it is recommended to use symmetric multiprocessing (SMP)
systems with 8 GB or more system memory and a high capacity, fast hard drive. Build servers
can employ distributed compilation, but this is out of the scope of this book. Due to different
bottlenecks in the build process, there does not seem to be much improvement above 8 CPUs
or around 16 GB RAM.
The first build will also download all the sources from the Internet, so a fast Internet
connection is also recommended.
How to do it...
Yocto supports several distributions, and each Yocto release will document a list of the
supported ones. Although the use of a supported Linux distribution is strongly advised, Yocto
is able to run on any Linux system if it has the following dependencies:
Yocto also provides a way to install the correct version of these tools by either downloading
a buildtools-tarball or building one on a supported machine. This allows virtually any Linux
distribution to be able to run Yocto, and also makes sure that it will be possible to replicate
your Yocto build system in the future. This is important for embedded products with long-term
availability requirements.
This book will use the Ubuntu 14.04 Long-Term Stable (LTS) Linux distribution for all
examples. Instructions to install on other Linux distributions can be found on the Supported
Linux Distributions section of the Yocto Project Development Manual, but the examples will
only be tested with Ubuntu 14.04 LTS.
3
How it works...
The preceding command will use apt-get, the Advanced Packaging Tool (APT),
command-line tool. It is a frontend of the dpkg package manager that is included in the
Ubuntu distribution. It will install all the required packages and their dependencies to support
all the features of the Yocto project.
There's more...
If build times are an important factor for you, there are certain steps you can take when
preparing your disks to optimize them even further:
Place the build directories on their own disk partition or a fast external drive.
Use the ext4 filesystem but configure it not to use journalism on your Yocto-dedicated
partitions. Be aware that power losses may corrupt your build data.
Mount the filesystem in such a way that read times are not written/recorded on
file reads, disable write barriers, and delay committing filesystem changes with the
following mount options:
noatime,barrier=0,commit=6000.
These changes reduce the data integrity safeguards, but with the separation of the build
directories to their own disk, failures would only affect temporary build data, which can be
erased and regenerated.
Chapter 1
See also
The complete Yocto project installation instructions for Ubuntu and other supported
distributions can be found on the Yocto Project Reference Manual at http://www.
yoctoproject.org/docs/1.7.1/ref-manual/ref-manual.html
Installing Poky
This recipe will explain how to set up your host Linux system with Poky, the Yocto project
reference system.
Getting ready
Poky uses the OpenEmbedded build system, and as such, uses the BitBake tool, a task
scheduler written in Python which forked from Gentoo's Portage tool. You can think of BitBake
as the make utility in Yocto. It will parse the configuration and recipe metadata, schedule a
task list, and run through it.
BitBake is also the command-line interface to Yocto.
Poky and BitBake are two of the open source projects used by Yocto. The Poky project
is maintained by the Yocto community. You can download Poky from its Git repository at
http://git.yoctoproject.org/cgit/cgit.cgi/poky/.
Development discussions can be followed and contributed to by visiting the development
mailing list at https://lists.yoctoproject.org/listinfo/poky.
BitBake, on the other hand, is maintained by both the Yocto and OpenEmbedded
communities, as the tool is used by both. BitBake can be downloaded from its Git repository at
http://git.openembedded.org/bitbake/.
Development discussions can be followed and contributed to by visiting the development
mailing list at http://lists.openembedded.org/mailman/listinfo/bitbake-devel.
The Poky build system only supports virtualized QEMU machines for the following
architectures:
ARM (qemuarm)
x86 (qemux86)
x86-64 (qemux86-64)
PowerPC (qemuppc)
To develop on different hardware, you will need to complement Poky with hardware-specific
Yocto layers. This will be covered later on.
How to do it...
The Poky project incorporates a stable BitBake release, so to get started with Yocto, we only
need to install Poky in our Linux host system.
Note that you can also install BitBake independently
through your distribution's package management system.
This is not recommended and can be a source of problems,
as BitBake needs to be compatible with the metadata used
in Yocto. If you have installed BitBake from your distribution,
please remove it.
The current Yocto release is 1.7.1, or Dizzy, so we will install that into our host system. We will
use the /opt/yocto folder as the installation path:
$ sudo install -o $(id -u) -g $(id -g) -d /opt/yocto
$ cd /opt/yocto
$ git clone --branch dizzy git://git.yoctoproject.org/poky
How it works...
The previous instructions will use Git (the source code management system command-line
tool) to clone the Poky repository, which includes BitBake, into a new poky directory on our
current path, and point it to the Dizzy stable branch.
Chapter 1
There's more...
Poky contains three metadata directories, meta, meta-yocto, and meta-yocto-bsp, as
well as a template metadata layer, meta-skeleton, that can be used as a base for new
layers. Poky's three metadata directories are explained here:
See also
How to do it...
The first thing we need to do is create a build directory for our project, where the build
output will be generated. Sometimes, the build directory may be referred to as the project
directory, but build directory is the appropriate Yocto term.
There is no right way to structure the build directories when you have multiple projects, but
a good practice is to have one build directory per architecture or machine type. They can
all share a common downloads folders, and even a shared state cache (this will be covered
later on), so keeping them separate won't affect the build performance, but it will allow you to
develop on multiple projects simultaneously.
How it works...
Both scripts call the scripts/oe-setup-builddir script inside the poky directory to
create the build directory.
On creation, the build directory contains a conf directory with the following three files:
bblayers.conf: This file lists the metadata layers to be considered for this project.
local.conf: This file contains the project-specific configuration variables. You can
set common configuration variables to different projects with a site.conf file, but
Chapter 1
templateconf.cfg: This file contains the directory that includes the template
configuration files used to create the project. By default it uses the one pointed to by
the templateconf file in your Poky installation directory, which is meta-yocto/
conf by default.
To start a build from scratch, that's all the build directory needs.
Erasing everything apart from these files will recreate your build from
scratch.
$ cd /opt/yocto/poky/qemuarm
$ rm -Rf tmp sstate-cache
There's more...
You can specify a different template configuration file to use when you create your build
directory using the TEMPLATECONF variable; for example:
$ TEMPLATECONF=meta-custom/config source oe-init-build-env <builddir>
The TEMPLATECONF variable needs to refer to a directory containing templates for both
local.conf and bblayer.conf, but named local.conf.sample and bblayers.
conf.sample.
For our purposes, we can use the unmodified default project configuration files.
Getting ready
Poky contains a set of default target images. You can list them by executing the following
commands:
$ cd /opt/yocto/poky
$ ls meta*/recipes*/images/*.bb
console-only image
Base compliance
graphical terminal
based image
You will also find images with the following suffixes:
dev: These images are suitable for development work, as they contain headers and
libraries.
sdk: These images include a complete SDK that can be used for development on
the target.
initramfs: This is an image that can be used for a RAM-based root filesystem,
How to do it...
To build an image, we need to configure the MACHINE we are building it for and pass its name
to BitBake. For example, for the qemuarm machine, we would run the following:
$ cd /opt/yocto/poky/qemuarm
$ MACHINE=qemuarm bitbake core-image-minimal
Or we could export the MACHINE variable to the current shell environment with the following:
$ export MACHINE=qemuarm
But the preferred and persistent way to do it is to edit the conf/local.conf configuration
file to change the default machine to qemuarm:
- #MACHINE ?= "qemuarm"
+ MACHINE ?= "qemuarm"
10
Chapter 1
Then you can just execute the following:
$ bitbake core-image-minimal
How it works...
When you pass a target recipe to BitBake, it first parses the following configuration files:
conf/local.conf: This file is used for any other configuration the user may have
And then BitBake parses the target recipe that has been provided and its dependencies.
The outcome is a set of interdependent tasks that BitBake will then execute in order.
There's more...
Most developers won't be interested in keeping the whole build output for every package, so it
is recommended to configure your project to remove it with the following configuration in your
conf/local.conf file:
INHERIT += "rm_work"
But at the same time, configuring it for all packages means that you won't be able to develop
or debug them.
You can add a list of packages to exclude from cleaning by adding them to the RM_WORK_
EXCLUDE variable. For example, if you are going to do BSP work, a good setting might be:
RM_WORK_EXCLUDE += "linux-yocto u-boot"
Remember that you can use a custom template local.conf.sample configuration file in
your own layer to keep these configurations and apply them for all projects so that they can be
shared across all developers.
Once the build finishes, you can find the output images on the tmp/deploy/images/
qemuarm directory inside your build directory.
11
You can test run your images on the QEMU emulator by executing this:
$ runqemu qemuarm core-image-minimal
The runqemu script included in Poky's scripts directory is a launch wrapper around the
QEMU machine emulator to simplify its usage.
Getting ready
The first thing to do is to select which base hardware your design is going to be based on. We
will use a board that is based on a Freescale i.MX6 System on Chip (SoC) as a starting point
for our embedded product design.
This recipe gives an overview of the support for Freescale hardware in the Yocto project.
How to do it...
The SoC manufacturer (in this case, Freescale) has a range of reference design boards for
purchase, as well as official Yocto-based software releases. Similarly, other manufacturers that
use Freescale's SoCs offer reference design boards and their own Yocto-based software releases.
Selecting the appropriate hardware to base your design on is one of the most important design
decisions for an embedded product. Depending on your product needs, you will decide to either:
12
Chapter 1
Most of the times, a production-ready board will not match the specific requirements of an
professional embedded system, and the process of designing a complete carrier board using
Freescale's SoC would be too time consuming. So, using an appropriate module that already
solves the most technically challenging design aspects is a common choice.
Some of the characteristics that are important to consider are:
Power management
Long-term availability
The Yocto community layers that support Freescale-based boards are called meta-fsl-arm
and meta-fsl-arm-extras. The selection of boards that are supported on meta-fslarm is limited to Freescale reference designs, which would be the starting point if you are
considering designing your own carrier board around Freescale's SoC. Boards from other
vendors are maintained on the meta-fsl-arm-extras layer.
There are other embedded manufacturers that use meta-fsl-arm, but they have
not integrated their boards in the meta-fsl-arm-extras community layer. These
manufacturers will keep their own BSP layers, which depend on meta-fsl-arm, with specific
support for their hardware. An example of this is Digi International and its ConnectCore 6
module, which is based on the i.MX6 SoC.
How it works...
To understand Freescale Yocto ecosystem, we need to start with the Freescale community
BSP, comprising the meta-fsl-arm layer with support for Freescale reference boards,
and its companion, meta-fsl-arm-extra, with support for boards from other vendors,
and its differences with the official Freescale Yocto releases that Freescale offers for their
reference designs.
There are some key differences between the community and Freescale Yocto releases:
Freescale releases go through an internal QA and validation test process, and they
are maintained by Freescale support.
Freescale releases for a specific platform reach a maturity point, after which they
are no longer worked on. At this point, all the development work has been integrated
into the community layer and the platforms are further maintained by the Freescale
BSP community.
Freescale Yocto releases are not Yocto compatible, while the community release is.
13
There's more...
The Freescale BSP community extends Poky with the following layers:
Other Linux kernel and U-Boot versions are available, but keeping the manufacturer's
supported version is recommended.
14
Chapter 1
The meta-fsl-arm layer includes Freescale's proprietary binaries to enable some
hardware features most notably its hardware graphics, multimedia, and encryption
capabilities. To make use of these capabilities, the end user needs to accept
Freescale's End-User License Agreement (EULA), which is included in the metafsl-arm layer. To accept the license, the following line needs to be added to the
project's conf/local.conf configuration file:
ACCEPT_FSL_EULA = "1"
boards; for example, the Wandboard. To download the layer's content, you may visit
https://github.com/Freescale/meta-fsl-arm-extra/.
meta-fsl-demos: This layer adds a metadata layer for demonstration target
images. To download the layer's content, you may visit https://github.com/
Freescale/meta-fsl-demos.
Freescale uses another layer on top of the layers above for their official software releases:
meta-fsl-bsp-release.
See also
For more information, refer to the FSL community BSP release notes available at
http://freescale.github.io/doc/release-notes/1.7/
Getting ready
With so many layers, manually cloning each of them and adding them to your project's
conf/bblayers.conf file is cumbersome. The community is using the repo tool developed
by Google for their community Android to ease the installation of Yocto.
To install repo in your host system, type in the following commands:
$ sudo curl http://commondatastorage.googleapis.com/git-repodownloads/repo > /usr/local/sbin/repo
$ sudo chmod a+x /usr/local/sbin/repo
The repo tool is a Python utility that parses an XML file, called manifest, with a list of Git
repositories. The repo tool is then used to manage those repositories as a whole.
15
How to do it...
For example, we will use repo to download all the repositories listed in the previous recipe to
our host system. For that, we will point it to the Freescale community BSP manifest for the
Dizzy release:
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<default sync-j="4" revision="master"/>
<remote fetch="git://git.yoctoproject.org" name="yocto"/>
<remote fetch="git://github.com/Freescale" name="freescale"/>
<remote fetch="git://git.openembedded.org" name="oe"/>
<project remote="yocto" revision="dizzy" name="poky"
path="sources/poky"/>
<project remote="yocto" revision="dizzy" name="meta-fsl-arm"
path="sources/meta-fsl-arm"/>
<project remote="oe" revision="dizzy" name="meta-openembedded"
path="sources/meta-openembedded"/>
<project remote="freescale" revision="dizzy" name="fslcommunity-bsp-base" path="sources/base">
<copyfile dest="README" src="README"/>
<copyfile dest="setup-environment" src="setupenvironment"/>
</project>
<project remote="freescale" revision="dizzy" name="meta-fsl-armextra" path="sources/meta-fsl-arm-extra"/>
<project remote="freescale" revision="dizzy" name="meta-fsldemos" path="sources/meta-fsl-demos"/>
<project remote="freescale" revision="dizzy"
name="Documentation" path="sources/Documentation"/>
</manifest>>
The manifest file shows all the installation paths and repository sources for the different
components that are going to be installed.
How it works...
The manifest file is a list of the different layers that are needed for the Freescale community
BSP release. We can now use repo to install it. Run the following:
$ mkdir /opt/yocto/fsl-community-bsp
$ cd /opt/yocto/fsl-community-bsp
$ repo init -u https://github.com/Freescale/fsl-community-bspplatform -b dizzy
$ repo sync
16
Chapter 1
You can optionally pass a -jN argument to sync if you have a multicore machine for
multithreaded operations; for example, you could pass repo sync -j8 in an 8-core
host system.
There's more...
To list the hardware boards supported by the different layers, we may run:
$ ls sources/meta-fsl*/conf/machine/*.conf
And to list the newly introduced target images, use the following:
$ ls sources/meta-fsl*/recipes*/images/*.bb
The community Freescale BSP release introduces the following new target images:
qte-in-use-image: This is a graphical image that includes support for Qt4 over
the framebuffer
qt-in-use-image: This is a graphical image that includes support for Qt4 over the
X11 Windows system
See also
Instructions to use the repo tool, including using repo with proxy servers, can be
found in the Android documentation at https://source.android.com/source/
downloading.html
17
How to do it...
To build an image for the wandboard-quad machine, use the following commands:
$ cd /opt/yocto/fsl-community-bsp
$ mkdir -p wandboard-quad
$ MACHINE=wandboard-quad source setup-environment wandboard-quad
$ bitbake core-image-minimal
How it works...
The setup-environment script will create a build directory, set up the MACHINE variable,
and prompt you to accept the Freescale EULA as described earlier. Your conf/local.conf
configuration file will be updated both with the specified machine and the EULA acceptance
variable.
Remember that if you close your terminal session, you will
need to set up the environment again before being able to
use BitBake. You can safely rerun the setup-environment
script as seen previously, as it will not touch an existing conf/
local.conf file. Run the following:
$ cd /opt/yocto/fsl-community-bsp/
$ source setup-environment wandboard-quad
Here, /dev/sdN corresponds to the device node assigned to the microSD card in your
host system.
Be careful when running the dd command, as it could harm
your machine. You need to be absolutely sure that the sdN
device corresponds to your microSD card and not a drive on
your development machine.
18
Chapter 1
See also
You can find more information regarding the repo tool on Android's documentation at
https://source.android.com/source/using-repo.html
Getting ready
1. Without the microSD card inserted, plug in a microUSB-to-USB cable to the USB
OTG interface of your Wandboard. Check the lsusb utility on your Linux host to see
whether the Wandboard appears as follows:
Bus 002 Device 006: ID 15a2:0054 Freescale Semiconductor, Inc.
i.MX6Q SystemOnChip in RecoveryMode
If you don't see this, try a different power supply. It should be 5V, 10W.
2. Make sure you connect a NULL modem serial cable between the RS232 connector
in your Wandboard target and a serial port on your Linux host. Then open a terminal
program like minicom with the following:
$ minicom -D /dev/ttyS0 -b 115200
You will need to add your user to the dialout group, or try to run
the command as sudo. This should open a 115200 8N1 serial
connection. The serial device may vary in your Linux host. For
example, a USB-to-serial adapter may be detected as /dev/
ttyUSB0. Also, make sure both hardware and software flow
control are disabled.
How to do it...
1. Insert the microSD card image to the module slot, not the base board, as the latter
is only used for storage and not for booting, and power it. You should see the U-Boot
banner in the minicom session output.
2. If not, you may have a problem with the serial communication. By default, the
Ethernet interface in the FSL community BSP image is configured to request an
address by DHCP, so you can use that to connect to the target.
Make sure you have a DHCP server running on the test network where the target is.
19
There's more...
If everything else fails, you can verify the position of the bootloader on your microSD card. You
can dump the contents of the first blocks of your microSD card with:
$ sudo dd if=/dev/sdN of=/tmp/sdcard.img count=10
You should see a U-Boot header at offset 0x400. That's the offset where the i.MX6 boot ROM
will be looking for the bootloader when bootstrapped to boot from the microSD interface. Use
the following commands:
$ head /tmp/sdcard.img | hexdump
0000400 00d1 4020 0000 1780 0000 0000 f42c 177f
You can recognize the U-Boot header by dumping the U-Boot image from your build. Run the
following commands:
$ head u-boot-wandboard-quad.imx | hexdump
0000000 00d1 4020 0000 1780 0000 0000 f42c 177f
20
Chapter 1
Getting ready
The ideal setup for development work is to use both TFTP and NFS servers in your host system
and to only store the U-Boot bootloader in either the eMMC or a microSD card. With this setup,
the bootloader will fetch the Linux kernel from the TFTP server and the kernel will mount the
root filesystem from the NFS server. Changes to either the kernel or the root filesystem are
available without the need to reprogram. Only bootloader development work would need you
to reprogram the physical media.
Now copy the Linux kernel and device tree from your build directory as follows:
$ cd /opt/yocto/fsl-community-bsp/wandboardquad/tmp/deploy/images/wandboard-quad/
$ cp zImage-wandboard-quad.bin zImage-imx6q-wandboard.dtb
/var/lib/tftpboot
21
Next, we will configure the NFS server to export the /nfsroot folder:
/etc/exports:
/nfsroot/ *(rw,no_root_squash,async,no_subtree_check)
We will then restart the NFS server for the configuration changes to take effect:
$ sudo service nfs-kernel-server restart
How to do it...
Boot the Wandboard and stop at the U-Boot prompt by pressing any key on the serial console.
Then run through the following steps:
1. Get an IP address by DHCP:
> dhcp
2. Configure the IP address of your host system, where the TFTP and NFS servers have
been set up:
> setenv serverip <host_ip>
5. If you have configured a static IP address, you need to disable DHCP on boot
by running:
> setenv ip_dyn no
22
Chapter 1
6. Save the U-Boot environment to the microSD card:
> saveenv
7.
The Linux kernel and device tree will be fetched from the TFTP server, and the root filesystem
will be mounted by the kernel from the NFS share after getting a DHCP address from your
network (unless using static IP addresses).
You should be able to log in with the root user without a password prompt.
Sharing downloads
You will usually work on several projects simultaneously, probably for different hardware
platforms or different target images. In such cases, it is important to optimize the build times
by sharing downloads.
Getting ready
The build system runs a search for downloaded sources in a number of places:
It looks into the configured premirrors, which are usually local to your organization.
It then tries to fetch from the upstream source as configured in the package recipe.
Finally, it checks the configured mirrors. Mirrors are public alternate locations for
the source.
If a package source is not found in any of the these four, the package build will fail with an
error. Build warnings are also issued when upstream fetching fails and mirrors are tried, so
that the upstream problem can be looked at.
The Yocto project maintains a set of mirrors to isolate the build system from problems with
the upstream servers. However, when adding external layers, you could be adding support for
packages that are not in the Yocto project's mirror servers, or other configured mirrors, so it is
recommended that you keep a local premirror to avoid problems with source availability.
The default Poky setting for a new project is to store the downloaded package sources on the
current build directory. This is the first place the build system will run a search for source
downloads. This setting can be configured in your project's conf/local.conf file with the
DL_DIR configuration variable.
23
How to do it...
To optimize the build time, it is recommended to keep a shared downloads directory
between all your projects. The setup-environment script of the meta-fsl-arm layer
changes the default DL_DIR to the fsl-community-bsp directory created by the repo tool.
With this setup, the downloads folder will already be shared between all the projects in your
host system. It is configured as:
DL_DIR ?= "${BSPDIR}/downloads/"
A more scalable setup (for instance, for teams that are remotely distributed) is to configure
a premirror. For example, adding the following to your conf/local.conf file:
INHERIT += "own-mirrors"
SOURCE_MIRROR_URL = "http://example.com/my-source-mirror"
A usual setup is to have a build server serve its downloads directory. The build server can be
configured to prepare tarballs of the Git directories to avoid having to perform Git operations
from upstream servers. This setting in your conf/local.conf file will affect the build
performance, but this is usually acceptable in a build server. Add the following:
BB_GENERATE_MIRROR_TARBALLS = "1"
An advantage of this setup is that the build server's downloads folder can also be backed up
to guarantee source availability for your products in the future. This is especially important in
embedded products with long-term availability requirements.
In order to test this setup, you may check to see whether a build is possible just by using the
premirrors with the following:
BB_FETCH_PREMIRRORONLY = "1"
This setting in your conf/local.conf file can also be distributed across the team with the
TEMPLATECONF variable during the project's creation.
24
Chapter 1
For this to work, the build system calculates a checksum of the given input data to a task. If
the input data changes, the task needs to be rebuilt. In simplistic terms, the build process
generates a run script for each task that can be checksummed and compared. It also keeps
track of a task's output, so that it can be reused.
A package recipe can modify the shared state caching to a task; for example, to always
force a rebuild by marking it as nostamp. A more in-depth explanation of the shared state
cache mechanism can be found in the Yocto Project Reference Manual at http://www.
yoctoproject.org/docs/1.7.1/ref-manual/ref-manual.html.
How to do it...
By default, the build system will use a shared state cache directory called sstate-cache on
your build directory to store the cached data. This can be changed with the SSTATE_DIR
configuration variable in your conf/local.conf file. The cached data is stored in directories
named with the first two characters of the hash. Inside, the filenames contain the whole task
checksum, so the cache validity can be ascertained just by looking at the filename. The build
process set scene tasks will evaluate the cached data and use it to accelerate the build if valid.
When you want to start a build from a clean state, you need to remove both the sstatecache directory and the tmp directory.
You can also instruct BitBake to ignore the shared state cache by using the --no-setscene
argument when running it.
It's a good practice to keep backups of clean shared state caches (for example, from a build
server), which can be used in case of shared state cache corruption.
There's more...
Sharing a shared state cache is possible; however, it needs to be approached with care. Not
all changes are detected by the shared state cache implementation, and when this happens,
some or all of the cache needs to be invalidated. This can cause problems when the state
cache is being shared.
The recommendation in this case depends on the use case. Developers working on Yocto
metadata should keep the shared state cache as default, separated per project.
However, validation and testing engineers, kernel and bootloader developers, and application
developers would probably benefit from a well-maintained shared state cache.
To configure an NFS share drive to be shared among the development team to speed up the
builds, you can add the following to your conf/local.conf configuration file:
SSTATE_MIRRORS ?= "\
file://.* file:///nfs/local/mount/sstate/PATH"
25
Getting ready
An option is to manually copy the build binaries to the target's root filesystem, either copying
it to the NFS share on the host system the target is mounting its root filesystem from (as
explained in the Configuring network booting for a development setup recipe earlier) or using
any other method like SCP, FTP, or even a microSD card.
This method is also used by IDEs like Eclipse when debugging an application you are working
on. However, this method does not scale well when you need to install several packages and
dependencies.
The next option would be to copy the packaged binaries (that is, the RPM, deb, or ipk
packages) to the target's filesystem and then use the target's package management system
to install them. For this to work, your target's filesystem needs to be built with package
management tools. Doing this is as easy as adding the package-management feature
to your root filesystem; for example, you may add the following line to your project's
conf/local.conf file:
EXTRA_IMAGE_FEATURES += "package-management"
So for an RPM package, you will copy it to the target and use the rpm or smart utilities to
install it. The smart package management tool is GPL licensed and can work with a variety
of package formats.
26
Chapter 1
However, the most optimized way to do this is to convert your host system package's output
directory into a package feed. For example, if you are using the default RPM package format,
you may convert tmp/deploy/rpm in your build directory into a package feed that your
target can use to update.
For this to work, you need to configure an HTTP server on your computer that serves
the packages.
Versioning packages
You also need to make sure that the generated packages are correctly versioned, and that
means updating the recipe revision, PR, with every change. It is possible to do this manually, but
the recommendedand compulsory way if you want to use package feedsis to use a PR server.
However, the PR server is not enabled by default. The packages generated without a PR
server are consistent with each other but offer no update guarantees for a system that is
already running.
The simplest PR server configuration is to run it locally on your host system. To do this, you
add the following to your conf/local.conf file:
PRSERV_HOST = "localhost:0"
And you will update the project's build configuration to use the centralized PR server, editing
conf/local.conf as follows:
PRSERV_HOST = "<server_ip>:<port>"
Also, if you are using a shared state cache as described before, all of the contributors to the
shared state cache need to use the same PR server.
Once the feed's integrity is guaranteed, we need to configure an HTTP server to serve the feed.
How to do it...
We will use lighttpd for this example, as it is lightweight and easy to configure. Follow
these steps:
1. Install the web server:
$ sudo apt-get install lighttpd
27
3. Refresh the package index. This needs to be done manually to update the package
feed after every build:
$ bitbake package-index
4. Then we need to configure our target filesystem with the new package feeds:
# smart channel --add all type=rpm-md \
baseurl=http://<server_ip>/wandboard-quad/rpm/all
5. Once the setup is ready, we will be able to query and update packages from the
target's root filesystem with the following:
# smart update
# smart query <package_name>
# smart install <package_name>
To make this change persistent in the target's root filesystem, we can configure the package
feeds at compilation time by using the PACKAGE_FEED_URIS variable in conf/local.conf
as follows:
PACKAGE_FEED_URIS = "http://<server_ip>/wandboard-quad"
See also
More information and a user manual for the smart utility can be found at
https://labix.org/smart/
28
Chapter 1
How to do it...
To enable build history, add the following to your conf/local.conf file:
INHERIT += "buildhistory"
The preceding line of code enables the storage of build history in a local Git repository.
The Git repository location can be set by the BUILDHISTORY_DIR variable, which by default
is set to a buildhistory directory on your build directory.
By default, buildhistory tracks changes to packages, images, and SDKs. This is
configurable using the BUILDHISTORY_FEATURES variable. For example, to track only image
changes, add the following to your conf/local.conf:
BUILDHISTORY_FEATURES = "image"
It can also track specific files and copy them to the buildhistory directory. By default, this
includes only /etc/passwd and /etc/groups, but it can be used to track any important
files like security certificates. The files need to be added with the BUILDHISTORY_IMAGE_
FILES variable in your conf/local.conf file as follows:
BUILDHISTORY_IMAGE_FILES += "/path/to/file"
Build history will slow down the build, increase the build size, and may also grow the Git
directory to an unmanageable size. The recommendation is to enable it on a build server for
software releases, or in specific cases, such as when updating production software.
29
How it works...
When enabled, it will keep a record of the changes to each package and image in the form of
a Git repository in a way that can be explored and analyzed.
For a package, it records the following information:
Dependencies
Package size
Files
Build configuration
Dependency graphs
SDK configuration
List of both host and target files, including ownership and permissions
Dependency graphs
Using a Django-1.4-based web interface. You will need to import the build history data
to the application's database after every build. The details are available at http://
git.yoctoproject.org/cgit/cgit.cgi/buildhistory-web/tree/README.
30
Chapter 1
There's more...
To maintain the build history, it's important to optimize it and avoid it from growing over time.
Periodic backups of the build history and clean-ups of older data are important to keep the
build history repository at a manageable size.
Once the buildhistory directory has been backed up, the following process will trim it and
keep only the most recent history:
1. Copy your repository to a temporary RAM filesystem (tmpfs) to speed things up.
Check the output of the df -h command to see which directories are tmpfs
filesystems and how much space they have available, and use one. For example, in
Ubuntu, the /run/shm directory is available.
2. Add a graft point for a commit one month ago with no parents:
$ git rev-parse "HEAD@{1 month ago}" > .git/info/grafts
5. Replace the old buildhistory directory with the new cleaned one:
$ rm -rf buildhistory
$ mv buildhistory.new buildhistory
How to do it...
To enable the collection of statistics, your project needs to inherit the buildstats class
by adding it to USER_CLASSES in your conf/local.conf file. By default, the fslcommunity-bsp build project is configured to enable them.
USER_CLASSES ?= "buildstats"
You can configure the location of these statistics with the BUILDSTATS_BASE variable, and
by default it is set to the buildstats folder in the tmp directory under the build directory
(tmp/buildstats).
31
How it works...
The accuracy of the data depends on the download directory, DL_DIR, and the shared state
cache directory, SSTATE_DIR, existing on the same partition or volume, so you may need to
configure them accordingly if you are planning to use the build data.
An example build-stats file looks like the following:
Host Info: Linux agonzal 3.13.0-35-generic #62-Ubuntu SMP Fri Aug
15 01:58:42 UTC 2014 x86_64 x86_64
Build Started: 1411486841.52
Uncompressed Rootfs size: 6.2M /opt/yocto/fsl-communitybsp/wandboard-quad/tmp/work/wandboard_quad-poky-linuxgnueabi/core-image-minimal/1.0-r0/rootfs
Elapsed time: 2878.26 seconds
CPU usage: 51.5%
EndIOinProgress: 0
EndReadsComp: 0
EndReadsMerged: 55289561
EndSectRead: 65147300
EndSectWrite: 250044353
EndTimeIO: 14415452
EndTimeReads: 10338443
EndTimeWrite: 750935284
EndWTimeIO: 816314180
EndWritesComp: 0
StartIOinProgress: 0
StartReadsComp: 0
StartReadsMerged: 52319544
StartSectRead: 59228240
StartSectWrite: 207536552
StartTimeIO: 13116200
StartTimeReads: 8831854
StartTimeWrite: 3861639688
StartWTimeIO: 3921064032
StartWritesComp: 0
32
Chapter 1
These disk statistics come from the Linux kernel disk I/O stats (https://www.kernel.org/
doc/Documentation/iostats.txt). The different elements are explained here:
IOinProgress: This is the total number of I/Os in progress when reading /proc/diskstats
WTimeIO: This is the total number of weighted time while performing I/O
And inside each package, we have a list of tasks; for example, for ncurses-5.9-r15.1,
we have the following tasks:
do_compile
do_fetch
do_package
do_package_write_rpm
do_populate_lic
do_rm_work
do_configure
do_install
do_packagedata
do_patch
do_populate_sysroot
do_unpack
Each one of them contain, in the same format as earlier, the following:
Build time
CPU usage
Disk stats
33
There's more...
You can also obtain a graphical representation of the data using the pybootchartgui.
py tool included in the Poky source. From your project's build folder, you can execute the
following command to obtain a bootchart.png graphic in /tmp:
$ ../sources/poky/scripts/pybootchartgui/pybootchartgui.py
tmp/buildstats/core-image-minimal-wandboard-quad/ -o /tmp
Getting ready
Let's first introduce some of the usual use cases on a debugging session.
Finding recipes
A good way to check whether a specific package is supported in your current layers is to
search for it as follows:
$ find -name "*busybox*"
This will recursively search all layers for the BusyBox pattern. You can limit the search to
recipes and append files by executing:
$ find -name "*busybox*.bb*"
Optionally, to locate the source directory for a specific package recipe like BusyBox, use the
following command:
$ bitbake -e busybox | grep ^S=
You could also execute the following command to locate the working directory for a package or
image recipe:
$ bitbake -e <target> | grep ^WORKDIR=
34
Chapter 1
It will unpack and patch the source, and open a new terminal (it will autodetect your terminal
type or it can be set with OE_TERMINAL) in the target source directory, which has the
environment correctly setup.
While in a graphical environment, devshell opens a new terminal
or console window, but if we are working on a non-graphical
environment, like telnet or SSH, you may need to specify screen
as your terminal in your conf/local.conf configuration file
as follows:
OE_TERMINAL = "screen"
Inside the devshell, you can run development commands like configure and make or invoke
the cross-compiler directly (use the $CC environment variable, which has been set up already).
How to do it...
The starting point for debugging a package build error is the BitBake error message printed on
the build process. This will usually point us to the task that failed to build.
To list all the tasks available for a given recipe, with descriptions, we execute the following:
$ bitbake -c listtasks <target>
If you need to recreate the error, you can force a build with the following:
$ bitbake -f <target>
Or you can ask BitBake to force-run only a specific task using the following command:
$ bitbake -c compile -f <target>
35
and run.do_<task>.<pid>.
But luckily, we also have symbolic links, without the pid part, that link to the latest version.
The log files will contain the output of the task, and that is usually the only information we
need to debug the problem. The run file contains the actual code executed by BitBake to
generate the log mentioned before. This is only needed when debugging complex build issues.
Python tasks, on the other hand, do not currently write files as described previously, although
it is planned to do so in the future. Python tasks execute internally and log information to
the terminal.
bb.plain: This uses logger.plain. It can be used for debugging, but should not
bb.debug: This should be passed log level as the first argument and uses logger.
debug.
To print debug output from bash in our recipes, we need to use the logging class
by executing:
inherit logging
bbplain: This function outputs literally what's passed in. It can be used in debugging
36
Chapter 1
bbfatal: This function halts the build and prints an error message as with bberror.
bbdebug: This function prints debug messages with log level passed as the first
Looking at dependencies
You can ask BitBake to print the current and provided versions of packages with the
following command:
$ bitbake --show-versions
To analyze what dependencies are pulled in by a package, we can ask BitBake to create DOT
files that describe these dependencies by running the following:
$ bitbake -g <target>
The DOT format is a text description language for graphics that is understood by the GraphViz
open source package and all the utilities that use it. DOT files can be visualized or further
processed.
You can omit dependencies from the graph to produce more readable output. For example, to
omit dependencies from glibc, you would run the following command:
$ bitbake -g <target> -I glibc
Once the preceding commands have been run, we get three files in the current directory:
There is also a pn-buildlist file with a list of packages that would be built by the
given target.
37
However, the most useful way to display dependency data is to ask BitBake to display it
graphically with the dependency explorer, as follows:
$ bitbake -g -u depexp <target>
Debugging BitBake
It is not common to have to debug BitBake itself, but you may find a bug in BitBake and want
to explore it by yourself before reporting it to the BitBake community. For such cases, you
can ask BitBake to output the debug information at three different levels with the -D flag. To
display all the debug information, run the following command:
$ bitbake -DDD <target>
38
Chapter 1
By default, the error information is stored under tmp/log/error-report under the build
directory, but you can set a specific location with the ERR_REPORT_DIR variable.
When the error reporting tool is activated, a build error will be captured in a file in the errorreport folder. The build output will also print a command to send the error log to the server:
$ send-error-report ${LOG_DIR}/error-report/error-report_${TSTAMP}
When this command is executed, it will report back with a link to the upstream error.
You can set up a local error server, and use that instead by passing a server argument. The
error server code and setting up details can be found at http://git.yoctoproject.org/
cgit/cgit.cgi/error-report-web/tree/README.
There's more...
Although you can use Linux utilities to parse Yocto's metadata and build output, BitBake lacks
a command base UI for common tasks. One project that aims to provide it is bb, which is
available at https://github.com/kergoth/bb.
To use it, you need to clone the repository locally by executing the following command:
$ cd /opt/yocto/fsl-community-bsp/sources
$ git clone https://github.com/kergoth/bb.git
Then run the bb/bin/bb init command, which prompts you to add a bash command to
your ~/.bash_profile file.
You can either do that or execute it in your current shell as follows:
$ eval "$(/opt/yocto/fsl-community-bsp/sources/bb/bin/bb init -)"
39
Some of the tasks that are made easier by the bb utility are:
Displaying either the global BitBake environment or the environment for a specific
package and grepping for a specific variable:
$ bb show -r <recipe> <variable>
40
Get more information Embedded Linux Projects Using Yocto Project Cookbook
www.PacktPub.com
Stay Connected: