Skip to content

flake: introduce special + syntax to combine sets at invocation time#2429

Open
charludo wants to merge 2 commits into
mainfrom
ch/nix-sets-combine
Open

flake: introduce special + syntax to combine sets at invocation time#2429
charludo wants to merge 2 commits into
mainfrom
ch/nix-sets-combine

Conversation

@charludo

@charludo charludo commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

This is a suggestion on how to combine arbitrary sets. Any permutation of set names joined by + accesses the package set with all specified overlays applied. To keep eval time down and to prevent accidental overrides, set names are internally sorted after splitting on +.

@charludo charludo requested review from burgerdev and sespiros June 3, 2026 08:59
@charludo charludo added the no changelog PRs not listed in the release notes label Jun 3, 2026
@charludo charludo marked this pull request as ready for review June 10, 2026 07:17

@sespiros sespiros left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this indeed looks technically neat and I am happy to merge since this is dev-only and also easily reversible, but I do have some concerns (that I tried to express in #2405 (comment)) on how useful this added complexity will be. Could you tell me some concrete use cases you have in mind before we start building on this? Other than this high level comment/question, just some inline comments.

To share my thoughts a bit, in the concrete use cases I had so far (badaml tests), I am not sure if this composability would bring that much benefit other than simply taking the debug overrides out of the badaml sets. Most of the other overrides couldn't be split out in separate composable sets that would be useful to any other combination of sets. Could I split out qemu-wrapped too as a reusable set for instance? I could create a qemu-acpi set (that overrides qemu-wrapped with the withACPITable flag) and a qemu-serial set (for the withSerialLog flag). But then, does running ... .#badaml-vuln+debug+qemu-serial+qemu-acpi.foo vs ... .#badaml-vuln.foo make my life any easier than simply having a set which is monolithic and per use-case? That actually wouldn't even be possible due to the limit of 3 which I believe is there so that the possibilities don't explode. Moreover there are cross-dependencies, i.e supplying withACPITable to qemu without specifying withACPIDebug to kernel-uvm is not useful so now I need to be aware of that vs having a per-use case set in that folder. That's why in #2405 I opted for this simple approach of prepending sets with _ to indicate a part of a set. otoh we could have both (parts of sets and composable sets and only allow composing sets).

Other concrete upcoming use cases I see is the oak set and the runtime-rs set but will we want to compose these/is it meaningful to be able to compose all those different combinations? If it is, it seems much more intentional to me to see a set in that folder named runtime-rs_oak that indicates that we do care about that particular combination.

Then if it's only some flavor of debug that we want to attach in these per-use-case sets, I think that could be done in some simpler and more straightforward way.

Comment thread flake.nix
];

sets = setsFromDirectory ./overlays/sets;
setsDir = ./overlays/sets;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI comment suggestion, feel free to keep or drop.

Suggested change
setsDir = ./overlays/sets;
# Sets are built from the overlays in ./overlays/sets. Beyond the single-file
# sets, any combination of up to maxCombineDepth overlays is exposed under a
# name joining the set names with "+". Each combination is evaluated once and
# stored under its sorted (canonical) name; every permutation of the names is
# registered as an alias of that same evaluation, so the order the user types
# does not matter and does not cost an extra eval.
setsDir = ./overlays/sets;

Comment thread flake.nix
setsDir = ./overlays/sets;
setNames = map (nixpkgs.lib.removeSuffix ".nix") (builtins.attrNames (builtins.readDir setsDir));

nonEmptySubsets =

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment on what this function does in a similar spirit to the one setsFromDirectory had. Same for the rest of the functions that build towards the final attribute set (permutations, canonicalName, canonicalSets, sets).

Comment thread flake.nix

sets = setsFromDirectory ./overlays/sets;
setsDir = ./overlays/sets;
setNames = map (nixpkgs.lib.removeSuffix ".nix") (builtins.attrNames (builtins.readDir setsDir));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my high level comment too but what do you think about excluding here sets starting with "_" to allow for parts of sets?

Comment thread flake.nix
canonicalName =
subset: nixpkgs.lib.concatStringsSep "+" (nixpkgs.lib.sort builtins.lessThan subset);

subsets = builtins.filter (s: builtins.length s <= 3) (nonEmptySubsets setNames);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract literal 3 as maxCombineDepth or equivalent.

Comment thread flake.nix
canonicalSets = builtins.listToAttrs (
map (s: {
name = canonicalName s;
value = mkSet ((defaultOverlays (canonicalName s)) ++ map (n: import (setsDir + "/${n}.nix")) s);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nitpicking/not sure if intentional but the overlays here are applied in the order of s but s comes from nonEmptySets which is in reverse alphabetical order. So applying a+b applies the overlays in reverse order.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no changelog PRs not listed in the release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants