Cross-Platform Yocto Development with VSCode Dev containers
VSCode and Docker offer a clean way to build Yocto projects on Mac, Windows, and Linux
By Bailey Blankenship onYocto is an ecosystem of tools for building embedded Linux distributions. Its tools are meant to be run on a Linux machine - a powerful one. If you’re a Mac or Windows user, you have a few options:
- Use a virtual machine (Parallels, VirtualBox, etc.)
- Use CROPS, which is a container-based development system maintained by the Yocto team.
A virtual machine could be a win. You’ll have some processing overhead to run your Linux distro’s UI (unless you use a server distro), but in general, it’s a fine option. However, if you’re a little Apple simp like me, you’ll be emulating an x86 machine on an ARM-based M* processor, which adds a good bit of overhead.
CROPS is great, and we’ll be taking a similar approach that’s a bit more developer-friendly.
A Clean Solution: VSCode’s Dev Containers
Dev Containers are a feature of VSCode that allows a repository owner to craft a development environment based on Docker containers.
Because we’re using containers, the only requirement of our developers is that they have Docker installed. Easy.
This development environment is configured in a devcontainer.json
file that lives in a .devcontainer
folder at the root of the project.
When developers open a repository with a Dev Container in VSCode, they’re prompted to reopen the codebase inside the container-based development environment.
Let’s walk through the setup of a VSCode Dev Container-based development environment for Yocto.
1. Increase Docker Desktop’s Resource Limits
Yocto projects take up a lot of space - like 100GB - so you’ll need to double-check your Docker Dekstop configuration such that the Virtual disk limit is at least 120GB (to give some room for other stuff). You’ll also want to set the CPU and memory limits to their max so that your build takes full advantage of the machine.
On Mac or Windows:
- Open Docker Desktop’s dashboard
- Navigate to Settings > Resources
- Increase your CPU and Memory usage to max; ensure that the Virtual Disk has >120GB of space
2. Obtain a Yocto project
If you don’t already have a Yocto repo to work with, now is a good time to clone Poky, a Yocto template project, and open it in VSCode. In the below example, I use Poky’s kirkstone
branch, which uses the kirkstone
version of Yocto and has long-term support until 2026.
If you already have a Yocto project, open it in VSCode.
git clone git://git.yoctoproject.org/poky -b kirkstone
cd poky
code .
3. Set up the Dockerfile
As suggested by the name, Dev Containers use containers to run development environments.
To begin, we’ll add a folder called .devcontainer
to the root of our project and then create a Dockerfile
there.
Add this to .devcontainer/Dockerfile
:
FROM ubuntu:22.04
# Install packages per Yocto's requirements
RUN apt update && export DEBIAN_FRONTEND=noninteractive \
&& apt install -y --no-install-recommends \
sudo \
gawk \
wget \
git \
diffstat \
unzip \
texinfo \
gcc \
build-essential \
chrpath \
socat \
cpio \
python3 \
python3-pip \
python3-pexpect \
xz-utils \
debianutils \
iputils-ping \
python3-git \
python3-jinja2 \
libegl1-mesa \
libsdl1.2-dev \
python3-subunit \
mesa-common-dev \
zstd \
liblz4-tool \
file \
locales \
libacl1 \
&& apt clean \
&& rm -rf /var/lib/apt/lists/*
# Set default locale to en_US.UTF-8
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
echo 'LANG="en_US.UTF-8"'>/etc/default/locale && \
dpkg-reconfigure --frontend=noninteractive locales && \
update-locale LANG=en_US.UTF-8
# Set up a non-root user
ARG USER_NAME=yocto
ARG HOST_UID=1000
ARG HOST_GID=$HOST_UID
# Create the user and its group
RUN groupadd --gid $HOST_GID $USER_NAME && \
useradd --gid $HOST_GID --uid $HOST_UID --shell /bin/bash --create-home $USER_NAME && \
# Add sudo support for the user
usermod -aG sudo $USER_NAME && \
# Don't require a password for sudo
echo "$USER_NAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
USER $USER_NAME
Kinda Quick Explanation
We set up our Dockerfile such that it adheres to the system requirements of the Yocto project.
We’ll start by using
Ubuntu 22.04
, which is officially supported, and then install the required packages listed in Yocto’s documentation. There are some flags in the package installation command to say that we’re non-interactive (meaning the user isn’t able to interact with the installation process with the terminal) and to auto-approve (-y
flag) all of the package installs. We also clean up a bit afterward so that our container stays slim.Then we set the default locale to
en_US.UTF-8
. I had to Google around for a minute on this one. But if you don’t have this set, Yocto will get upset, so you’ve gotta set that locale.Then we set up a non-root user. By default, the Linux user in containers is
root
. Again, Yocto will complain. So we set up a new user namedyocto
and use theUSER
command in the Dockerfile to make that the container’s user.
4. Set up the dev container
Add this to .devcontainer/devcontainer.json
:
{
"name": "Yocto",
"build": {
// Use a Dockerfile to build a Yocto-compatible Linux environment
"dockerfile": "Dockerfile"
},
// Mount the build directory as a Docker Volume to persist build artifacts
// while still using a Yocto-compatible filesystem
"mounts": [
"source=${localWorkspaceFolderBasename}-build,target=${containerWorkspaceFolder}/build,type=volume"
],
"postCreateCommand": "sudo chown yocto build && sudo chgrp yocto build"
}
Kinda Quick Explanation
In the
build
section, we specify that our dev container should be built from a Dockerfile in our repo at the provided path.The
mounts
section indicates that we’d like to mount a Docker-managed volume (aka Named Volume) at the path/workspaces/repo-name/build
(${containerWorkspaceFolder}
resolves to/workspaces/repo-name
).If we didn’t have this, then by default, VSCode would use a bind mount to mount the repo’s folder, which resides on the host (aka your Mac or Windows OS), into the container. This behavior is similar to what you’d see in Linux when you mount an external hard drive. This is problematic because that mounted folder inherits the behaviors of your host’s filesystem. In the case of Mac and Windows machines, their filesystems are “Case Insensitive”, meaning that
/Dog.txt
and/dog.txt
are treated as the same file. Why? Who’s to say? But that’s not how things work in Linux and will cause problems when building Yocto projects.In this configuration, we use a Docker Volume just for the
build
folder. Docker will manage this for us, and it’ll do it in a way that’s compatible with Yocto. We chose this folder because that’s where most of Yocto’s work is done, and that’s where Yocto cares about the filesystem. Read more here. The rest of the files are still bind mounted, but Yocto doesn’t care about their filesystem as much.In the
postCreateCommand
, we change the permissions of thebuild
folder we mounted to be owned by the container’s user (yocto
). By default, the owner is set toroot
, so our yocto user wouldn’t have permission to use it.
5. Run the dev container 🎉
In VSCode, open the command pallet (cmd-shift-p), type “Dev Containers”, and select Dev Containers: Rebuild and Reopen in Container
. Then just sip ur coffee and hang tight - VSCode will tell Docker to build the container, then it will reopen itself in the container. If something fails, make sure Docker Desktop is running.
Once VSCode has reopened the codebase, open a terminal in VSCode and build the example image:
source oe-init-build-env
bitbake core-image-sato
Now sit back and relax for at least one, maybe two, extended editions of Lord of the Rings. This first build will take a few hours.
Use Dev Containers for projects with toolchains
Dev Containers with VSCode are ridiculously convenient. They improve output for your dev team by allowing them to get started immediately without fiddling with environment setup, and they help ensure repeatable builds between various systems. For most codebases that entail a tedious software toolchain, Dev Containers are the way to go.
You can modify the steps above to launch a container with a C, C++, or even a FORTRAN toolchain with relative ease. The only caveat is that projects that produce GUIs will be tricky, but they’re still workable with X11 forwarding.
Ringtail Labs can help your team
We’re experts in DevOps and embedded systems. If you need help architecting your infrastructure, improving your development team, or working with Yocto, you should schedule a meeting with us. We’re happy to help!
Any errors or omissions? Please let us know at hello@ringtaillabs.com