Wrappers and hooks: do not invoke wrapProgram directly

One of the big issues we’re having with wrappers is nested wrappers. It is not uncommon that during a build nested wrappers are created, either automatically using setup hooks, manually, or as a combination.
Furthermore, the behaviour when having multiple setup hooks is also not always obvious. E.g., wrapQtAppsHook ignores scripts whereas other hooks typically do not.

Earlier I suggested the concept of declarative wrappers, but there are limitations to that as well. Specifically, not all the information that is needed to generate wrappers is known up front, increasing the burden of writing derivations.

I now suggest that hooks do not actually create wrappers, but simply “tell” what needs to be done for a path, e.g. in a JSON file or a shell array. After all “normal” setup hooks are executed, we run a hook that invokes wrapProgram for the paths mentioned in the file or array.

This is quite similar as suggested before in Nix wrappers: improvements and https://github.com/NixOS/nixpkgs/issues/23018, although the binary is for now out of scope.

2 Likes

This sounds like the most obvious and simple solution we can have to nested wrappers being created by using multiple wrapper setup hooks.

Edit: I think I misunderstood what you meant the first time around, I’m reading through the links now.

I use this https://github.com/deliciouslytyped/nix-rootedoverlay/blob/c97e57f249df286c955fccef2a072019333b4e33/lib.nix#L4 to accumulate a list of things using successive overrides.

Maybe something like this could be done?

Well the basic idea is pretty simple, having an attrset that has a composing attribute and “carrying” an environment (which is kind of the whole point of rootedoverlay), is not as simple. It’s not complicated if you’re used to dealing with heavily recursive things and overlay systems, it’s just not the simplest thing.
I’m doing it with a full on overlay system here though (like a microcosm of nixpkgs) - a drv should be simpler.

Sidenote: I just realized I probably want something like this for my current fiddlings with the Idris package set, where I’m nesting some wrappers that happen to set disjunct sets of env vars. It gets uglier when they aren’t disjunct. You have to use --run if you want to default to a previously set variable using ${somevar:-somevalue}. Declarative wrappers may (?) help produce cleaner output in the case that you know at nix-time whether a variable will be overridden.

wrapQtAppsHook populates qtWrapperArgs with the appropriate arguments to wrapProgram. I cribbed that from wrapGAppsHook, which does something similar. So, I think we are not far off from what @FRidh suggests. We will also want a way to set the arguments to wrapProgram per-target. I originally wanted to do something like this when I introduced wrapQtAppsHook. The scope of the change was much larger than my appetite, so I abandoned that aspect of it, but not before wasting a lot of time trying and failing to do it right.

1 Like