Memoize undeclared systems

The memoize function is not a pretty thing in terms of implementation,
but it's exactly what we need to solve this UX problem and performance
problem.

Without this, every distinct `withSystem` call will cause a re-evaluation
of the `perSystem` module, which is inefficient. Now, it's a one-time
13KB and length(system) attribute lookups: negligible compared to any
instantiations and such.

Nix doesn't offer memoization for functions yet, so this is the best we
can do.
This commit is contained in:
Robert Hensing 2025-07-21 20:01:38 +02:00
parent 7782624440
commit 577772566b
7 changed files with 120 additions and 2 deletions

View file

@ -59,6 +59,14 @@ let
}
'';
/**
We primarily use `systems` to help memoize the per system context, but that
doesn't extend to arbitrary `system`s.
For that, we use the slightly less efficient, but perfectly acceptable
`memoizeStr` function.
*/
otherMemoizedSystems = flake-parts-lib.memoizeStr config.perSystem;
in
{
options = {
@ -139,8 +147,7 @@ in
config = {
allSystems = genAttrs config.systems config.perSystem;
# TODO: Sub-optimal error message. Get Nix to support a memoization primop, or get Nix Flakes to support systems properly or get Nix Flakes to add a name to flakes.
_module.args.getSystem = system: config.allSystems.${system} or (builtins.trace "using non-memoized system ${system}" config.perSystem system);
_module.args.getSystem = system: config.allSystems.${system} or (otherMemoizedSystems system);
# The warning is there for a reason. Only use this in situations where the
# performance cost has already been incurred, such as in `flakeModules.easyOverlay`,