Back to Articles

Common Yocto Variables

Common Variables for Yocto Recipes

Common Yocto Variables

When writing Yocto recipes there are some common variables that you use all the time, especially in do_install() and when debugging where BitBake has put things.

An example of this would be:

do_install() {
    install -d ${D}${bindir}
    install -m 0755 ${B}/my-program ${D}${bindir}/my-program

    install -d ${D}${sysconfdir}/my-program
    install -m 0644 ${UNPACKDIR}/my-program.conf ${D}${sysconfdir}/my-program/my-program.conf
}

The important detail is that ${D} is a temporary install root inside the build directory. ${D}${bindir} means “install into /usr/bin in the package being created”, not “copy this file into /usr/bin on my build machine”.

These variables are defined in meta/conf/bitbake.conf. The exact final value can still be affected by distro, machine, class and recipe configuration, so if in doubt check the recipe environment:

bitbake -e <recipe> | less
Common build and recipe working directories
VariableTypical Wrynose value
WORKDIR${TMPDIR}/work/${MULTIMACH_TARGET_SYS}/${PN}/${PV}
UNPACKDIR${WORKDIR}/sources
S${UNPACKDIR}/${BP}
B${S}
D${WORKDIR}/image

${WORKDIR} is the per-recipe working area. It contains logs, unpacked sources, sysroots, packaging output and other task data.

${UNPACKDIR} is where fetched sources and local file:// entries are unpacked in current OE-Core. For recipes that install a local script or config file, this is often the path you want.

${S} is the source tree used by patch, configure and compile tasks. The default is ${UNPACKDIR}/${BP}, but many recipes set it explicitly when the source unpacks somewhere else.

${B} is the build directory. By default it is the same as ${S}, but classes such as cmake often use a separate build directory.

${D} is the image directory used by do_install(). Files installed here are later split into packages by do_package.

Common target filesystem directories
VariableDefault target path
bindir/usr/bin
sbindir/usr/sbin
libdir/usr/lib
libexecdir/usr/libexec
sysconfdir/etc
servicedir/srv
localstatedir/var
datadir/usr/share
infodir/usr/share/info
mandir/usr/share/man
docdir/usr/share/doc
includedir/usr/include

These are target filesystem paths. In a recipe you normally combine them with ${D} during installation:

do_install() {
    install -d ${D}${libexecdir}/my-program
    install -m 0755 ${B}/helper ${D}${libexecdir}/my-program/helper

    install -d ${D}${localstatedir}/lib/my-program
}

That installs files under ${D}/usr/libexec/my-program and ${D}/var/lib/my-program while the package is being built. If the package is installed on the target, those become /usr/libexec/my-program and /var/lib/my-program.

servicedir and localstatedir are easy to confuse. In Wrynose, servicedir is /srv, while localstatedir is /var. Most recipe install paths that need persistent state use ${localstatedir}, for example ${localstatedir}/lib/<name>.

Other useful target directories
VariableDefault target path
sharedstatedir/com
systemd_unitdir/usr/lib/systemd
systemd_system_unitdir/usr/lib/systemd/system
systemd_user_unitdir/usr/lib/systemd/user

For systemd services, recipes normally install unit files into ${D}${systemd_system_unitdir} and let the systemd class handle package integration:

inherit systemd

SYSTEMD_SERVICE:${PN} = "my-program.service"

do_install() {
    install -d ${D}${systemd_system_unitdir}
    install -m 0644 ${UNPACKDIR}/my-program.service ${D}${systemd_system_unitdir}/my-program.service
}

This is the kind of thing these variables are for: write the recipe in terms of Yocto’s target layout, not whatever happens to be true on your build host.