Understanding Gentoo Package Management: Portage, emerge, and Friends
Gentoo Linux stands apart from most distributions through its source-based package management model. While binary-based distributions like Debian (APT), Fedora (DNF), and Arch (Pacman) ship pre-compiled binaries, Gentoo's Portage system compiles software from source code on your own machine. This fundamental difference unlocks unparalleled flexibility but also demands a deeper understanding of how packages are fetched, built, and installed. This guide covers the core concepts, practical usage, and best practices for mastering Gentoo's package management, with comparisons to APT, DNF, and Pacman to help developers coming from other ecosystems.
What Makes Gentoo's Package Management Unique
At the heart of Gentoo lies Portage, a package management system inspired by FreeBSD's ports. The primary user-facing tool is emerge, which handles dependency resolution, source fetching, compilation, installation, and removal. Unlike APT's binary .deb packages, DNF's .rpm packages, or Pacman's .pkg.tar.zst archives, Portage operates on ebuilds — bash scripts that describe how to obtain, configure, compile, and install a piece of software.
The key differentiators are:
- USE flags — a declarative system for enabling or disabling optional features across your entire system
- CFLAGS/CXXFLAGS — compiler optimization flags you control globally
- SLOTs — the ability to install multiple versions of the same library or application side by side
- Profiles — system-wide configuration sets that define default USE flags and package sets
- Overlays — community-maintained repositories that extend the official Gentoo tree
The Portage Ecosystem: Key Components
Before diving into commands, it's essential to understand the files and directories that power Portage:
/etc/portage/— the central configuration directory for all Portage settings/var/db/repos/gentoo/— the official Gentoo ebuild repository (the "tree")/var/cache/edb/— Portage's internal database cache/etc/portage/make.conf— the main configuration file where you set USE flags, compiler flags, and make options/etc/portage/package.use— per-package USE flag overrides/etc/portage/package.accept_keywords— controls package stability levels (stable vs. testing)/etc/portage/package.mask— prevents specific packages from being installed/etc/portage/package.unmask— allows packages that are otherwise masked
Comparison: emerge vs. APT, DNF, and Pacman
Developers coming from other distributions will find these parallels helpful for translating familiar operations into emerge commands:
| Operation | Gentoo (emerge) | Debian (APT) | Fedora (DNF) | Arch (Pacman) |
|---|---|---|---|---|
| Install a package | emerge app-misc/neofetch |
apt install neofetch |
dnf install neofetch |
pacman -S neofetch |
| Remove a package | emerge --unmerge neofetch |
apt remove neofetch |
dnf remove neofetch |
pacman -R neofetch |
| Update package list | emerge --sync |
apt update |
dnf check-update |
pacman -Sy |
| Upgrade all packages | emerge -uDN @world |
apt upgrade |
dnf upgrade |
pacman -Syu |
| Search for a package | emerge --search firefox |
apt search firefox |
dnf search firefox |
pacman -Ss firefox |
| List installed packages | qlist -I (from app-portage/portage-utils) |
apt list --installed |
dnf list --installed |
pacman -Q |
| Show package info | emerge -pv packagename |
apt show packagename |
dnf info packagename |
pacman -Qi packagename |
| Verify dependencies | emerge -p packagename |
apt-cache depends |
dnf deplist |
pacman -Qi |
Essential emerge Commands with Practical Examples
Installing and Updating the System
The @world set represents every package you've explicitly requested to install, plus system packages. Updating world is the standard way to keep a Gentoo system current:
# Synchronize the Portage tree (equivalent to apt update)
emerge --sync
# Perform a full system upgrade with new USE flags applied
emerge --update --deep --newuse @world
# The shorthand version combines flags:
emerge -uDN @world
# Clean up orphaned dependencies after an update
emerge --depclean
The --deep (-D) flag forces emerge to recalculate dependencies for the entire tree, not just direct dependencies. The --newuse (-N) flag rebuilds packages when their USE flags have changed since the last build.
Pretend Mode: The Safety Net
Always use --pretend (-p) or --ask (-a) before making changes. This shows exactly what will happen without executing anything:
# See what would be installed, with USE flags shown
emerge -p firefox
# Sample output:
# [ebuild N ] www-client/firefox-115.0.1::gentoo
# USE="clang dbus gtk+ hwaccel jack lto openh264 pulseaudio
# samba selinux wifi -debug -gnome (-hardened) -wayland"
# L10N="ach af an ar ast az be bg bn br bs ca ca-valencia cak cs
# cy da de dsb el en-GB eo es-AR es-CL es-ES es-MX et eu fa
# ff fi fr fy ga gd gl gn gu he hi hr hsb hu hy ia id is it
# ja ka kab kk km kn ko lij lt lv mk mr ms my nb ne nl nn
# oc pa pl pt-BR pt-PT rm ro ru sc sk sl sq sr sv-SE szl ta
# te th tl tr trs uk ur uz vi zh-CN zh-TW"
# 0 KiB
# Ask for confirmation interactively
emerge -a firefox
Working with USE Flags
USE flags are Gentoo's killer feature. They control optional dependencies and features at a global level. Here's how to inspect and manipulate them:
# List all active USE flags on your system
emerge --info | grep USE
# Check which USE flags a specific package recognizes
emerge -pv app-editors/vim
# Example output shows flags in parentheses:
# app-editors/vim-9.0.2167::gentoo
# USE="X acl crypt nls python -debug -lua -minimal -perl
# -racket -ruby -sodium -sound -tcl -terminal -vim-picker"
# PYTHON_TARGETS="python3_11 python3_12"
# Set a global USE flag in /etc/portage/make.conf
# Add this line to enable system-wide pulseaudio support:
USE="... pulseaudio ..."
# Set a per-package USE flag in /etc/portage/package.use
# Create or edit the file:
echo "app-editors/vim perl python" >> /etc/portage/package.use
# Apply changes after modifying USE flags
emerge -uDN @world
Searching and Discovering Packages
# Basic search by name
emerge --search terminal
# Search with regular expressions
emerge --search "^app-.*terminal"
# Search package descriptions only
emerge --searchdesc terminal
# Use equery for advanced queries (install app-portage/gentoolkit first)
emerge app-portage/gentoolkit
# List all files installed by a package
equery files app-editors/vim
# Find which package owns a specific file
equery belongs /usr/bin/vim
# Show dependency graph
equery depgraph firefox
# List packages that depend on a given package
equery depends python
Managing Configuration Files
After an update, configuration files may need attention. Portage protects your existing configs and flags conflicts:
# Find configuration files that need updating
dispatch-conf
# Alternative tool with interactive merge capabilities
etc-update
# dispatch-conf workflow:
# 1. It presents each changed config file
# 2. Options: 'u' = use new version, 'z' = zap (discard) new,
# 'm' = merge interactively
# 3. RCS merge tools (like sdiff) help resolve conflicts
Binary Package Support (A Modern Addition)
Gentoo now offers a binary package host for many packages, reducing compile times dramatically. This brings Gentoo closer to the APT/DNF/Pacman experience while retaining source flexibility:
# Enable binary packages in make.conf:
# FEATURES="getbinpkg"
# Or set it via the environment
# Fetch binary packages when available
emerge -g firefox
# or equivalently:
emerge --getbinpkg firefox
# Use binary packages only (no fallback to source)
emerge -gK firefox
# List available binary packages
emerge -gp firefox
Advanced Portage Configuration
The make.conf File Explained
Your /etc/portage/make.conf is the heart of Gentoo customization. Here's a well-commented example:
# Example /etc/portage/make.conf for a developer workstation
# Compiler flags - march=native auto-detects your CPU
CFLAGS="-march=native -O2 -pipe"
CXXFLAGS="${CFLAGS}"
MAKEOPTS="-j8" # parallel compile jobs (typically cores + 1)
# Global USE flags
USE="wayland X dbus pulseaudio gtk qt5 qt6
networkmanager samba cups python
-gnome -kde -systemd"
# Accept licenses for proprietary software
ACCEPT_LICENSE="*"
# Video cards (for GPU-accelerated packages)
VIDEO_CARDS="intel i965 radeon amdgpu"
# Input devices
INPUT_DEVICES="libinput keyboard mouse"
# Language support
L10N="en en-US"
# Python targets
PYTHON_TARGETS="python3_11 python3_12"
# Portage features
FEATURES="parallel-fetch buildpkg getbinpkg"
# Mirror selection for faster downloads
GENTOO_MIRRORS="https://mirrors.rit.edu/gentoo/ http://gentoo.osuosl.org/"
Package Masking and Unmasking
Control which versions of packages are eligible for installation:
# Mask a specific version (prevent installation)
echo ">=dev-lang/python-3.12.0" >> /etc/portage/package.mask
# Unmask a package that is masked by the profile
echo "sys-kernel/gentoo-kernel-bin" >> /etc/portage/package.unmask
# Accept testing (~amd64) packages for specific packages
echo "app-editors/neovim ~amd64" >> /etc/portage/package.accept_keywords
# Accept all testing packages for a category
echo "app-emulation/* ~amd64" >> /etc/portage/package.accept_keywords
Working with Overlays (Community Repositories)
Overlays are Gentoo's equivalent to PPAs (Ubuntu) or the AUR (Arch). They provide additional packages not in the main tree:
# List available overlays
emerge app-eselect/eselect-repository
eselect repository list
# Add the popular GURU overlay (community-maintained)
eselect repository enable guru
# Add a custom overlay via layman (legacy method)
emerge app-portage/layman
layman -a librewolf
# Sync all overlays including custom ones
emerge --sync
# Install a package from a specific overlay
emerge -pv app-misc/package-from-overlay
Handling Dependencies and Conflicts
Resolving Slot Conflicts
SLOTs allow multiple versions of libraries to coexist. Sometimes emerge needs help resolving which SLOT to use:
# View slot conflicts
emerge -pv @world
# Example conflict message:
# [blocks B] dev-lang/python:3.10
# ("dev-lang/python:3.10" is blocking dev-lang/python:3.11)
# Resolve by migrating to the newer slot
emerge -C dev-lang/python:3.10
emerge dev-lang/python:3.11
# Set preferred Python version in make.conf:
# PYTHON_TARGETS="python3_11 python3_12"
# PYTHON_SINGLE_TARGET="python3_12"
Rebuilding Reverse Dependencies
When a library changes, packages depending on it need rebuilding. The @preserved-rebuild set handles this automatically:
# After a library update, rebuild consumers
emerge @preserved-rebuild
# Manually rebuild all packages depending on a specific library
emerge -1 $(equery depends --all-only dev-libs/openssl | awk '{print $1}')
# The -1 (--oneshot) flag adds packages to the dependency list
# without adding them to @world
Performance and Maintenance Best Practices
Speeding Up Compilation
# Use distcc for distributed compilation across machines
emerge app-misc/distcc
# In make.conf:
# FEATURES="distcc"
# MAKEOPTS="-j12" # total jobs across all machines
# Use ccache to cache compiled objects
emerge dev-util/ccache
# In make.conf:
# FEATURES="ccache"
# CCACHE_DIR="/var/cache/ccache"
# CCACHE_SIZE="5G"
# Enable parallel fetching and compilation
# Already in make.conf:
# FEATURES="parallel-fetch parallel-install"
Regular Maintenance Routine
# Weekly maintenance script example
#!/bin/bash
# 1. Sync the tree
emerge --sync
# 2. Check for news items (important announcements)
eselect news read
# 3. Run a full system update with verbose output
emerge -uDNva --with-bdeps=y @world
# 4. Clean orphaned packages
emerge --depclean -a
# 5. Rebuild preserved libraries
emerge @preserved-rebuild
# 6. Update configuration files
dispatch-conf
# 7. Check for revdep problems
emerge app-portage/gentoolkit
revdep-rebuild -i
# 8. Clean old distfiles to free space
eclean-dist --destructive
Handling Emergencies and Broken Builds
# If a build fails, resume with skipping the failed package
emerge --resume --skipfirst
# Resume without skipping (retry the same package)
emerge --resume
# Check the build log for errors
cat /var/tmp/portage/category/package/temp/build.log
# Search for specific error messages
grep -i error /var/tmp/portage/category/package/temp/build.log
# Rebuild a package with debug symbols
CFLAGS="-march=native -O1 -g" emerge app-misc/troublesome-package
# Use the saved config to rebuild with previous settings
emerge --config app-misc/troublesome-package
Deep Dive: Ebuild Anatomy
Understanding ebuilds helps you troubleshoot and even write your own packages. Here's a simplified ebuild structure:
# Example ebuild: app-misc/hello-world/hello-world-1.0.ebuild
# Copyright 2024 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=8
DESCRIPTION="A simple hello world program"
HOMEPAGE="https://example.com/hello-world"
SRC_URI="https://example.com/files/${P}.tar.gz"
LICENSE="MIT"
SLOT="0"
KEYWORDS="~amd64 ~x86"
IUSE="doc test"
DEPEND=""
RDEPEND="${DEPEND}"
BDEPEND="test? ( dev-util/criterion )"
src_prepare() {
default
# Apply patches or modify source here
}
src_configure() {
# Configure the build (equivalent to ./configure)
econf --enable-feature
}
src_compile() {
# Compile the source
emake
}
src_install() {
# Install files into the temporary image directory
emake DESTDIR="${D}" install
use doc && dodoc README.md
}
src_test() {
# Run the test suite
emake test
}
Common Workflows for Developers
Setting Up a Development Environment
# Install development tools as a set
emerge -a app-editors/vim app-shells/bash dev-vcs/git \
dev-util/cmake dev-util/ninja sys-devel/gcc sys-devel/gdb \
dev-python/pip dev-lang/go
# Create a custom set for your project
# Edit /etc/portage/sets/project-set:
emerge -a @project-set
# Example project-set file:
# app-editors/vim
# dev-vcs/git
# dev-lang/python:3.12
# dev-python/flask
# dev-python/requests
# dev-db/postgresql
Installing Multiple Versions of Tools
# Install multiple Go versions using SLOTs
emerge dev-lang/go:1.21
emerge dev-lang/go:1.22
# Switch between them with eselect
eselect go set 1.22
# Same for Python
emerge dev-lang/python:3.10
emerge dev-lang/python:3.11
emerge dev-lang/python:3.12
eselect python set 3.12
Security and Verification
# Verify package integrity with checksums
emerge -f --digest app-misc/some-package
# Check for known vulnerabilities (GLSA - Gentoo Linux Security Advisories)
emerge app-portage/gentoolkit
glsa-check -t all
# Apply security fixes only
glsa-check -f affected
emerge -a $(glsa-check -p affected)
# Verify installed binaries against the package database
equery check app-misc/some-package
Conclusion
Gentoo's Portage system represents a fundamentally different philosophy from APT, DNF, and Pacman. Where those tools optimize for speed and simplicity through pre-compiled binaries, Portage optimizes for flexibility and control through source compilation and USE flags. The learning curve is steeper — you must understand compiler flags, slot conflicts, and dependency graphs — but the payoff is a system tailored precisely to your needs, with no unnecessary dependencies bloating your installation. The addition of binary package support in recent years bridges the gap, offering the best of both worlds when compilation speed matters. For developers who want complete control over their operating system's composition, or who need to test against multiple library versions, Gentoo's package management remains unmatched. The key to success is methodical practice: always use --pretend first, keep your make.conf well-documented, run regular maintenance cycles, and treat the Portage tree as a living system that rewards careful attention. With these habits, emerge becomes not just a package manager but a powerful development tool in its own right.