Supporting multiple build configurations with Yocto
- 18 May, 2025

When adding new MACHINE and DISTRO configurations to Yocto, handling build setup for all of them can become complicated. The increased complexity is especially obvious when new DISTRO configurations are introduced, since different build directories are needed in order to avoid polluting each other’s environment (like we had in the previous post on QEMU NOR SPI).
Having separate build directories also means that builds for both configurations cannot be performed at the same time
using the same bitbake
instance, and products of one build cannot be easily used in another build.
Yocto has a solution for this problem: multiconfig.
Tip
Yocto does support dynamic-layers which can
help when different configurations depend on different layers. The same can be accomplished using multiconfig with
BBMASK
to mask layers that should not be used for the selected configuration.
Yocto multiconfig
Yocto multiconfig provides a mechanism to specify different configurations, as if having different local.conf
files,
but making builds in the same build
directory. That way, the shared state cache and download directories are shared
between configurations, which saves both time during build and space on the build machine.
It is also possible to specify that multiconfigs should use different TMPDIR
, which is useful when different DISTROs
are used between multiconfigs, in order to avoid polluting each other’s environment.
The multiconfig is defined in the conf/multiconfig
directory of a layer or in the build directory. For each
multiconfig option an entry in the BBMULTICONFIG
variable of the local.conf
should exist. There is also the default
configuration, where configuration stems only from the local.conf
file.
Looking to apply the multiconfig for the setup in QEMU SPI NOR post, the default configuration
will cover the regular build running from the eMMC, and a new multiconfig called recovery
will be introduced to cover
the build of recovery image. Therefore, the local.conf
should contain the following definition
BBMULTICONFIG = "recovery"
The value of the current multiconfig that is used for building can be fetched using BB_CURRENT_MC
, so that parameter
can be used in recipes to have conditional includes. Of course, the regular ways to make disctinction between builds,
like MACHINEOVERRIDES
or DISTROOVERRIDES
still apply, so BB_CURRENT_MC
should only be used as a supplement.
Note
The Yocto multiconfig page covers all the details on use of multiconfig with examples.
Example multiconfig
Tip
All of the changes that will be described, plus a few more which are required for this to work, are available in the
scarthgap
branch of
meta-mistra and
qemu-sunxi-yocto
repositories in Github.
Continuing our example, the local.conf
(from where the default configuration stems) should be configured to specify
the default DISTRO to be mistra-framebuffer
and the default MACHINE cubieboard-ng
.
DISTRO ?= "mistra-framebuffer"
MACHINE ?= "cubieboard-ng"
The recovery multiconfig will then change DISTRO to mistra-recovery
in the conf/multiconfig/recovery.conf
file in
the meta-mistra
layer.
- recovery.conf
TMPDIR .= "-${BB_CURRENT_MC}"
DISTRO = "mistra-recovery"
MACHINE = "cubieboard-ng"
TMPDIR .= "-${BB_CURRENT_MC}"
DISTRO = "mistra-recovery"
MACHINE = "cubieboard-ng"
Since different DISTRO is used compared to the default configuration, the TMPDIR
is redefined to have multiconfig
value in it, so it is different from the other configurations.
Running builds
After the multiconfig definition is in place, the build is done using bitbake
. The format of the target that is built
is mc:<multiconfig>:<recipe>
, where <multiconfig>
is an empty string for the default configuration.
So, if we want to build the update-image
for the default configuration, command would be
bitbake mc::update-image
The command for building the bootloader and mistra-swupdate-recovery
for the recovery multiconfig is
bitbake mc:recovery:virtual/bootloader mc:recovery:mistra-swupdate-recovery
And the command to build all these three targets at the same time
bitbake mc::update-image mc:recovery:virtual/bootloader mc:recovery:mistra-swupdate-recovery
The output files for all the targets would be under the same build
but different TMPDIR
directories (tmp
and
tmp-recovery
).
Multiconfig task dependencies
Multiconfig also provides a way to specify dependencies between tasks in different configs using mcdepends
, which
simplifies integration between different configs.
For instance, if we wanted to include the recovery fitImage in the rootfs of the regular mistra-swupdate
(for instance
if we wanted to update the stored fitImage in the SPI NOR flash memory), we could add the following dependency in the
mistra-swupdate.bb
do_rootfs[mcdepends] = "mc::recovery:virtual/kernel:do_deploy"
and copy the file in the ROOTFS_POSTPROCESS_COMMAND
copy_fitimage() {
install -d ${IMAGE_DIR}/usr/share/recovery
install -m 0644 ${TMPDIR}-recovery/deploy/images/cubieboard-ng/fitImage-cubieboard-ng.bin ${IMAGE_DIR}/usr/share/recovery/fitImage
}
ROOTFS_POSTPROCESS_COMMAND += "copy_fitimage"
Things to keep in mind
Multiconfig comes with many benefits, but there are also some things to keep in mind before using them.
With more multiconfigs that are used, the preparation step, where dependencies between tasks and recipes are analyzed, takes much longer every time configuration is changed, since that same step is done for all of the defined multiconfig options, plus the default configuration.
This also means that each of the multiconfig configurations has to be valid for all recipes at the time of building.
Therefore, masking unused parts of layers using BBMASK
and scoping recipes that apply to certain configurations using
COMPATIBLE_MACHINE
should be done in order to streamline builds.
Summary
This was a short overview on Yocto multiconfig. Multiconfig allows creating separate build configurations and specifying dependencies between them, so they can all be built at the same time and within the same build directory, sharing same download and sstate cache, which saves both time and space.