Not everyone on your team needs to rebuild the whole Linux image every day. Application developers usually just need a cross-compiler, the right headers, and the right libraries for your target board — nothing more. Yocto’s populate_sdk task packages exactly that into one self-installing shell script. This lecture, from EmbeddedPathashala’s free linux device drivers course, walks through building, installing, and actually using that SDK correctly.
meta-toolchain
cross compiler
sysroot
free linux device drivers course
free linux kernel development course
What You Will Learn
- Generating a full SDK for a specific image with populate_sdk
- Generating a minimal C/C++-only toolchain with meta-toolchain
- Installing the SDK and sourcing its environment script
- Why a raw cross-compiler can’t find stdio.h and how to fix it
- Enabling static libraries in the SDK
Prerequisites
You should already have a custom image recipe building successfully — covered in the previous lecture of this free embedded linux course — since the SDK is generated from a specific image target, not from thin air.
Why a Full SDK Instead of a System Cross-Compiler
A generic ARM or AArch64 cross-compiler installed from your distro’s package manager knows nothing about your target’s actual root filesystem — it has no idea which C library version you’re using, which optional libraries (OpenSSL, libcurl, a vendor SDK) are present on the device, or which kernel headers match your running kernel. Yocto’s SDK generation solves this by packaging a compiler that is pre-configured with a matching sysroot pulled directly from the same build that produced your target image, so what compiles against the SDK will actually run on the device.
Generating the SDK
Run populate_sdk against whatever image recipe defines your product, for example the ep-diag-image built in the previous lecture:
$ bitbake ep-diag-image -c populate_sdk
The result lands in tmp/deploy/sdk/ as a single self-installing script following this naming pattern:
poky-<c_library>-<host_machine>-<image_name>-<target_machine>-toolchain-<version>.sh
A real example for an ARM Cortex-A8 board:
poky-glibc-x86_64-ep-diag-image-cortexa8hf-neon-toolchain-6.0.sh
Static Libraries: On by Default? No.
By default the generated toolchain ships dynamic libraries only. If your application needs to link statically, enable it before generating the SDK — either for one specific library:
TOOLCHAIN_TARGET_TASK:append = " glibc-staticdev"
or globally across everything the SDK installs:
SDKIMAGE_FEATURES:append = " staticdev-pkgs"
A Minimal Toolchain-Only Alternative
If application developers only need C/C++ compilers, the C library, and headers — no full sysroot matching a specific image — meta-toolchain is faster to build and much smaller to distribute:
$ bitbake meta-toolchain
Installing and Activating the SDK
Run the generated script directly. It installs to /opt/poky by default, but prompts for a custom location:
$ tmp/deploy/sdk/poky-glibc-x86_64-ep-diag-image-cortexa8hf-neon-toolchain-6.0.sh
Enter target directory for SDK (default: /opt/poky/6.0):
You are about to install the SDK to "/opt/poky/6.0". Proceed [Y/n]? Y
Extracting SDK.....................................done
Setting it up...done
SDK has been successfully set up and is ready to be used.
Before compiling anything, source the environment setup script that was generated alongside it — this exports CC, CXX, PKG_CONFIG_SYSROOT_DIR, and the target triple:
$ . /opt/poky/6.0/environment-setup-cortexa8hf-neon-poky-linux-gnueabi
The stdio.h Trap — and Why $CC Fixes It
Toolchains generated this way are deliberately generic across a whole family of ARM cores, so the compiler binary itself has no sysroot baked in:
$ arm-poky-linux-gnueabi-gcc --print-sysroot
/not/exist
Call the raw compiler binary directly and it will fail to find even the standard C headers:
$ arm-poky-linux-gnueabi-gcc ep_diag.c -o ep_diag
ep_diag.c:1:19: fatal error: stdio.h: No such file or directory
1 | #include <stdio.h>
| ^
compilation terminated.
This is expected — the fine-tuning (correct sysroot, correct CPU flags) is applied at invocation time by the environment setup script through the $CC variable, not baked permanently into the binary. Always compile through $CC, never by calling the compiler binary name directly:
$ $CC ep_diag.c -o ep_diag
$ file ep_diag
ep_diag: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked
Real-World Use Case
A common team setup: the core platform team builds and publishes a versioned SDK script (e.g., toolchain-6.0.sh) to an internal artifact server after every image release. Application developers install it once, source the environment script in their shell profile or CI pipeline, and cross-compile without ever touching a Yocto build tree themselves — cutting build-onboarding time from hours to minutes.
Common Mistakes and Troubleshooting
- Calling the compiler by name instead of $CC — causes the stdio.h error above; always source the environment script first.
- Forgetting to re-source after opening a new terminal — the environment variables don’t persist across shells.
- Building an SDK from the wrong image — if application code links against a library only present in a different image, use
populate_sdkagainst that image, not a generic one. - Assuming static libraries are included — they are opt-in via
staticdev-pkgs, as shown above.
Best Practices
- Version your SDK scripts to match image releases so application developers always know which SDK pairs with which firmware build.
- Prefer
populate_sdkovermeta-toolchainwhenever application code depends on product-specific libraries. - Automate SDK generation in CI so it’s rebuilt every time the underlying image changes, instead of going stale.
Performance Considerations
populate_sdk reuses the shared state cache from your normal image build, so running it right after a successful image build is usually fast. Running it cold, on a fresh build directory, rebuilds a large dependency tree and can take as long as the original image build itself.
Summary and Key Takeaways
populate_sdk gives application developers a self-contained, correctly-configured cross-compiler without needing your full Yocto build tree. Always compile through $CC after sourcing the environment script, and choose between populate_sdk and meta-toolchain based on whether developers need your product’s exact sysroot or just a generic compiler.
Conclusion
A well-maintained SDK is often the single biggest quality-of-life improvement you can offer application teams working alongside a Yocto-based platform — a key practical skill in this free linux kernel development course series. Next, we’ll look at license auditing so you can verify exactly what’s shipping inside your image before it goes out the door.
FAQ
Do I need root to install the SDK?
Only if you install to a system directory like the default /opt/poky; installing to a directory you own doesn’t require sudo.
Can multiple SDK versions coexist on one machine?
Yes — each install path includes the version number by default, so different product versions can be installed side by side.
Why does my SDK not include OpenSSL headers?
The SDK sysroot only includes what the source image installs; if the image doesn’t depend on OpenSSL, add it to the image recipe’s IMAGE_INSTALL and regenerate the SDK.
Is meta-toolchain faster to build than populate_sdk?
Yes, since it skips packaging the full target sysroot and only builds the compiler, C library, and headers.
Does sourcing the environment script affect my normal system compiler?
Only within that shell session — it exports CC/CXX pointing at the cross-compiler for that session only, leaving your system gcc untouched elsewhere.
More Free Yocto and Embedded Linux Lectures
Continue this free linux device drivers course and free embedded systems course track at EmbeddedPathashala.

2 Comments