numtide / flake-utils

Pure Nix flake utility functions [maintainer=@zimbatm]
MIT License
1.14k stars 78 forks source link

Potential feature-freeze or deprecation in favor of flake-parts #86

Open HariAmoor-professional opened 1 year ago

HariAmoor-professional commented 1 year ago

Unless I'm mistaken, the preferred solution for generalizing across system architectures with Nix flakes is flake-parts by the Hercules CI team; reason being, you can separate attributes that are truly hermetic from those that depend on a particular system with flake-parts, but not with flake-utils.

Conjecturally, we might either put flake-parts in the nix-community organization or even integrate it into the Nix mainline once flakes themselves are stable. In either case, there should be no reason to maintain this repo other than for compatibility.

cc @srid @roberth

roberth commented 1 year ago

truly hermetic

As in not having system as an input? Nix already guarantees an inescapable hermeticity in pure mode, which is enabled by default for flake evaluation.

you can separate attributes that are truly hermetic from those that depend on a particular system with flake-parts, but not with flake-utils.

I think you can, but it doesn't have to be part of flake-utils. Attribute merging doesn't seem to be in scope for flake-utils, so you'd use the built-in // syntax to declare both system-dependent and system-independent things: eachDefaultSystem (system: .....) // { nixosConfigurations = ... }. For a simple enough flake, no merging and no module reuse may be good enough.

put flake-parts in the nix-community

This doesn't seem particularly useful to me, as it's rare for it to need contributions. Contributions and feature requests that do come in and I honestly don't know who to entrust with this highly specialized task.

integrate it into the Nix mainline once flakes themselves are stable

This would have to include the module system, which is still evolving. By pinning the module system implementation in the flake lock, we can guarantee that a flake is reproducible years if not decades into the future. If we were to pin/vendor it in Nix, we would lose either the ability to improve the module system, or lose the ability to reproduce flakes years from now. Also it would burden the Nix maintainer team, which has a tough enough job already, and it has more useful opportunities to explore. I try not to imagine how Flakes would have flourished if it weren't bottlenecked at the nix repo. It didn't have to be. Same with nix-shell/nix develop, which is secretly a stdenv (Nixpkgs) feature.

HariAmoor-professional commented 1 year ago

As in not having system as an input?

@roberth As in, if you outputs = {...}: { myAttribute = mkIf (system == system') myAttribute'; } // { ... }; in your flake (excuse me for unsanitarily one-lining everything), then you're defining an attribute that exists iff a runtime condition holds, i.e., system == system', where you could have system' = "x86_64-linux" or something. In other words, a flake whose return-set changes based on runtime conditions isn't truly hermetic.

I could be wrong about whether or not this is allowed by default, though; I think it is, but I'm not sure.

[A generic attribute definition] doesn't have to be part of flake-utils

This is fair; you could always use //, although it's the less clean option. With that said, the community should converge around one best-practice for handling system-specific flakes rather than maintaining multiple competing solutions in the long run (at least IMO).

flake-parts is my preference for the reasons I mentioned, so I see no reason for this repo to exist, but it's up to Numtide to decide whether or not they want to maintain it. Granted, I have known some to believe that flake-parts over-engineered; I've personally not had any problem, coming from the Haskell side, but Nix also isn't only for Haskell stuff.

This would have to include the module system

I was thinking to just make system a parameter to outputs; that way, the whole output could be defined on a per-system basis. Perhaps this is what you mean by "having system as an input", although it's not exactly the same.

Perhaps you could set constraints on supported system architectures in inputs. @srid generally sets systems (as a parameter to flake-parts.lib.mkFlake) to lib.systems.flakeExposed by default, but specifies a list of systems with upstream support in the README; that way, users can build for whatever system they want, but maintainers don't have to support some obscure architecture that they don't care about. I think this is the predominant use-case.