Gentoo USE Flags: Architecture, Merge Order, and Failure Modes
Gentoo's USE flag system lets admins toggle compile‑time features globally or per‑package without editing ebuilds. It explains IUSE declaration, REQUIRED_USE constraints, trust boundaries, operational checks, and failure modes keeping a source-built system consistent.
19 Sept 2025, 12:29 UTC

The Problem: Controlling Optional Features Without Editing Every Package
\nGentoo's defining characteristic is building everything from source. That means every optional feature — SSL backend, GUI toolkit, hardware acceleration, documentation format — must be decided at compile time. The USE flag system is the mechanism that lets an administrator enable or disable these features globally, per-package, or per-repository without touching ebuild source files. Understanding how flags are declared, merged, and enforced is essential for keeping a source-built system consistent and for diagnosing the rebuild cascades that follow a flag change.
\n\nRequirements the Design Must Satisfy
\n- \n
- Express optional features as simple tokens that any ebuild can reference. \n
- Provide system-wide defaults that reflect a chosen profile (desktop, server, hardened, etc.). \n
- Allow per-package overrides without forking or patching ebuilds. \n
- Enforce hard constraints: some flag combinations are mutually exclusive or required together. \n
- Make dependency resolution deterministic so the same configuration always produces the same build plan. \n
- Trigger only the minimal necessary rebuilds when flags change. \n
Smallest Suitable Design: Flat Tokens, Layered Configuration, Merge at Build Time
\nUSE flags are a flat namespace of strings (e.g., ssl, wayland, avx2). Each ebuild declares the flags it understands in IUSE. The active profile supplies baseline defaults via make.defaults. The administrator sets global additions or removals in /etc/portage/make.conf (or package.use for per-package rules). Portage merges these layers into a single effective flag set for each package just before the build starts, exporting them as environment variables (USE=...) that the ebuild's shell functions can test.
Layer Precedence (highest wins)
\n- \n
- Per-package
/etc/portage/package.use/<pkg>(or entries inpackage.use/*) \n /etc/portage/make.confUSE=andUSE_EXPANDvariables \n- Profile
make.defaults(selected viaeselect profile) \n - Repository-level
use.mask/use.force(hard masks/forces) \n - Ebuild
IUSEdefaults (the+or-prefix on a flag inIUSE) \n
Flags prefixed with - in any layer explicitly disable that feature. A flag not present in the final merged set is treated as disabled.
Hard Constraints: REQUIRED_USE
\nAn ebuild can declare REQUIRED_USE expressions that Portage evaluates after merging. Examples:
# At least one SSL backend must be chosen\\nREQUIRED_USE=\\\"|| ( ssl gnutls mbedtls )\\\"\\n\\n# Wayland and X11 are mutually exclusive for this package\\nREQUIRED_USE=\\\"^^ ( wayland X )\\\"\\n\\n# If 'doc' is enabled, 'latex' must also be enabled\\nREQUIRED_USE=\\\"doc? ( latex )\\\"\\n\nIf the effective flags violate REQUIRED_USE, Portage refuses to build the package and prints the unsatisfied expression.
Trust and Data Boundaries
\nEbuilds are shell scripts executed with root privileges during the build phase (fetch, unpack, compile, install). The trust boundary is therefore the ebuild author plus the local administrator. USE flags originate entirely from local configuration and profiles — they never come from remote sources during resolution. Portage's sandbox (FEATURES=\\\"sandbox\\\") restricts filesystem and network access during the build, but it cannot prevent a malicious ebuild from executing arbitrary code as root. Adding an untrusted overlay effectively grants that overlay's maintainers code execution on the build host.
Because the same flag string can mean different things in different ebuilds (e.g., ssl might select OpenSSL in one package and GnuTLS in another), enabling a flag globally is not a guarantee of one specific feature everywhere. Always verify per-package semantics with equery uses.
Operational Checks: Preview Before You Commit
\nBefore changing any flag, run a pretend merge to see the resolved flags, dependency graph, and rebuild set:
\n# Run as root or with sudo\\nemerge --pretend --verbose --deep --newuse @world\\n\nKey output fields:
\n- \n
- USE= line per package shows the effective flags after all layers merge. \n
- [ebuild N ] = new install; [ebuild R ] = rebuild triggered by flag change; [ebuild U ] = version upgrade. \n
- Dependency atoms with
[use=...]show which flags pulled in each dependency. \n
After applying changes and rebuilding, run:
\n# Detect broken dynamic linkage after library upgrades\\nrevdep-rebuild --library libexample.so.1\\n\\n# Remove dependencies no longer referenced by any installed package\\nemerge --depclean --pretend # preview first\\nemerge --depclean # actually remove\\n\n\nConcrete Example: Switching a Package's SSL Backend
\nSuppose net-misc/curl currently builds with OpenSSL (+ssl) and you want to use GnuTLS instead.
- \n
- Inspect valid flags:
equery uses net-misc/curlshowsIUSE=... +ssl gnutls ...and current state. \n - Check REQUIRED_USE:
cat /var/db/repos/gentoo/net-misc/curl/curl-*.ebuild | grep REQUIRED_USEreveals|| ( ssl gnutls mbedtls )— exactly one must be enabled. \n - Create per-package override:
echo 'net-misc/curl -ssl gnutls' > /etc/portage/package.use/curl. \n - Preview the change:
emerge --pretend --verbose net-misc/curlconfirmsUSE=\\\"-ssl gnutls\\\"and shows any dependent packages that will rebuild. \n - Apply:
emerge --ask net-misc/curl. \n - Verify:
curl --versionnow lists GnuTLS;equery uses net-misc/curlshows-ssl +gnutls. \n
If the pretend step shows a large rebuild set (e.g., 50+ packages), consider whether the flag change is worth the compile time or whether a binary package (--getbinpkg) with matching flags exists.
Failure Modes
\nInvalid, Masked, or Conflicting Flag Combinations
\n- \n
- Enabling a flag not in
IUSEproduces a warning but no effect. \n use.maskin the profile or repository blocks a flag globally; Portage treats it as forced off. \nREQUIRED_USEviolations halt resolution with a clear error message. \n
Large Rebuild Cascades
\nChanging a global flag like wayland or systemd can trigger rebuilds of hundreds of packages. Use --pretend to measure impact before committing.
Slot Conflicts and Circular Dependencies
\nMultiple versions of the same package (different slots) may be pulled in with incompatible flag requirements. Portage reports Slot conflict: and requires manual intervention — often masking one version or adjusting flags on the dependent package.
Interrupted Builds and Partial Database State
\nIf a build is killed (OOM, power loss, Ctrl-C), the package database may record the package as installed while files are missing or incomplete. Recovery: emerge --resume continues the merge list; emerge --oneshot =category/package-version re-installs a specific atom.
Conditions That Would Change the Design
\nAdopting Prebuilt Binary Packages (binpkgs)
\nBinary packages are reusable only when the consumer's USE flags, compiler version, CFLAGS, CHOST, and ABI match the build that produced them. A mismatch forces a local rebuild or, worse, silent ABI breakage. If a site standardizes on binpkgs, the central role of per-machine USE flags diminishes — flags become a build-server concern.
Third-Party Overlays
\nOverlays can introduce new flags, redefine existing ones, or ship ebuilds with conflicting REQUIRED_USE. Portage resolves overlays by repository priority (repos.conf priority), but flag semantics remain per-ebuild. Audit overlays with equery uses before enabling them globally.
Keyword Changes (Stable vs. Testing)
\nSwitching a package to ~amd64 (testing) via /etc/portage/package.accept_keywords can pull in newer dependencies with different flag defaults or new REQUIRED_USE constraints. Always pretend-merge after keyword changes.
Moving Away from Source-Based Builds
\nIf the system shifts to a binary distribution model (e.g., Gentoo Prefix on a foreign OS, or a container base image), USE flags become a build-time configuration for the image producer, not a runtime tuning knob for the consumer.
\n\nVerification Checklist for a Live System
\n- \n
emerge --info— shows active profile, effectiveUSE,FEATURES,MAKEOPTS. \neselect profile list— lists available profiles; the active one is marked. \n- Inspect
$(portageq get_repo_path / gentoo)/profiles/formake.defaults,use.mask,use.force. \n equery uses <pkg>(fromapp-portage/gentoolkit) — lists valid flags and current state for any package. \neselect news list— read latest news items before major upgrades; Portage publishes required manual steps there. \n
Limitations
\n- \n
- Profile paths, default USE values, and eclass internals change across Gentoo releases. Any specific flag list or default shown here is historical until checked against the installed repository. \n
- Binary package compatibility depends on exact toolchain and flag matching; there is no automatic translation layer. \n
- Sandboxing mitigates but does not eliminate risk from untrusted ebuilds. \n
How to Check the Result
\nAfter any flag change and rebuild, run equery uses <pkg> on a representative package to confirm the effective flags match intent. Then run revdep-rebuild to catch any missed linkage breakage. If both pass, the change is consistent.