xorg-silence-aliases¶
Overlays
A nixpkgs overlay that silences the eval-time deprecation warnings emitted for
legacy pkgs.xorg.<name> accesses — without changing which derivation you get.
The problem¶
nixpkgs has, over many releases, been promoting packages out of the xorg
scope up to the top level: xorg.xrandr became xrandr, xorg.setxkbmap
became setxkbmap, and so on. To stay backward-compatible, nixpkgs keeps the
old xorg.<name> attribute alive — but wraps it in a builtins.trace
deprecation warning. So every time anything in your config still reaches for
the old spelling (your own modules, or third-party modules you import), you get
a wall of:
printed on every evaluation — nixos-rebuild, nix build, nix flake
check, CI. It's pure noise: the two spellings already resolve to the same
package. But it drowns out warnings you actually care about.
The insight / trap¶
You can't easily fix every call site (some live in packages you don't own), and
you don't want to drop the old attribute (that would break the call sites
outright). The fix is to re-alias each promoted name back onto xorg, but
point it at the promoted top-level derivation — so the old spelling stops
being the deprecated wrapper and becomes a plain reference to the same package.
Both xorg.xrandr and xrandr then resolve to one identical derivation, and
the warning is gone.
Two subtleties this recipe bakes in:
-
Use
final(self), notprev, on the right-hand side.final.xrandris the fully-overlaid value, so the alias tracks any later overlay that replaces the top-level package. Aliasing toprev.xrandrwould pin the old spelling to the pre-overlay derivation and silently desync the two names. -
Only alias names that actually exist at the top level. Which names have been promoted varies by nixpkgs version. Blindly writing
xorg.foo = final.foobreaks the dayfooisn't a top-level attribute on your channel. This overlay filters the candidate list throughlib.hasAttr name final, so unpromoted names are left untouched and the overlay stays a safe drop-in across channels.
Usage¶
Plain overlay list:
As a flake output:
There are no options to configure — import it and the noise is gone.
Caveats¶
- This only silences the
xorg-scope promotions. Other unrelated nixpkgs deprecation warnings are untouched (by design). - If a future nixpkgs warns about a name not in
promotedNames, add it to the list indefault.nix; thehasAttrfilter makes extra entries harmless. - It changes nothing about what you build — the derivations are byte-identical before and after. It only removes the trace output.
Source¶
overlays/xorg-silence-aliases/default.nix
# xorg-silence-aliases
#
# A nixpkgs overlay that silences the eval-time deprecation warnings emitted for
# legacy `pkgs.xorg.<name>` accesses.
#
# nixpkgs keeps promoting packages out of the `xorg` package scope up to the
# top level (e.g. `xorg.xrandr` -> `xrandr`). Each legacy access to the old
# `xorg.<name>` spelling then trips a `builtins.trace` deprecation warning at
# evaluation time. This overlay re-points every promoted name back onto the
# `xorg` attrset so BOTH spellings resolve to the *same* derivation and the
# warning disappears.
#
# Usage:
# nixpkgs.overlays = [ (import ./xorg-silence-aliases) ];
# or as a flake overlay:
# overlays.default = import ./overlays/xorg-silence-aliases;
#
# The list below is the set of names that have (at various nixpkgs versions)
# been promoted out of `xorg`. Rather than hardcode `xorg.foo = final.foo` for
# each — which would break the day a name is *not* present at the top level on
# your channel — we alias only the names that actually exist as a top-level
# attribute of `final`. That keeps the overlay a safe drop-in across channels:
# names that have not been promoted (yet, or on your pin) are simply left alone.
#
# `final` (a.k.a. `self`) is used for the right-hand sides on purpose: it is the
# fully-overlaid package set, so the alias tracks any *later* overlay that
# replaces the top-level derivation. Using `prev` here would pin the alias to
# the pre-overlay value and could desync the two spellings.
final: prev:
let
# Names that have been (or may be) promoted out of the `xorg` scope to the
# top level. Extend this list if your channel warns about a name not covered.
promotedNames = [
"appres"
"bdftopcf"
"bitmap"
"editres"
"fonttosfnt"
"gccmakedep"
"iceauth"
"ico"
"imake"
"libdmx"
"libfontenc"
"libpciaccess"
"libxcb"
"libxcvt"
"libxkbfile"
"libxshmfence"
"listres"
"lndir"
"luit"
"makedepend"
"mkfontscale"
"oclock"
"pixman"
"sessreg"
"setxkbmap"
"smproxy"
"transset"
"viewres"
"wrapWithXFileSearchPathHook"
"x11perf"
"xauth"
"xbacklight"
"xbitmaps"
"xcalc"
"xclock"
"xcmsdb"
"xcompmgr"
"xconsole"
"xcursorgen"
"xdm"
"xdpyinfo"
"xdriinfo"
"xev"
"xeyes"
"xfd"
"xfontsel"
"xfs"
"xfsinfo"
"xgamma"
"xgc"
"xhost"
"xinit"
"xinput"
"xkbcomp"
"xkbevd"
"xkbprint"
"xkbutils"
"xkill"
"xload"
"xlsatoms"
"xlsclients"
"xlsfonts"
"xmag"
"xmessage"
"xmodmap"
"xmore"
"xorgproto"
"xpr"
"xprop"
"xrandr"
"xrdb"
"xrefresh"
"xset"
"xsetroot"
"xsm"
"xstdcmap"
"xtrans"
"xvfb"
"xvinfo"
"xwd"
"xwininfo"
"xwud"
];
lib = prev.lib;
# Keep only names that are actually present at the top level of the overlaid
# set, and map each to its promoted top-level derivation.
aliases = lib.genAttrs
(lib.filter (name: lib.hasAttr name final) promotedNames)
(name: final.${name});
in
{
xorg = prev.xorg // aliases;
}