Gentoo USE Flags: Controlling What Actually Gets Compiled Into Your Packages
Gentoo USE flags let you decide which optional features get compiled into each package. Learn how global and per-package settings interact, how to preview changes safely, and the mistakes that silently waste rebuilds.
12 Oct 2025, 00:11 UTC

On most distributions, the package maintainer decides which optional features your binaries ship with. Gentoo hands that decision to you through USE flags: per-package build-time switches that enable or disable optional features in an ebuild before compilation. The practical payoff is real — fewer pulled-in dependencies, smaller attack surface, and binaries that match your system — but only if you configure the flags deliberately and verify the result before a world update surprises you.
What a USE flag actually does
A USE flag is a named toggle defined by the ebuild author. When Portage builds a package, it evaluates the flag and changes the build accordingly: passing or omitting configure options, adding or dropping dependencies, and installing or skipping components. For example, enabling alsa on a media library typically adds media-libs/alsa-lib as a dependency and passes the corresponding enable flag to the build system.
Two constraints matter up front. First, you can only toggle flags the ebuild author defined — inventing a flag name does nothing; unknown flags are silently ignored. Second, flags are evaluated at build time, so changing one has no effect until you rebuild the affected packages.
Global versus per-package configuration
Global flags live in /etc/portage/make.conf and apply to every package that knows about them:
# /etc/portage/make.conf
USE="X wayland alsa pipewire -gtk3 -qt5"
Prefixing a flag with a minus sign explicitly disables it, which overrides defaults set by your selected profile. Profiles (chosen with eselect profile list / eselect profile set) ship sensible baseline USE sets, so your make.conf line is a delta on top of that, not the full picture.
Per-package overrides go in /etc/portage/package.use (a file, or a directory of files). This is where you keep exceptions so your global set stays clean:
# /etc/portage/package.use
# Build Portage itself without X11 support
sys-apps/portage -X
# Require ALSA support in libv4l
media-libs/libv4l alsa
The resolution order is roughly: profile defaults, then make.conf, then package.use, with later layers winning. That means a per-package entry always beats your global setting for that atom.
A worked example: trimming a desktop package
Say you run a Wayland-only desktop and want to stop pulling in X11 support everywhere. The workflow is:
- Check the effective flags first. Run
emerge --info | grep ^USEas any user to see the merged global USE set from profile plusmake.conf. - Edit
make.confto add-X(or switch to a Wayland-oriented profile, which often does this for you). - Preview the impact before building anything:
emerge -avuDN --with-bdeps=y @world. The-N(--newuse) flag tells Portage to rebuild packages whose USE settings changed;-aasks for confirmation;-uDNcovers updates, deep dependencies, and new USE. Read the colored USE diff in the output — red/green markers show exactly which flags flip per package. - Confirm, then let it rebuild. Expect a long compile on a desktop system.
For a single quick check on one package, emerge -pv media-libs/libv4l shows the flags that package will build with, without touching anything.
Limits and common mistakes
- Stale tree, stale results. If you change USE flags but haven't synced recently (
emerge --syncoremaint sync -a), you may rebuild against old ebuilds whose flag semantics differ from what you read in current documentation. Sync first, then change flags. - Typos are silent.
USE="alsaa"fails quietly — the flag is simply unknown and ignored. If a build doesn't behave as expected, verify the flag exists for that package withequery uses <package>(fromapp-portage/gentoolkit). - Conflicting flags. Some ebuilds don't handle contradictory combinations (for example, enabling two mutually exclusive backends). The build fails partway through with a configure error. The fix is to pick one backend, usually via a
package.useentry for that package. - Assuming a flag pulls everything. A USE flag only does what the ebuild's conditionals say. Enabling
alsaon a package that has no ALSA code path changes nothing. Checkequery usesdescriptions to see what each flag claims to do. - Dangerous overrides on system packages. Disabling flags on critical components — the kernel sources' helpers, your init system,
sys-libs/glibc, or anything in your initramfs — can produce an unbootable system. Test aggressive flag changes on a non-critical machine or in a chroot first, and keep a known-good binary package (quickpkg) of anything essential before rebuilding it. - Forgetting the rebuild. Editing
package.usechanges nothing on disk until you runemerge -avuDN @world. The config file is input to the next build, not a live setting.
Verifying the result
After a USE-driven rebuild, confirm three things. First, emerge --info | grep ^USE reflects your intended global set. Second, for a specific package, emerge -pv <atom> shows the per-package flags as Portage resolved them, including your package.use overrides. Third, inspect the actual binary: for a library where you disabled X11, ldd /usr/lib/libv4l2.so | grep -i x11 should return nothing. If a dependency you expected to drop is still linked, the flag either doesn't control that code path or another package still requires it — equery depends <atom> tells you which.
The habit that separates a smooth Gentoo system from a frustrating one is simple: never change USE flags and rebuild blind. Preview with --ask --verbose --newuse, read the flag diff, and verify the built artifacts afterward.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.