Eve’s product#
Eve works for Ruggedify Technologies AB.
Her newest product will be rugged tablet used by maintenance technicians.
She will make everything available as open-source and to enable customers to create their own software and customize the product best for their technicians.
She will need Wifi, Bluetooth and a few GPIOs to interact with.
For the UI she chooses Flutter, because it doesn’t come with additional costs.
The following steps will be needed to turn his project into a product.
Create a project layer
First of all you will need to create a project layer.
You will need the following
a git server to host the repository (e.g. Github, Gitlab, your in-house git)
an empty repository (e.g. meta-myproduct)
Now you can create the project layer, as described by Create your project layer.
Create a project distro
Now it is time to create a custom distro
.
Adjust the highlighted lines
The highlighted lines need to be configured according to your needs
For that create a file with the following content under <path/to/project-layer>/conf/distro/my-distro.conf
.
DISTRO = "my-distro" # change the name according to your preferences
DISTRO_NAME = "My Distro" # change the name according to your preferences
DISTRO_BASEVERSION = "1.2.3" # you can change the version according to your preferences
DISTRO_VERSION = "${DISTRO_BASEVERSION}"
SDK_VENDOR = "-mydistroosdk"
SDK_VERSION = "${DISTRO_VERSION}"
SDK_NAME = "${DISTRO}-${TCLIBC}-${SDKMACHINE}-${IMAGE_BASENAME}-${TUNE_PKGARCH}-${MACHINE}"
SDKPATHINSTALL = "/opt/mydistro/${SDK_VERSION}/${MACHINE}"
TARGET_VENDOR = "-mydistro" # you can change the version according to your preferences
DISTROOVERRIDES .= ":my-distro" # needs to match setting from DISTRO
# add the DISTRO_FEATURES you need here, see below for more details
DISTRO_FEATURES = ""
TCLIBCAPPEND = ""
require conf/distro/include/no-static-libs.inc
require conf/distro/include/yocto-uninative.inc
require conf/distro/include/security_flags.inc
require conf/distro/include/simplecore-distro/preferred_versions.inc
INHERIT += "uninative"
DISTRO_FEATURES
Please select the DISTRO_FEATURES
you require and add them to above’s config file at DISTRO_FEATURES
.
Possible options are
alsa
- Include ALSA audio supportbluetooth
- bluetooth support.directfb
- DirectFB (direct framebuffer graphics) support.ipsec
- IPSec support.ipv6
- IPv6 support.keyboard
- keyboard support .ldconfig
- support for ldconfig and ld.so.conf on the target.nfs
- NFS client support (for mounting NFS exports on device).opengl
- Open Graphics Library, used for rendering two and three-dimensional graphics.pci
- PCI bus support.pcmcia
- PCMCIA/CompactFlash support.ppp
- PPP dialup support (also required for modem connections).smbfs
- SMB networks client support (for mounting Samba/Microsoft Windows shares on device).systemd
- support for SystemD.usbgadget
- USB Gadget Device support (for USB networking/serial/storage).usbhost
- USB Host support (allows to connect external keyboard, mouse, storage, network etc).usrmerge
- Merges the /bin, /sbin, /lib, and /lib64 directories into their respective counterparts in the /usr directory to provide better package and application compatibility.wayland
- the Wayland display server protocol, required for graphical applications.virtualization
- Support for container and other virtualization techniques.wifi
- WiFi support.
Only select what you need
Please select only the mandatory options. In case you are unsure omit the item
Now you can select your custom distribution config by setting in local.conf
DISTRO = "my-distro"
For DISTRO_FEATURES
Eve chooses
ipv6 wifi bluetooth systemd
Create a build manifest
To define what layers and settings your product image will require, it is needed to define a so called manifest
.
These are files that define repositories and their used revision in a reproducible way.
First you will need to create a new repository on your git server.
There are different tools available, but we would recommend
repo is the reference tool used by Google Android to manage different repositories.
It uses xml
files to configure what repository is checkout with what revision.
Create a manifest
Create a file named default.xml
in your manifest repository.
You can create such a file with the help of Scotty.
Just run
$ scotty export --mode repo
to create a good starting point for your project
Create a config template
As repo only specializes in managing git repositories, you will need to create a bitbake template to configure the Yocto build.
You can create such a files with the help of Scotty.
Just run
$ scotty export --mode local.conf
# and
$ scotty export --mode bblayers.conf
to create a good starting point for your project
Build
$ repo init -u git://<URL to your git server hosting your project layer>.git
$ repo sync
$ TEMPLATECONF=sources/meta-my-project-layer/template/my-template source sources/poky/oe-init-build-env
now you can start your bitbake build with
$ bitbake my-image
kas is a widely known tool to manage bitbake layers and build configuration.
Create a manifest
Everything is controlled by a single yaml
file.
You can create such a file with the help of Scotty.
Just run
$ scotty export --mode kas
to create a good starting point for your project
Build
$ kas build <yaml config file>
Application recipes
For each of your product application can services you’ll need to create recipes. Please see Create a recipe on how to do that.
After following the guide Eve has created this recipe
service-ui_git.bb
Application services
For each of your recipe (if they don’t ship systemd services on their own), you will need to create SystemD Service Units.
We recommend to create a new recipe for each of your applications/services.
create service unit
Under <path/to/project-layer>/recipes-project/<service name>/files/<service name>.service
create a file with
the following content
[Unit]
# A brief description of your service
Description=My custom service
[Service]
# the following line defines what to run
ExecStart=/usr/bin/my-service
[Install]
WantedBy=multi-user.target
create service recipe
Under <path/to/project-layer>/recipes-project/<service name>/<service name>_1.0.bb
add the following content.
SUMMARY = "${BPN} systemd service"
LICENSE = "CLOSED"
SRC_URI = "file://${BPN}.service"
inherit allarch
S = "${WORKDIR}"
do_install() {
install -d ${D}${systemd_system_unitdir}
install -m 0644 ${WORKDIR}/${BPN}.service ${D}${systemd_system_unitdir}
}
FILES:${PN} += "${systemd_system_unitdir}"
RDEPENDS:${PN} += "<name of the application this service is for>"
e.g. if the application recipe is called backend
the recipe needs to look like that
SUMMARY = "${BPN} systemd service"
LICENSE = "CLOSED"
SRC_URI = "file://${BPN}.service"
inherit allarch
S = "${WORKDIR}"
do_install() {
install -d ${D}${systemd_system_unitdir}
install -m 0644 ${WORKDIR}/${BPN}.service ${D}${systemd_system_unitdir}
}
FILES:${PN} += "${systemd_system_unitdir}"
RDEPENDS:${PN} += "backend"
For Eve application she will need to create
service-ui-service
Defining the image
Time to create your project specific image, create a recipe in your project specific layer.
E.g. at <path/to/project-layer>/recipes-core/images/my-image.bb
SUMMARY = "My project image"
LICENSE = "CLOSED"
inherit core-image
# Install additional packages/recipe by adding to the
# following line
IMAGE_INSTALL += ""
To add the right recipes for this image Eve adds
IMAGE_INSTALL += "\
service-ui-service \
"
to her image
SimpleCoreIO integration
To integrate SimpleCoreIO create the following recipes
libsimplecoreio
At <path/to/project-layer>/recipes-bsp/simplecoreio/libsimplecoreio_git.bb
SUMMARY = "Add userspace support for simplecoreio"
AUTHOR = "Tria"
LICENSE = "MIT & GPL-2.0-or-later"
LIC_FILES_CHKSUM = "file://LICENSE;md5=76e7da7e63cd7004b01b402febe8bdd0"
DEPENDS += "libgpiod"
SRC_URI = "\
git://git@github.com/avnet-embedded/simplecoreio.git;protocol=ssh;branch=master \
"
SRCREV = "33d837fe54fbdc474443a9404664fd222354d412"
S = "${WORKDIR}/git"
UPSTREAM_CHECK_COMMITS = "1"
inherit python3native
EXTRA_OEMAKE = "PREFIX=${prefix} CC='${CC}' CFLAGS='${CFLAGS}' DESTDIR=${D} LIBDIR=${libdir} INCLUDEDIR=${includedir} PYTHON_LIBDIR=${PYTHON_SITEPACKAGES_DIR}"
do_install() {
oe_runmake install install-python3 install-examples install-mock install-tools
}
PACKAGE_BEFORE_PN += "${PN}-examples ${PN}-python ${PN}-python-examples ${PN}-mock ${PN}-tools"
FILES:${PN} += "${libdir}/libsimplecoreio.so.* ${datadir} ${systemd_system_unitdir}"
FILES:${PN}-examples += "${bindir}/libsimplecoreio-example"
FILES:${PN}-tools += "${bindir}/simplecoreio-list"
FILES:${PN}-python += "${PYTHON_SITEPACKAGES_DIR}/simplecoreio"
FILES:${PN}-mock += "${bindir}/gpio-mock-cdev"
FILES:${PN}-python-examples += "${bindir}/libsimplecoreio-example.py"
RDEPENDS:${PN} += "libgpiod mscio-drivers"
RDEPENDS:${PN}-examples += "${PN}"
RDEPENDS:${PN}-tools += "${PN}"
RDEPENDS:${PN}-python += "${PN} ${PYTHON_PN}-ctypes libgpiod-python"
RDEPENDS:${PN}-python-examples += "${PN}-python"
simplecore-names
and at <path/to/project-layer>/recipes-bsp/simplecoreio/simplecore-names_git.bb
SUMMARY = "Provides rules for providing consistent names to various interfaces"
LICENSE = "MIT"
SRC_URI = "\
git://git@github.com/avnet-embedded/simplecoreio.git;protocol=ssh;branch=master \
"
SRCREV = "33d837fe54fbdc474443a9404664fd222354d412"
LIC_FILES_CHKSUM = "file://../LICENSE;md5=76e7da7e63cd7004b01b402febe8bdd0"
S = "${WORKDIR}/git/configs"
UPSTREAM_CHECK_COMMITS = "1"
inherit systemd
do_install() {
# systemd network files
install -d "${D}${systemd_unitdir}/network"
if [ -e "${S}/systemd/network/all/" ]; then
for file in ${S}/systemd/network/all/*; do
install -m 644 "$file" "${D}${systemd_unitdir}/network"
done
fi
if [ -e "${S}/systemd/network/${MACHINE}/" ]; then
# overwrite by MACHINE specifics
for file in ${S}/systemd/network/${MACHINE}/*; do
install -m 644 "$file" "${D}${systemd_unitdir}/network"
done
fi
# systemd service files
install -m 0755 -d "${D}${systemd_system_unitdir}"
if [ -e "${S}/systemd/services/all" ]; then
for file in ${S}/systemd/services/all/*; do
install -m 644 "$file" "${D}${systemd_system_unitdir}"
done
fi
if [ -e "${S}/systemd/services/${MACHINE}" ]; then
for file in ${S}/systemd/services/${MACHINE}/*; do
install -m 644 "$file" "${D}${systemd_system_unitdir}"
done
fi
# udev rules
install -d "${D}${nonarch_base_libdir}/udev/rules.d"
if [ -e "${S}/udev/rules/all/" ]; then
for file in ${S}/udev/rules/all/*; do
install -m 644 "$file" "${D}${nonarch_base_libdir}/udev/rules.d"
done
fi
if [ -e "${S}/udev/rules/${MACHINE}/" ]; then
# overwrite by MACHINE specifics
for file in ${S}/udev/rules/${MACHINE}/*; do
install -m 644 "$file" "${D}${nonarch_base_libdir}/udev/rules.d"
done
fi
# udev scripts
install -d "${D}${nonarch_base_libdir}/udev/scripts"
if [ -e "${S}/udev/scripts/all" ]; then
for file in ${S}/udev/scripts/all/*; do
install -m 755 "$file" "${D}${nonarch_base_libdir}/udev/scripts"
done
fi
if [ -e "${S}/udev/scripts/${MACHINE}" ]; then
for file in ${S}/udev/scripts/${MACHINE}/*; do
install -m 755 "$file" "${D}${nonarch_base_libdir}/udev/scripts"
done
fi
# other files
if [ -e "${S}/files/all" ]; then
cp -r ${S}/files/all/* ${D}
fi
if [ -e "${S}/files/${MACHINE}" ]; then
cp -r ${S}/files/${MACHINE}/* ${D}
fi
chown -R root:root ${D}/*
}
SYSTEMD_SERVICE:${PN} = "systemd-udev-retrigger.service"
FILES:${PN} += "/ ${systemd_unitdir}/network ${nonarch_base_libdir}/udev ${systemd_system_unitdir}"
Reference in your image
and finally add to your image
IMAGE_INSTALL += "libsimplecoreio simplecore-names"
Setup testing
As you more and more shape your project into a product, we recommend that you consider adding automated testing to your CI/CD pipelines.
From experience we recommend to have a look at
Storage for SBOMs and copy-left artifacts
As your product will most certainly contain Copyleft licensed code, you will need to make these parts of the code available to users that request it.
So one of the tasks will be to create a webserver, that will host archives created by the build.
Enable archive.bbclass
Add the following line to your distro config
INHERIT += "archiver"
Copy archives after each build
After each (release) build you will have to copy the files from
$ cp -r build/tmp/deploy/sources/* /path/to/your/webservers/www-root/
if the webserver is a remote machine you may consider using rsync for that.
Optional registration wall
You are not required to make those sources available to everyone but the actual users of your product, so you may want to add a registration wall to the webserver - speak to your IT department about the options
You will likely be also required to provide Software Bills of Material (or short SBOM)
Enable create-spdx.bbclass
Add the following line to your distro config
INHERIT += "create-spdx"
SPDX_INCLUDE_SOURCES = "1"
SPDX_UUID_NAMESPACE = "<URL of your webserver>/spdx"
SPDX_ORG = "<Your company name>"
Copy SBOMs after each build
After each (release) build you will have to copy the files from
$ cp -r build/tmp/deploy/spdx/* /path/to/your/webservers/www-root/spdx/
if the webserver is a remote machine you may consider using rsync for that.
You may also want to have a look at the following webinar, which provides further steps and recommendations
Talk to our experts
In case you need further support