When debugging BitBake compilation errors, applying custom patches, or inspecting intermediate build headers in the Yocto Project, software engineers frequently need to locate the exact directory where source code is unpacked on disk. BitBake manages unpacked source code inside an isolated environment governed by two key build variables: WORKDIR (the recipe’s base working workspace) and S (the specific directory containing unpacked source files).

Yocto Build Directory Structure: WORKDIR and S

In OpenEmbedded and Yocto Project builds, every recipe receives a unique workspace inside build/tmp/work/. The base path of this workspace is assigned to the WORKDIR variable, which is defined in meta/conf/bitbake.conf as:

meta/conf/bitbake.confbitbake
TMPDIR = "${TOPDIR}/tmp"
WORKDIR = "${TMPDIR}/work/${MULTIMACH_TARGET_SYS}/${PN}/${EXTENDPE}${PV}-${PR}"

Inside WORKDIR, BitBake expects the unpacked source files to reside in the directory specified by the S (Source) variable. By default, S is configured as:

meta/conf/bitbake.confbitbake
BP = "${BPN}-${PV}"
S = "${WORKDIR}/${BP}"

For a recipe named helloworld version 1.0 targeting an ARM Cortex-A7 architecture, BitBake resolves these variables to the following concrete filesystem paths:

Resolved Filesystem Pathstext
WORKDIR = build/tmp/work/cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi/helloworld/1.0-r0/
S       = build/tmp/work/cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi/helloworld/1.0-r0/helloworld-1.0/

Common Recipe Overrides for the S Variable

Because different source code repositories and archives extract into different directory layouts, recipes often override S to match the actual folder structure:

  • Git Repositories (`SRC_URI = "git://..."`) - BitBake’s Git fetcher automatically unpacks cloned repositories into a subfolder named git. Recipes fetching from Git must set S = "${WORKDIR}/git".

  • Tarballs with Non-Standard Top-Level Folders - If a release tarball extracts to myapp-src-v2, the recipe must explicitly set S = "${WORKDIR}/myapp-src-v2".

  • Out-of-Tree Builds (`B` Variable) - While S defines where source files reside, B defines where compiler output files (.o, .so) are generated. By default B = "${S}", but CMake and Autotools recipes frequently set B = "${WORKDIR}/build".

How to Inspect WORKDIR and S for Any Recipe

Rather than manually expanding environment variables or guessing target architecture strings, you can query BitBake directly using bitbake -e to view the fully expanded variables for any recipe:

Terminalbash
bitbake -e helloworld | grep -E "^WORKDIR=|^S=|^B="
WORKDIR="/home/developer/poky/build/tmp/work/cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi/helloworld/1.0-r0"
S="/home/developer/poky/build/tmp/work/cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi/helloworld/1.0-r0/helloworld-1.0"
B="/home/developer/poky/build/tmp/work/cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi/helloworld/1.0-r0/helloworld-1.0"

Interactive Source Inspection: devshell and devtool

For active debugging and kernel/driver development, Yocto provides dedicated commands to interact directly with the unpacked source tree:

Terminalbash
bitbake -c devshell helloworld
Terminalbash
devtool modify helloworld
INFO: Source tree extracted to /home/developer/poky/build/workspace/sources/helloworld

Troubleshooting Common Yocto Source Path Errors

  • "S = ... does not exist" Error - Occurs during do_unpack or do_patch when the actual unpacked directory name does not match the value of S. Remedy: inspect the unpacked subfolder inside ${WORKDIR} and update S in your .bb file.

  • Missing WORKDIR Directory (`rm_work`) - If your local.conf contains INHERIT += "rm_work", BitBake automatically deletes ${WORKDIR} after package compilation completes to preserve disk space. Comment out rm_work during debugging sessions.

Understanding how BitBake resolves ${WORKDIR} and ${S} allows embedded systems engineers to rapidly inspect source files, diagnose build failures, and streamline Yocto recipe development.