nix-env: understading available attribute paths in the active Nix expression

Viewed 745

In my NixOS machine, I can use nix-env to query about the ghc package in two ways:

One is nix-env -f '<nixpkgs>' -qaP ghc which results in the output

ghc  ghc-8.6.5

Another is nix-env -qaP ghc which results in the output

nixpkgs.ghc  ghc-8.6.5

For the second case, I would like to understand why the active Nix expression has a nixpkgs root attribute.

The contents of the ~/.nix-defexpr folder and several subfolders are the following:

enter image description here

How is the active Nix expression assembled from the contents of ~/.nix-defexpr? Why there isn't a channels root attribute? Does the name of the nixpkgs root attribute derive from the name of the nixpkgs folder, or is it derived from the contents of the folder, perhaps from something declared in the default.nix file?

1 Answers

The Nix manual has some info on how .nix-defexpr is assembled:

The Nix expressions in this directory are combined into a single set, with each file as an attribute that has the name of the file.

It doesn't mention what happens if the contents are themselves directories, though. But I found this GitHub issue that explains things a little more:

  • If a directory is a valid expression (i.e. has default.nix) its expression will be added to the set, otherwise it will be traversed recursively.
  • Names of intermediate directories are completely ignored (i.e. do not take any part in attrpaths).
  • manifest.nix is recursively ignored.

So, there isn't a channels root attribute because the folder doesn't have a default.nix expression.

Ok. Then, as an experiment, I created a folder .nix-defexpr/foo with a file default.nix with contents { zzz = 4; } inside. When I execute nix-env --install -A foo.zzz I get:

error: expression does not evaluate to a derivation (or a set or list of those)

Which means that it actually found the path! The problem is that 4 is not a derivation.

But what if I create another folder .nix-defexpr/whatever and put a copy of the folder foo there? Won't there be some kind of name collision? Yes, there is:

8f792ff4f96a:~# nix-env --install -A foo.zzz
warning: name collision in input Nix expressions, skipping '/root/.nix-defexpr/whatever/foo'
Related