stefan's blag and stuff

Blog – 2017-09-13 – How to do a basic and simple Yocto build

The Yocto Project is an effort by the Linux Foundation to make building Linux based systems for embedded devices easier and more consistent. The community and industrial partners develop and maintain the Yocto build system. It consists of the reference distribution poky which is bundled together with bitbake, openembedded-core and an extensive amount of documentation in a git repository that is also called poky. Other known buildsystems for embedded devices are: ptxdist, buildroot and openwrt.

In the last three years of my professional software developer life I used and work with the Yocto build system. As with every piece of software you use in your daily work, I have learned to hate it :-) Since the internet lacks some good and brain-dump copy&paste guides to just try out and build a poky image, here is it. My step by step guide: How to do a basic and simple Yocto build.

I use the name simple instead of minimal for these build instructions, because you do not have to configure at lot of stuff. It works out of the box and should work reliable for different versions of poky.

It's also not minimal because the build requires 30 GB of disk space and needs to download 5.2 GB of source code archives.

Building step by step

First you have to checkout the poky, the Yocto reference distribution. It is the core of most Yocto BSPs and distributions out there.

$ git clone git://git.yoctoproject.org/poky.git poky
$ cd poky
$ git checkout -b pyro yocto-2.3.1
Switched to a new branch 'pyro'
$ git branch --set-upstream-to origin/pyro
Branch pyro set up to track remote branch pyro from origin.
$ git status
On branch pyro
Your branch is behind 'origin/pyro' by 182 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)
nothing to commit, working directory clean

The commands clone the git repository from yoctoproject.org, checkouts the last stable release tag yocto-2.3.1 and configures the remote tracking branch to the stable branch pyro (for the yocto-2.3.* releases).

The build system is ready, now you have to configure your poky build:

$ . oe-init-build-env
build$ vim conf/local.conf # Enable 'MACHINE ?= "qemuarm"'

The first command populates default configuration files local.conf and bblayers.conf from the poky sample files meta-poky/conf/{local.conf.sample,bblayers.conf.sample} into the directory build/conf.

In the second command you changed the MACHINE (=target architecture / board) to qemuarm, because you don't have a real hardware device lying around, right? And for demonstration purposes it's easier to use simulated hardware.

I choose the arm architecture, because that's the platform I use at work currently. The other available MACHINES qemumips, qemuppc and qemux86 (including their 64bit variants) should work the same.

Before you can start the build you mostly have to install some additional development packages on your Ubuntu, Debian, ... machine. See Section The Build Host Packages in the Yocto documentation.

To start the build execute:

build$ time bitbake core-image-minimal -c fetchall
real    65m16.135s
user    7m59.632s
sys     2m22.504s

build$ time bitbake core-image-minimal
real    98m15.318s
user    295m48.664s
sys     27m2.240s

I have splitted the build step into a download and a compile phase. You can also just execute the second command directly and bitbake will happily download and compile at the same time.

The above build was done on an Intel Core i5 CPU with four Cores and an SSD. The build time does depend heavily on your build machine.

After the build has finished you have the final build outputs (kernel, modules, device tree and root filesystem) lying around in:

build$ find tmp/deploy/images/
tmp/deploy/images/
tmp/deploy/images/qemuarm/
tmp/deploy/images/qemuarm/core-image-minimal-qemuarm.tar.bz2
tmp/deploy/images/qemuarm/core-image-minimal-qemuarm-20170913170931.testdata.json
tmp/deploy/images/qemuarm/core-image-minimal-qemuarm.testdata.json
tmp/deploy/images/qemuarm/modules-qemuarm.tgz
tmp/deploy/images/qemuarm/core-image-minimal-qemuarm-20170913170931.qemuboot.conf
tmp/deploy/images/qemuarm/zImage--4.10.9+git0+ad2e885015_718b0a5464-r0-versatile-pb-20170913170931.dtb
tmp/deploy/images/qemuarm/zImage-versatile-pb.dtb
tmp/deploy/images/qemuarm/core-image-minimal-qemuarm-20170913170931.rootfs.manifest
tmp/deploy/images/qemuarm/zImage-qemuarm.bin
tmp/deploy/images/qemuarm/modules--4.10.9+git0+ad2e885015_718b0a5464-r0-qemuarm-20170913170931.tgz
tmp/deploy/images/qemuarm/core-image-minimal-qemuarm.qemuboot.conf
tmp/deploy/images/qemuarm/zImage--4.10.9+git0+ad2e885015_718b0a5464-r0-qemuarm-20170913170931.bin
tmp/deploy/images/qemuarm/core-image-minimal-qemuarm.manifest
tmp/deploy/images/qemuarm/zImage
tmp/deploy/images/qemuarm/core-image-minimal-qemuarm-20170913170931.rootfs.tar.bz2
tmp/deploy/images/qemuarm/core-image-minimal-qemuarm.ext4
tmp/deploy/images/qemuarm/core-image-minimal-qemuarm-20170913170931.rootfs.ext4

To give an overview of the used disk space:

build$ du -hs *
[...]
5,2G    downloads
1,4G    sstate-cache
20G     tmp

If you have installed qemu on your host machine you can now run the generated image:

build$ runqemu qemuarm

This will open an extra X window showing the framebuffer console of your emulated ARM device. After it has booted up, you can logging with the username root (without a password). Congratulations you have build and run your first Yocto build.

The runqemu script also opens a local network device tap0. You should be able to ping the qemu device from your build host with:

$ ip addr
8: tap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 36:68:f3:67:e3:c5 brd ff:ff:ff:ff:ff:ff
    inet 192.168.7.1/32 brd 192.168.7.255 scope global tap0
       valid_lft forever preferred_lft forever
    inet6 fe80::3468:f3ff:fe67:e3c5/64 scope link
       valid_lft forever preferred_lft forever

$ ping 192.168.7.2
PING 192.168.7.2 (192.168.7.2) 56(84) bytes of data.
64 bytes from 192.168.7.2: icmp_seq=1 ttl=64 time=2.06 ms

A SSH daemon is not installed on the target root filesystem. So you cannot ssh into the qemu device right now. Installing openssh or dropbear on the root filesystem with the Yocto build system is left as an exercise to the reader.

Just kidding ... :-) Put the line:

IMAGE_INTALL_append = " openssh-sshd"

into the file conf/local.conf, rebuild, restart the qemu device and execute

$ ssh root@192.168.7.2
root@qemuarm:~# uname -a
Linux qemuarm 4.10.9-yocto-standard #1 PREEMPT Wed Sep 13 20:13:12 CEST 2017 armv5tejl GNU/Linux

Have fun!

Further reading