Articles
Common Yocto Variables
Common Variables for Yocto Recipes

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
| Variable | Typical 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.
| Variable | Default 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>.
| Variable | Default 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.


