Yocto IMAGE_INSTALL vs RDEPENDS — Where Does the Package Go?
Yocto IMAGE_INSTALL vs RDEPENDS is the usual fork when someone asks “why is this package on the rootfs?” Short split: packages (or packagegroups) you mean to put on this image belong in IMAGE_INSTALL; packages another package must have at runtime belong in RDEPENDS. This is a minimal howto from the Yocto Project Customizing Images chapter and the Variables Glossary. No board anecdotes, no pricing, no affiliates.
When do you use IMAGE_INSTALL?
One-line answer: Names you intentionally include on the root filesystem go in image-side IMAGE_INSTALL. For local experiments use IMAGE_INSTALL:append in local.conf; for product images prefer a custom image recipe and/or packagegroups.
From the docs:
- Prefer
IMAGE_INSTALL:append = " pkg"inlocal.conf. The leading space matters;:appendavoids ordering fights with?=/ image recipes better than+=. - Limit to one image with a pn override, e.g.
IMAGE_INSTALL:append:pn-core-image-minimal = " strace". - For
core-image-*only,CORE_IMAGE_EXTRA_INSTALLis an option. - For complex images, create an
inherit packagegrouprecipe and add that packagegroup package toIMAGE_INSTALL(Custom Package Groups).
Minimal local.conf example:
IMAGE_INSTALL:append = " strace"
# IMAGE_INSTALL:append:pn-core-image-minimal = " strace"
Custom image skeleton:
IMAGE_INSTALL = "packagegroup-core-boot my-app"
inherit core-image
IMAGE_INSTALL declares membership of this image. “App A always needs library B at runtime” is recipe RDEPENDS, not a flat image dump of every library.
When do you use RDEPENDS?
One-line answer: RDEPENDS:pkg is a hard runtime dependency on package names. If pkg is installed, its RDEPENDS targets are pulled in. Packagegroups list their contents the same way.
Glossary points:
- Not the same as build-time
DEPENDS(sysroot / headers / link).RDEPENDSis “must be on the target with this package.” - Always use a package override:
RDEPENDS:${PN} = "libfoo". - In a packagegroup, each entry in
PACKAGESgetsRDEPENDS:${PN}-…; the image then only needs those packagegroup names inIMAGE_INSTALL.
Documented packagegroup pattern:
DESCRIPTION = "My Custom Package Groups"
inherit packagegroup
PACKAGES = "${PN}-apps ${PN}-tools"
RDEPENDS:${PN}-apps = "\
dropbear \
portmap \
psplash \
"
RDEPENDS:${PN}-tools = "\
oprofile \
lttng-tools \
"
RRECOMMENDS:${PN}-tools = "kernel-module-oprofile"
Then on the image:
IMAGE_INSTALL:append = " packagegroup-custom-apps"
Optional pieces use RRECOMMENDS. BAD_RECOMMENDATIONS / NO_RECOMMENDATIONS can drop recommends; they do not override a hard RDEPENDS.
What goes wrong if you use both?
One-line answer: Listing the same package in IMAGE_INSTALL and in some package’s RDEPENDS usually still installs, but removal, exclusion, and audits break. Two paths now “own” why the package is on the image.
Common failure modes:
- Removed from IMAGE_INSTALL but still on the rootfs — another package’s (or packagegroup’s)
RDEPENDSpulls it back. - PACKAGE_EXCLUDE / BAD_RECOMMENDATIONS surprise — the glossary states recommends can be blocked; a hard
RDEPENDScauses the build system to keep installing to avoid dependency errors. - Scattered policy — the same name in image recipe,
local.conf, app recipe, and packagegroup makes “why is it in the product image?” multi-path. That is why the manual pushes packagegroups: bundle with RDEPENDS, install the group via IMAGE_INSTALL. - Role mix-up — stuffing libraries only into
IMAGE_INSTALLwhile leaving appRDEPENDSempty means other images/SDK/package feeds miss the dependency. Duplicating an app’sRDEPENDSentries again inIMAGE_INSTALLis usually noise (unless you intentionally pin).
Practical split aligned with the manual:
| Goal | Where |
|---|---|
| Must be on this image (app, tool, packagegroup) | IMAGE_INSTALL (:append / image recipe) |
| Hard runtime need of a package | RDEPENDS:pkg |
| Shared product bundle | inherit packagegroup + RDEPENDS → group name in IMAGE_INSTALL |
| Nice-to-have | RRECOMMENDS (optional BAD_RECOMMENDATIONS) |
Reduce duplication:
- Put real runtime must-haves on the consumer recipe’s
RDEPENDS. - Bundle product sets in packagegroup
RDEPENDS. - Put app or packagegroup names (not every transitive library) on
IMAGE_INSTALL. - When removing, check who still holds an
RDEPENDSedge (bitbake -e, buildhistory, package graphs)—not only the image list.
FAQ
Q. May I put libraries directly in IMAGE_INSTALL?
A. Yes, but if consumers omit RDEPENDS, other images or package installs can break. Prefer consumer RDEPENDS (or automatic shlib deps).
Q. Is a long IMAGE_INSTALL without packagegroups OK?
A. Fine for prototypes and local.conf. The manual calls packagegroups the best approach for complex custom images.
Q. Do I need both RDEPENDS and DEPENDS?
A. Different jobs: headers/link → DEPENDS; must co-exist on target → RDEPENDS. Auto runtime deps cover many shared libs; scripts/data/explicit package names still need RDEPENDS.
Takeaways
Image membership is IMAGE_INSTALL; hard runtime edges are RDEPENDS. Packagegroups bundle the latter and put only the group on the former—the mega-manual flow. Duplicating the same package on both rarely helps install and often hurts removal and audits. See Customizing Images and the Variables Glossary for IMAGE_INSTALL / RDEPENDS.
Official sources
- Customizing Images
- Variables Glossary (
IMAGE_INSTALL,RDEPENDS,RRECOMMENDS,BAD_RECOMMENDATIONS,PACKAGE_EXCLUDE) - OE-Core example:
meta/recipes-core/packagegroups/packagegroup-base.bb