Last Updated on August 5, 2026
Overview
The primary goal of using the Yocto Project® and OpenEmbedded to develop embedded Linux systems is to produce a small, well-optimized root filesystem (rootfs) image. A standard image provides a simplified starting point; even simple “Hello World” applications can have a significant impact on the final storage size. This study examines the flash storage effects of ten different “Hello World” applications. In particular, it compares classic compiled languages (C, C++) against interpreted and runtime-heavy ecosystems (Rust, Go, Python, Node.js/npm) to demonstrate how heavily runtime dependencies (RDEPENDS) impact firmware size. It’s the updated version of The Storage Footprint of Hello World: Comparing Yocto Package Dependencies.
Key Takeaways
- The Minimalists:
- C and C++ binaries have a negligible impact, adding fewer than 100 KB to the rootfs.
- The Autonomous Heavyweights:
- Rust remains highly compact; on the other hand, Go requires significantly more binary storage for its autonomous runtime environment.
- The Image Ballooners:
- Moreover, high-level interpreted environments like Python and Node.js immediately add tens of megabytes to the flash footprint due to dense core dependencies.
- The Uninstallation Dilemma:
- Furthermore, executing opkg remove –autoremove fails to fully clean up opkg metadata. Consequently, additional steps (opkg clean) are required, not to leave behind permanent “ghost” files that waste precious flash blocks. Additionally, configuration files deployed to the /etc/ directory are frequently left behind during a standard package uninstallation. This occurs due to a deliberate safety mechanism built into modern package managers and specific file management behaviors within OpenEmbedded.
Case Studies: Real-World Flash Footprints
Testing shows a significant difference between the standalone package size and the actual storage impact on the target root filesystem after fully evaluating dependencies.
Root Filesystem (rootfs) Installation Delta
| Application Name | Compressed .ipk Size | Runtime Dependencies (RDEPENDS) | Rootfs Increase (Delta) |
|---|---|---|---|
| 95.01_hello-cpp | 3,000 Bytes | libc6, libstdc++6 | +84 KB |
| 95.02_hello-cmake | 2,534 Bytes | libc6 | +84 KB |
| 95.21_rust-hello-world | 177,614 Bytes | libc6, libgcc1 | +408 KB |
| 95.25_golang-helloworld | 656,584 Bytes | None reported by opkg | +1,532 KB |
| 95.17_hello-python3 | 5,186 Bytes | python3-core | +18,900 KB |
| 95.22_npm-hello-world | 2,130 Bytes | brotli, c-ares, icu, nodejs | +72,656 KB |
| 95.23_npm-registry-hello-international | 85,726 Bytes | node-lodash, nodejs | +76,400 KB |
Technical Summary: The Uninstallation Dilemma
We do not recommend using a package manager on the target, but its behavior during cleanup is an important aspect of live storage management when used. Testing demonstrates that running opkg remove –autoremove && opkg clean does not fully restore the system to its baseline configuration.
Post-Uninstallation Cleanup Metrics
| Application Name | Delta After Install | Delta After Uninstall | Permanent Loss (Leftover Garbage) |
|---|---|---|---|
| 95.01_hello-cpp | +84 KB | +8 KB | 8 KB |
| 95.21_rust-hello-world | +408 KB | +8 KB | 8 KB |
| 95.17_hello-python3 | +18,900 KB | +24 KB | 24 KB |
| 95.22_npm-hello-world | +72,656 KB | +24 KB | 24 KB |
| 95.24_python-poetry-helloworld | +50,524 KB | +732 KB | 732 KB |
Why does storage remain occupied?
The team enhanced the test cases to create tarballs of the root filesystem, allowing for an exact analysis of what causes the leftover garbage. First, we conduct a filesystem snapshot before installing anything; then, we take another snapshot after installing the application under test; and finally, we perform a last snapshot after uninstalling the application.
Small increase in filesystem size after uninstall
It turns out that there are several reasons why we find leftover garbage after opkg remove –autoremove. The main reason is opkg metadata (package feed information and locally downloaded packages), which can be removed with opkg clean. This new case study adds this step. Additional and modified files explain the 8 KB and 24 KB increases in filesystem size.
These are the leftovers for 95.17_hello-python3:
/etc/.nfs000000000054475500000001 # new file
/etc/ld.so.cache # slightly increased size
/lib -> /usr/lib/ # lib is a symlink to /usr/lib
/lib/python3.14 # empty directories
├── lib-dynload
└── __pycache__
/root/.ash_history # slightly increased size
/usr/lib/python3.14 # empty directories (same as /lib/python3.14)
├── lib-dynload
└── __pycache__
/var/cache/ldconfig/aux-cache # slightly increased size
/var/lib/opkg/status # same size, but modified
/var/log -> /var/volatile/log/ # tmpfs on /var/volatile type tmpfs (rw,relatime)
/var/log/messages # increased size
/var/volatile/log/messages # increased size (same as /var/log/messages), RAM and not flash
Big increase in filesystem size after uninstall
These are the leftovers for 95.24_python-poetry-helloworld:
/etc/ssl/certs/* # symlinks, but also
/etc/ssl/certs/ca-certificates.crt # with 668 KB this seems to be main issue
/etc/.nfs000000000054475500000001 # new file
/etc/ld.so.cache # slightly increased size
/lib -> /usr/lib/ # lib is a symlink to /usr/lib
/lib/python3.14 # empty directories
├── lib-dynload
├── __pycache__
├── site-packages
└── string
/root/.ash_history # slightly increased size
/usr//lib/python3.14 # empty directories
├── lib-dynload
├── __pycache__
├── site-packages
└── string
/var/cache/ldconfig/aux-cache # slightly increased size
/var/lib/opkg/status # same size, but modified
/var/log -> /var/volatile/log/ # tmpfs on /var/volatile type tmpfs (rw,relatime)
/var/log/messages # increased size
/var/volatile/log/messages # increased size (same as /var/log/messages), RAM and not flash
Consequently, 95.24_python-poetry-helloworld results in a substantial 732 KB leftover footprint, as files under /etc/ssl/certs/* are installed during runtime setup; however, they are ignored during the uninstallation routine.
As already mentioned above, configuration files deployed to the /etc/ directory are often left behind during a standard package uninstallation or opkg remove –autoremove. Modern package managers implement a deliberate safety mechanism, and specific file management behaviors within OpenEmbedded contribute to this issue.
Practical Conclusion
When constructing a custom BitBake image for resource-constrained hardware, it is essential to prioritize language selection; consequently, this decision significantly influences the overall efficiency and performance of the system. An unchecked Node.js or Python implementation can instantly defeat the entire optimization workflow of a core-image-minimal setup. Embedded engineering teams must tightly audit RDEPENDS trees to safeguard systems against permanent flash bloat. Typically, there is no need to account for residual uninstallation overhead; however, this is because you will not be using a package manager on your target system. It’s not atomic, and there are better solutions out there for atomic software updates on embedded target systems.
Related Links
- The Storage Footprint of Hello World: Comparing Yocto Package Dependencies (initial version of this blog post)
- The RAM Footprint of Hello World: Comparing Yocto Runtime Memory Consumption
Appendix
To learn how Embedded-Linux works, take a look here. To learn more about the Yocto Project®, take a look here.