I read the Nixpkgs manual.

It took a long time. It was a very long manual.

And I learned a lot. But not quite as much as I wanted to.

Now I thought I’d do another little summary of my thoughts and feelings, for myself and others.


My overwhelming memory of the Nixpkgs manual-reading experience is: cross-compilation is a hot mess.

You know when you’re doing code review, and you find some code that doesn’t really make sense, so you go to talk to the author, and they can’t explain it to you in a way that makes any sense? It’s usually a very strong signal that the code needs work; that the author has not quite hit on the correct design yet. It’s sort of like the reverse-Kolmogorov complexity: how many English words it takes to explain software is a good measure of the complexity of the software.

Now, I have no idea if that’s the case with Nix’s cross-compilation support. I haven’t talked about it with anyone; I just read some words in the manual. It’s quite possible that it just isn’t written up very well, but that the solution itself is sound and elegant. But it doesn’t give me a lot of… confidence, in the design.

And I think that, if cross-compilation should work by default for as many packages as possible, it is important to communicate to users how they can make that work, in simple language that can be understood by someone (like me) who has not given a lot of thought to cross-compilation before. I feel like the current state of the documentation is probably illegible to people who don’t already know how it works, and I would venture a guess that this means the “average” Nix user (like me) doesn’t know what they should be doing in order to support it. So I’m just not going to think about it, and hope that it works.

Which is maybe fine? Like, the ideal solution is “cross-compilation just works out of the box and you never have to think about how it works just add dependencies to buildInputs or whatever.” But I don’t… know if that’s the case. And I suspect it isn’t, based on my trivial attempt to cross-compile GNU hello failing.

What is a derivation

So I still don’t really know what a derivation is. Reading the Nixpkgs manual taught me the very important bit of information that a derivation is an attribute set with { type = "derivation"; }, but… I dunno. I still don’t know what a .drv file is. I still don’t understand Nix’s side-effect-evaluation model. I still don’t… I still can’t explain how Nix works or when software gets installed or anything else.

Which is… yeah. I think it’s something that I’ll have to investigate on its own.

Attribute sets

This is such a dumb thing, but I think it was actually a useful thing to learn. I was really annoyed, when reading the Nix manual, that Nix called its little map/dictionary/object things “sets.” Because they aren’t sets. But now I know that “set” is just shorthand for “attribute set,” and the use of the term no longer bothers me. It’s a dumb thing, but it’s something that I think would improve the experience of using Nix if it were pointed out as soon as the term “set” were introducted.

Developing with Nix

So mkShell is a very important thing to know about, I think, and the Nixpkgs manual did explain it, eventually. It seems important enough to mention it in the Nix manual, though.

But I don’t really know… if I would ever do something more than write a shell.nix. I don’t understand why or if I would ever try to Nixify my language-specific dependencies. I guess I don’t really see the value add.

Which is okay! shell.nix is enough of a value add for me. I don’t need any more than that. I just… there seems to be more than that, but the manual never motivated… why. Why that exists; why I would use it. I feel like I might be missing out on a Nix superpower that I don’t understand.

Overlays and overrides

This was a really useful thing I learned, although I haven’t really had much practice doing it. But like “install tmux, but set src to my own fork” or whatever is a pretty useful thing to be able to do. It’s weird to me that there are multiple ways to do this, but so it is, I suppose.

I remember that the presentation of these concepts in the manual was a little confusing, but it all made sense after reading the whole thing. But they were sort of presented in reverse order.

This is a pretty specific complaint, but it’s one of those things in the Nixpkgs manual that seems sort of important to any user of Nix, thus a place where the documentation could be more useful.

The standard environment

Learning how the standard builder worked, and what packages were available by default in the standard environment… that was very useful reading. Unfortunately a lot of it was very confusing due to the cross-compilation stuff, and I don’t understand any of that, but a brief overview of like… the setupHook thing, the default PATH, and the phases, would be very useful.

I know the standard builder stuff is mentioned briefly in the Nix manual, but it would be nice to see slightly more without getting completely into the weeds.


One open question I came out of this manual with is: what is the stability guarantee here?

In some sense it feels like all of Nixpkgs is an API, that users of Nix might rely on. Is that true? How does that work? If I’m using helper functions in lib… are they always going to be there? Can I rely on them? Is there some versioning scheme? I don’t know.

The end

Okay. That’s the end. Those are my thoughts; those are my takeaways. That is the summary of… a month and a half’s journey of idle documentation-perusing?

Not that I am done learning Nix. Not by a long shot. But it’s nice to end this sidequest, and prepare to start another.