A short, unofficial guide on getting started with Yocto with a Raspberry Pi
Release: 3.5 "Kirkstone" - LTS Support: Apr 2022 - Apr 2024
Author: Jon Szymaniak (jynik / @sz_jynik)
License: CC BY-SA 2.0
Please report bugs, typos, feedback, and violations of best practice on the issue tracker.
If you're looking to build Linux-based firmware for embedded platforms, Yocto is a good option for you.
If you're looking to create automated, repeatable, version-controlled firmware builds with excellent traceability, change tracking, license auditing, configurable QA tests, and support for tons of software... Yocto is a great option for you!
So what is Yocto exactly? It's a bit of an umbrella project that pulls together multiple components, including the OpenEmbedded build system, to allow you to create custom-tailored embedded Linux "distributions" for your specific needs.
The purpose of this guide is to get you up and running with a minimal build for a Raspberry Pi so that you can get an initial sense of things before you dive further into the official documentation. (There's a lot, but it's really, really well done.)
Keep the following at an arm's length. In particular, the "Mega-Manual" is fantastic to search through (e.g. via "Ctrl-F") any time you encounter a term or variable name that you are unfamiliar with.
The follow white paper, written by yours truly, may also be of interest to you once you start to get your bearings. It's now super outdated (which I hope to address eventually), but a lot of the higher level "what & why" is still applicable.
Improving Your Embedded Linux Security Posture with Yocto (archive.org mirror)
Finally - please understand that there is a non-trivial learning curve with the Yocto and OpenEmbedded projects. Don't be discouraged, and reach out if you need help. Both projects have mailing lists, as well as a presence on sites like Stack Exchange. I generally will try to provide advice if folks reach out to me directly, time and general life situation permitting.
If you ultimately find that you're having a lot of trouble or just don't like something about Yocto/OpenEmbedded, consider kicking the tires on BuildRoot. You can find comparisons of all three projects here.
The nature and configuration of your build machine(s) will vary depending your needs. This guide DOES NOT cover a configuration suitable for production build deployments. Instead, this covers a "personal dev setup" installed onto a portable SSD that can be moved from machine to machine.
My personal preference for build host "minimum requirements" are as follows:
- (X|K)Ubuntu 20.04 LTS (or some similarly recent-ish distro of your choice)
- At least 8 GiB of RAM
- At least an Intel i5 (or AMD equivalent)
- At least 200 GiB of disk space, preferably on an SSD
- bash - Even if you love zsh or fish... trust me and just use bash for this.
To enable me to move from machine to machine (e.g., desktop to laptop) with my build environment, I use a portable SSD with the following restrictions,
- The SSD is formatted with EXT4. ZFS will cause you pain.
- All machines mount the SSD to the same exact mountpoint, i.e.
/portable
- The User and Group IDs I use between machines match. If you can't guarantee this with already existing users, consider making a new uid and gid for your builds.
If you decide to use a removable volume that's shared between multiple machines and deviate from those restrictions, you'll probably run into problems.
You'll need to install some tools to get started. For the (X|K|U)buntu apt users out there...
$ sudo apt install build-essential chrpath gawk git bmap-tools texinfo diffstat
So, let's assume the portable SSD I'm working with is always mounted to a
/portable
mountpoint.
Oftentimes I'll keep multiple Yocto releases on my system, so let's create a directory for the current version:
$ mkdir -p /portable/yocto/kirkstone
$ cd /portable/yocto/kirkstone
Let's also make some directories we'll use later:
$ mkdir /portable/yocto/kirkstone/builds
$ mkdir /portable/yocto/kirkstone/downloads
Now lets check out the kirkstone branch of "Poky" - Yocto's Build system:
$ git clone -b kirkstone git://git.yoctoproject.org/poky.git
The bitbake tool used by Yocto parses "recipes" that describe how to fetch, patch, configure, compile, install, package, and "deploy" software (into the top-level image artifact).
Collections of related "recipes" are grouped into "layers" and their names are prefixed with "meta-".
There's a layer dedicated to Raspberry Pi support. Let's fetch that. Note that
we're still in /portable/yocto/kirkstone
still!
$ git clone -b kirkstone https://github.com/agherzan/meta-raspberrypi.git
If you take a look at meta-raspberrypi/README.md
, you'll note that it has
dependencies on meta-oe, meta-multimedia, meta-networking, and meta-python.
Fortunately, these are all in one repo:
$ git clone -b kirkstone git://git.openembedded.org/meta-openembedded
Any time you want to work with the Yocto build system, you'll need your environment to be in the proper state. A provided script sets everything up for you.
The argument to this script is the build directory you want to work out of. This will be created and initialized if it doesn't exist. Lets start a new build directory called "rpi":
$ source /portable/yocto/kirkstone/poky/oe-init-build-env /portable/yocto/kirkstone/builds/rpi
You should see some text welcoming you into the environment. You will be placed into the rpi directory that was just created.
There are two files to configure in this directory:
conf/bblayers.conf
- Points the build environment to the layers you want to useconf/local.conf
- Build variables and options
So far we've cloned the get repository for a few "layers" but we haven't yet pointed the build tools to them. That's what we'll do now!
Briefly examine the contents of the conf/bblayers.conf
file. Note that the
only entries in the BBLAYERS
list are those associated with poky
. We
need to add the full paths to the meta-rasperrypi
and subdirectories within
the meta-openembedded
repository we cloned earlier.
Although we could edit this file manually, there's a bitbake-layers
command
that will help us out. Run the following command to see information about its
usage:
$ bitbake-layers -h
From the output of this command, we can see that we want to run the add-layer
sub-command. Run the command shown below, which has been split onto multiple
lines here for readability.
$ bitbake-layers add-layer \
/portable/yocto/kirkstone/meta-openembedded/meta-oe \
/portable/yocto/kirkstone/meta-openembedded/meta-multimedia \
/portable/yocto/kirkstone/meta-openembedded/meta-networking \
/portable/yocto/kirkstone/meta-openembedded/meta-python \
/portable/yocto/kirkstone/meta-raspberrypi
At this point, you might run into a HOSTTOOLS
error if some program(s)
is not installed on the system. For example, here's an error message that
indicates that we forgot to sudo apt install diffstat
:
ERROR: The following required tools (as specified by HOSTTOOLS) appear to be unavailable in PATH, please install them in order to proceed:
diffstat
After this command completes, note that the bblayers.conf
file has been updated.
Below is a sample of what you'll see.
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"
BBPATH = "${TOPDIR}"
BBFILES ?= ""
BBLAYERS ?= " \
/portable/yocto/kirkstone/poky/meta \
/portable/yocto/kirkstone/poky/meta-poky \
/portable/yocto/kirkstone/poky/meta-yocto-bsp \
/portable/yocto/kirkstone/meta-openembedded/meta-oe \
/portable/yocto/kirkstone/meta-openembedded/meta-multimedia \
/portable/yocto/kirkstone/meta-openembedded/meta-networking \
/portable/yocto/kirkstone/meta-openembedded/meta-python \
/portable/yocto/kirkstone/meta-raspberrypi \
"
Open up conf/local.conf
in your favorite editor and find this line:
MACHINE ??= "qemux86-64"
This denotes which platform we're targeting. This string corresponds
to <MACHINE>.conf
files traditionally stored in the conf/machine/
directories
provided by various "layers".
Take a look through the contents of the meta-raspberrypi/machine/
directory. Observe
that there's a .conf
file for each revision of the Raspberry Pi, and in some cases,
different variants of the same revision.
For instance, there's a "raspberrypi0
" and
a "raspberrypi0-wifi
" -- the former is the variant without built-in Wi-Fi, and the
later targets the variant with is. The "raspberrypi4-64
" configuration operates
the RPi 4 in its 64-bit mode, while the "raspberrypi4
" machine configuration
operates it in 32-bit mode.
If you look at the content in these machine configuration files, you'll find that
there's not a whole lot in there. This is because a majority of the "common stuff"
is all tucked away in files that are included (think #include in C/C++) via the
include
and required
directives.
Thus, the machine configuration files only override or expand upon variable definitions as-needed to do things like...
- Specify the U-Boot or Linux kernel target platform name
- Append extra items to a list of recommended firmware (e.g., Wi-Fi, BlueTooth module) recipes
- Tweak kernel command line arguments (e.g. serial console)
So now that we know a little bit more about what the "MACHINE
" variable does,
select the one that fits that platform that you'd like to build an image for.
As an example, let's target the Raspberry Pi 3 in 32-bit mode... just because we can.
This is done by changing the MACHINE
definition in local.conf
to:
MACHINE = "raspberrypi3"
Next, change the DL_DIR
variable to point to a location where we should
store downloaded files. I recommend setting this to something like...
DL_DIR = "/portable/yocto/kirkstone/downloads"
This variable specifies where we want to store downloaded files. For my own sanity, I generally have separate per-platform build directories. However, to save some time, I share the downloads between those builds so that I don't have to re-download items I already have. This is purely a matter of preference.
Before we're done editing the local.conf
file, take a quick skim through the
meta-raspberrypi
layer's docs/extra-build-config.md
file.
This describes a variety of local.conf
definitions that you can use to
enable/disable/modify what ultimately gets written to the config.txt
file
stored in the image's boot volume, which used to configure the Raspberry Pi at
runtime.
Frankly, the Raspberry Pi feels a bit weird and atypical in this regard. I think that this type of configuration deviates a bit from the spirit of Yocto/OpenEmbedded and suspect this stems from the fact that it's a designed to be a platform for people modify, customize, and hack on -- this differs from a product designed to implement only a very specific set of requirements, which is where I feel the Yocto project really shines.
If you plan on distributing your custom firmware build setup to other people (and especially if you are responsible for maintaining the firmware build process for your product), avoid heavy use of local.conf tweaks. Instead use custom distro layers, custom machine configuration files, and "bbappend" files -- we'll learn about those more a bit later. That being said -- it's also neighborly to provide a "known good" local.conf file template when creating your own "distro" layer... especially if you have some of your own custom dev/debug knobs people can turn!
For now, just roll with this, and know there's a "better" approach for builds that aren't just one-off experiments.
For the Raspberry Pi, below two settings you'll want to consider enabling, via
the documented additions to your local.conf
. Note that there's a few more
you may be interested in if you're planning to use I2C and SPI interfaces.
ENABLE_UART = "1"
- If you'd like to access a shell via the UARTRPI_USE_U_BOOT = "1"
- If you'd like to use the U-Boot bootloader
Moar shameless plugging: Why would you want to enable U-Boot? Well, to play with Depthcharge of course!
Let's start by building a very minimalist Linux image called "core-image-minimal". This will boot and drop you into a busybox environment as root. It won't include much more beyond that, however. (The idea is that this provides a minimalist base that other image recipes can build atop of.)
$ bitbake core-image-minimal
Another word of warning -- if you're a ZFS user on a 20.04 LTS, you'll run into an error like this. Remember when I said to use something like EXT4? This is why.
| bmaptool: ERROR: cannot generate bmap for file 'core-image-minimal-raspberrypi3-20210604145240.rootfs.wic': the file-system does not support "SEEK_HOLE" and "SEEK_DATA" but only provides a stub implementation
|
| WARNING: exit code 1 from a shell command.
The first builds will take quite sometime, given that you'll be fetching and
compling a toolchain, the kernel, and other core software. Once it's
complete, you'll find that your build artifacts located in: ./tmp/deploy/images/$MACHINE/
These build artifacts will be timestamped, with the most recent builds symlinked via shortend filenames without timestamps.
Once the build is complete -- and the first time you have to let the build process
fetch and build your core toolchain and software, it will take a while -- you'll
find your build artifacts located in ./tmp/deploy/images/<$MACHINE>
.
For now, let's just focus on artifacts starting with our image name, as this will lead us to our complete, all-in-one image that we can write to our device's non-volatile storage -- an SD card in the case of a dev-friendly RPi, but generally eMMC or NAND/NOR flash on other devices.
Below is an example directory listing, with some irrelevant items removed.
$ ls tmp/deploy/images/raspberrypi3/core-image-minimal*
tmp/deploy/images/raspberrypi3/core-image-minimal.env
tmp/deploy/images/raspberrypi3/core-image-minimal-raspberrypi3-20220225233439.rootfs.ext3
tmp/deploy/images/raspberrypi3/core-image-minimal-raspberrypi3-20220225233439.rootfs.manifest
tmp/deploy/images/raspberrypi3/core-image-minimal-raspberrypi3-20220225233439.rootfs.tar.bz2
tmp/deploy/images/raspberrypi3/core-image-minimal-raspberrypi3-20220225233439.rootfs.wic.bmap
tmp/deploy/images/raspberrypi3/core-image-minimal-raspberrypi3-20220225233439.rootfs.wic.bz2
tmp/deploy/images/raspberrypi3/core-image-minimal-raspberrypi3-20220225233439.testdata.json
tmp/deploy/images/raspberrypi3/core-image-minimal-raspberrypi3.ext3
tmp/deploy/images/raspberrypi3/core-image-minimal-raspberrypi3.manifest
tmp/deploy/images/raspberrypi3/core-image-minimal-raspberrypi3.tar.bz2
tmp/deploy/images/raspberrypi3/core-image-minimal-raspberrypi3.testdata.json
tmp/deploy/images/raspberrypi3/core-image-minimal-raspberrypi3.wic.bmap
tmp/deploy/images/raspberrypi3/core-image-minimal-raspberrypi3.wic.bz2
Simply put, these are your build artifacts and information about them including:
.manifest
- Included Recipes.env
- The build environment used during the process.testdata.json
- Test suite metadata.ext3
,.tar.bz2
,.wic.bmap
+wic.bz2
: Our file system images
In order to define what types of root filesystems image we want -- as well ready-to-flash composite images containing a bootloader, kernel, and filesystems -- we the IMAGE_FSTYPES. As you see here, there are a lot of available options!
In the case of the meta-raspberrypi layer, an include file that defines various properties about
our target ${MACHINE}
(raspberrypi3
), contains an "early default assignment" (?=
) of IMAGE_FSTYPES
,
resulting in the items shown above. Note that you can append to IMAGE_FSTYPES in local.conf
if you
would like to expirament with creating say,
The .wic
items may look new to you. These are (multi-partitioned) images creeted by the Wic tool.
Yeah, dd
is cool, but have you ever used bmaptool? This uses
the .wic.bmap
metadata file to determine where to write blocks of source image data (stored in the corresponding
.wic.bz2
file). This will generally be quicker than dd
and friends, as it will skip writes of "empty" regions
in the source image. You can find some additional information here.
Insert an SD card and take note of which block device it is (e.g. /dev/sdX
).
If you have volume automount enabled, be sure to umount
any SD card partitions.
Now you can write the image to your SD card. Take care not to clobber data on the wrong drive due to a typo at this point!
$ sudo bmaptool copy tmp/deploy/images/raspberrypi3/core-image-minimal-raspberrypi3.wic.bz2 /dev/sdc
bmaptool: info: discovered bmap file 'tmp/deploy/images/raspberrypi3/core-image-minimal-raspberrypi3.wic.bmap'
bmaptool: info: block map format version 2.0
bmaptool: info: 19546 blocks of size 4096 (76.3 MiB), mapped 8623 blocks (33.7 MiB or 44.1%)
bmaptool: info: copying image 'core-image-minimal-raspberrypi3.wic.bz2' to block device '/dev/sdc' using bmap file 'core-image-minimal-raspberrypi3.wic.bmap'
bmaptool: info: 100% copied
bmaptool: info: synchronizing '/dev/sdc'
bmaptool: info: copying time: 4.9s, copying speed 6.8 MiB/sec
If you receive the following error, you likely forgot to unmount one or more file systems (auto)mounted on the block device.
bmaptool: ERROR: An error occurred, here is the traceback:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/bmaptools/CLI.py", line 116, in open_block_device
descriptor = os.open(path, os.O_WRONLY | os.O_EXCL)
bmaptool: ERROR: cannot open block device '/dev/sdc' in exclusive mode: [Errno 16] Device or resource busy: '/dev/sdc'
Attach a USB-UART adapter to the UART pins on the Raspberry Pi's expansion connector as follows:
GND: Pin 6
TX: Pin 8
RX: Pin 10
Open the UART up in minicom, screen, etc. Plug in in the SD card and power on.
Via the UART, you should see boot text and then a login prompt akin to the following:
Poky (Yocto Project Reference Distro) 3.5 raspberrypi3 /dev/ttyS0
raspberrypi3 login:
Enter "root" and you'll be logged in. Look in your local.conf for an "EXTRA_IMAGE_FEATURES" to understand why password-less root login is enabled, let alone why root login is even enabled. Hint - it's a debug feature that you have to opt-out of!
From the console on the Raspberry Pi, run lsmod
. If you've used full-featured
and general purpose distributions like Raspbian in the past, you might notice that
none of the drivers you might have expected to see are loaded!
That's because core-image-minimal did not include the platform-specific kernel modules; it's a minimalist base image that you can expand upon to add additional functionality.
In fact, the core-image-base
recipe does just that, and may very well be a better
starting point for your custom firmware images!
To build this, run:
$ bitbake core-image-base
You'll see a bunch of new software being fetched, compiled, and staged for deployment in the firmware image. However, everything you've already built (that doesn't require rebuilding due to a configuration change) remains cached -- each successive build you do will generally require far less time.
When that's done, look for the core-image-base-raspberrypi3.wic.bz2
image in
./tmp/deploy/images/raspberrypi3/
.
Copy this to an SD card as you did earlier and boot it. Run lsmod
again and
observe that a whole slew of drivers have now been included in the image.
Note that (the relevant) additional interfaces are now active. (e.g. HDMI, Wi-Fi, Bluetooth)
At some point soon, you'll probably want to integrate your own software, scripts, or configuration changes into an image. Creating your own custom layer is the right place to begin introducing those changes.
As a general rule of thumb, you shouldn't be modifying the contents of other layers, provided that they are maintained reasonably well. Even in the cases when they aren't, there are often features (like BBMASK) that you can use to deal with undesired behavior from other layers, without needing to worry about maintaining a fork of the problematic layer.
Let's start with an overkill, but simple, example just to go through the process of creating a new layer:
Let's say you've added some initscripts to an image. After some debugging you've realized that BusyBox isn't configured with a particular command or argument that you need.
For example, try to run the commands "xz" and "unxz" from your shell on the Raspberry Pi and observe that they're not present on the system. (At the time of writing, these file compression Busybox "applets" are not enabled by default.) So, we'll enable these!
Copying entire recipes into your layer is considered a poor practice. Instead, the Yocto and OpenEmbedded communities prefer the use of a "bbappend" file, which will effectively let you append to the definition of a recipe found elsewhere. This allows you modify or redefine variable definitions, as well as make changes to the way software is fetched, compiled, "installed", and deployed.
In our case, we're going to use a bbappend file to change the .config
file
settings used to compile BusyBox.
First, we need to create a new layer. Let's call it "meta-mypi" and create it
using that bitbake-layer
command we used earlier:
Let's name our layer "meta-mypi":
$ bitbake-layers create-layer /portable/yocto/kirkstone/meta-mypi
When done, you should now have a /portable/yocto/kirkstone/meta-mypi
directory,
complete with a conf/ directory, an MIT license, a boilerplate README, and
an example recipe that we won't concern ourselves with here.
Recipes are stored in files with a .bb
extension.
If we want to add "stuff" or otherwise override definitions in an existing
recipe, we can do so by creating a corresponding .bbappend
file in our own layer.
A .bbappend
file must have the same name as its .bb
counterpart. As a
matter of best practice, should be located in the same relative path within the
layer.
The BusyBox recipe is found in poky/meta/recipes-core/busybox/busybox_1.35.0.bb
.
(The exact version string may have change since this tutorial was last updated.)
Note that this bitbake recipe includes the busybox.inc
file (via the require
directive),
where most of the work of the recipe is actually implemented.
The poky/meta/recipes-core/busybox/busybox
directory contains patches, "configuration fragments", while poky/meta/recipes-core/busybox/files
contains items to deploy within the target filesystem image. You'll see these referenced
via "file://" in the recipe's SRC_URI
definition.
The term "configuration fragments"
is most often used with respect to Linux kernel configuration, but applies to
the KConfig-esque configuration of BusyBox as well. Basically, these are .cfg
files that contain just a handful of CONFIG_FEATURE_<X>=y
entries. For recipes
designed to handle this this KConfig-like convention, we can simply use our bbappend
to introduce a .cfg
file that modifies our desired configuration tweak.
(Another quick aside...)
We won't talk about it here, and don't get bogged down by it, but know that
when using bbappend to tweak recipes (most of which don't use config fragments)
you may find yourself needing to add a little extra bit of shell or Python code
in a function within a recipe. Keep an eye out (i.e. grep around layers) for
recipes and bbappend files defining functions named do_configure_append()
or
do_configure_prepend()
to see examples of this. The Bitbake manual section
about Functions
explains what's going on with this syntax.
Okay, so we want to enable "xz" and "unxz", but where do we start?
Let's figure out what the state of the .config
file currently is, for the
Busybox binary we've already built.
To do this, we can do a few things, including:
-
Inspect the
poky/meta/recipes-core/busybox/busybox/defconfig
file, which gets combined with configuration fragments at build time. -
Look at the actual
.config
file that was used to configure the build that has already happened.
For the sake of learning more about bitbake, let's do number 2. Run the following command. This will launch a "devshell" which puts you in a fakeroot-esque environment, located at the working directory used when processing the BusyBox recipe.
$ bitbake -c devshell busybox
Once you're in this environment, run the command pwd
to see where exactly bitbake has plopped us.
You'll find that we're down a few directories into ./tmp/work/
.
While in the directory where our devshell has placed us, open the .config
file with your favorite editor.
Search for "XZ" and note that CONFIG_XZ
and CONFIG_UNXZ
are unset -- these are what we want to enable.
Close the console opened for the dev shell and navigate to your "meta-mypi" directory in a different terminal from the one you're using to run bitbake commands.
Create a meta-mypi/recipes-core/busybox/busybox
directory, just to mirror the paths we saw earlier
in the poky/meta
directory tree. Then, create a configuration fragment file in it that specifies
that we want CONFIG_XZ=y
and CONFIG_UNXZ=y
.
$ mkdir -p /portable/yocto/kirkstone/meta-mypi/recipes-core/busybox/busybox
$ echo "CONFIG_XZ=y" > /portable/yocto/kirkstone/meta-mypi/recipes-core/busybox/busybox/xz.cfg
$ echo "CONFIG_UNXZ=y" >> /portable/yocto/kirkstone/meta-mypi/recipes-core/busybox/busybox/xz.cfg
Next, lets create our actual bbappend file. Create the following file, again adjusting slightly if the busybox version has changed since the time of writing.
/portable/yocto/kirkstone/meta-mypi/recipes-core/busybox/busybox_.bbappend
You only need to put two lines in this file. Ensure you include the leading whitespace in the string on the second line.
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
SRC_URI_append := " file://xz.cfg"
By setting the FILESEXTRAPATHS
variable, we're instructing the OpenEmbedded build
system to look inside the directory in which our bbappend file resides (THISDIR
),
in a a subdirectory with the same name as our recipe, busybox. (See: PN
)
That's it, as far as the bbappend goes. The last thing to do is enable our new layer, since we haven't done that yet.
One final note - it would be incredibly annoying if you had to create a new bbappend file for every patch version bump to a piece of software. As noted here, you can actually use a "%" wildcard in the version portion of a recipe filename to match multiple version. We could have named our file, busybox_1.31.%.bbappend
, for example, to match all versions in the 1.35.x series.
From the terminal where you've been running bitbake
commands, run bitbake-layers add-layer
to add our "meta-mypi" layer. Refer back to the earlier section if you've forgotton how to do this.
Double check your conf/bblayers.conf
, just to see that the change took effect.
Now we can build our firmware image and our changes will take effect. First, we'll issue a "cleansstate" command to ensure busybox is reconfigured and rebuilt.
$ bitbake -c cleansstate busybox
$ bitbake core-image-base
Technically, that first command isn't necessary -- bitbake should detect the change and will
identify which core-image-base
dependencies that require rebuilding. It's quite smart like that.
However, I like to be explicit, just for my own sanity. Plus, this gave me the chance to note how to fully "clean" up the state of a recipe build, without having to have it redownloaded, which is what happens if you use "cleanall" instead of "cleansstate". Using "clean" is essentially like running "make clean" -- it will clean up compilation, but not configuration, artifacts.
When this completes, run bitbake devshell busybox
again and confirm that the .config
file has indeed been updated to reflect our changes. Then write the newly regenerated
core-image-base-raspberrypi3.wic.bz2
iamge to an SD card, boot it, and observe that you can now
use the "xz" and "unxz" commands in all their glory.
Well, that covers about < 1% of Yocto, but it's a great start on some commodity hardware. Having done this, you'll hopefully now have a better sense of what's discussed in the documentation.
If you ever get yourself into trouble, or find that a particular recipe is in a bad state,
check out the bitbake cleansstate <recipe>
and bitbake cleanall <recipe>
commands.
I'll leave it to you to look those up in the reference manual.
There's definitely quite a learning curve here, but I've found that the best way to tackle it is to just explore existing recipes, along with the implementation of the Yocto and OpenEmbedded components themselves.
If you run into strange errors, always start by checking for variable name typos. Those will getcha! If you find
yourself questioning your sanity, bitbake -e
is your friend. I'll let you look that one up too.
Good luck and happy hacking!
- jynik