I have a fairly simple situation where I’m defining an overlay in one flake and using it in another.
In the dependency flake I’ve defined a package called zlib - nb, there is already a package with the same name in nixpkgs, and put it into that flake’s overlay:
zlib = with pkgs; callPackage ./zlib.nix {};
in {
packages.default = zlib;
overlays = final: prev: { inherit zlib; };
That all builds fine and no errors there. nix eval --raw .# gives me the store path for this, /nix/store/vn36lf7ilbcnwl2bd0qpsixi7gfxkvmi-zlib. So far so good.
I then have a second flake, which imports the dependency flake, and uses its overlay to define pkgs:
where the derivation in main_package.nix lists zlib as one of its parameters.
Unfortunately it’s taking the pre-existing nixpkgs zlib instead of my new one, as I can see by looking at the store paths in nix show-derivation .#mainPackage. Am I making some elementary mistake here? I can’t see how.
Overlays are not system-spaced, so I’m not sure what you’re doing zlib.overlays.${system} for, nor why it’s not yelling at you when you try.
Also, when defining the overlay, you should probably be using zlib = final.callPackage ./zlib.nix {};, rather than pulling in a separate nixpkgs invocation just for zlib.
However, for the main question, of why it’s not picking up the new package, the only thing I can think of is that you defined callPackage with a let or an argument binding somehow, and it’s overriding the with pkgs;.
Yeah, a quick check of the code says flake-utils.lib.eachDefaultSystem doesn’t know about overlays not being system-spaced. I think you might be expected to know that yourself and put them in with // outside of the call.
What was the solution? I’m having a very similar problem, and I’m starting to wonder if it’s the difference between packages and legacyPackages, but I’m just grasping at straws at this point.
Truth be told, overlays were never really the best solution here. It would have been better to simply override zlib in the second argument of callPackage on the consuming package. The best overlay is no overlay, in most cases.
While that or similar may have worked for the original problem, mine is slightly different. I’m trying to idiomatically pass packages from a different flake to my NixOS and home-manager configurations. I think the best way to do that would be to have them available via pkgs, but importing nixpkgs with the overlay hadn’t worked for me.
And I figured it out after the fact, I had to make sure I was passing the pkgs to which I had applied the overlay through all of the necessary layers with the appropriate inherit directives.
For your purpose, I would simply use the packages directly from inputs, passing it into the nixos and home-manager modules with specialArgs as needed. There is no rule that all packages need to be in pkgs, and it really isn’t idiomatic to put them there if they aren’t part of nixpkgs. pkgs is supposed to be an instance of nixpkgs, not a universal namespace.
That does sound like a good fix (specialArgs was the one argument to configuration.nix that I hadn’t tried yet). Is there any documentation on why pkgs should be an instance of nixpkgs, or similar design decisions or paradigms?
There isn’t really a lot of documentation on best practices or paradigms with nix, unfortunately. A general rule most everyone does agree on is that it’s best not to use an overlay when another approach would suffice. Most things people think to use overlays for can be done with:
Separate variables passed through specialArgs or _module.args.
*.package options in nixos or home-manager.
Writing more complex expressions directly at the usage site, or in a let.
This is partly a performance concern, as overlays have a fairly high cost, since they need to essentially “rewire” the entirety of nixpkgs. It’s also simply a matter of sensibility: why invent a convoluted way to pass a variable around when a straightforward one exists?