Is there any difference in effect between using nixpkgs.legacyPackages.${system} and import stable apart from import being able to override packages? Can either one do everything the other can?
To add some context: The article â1000 instances of nixpkgsâ (forum post, article) mentions this approach to prevent importing nixpkgs all the time. I have the same question about the differences between them. Is importing/instantiating nixpkgs a bad thing? legacyPackages sounds âlegacyâ ( ), so my intuition is to avoid itâŚ
We need at least one instance of nixpkgs (per system). The question is who is going to hold it.
If your flake has no dependencies except nixpkgs, it doesnât make a difference to use one or the other. The issue is when flake A depends on flake B, and both create their own instance of nixpkgs. At scale, this will become a problem.
If all your flakes use nixpkgs.legacyPackages, and all of them âfollowâ the same nixpkgs flake, then that is a good way to ensure only one instance of nixpkgs to be used.
I still donât see the difference between the two. It looks like legacyPackages is a wrapper over to explicitly import the nixpkgs.
Given all dependencies follow the same nixpkgs flake; are you saying when import nixpkgs { inherit system; }; is used instead of nixpkgs.legacyPackages.${system}, there is no caching and the same expression is evaluated multiple times?
In that case, if A import nixpkgs { inherit system; } or accesses nixpkgs.legacyPackages.${system}, both are functionally the same. This is true but realistically, as flakes get more popular, few projects will have only a dependency on nixpkgs.
A depends on B and nixpkgs, B depends on nixpkgs
Now if both A and B import nixpkgs { inherit system; }, there are two instances of nixpkgs instead of one. In further cases where the dependency tree grows larger, the number of instances would grow linearly with the number of dependencies.
In contrast, if both A and B access nixpkgs.legacyPackages.${system}, and that they both depend on the same nixpkgs flake, there will only be one evaluation of nixpkgs.
For this case to work, another requirement is to use the inputs âfollowsâ feature, so they are both pinned to the same version of nixpkgs.
Thatâs right. If you call a function twice, Nix returns two fresh âthunksâ. As a person, you might deduce that the thunks should be the same, but Nix doesnât know that and re-evaluates them all over again.
There is one memorization happening, on the import boundary. So if two parts of the code import <nixpkgs/lib> for example, that will be the same reference. But for nixpkgs, import <nixpkgs> returns a function. That gets memorized but itâs not super interesting for us.
You can use nixpkgs.overlays if you only need the overlay for a nixosConfiguration.
Otherwise, you need to publish your own outputs as an overlay, and use the prev argument as a nixpkgs (because when the overlay is eventually used the user will supply a nixpkgs for it).
For âleafâ flakes that donât have dependants using import is totally fine by the way. Itâs probably also fine for use in a devShell, or checks. They wonât create excess nixpkgs instances, since the import-ed nixpkgs instance is the only one, and dependants donât really use those outputs (though they could in theory, hence the probably); This is only a problem if youâre higher up in a dependency tree.
I still donât see any difference in using import vs legacyPackages: even if A and B both use nixpkgs.legacyPackages, they are referring to different revisions of nixpkgs, which are locked in their flake.lock files. So itâs two different nixpkgs in any case.
Maybe I donât understand it correctly, but it seems kinda problem.
E.g. I have flake-based NixOS configuration pinned to a certain revision. Then I start a project with nix shell and write a flake.nix using nixpkgs inside. Those projectâs nixpkgs usually have another revision than my system. So installing a simple bash for nix shell will pull different revisions of all system libraries, which is kinda ridiculous
Yes. follows is how you can solve that with the current design, but itâs one of the big remaining problems with flakes. Flakehub is an initial investigation into a more scaleable solution.