A common scenario developers face is creating images for several
different machines that use the same software environment.
In this situation, it is tempting to set the
tunings and optimization flags for each build specifically for
the targeted hardware (i.e. "maxing out" the tunings).
Doing so can considerably add to build times and package feed
maintenance collectively for the machines.
For example, selecting tunes that are extremely specific to a
CPU core used in a system might enable some micro optimizations
in GCC for that particular system but would otherwise not gain
you much of a performance difference across the other systems
as compared to using a more general tuning across all the builds
(e.g. setting
DEFAULTTUNE
specifically for each machine's build).
Rather than "max out" each build's tunings, you can take steps that
cause the OpenEmbedded build system to reuse software across the
various machines where it makes sense.
If build speed and package feed maintenance are considerations, you should consider the points in this section that can help you optimize your tunings to best consider build times and package feed maintenance.
Share the Build Directory:
If at all possible, share the
TMPDIR
across builds.
The Yocto Project supports switching between different
MACHINE
values in the same TMPDIR
.
This practice is well supported and regularly used by
developers when building for multiple machines.
When you use the same TMPDIR
for
multiple machine builds, the OpenEmbedded build system can
reuse the existing native and often cross-recipes for
multiple machines.
Thus, build time decreases.
DISTRO
settings change or fundamental configuration settings
such as the filesystem layout, you need to work with
a clean TMPDIR
.
Sharing TMPDIR
under these
circumstances might work but since it is not
guaranteed, you should use a clean
TMPDIR
.
Enable the Appropriate Package Architecture: By default, the OpenEmbedded build system enables three levels of package architectures: "all", "tune" or "package", and "machine". Any given recipe usually selects one of these package architectures (types) for its output. Depending for what a given recipe creates packages, making sure you enable the appropriate package architecture can directly impact the build time.
A recipe that just generates scripts can enable
"all" architecture because there are no binaries to build.
To specifically enable "all" architecture, be sure your
recipe inherits the
allarch
class.
This class is useful for "all" architectures because it
configures many variables so packages can be used across
multiple architectures.
If your recipe needs to generate packages that are
machine-specific or when one of the build or runtime
dependencies is already machine-architecture dependent,
which makes your recipe also machine-architecture dependent,
make sure your recipe enables the "machine" package
architecture through the
MACHINE_ARCH
variable:
PACKAGE_ARCH = "${MACHINE_ARCH}"
When you do not specifically enable a package
architecture through the
PACKAGE_ARCH
,
The OpenEmbedded build system defaults to the
TUNE_PKGARCH
setting:
PACKAGE_ARCH = "${TUNE_PKGARCH}"
Choose a Generic Tuning File if Possible:
Some tunes are more generic and can run on multiple targets
(e.g. an armv5
set of packages could
run on armv6
and
armv7
processors in most cases).
Similarly, i486
binaries could work
on i586
and higher processors.
You should realize, however, that advances on newer
processor versions would not be used.
If you select the same tune for several different machines, the OpenEmbedded build system reuses software previously built, thus speeding up the overall build time. Realize that even though a new sysroot for each machine is generated, the software is not recompiled and only one package feed exists.
Manage Granular Level Packaging:
Sometimes cases exist where injecting another level
of package architecture beyond the three higher levels
noted earlier can be useful.
For example, consider the emgd
graphics stack in the
meta-intel
layer.
In this layer, a subset of software exists that is
compiled against something different from the rest of the
generic packages.
You can examine the key code in the
Source Repositories
"daisy" branch in
classes/emgd-gl.bbclass
.
For a specific set of packages, the code redefines
PACKAGE_ARCH
.
PACKAGE_EXTRA_ARCHS
is then appended with this extra tune name in
meta-intel-emgd.inc
.
The result is that when searching for packages, the
build system uses a four-level search and the packages
in this new level are preferred as compared to the standard
tune.
The overall result is that the build system reuses most
software from the common tune except for specific cases
as needed.
Use Tools to Debug Issues:
Sometimes you can run into situations where software is
being rebuilt when you think it should not be.
For example, the OpenEmbedded build system might not be
using shared state between machines when you think it
should be.
These types of situations are usually due to references
to machine-specific variables such as
MACHINE
,
SERIAL_CONSOLE
,
XSERVER
,
MACHINE_FEATURES
,
and so forth in code that is supposed to only be
tune-specific or when the recipe depends
(DEPENDS
,
RDEPENDS
,
RRECOMMENDS
,
RSUGGESTS
,
and so forth) on some other recipe that already has
PACKAGE_ARCH
defined as "${MACHINE_ARCH}".
For such cases, you can use some tools to help you sort out the situation:
sstate-diff-machines.sh
:
You can find this tool in the
scripts
directory of the
Source Repositories.
See the comments in the script for information on
how to use the tool.
BitBake's "-S printdiff" Option:
Using this option causes BitBake to try to
establish the closest signature match it can
(e.g. in the shared state cache) and then run
bitbake-diffsigs
over the
matches to determine the stamps and delta where
these two stamp trees diverge.