This is my first encounter with the term “overlays.” The manual describes it thus:

Overlays are used to add layers in the fixed-point used by Nixpkgs to compose the set of all packages.

Any questions?

Chapter 3. Overlays

This is the first time I have heard Nix use the term “fixed-point.” Although I understand, like, that term in general, I have no idea how to apply that here. I think of a fixed-point as a property of a certain function, and I don’t know what function the manual is referring to here. It’s weird to say “the fixed-point used by Nixpkgs.” My best guess is that it’s talking about evaluation of the recursive set of all packages. But… I don’t really know. That seems a strange term to throw around if that’s all we’re talking about.

I also, once again, don’t know how the term “compose” is being used here. “To compose the set of all packages” reads to me as “to assemble the set of all packages.” But using the terms “fixed-point” and “compose” in the same sentence obviously evokes the function composition definition of the term. But my brain can’t make sense of that, so I would classify this as just confusingly worded. I guess?

I wonder if I am missing something important by making this assumption.

Oh well. Perhaps this will make sense later.

The list of overlays can be set either explicitly in a Nix expression, or through <nixpkgs-overlays> or user configuration files.

Okay. I guess that’s a new magic NIX_PATH element?

The manual goes on to enumerate these three approaches.

The list of overlays can be passed explicitly when importing nixpkgs, for example import <nixpkgs> { overlays = [ overlay1 overlay2 ]; }.

Further overlays can be added by calling the pkgs.extend or pkgs.appendOverlays, although it is often preferable to avoid these functions, because they recompute the Nixpkgs fixpoint, which is somewhat expensive to do.

Okay. Now we use the shorthand fixpoint, which is the more familiar term to me, but there is still no explanation of what this means.

The second case is when I have nixpkgs-overlays in my NIX_PATH. If it’s a file, it’s a list. If it’s a directory, each .nix file in that directory (or path/default.nix file) is an individual overlay. And it explains the rules for ordering overlays, since order is significant.

Still no mention of what an overlay is or how I would use it. It sounds like a different kind of packageOverrides? I don’t understand.

3.2. Defining overlays

Okay. Here we see a definition and example of an overlay:

Overlays are Nix functions which accept two arguments, conventionally called self and super, and return a set of packages. For example, the following is a valid overlay.

self: super:

{
  boost = super.boost.override {
    python = self.python3;
  };
  rr = super.callPackage ./pkgs/rr {
    stdenv = self.stdenv_32bit;
  };
}

Alright. I can sort of see what we’re doing here. The manual explains that self is the “final” package set (I assume this means the package set with all of the overlays applied), and super is the “current” state, if we think of overlays as folding over a set of packages. The manual doesn’t say that; that’s how I’m reading it.

Aha!

Overlays are similar to other methods for customizing Nixpkgs, in particular the packageOverrides attribute described in Section 2.5, “Modify packages via packageOverrides”. Indeed, packageOverrides acts as an overlay with only the super argument. It is therefore appropriate for basic use, but overlays are more powerful and easier to distribute.

Got it. So this actually tells me more about packageOverrides than the section on packageOverrides did. I’m still salty about that section.

3.3. Using overlays to configure alternatives

Certain software packages have different implementations of the same interface. […] Nixpkgs has what we call alternatives, which are configured through overlays.

Okay. It goes on to give an example, using a package I have not heard of that can select a particular so to link, by using overlays:

self: super:

{
  blas = super.blas.override {
    blasProvider = self.mkl;
  }
  lapack = super.lapack.override {
    lapackProvider = self.mkl;
  }
}

Okay. This seems like it could be useful, although it appears to require buy-in from every package to allow itself to be configurable in this way. Hmm.

Wow, lotta text about this specific BLAS/LAPACK example. Is this… is this an important example? Is this relevant? I would prefer to see a second example, instead of learning more about the details of Intel MKL’s requirement to have openmp when running on a system with multiple processors.

I’m getting the sense that this was written by someone who spent a very long time making these particular packages work well in Nix. But it doesn’t make for the best… general example. We’re getting way into the weeds.

Maybe the Nixpkgs manual is going to tell us about every weird package in the ecosystem? I don’t know.

That’s it! That’s all we get on overlays.


  • What is “the fixed-point used by Nixpkgs”? What does that mean? Why is that term never defined or explained?