зеркало из
https://github.com/iharh/notes.git
synced 2025-11-01 06:06:08 +02:00
174 строки
7.4 KiB
Plaintext
174 строки
7.4 KiB
Plaintext
https://nixos.org/guides/nix-pills/nix-search-paths.html
|
|
|
|
Assuming you followed the previous posts, I hope you are now ready to understand nixpkgs.
|
|
But we have to find nixpkgs in our system first! So this is the step:
|
|
introducing some options and environment variables used by nix tools.
|
|
|
|
|
|
# 15.1. The NIX_PATH
|
|
|
|
The NIX_PATH environment variable is very important.
|
|
It's very similar to the PATH environment variable.
|
|
The syntax is similar, several paths are separated by a colon :.
|
|
Nix will then search for something in those paths from left to right.
|
|
|
|
Who uses NIX_PATH? The nix expressions!
|
|
Yes, NIX_PATH is not of much use by the nix tools themselves, rather it's used when writing nix expressions.
|
|
|
|
In the shell for example, when you execute the command ping, it's being searched in the PATH directories.
|
|
The first one found is the one being used.
|
|
|
|
In nix it's exactly the same, however the syntax is different.
|
|
Instead of just typing ping you have to type <ping>. Yes, I know... you are already thinking of <nixpkgs>.
|
|
However don't stop reading here, let's keep going.
|
|
|
|
What's NIX_PATH good for?
|
|
Nix expressions may refer to an "abstract" path such as <nixpkgs>, and it's possible to override it from the command line.
|
|
|
|
For ease we will use nix-instantiate --eval to do our tests.
|
|
I remind you, nix-instantiate is used to evaluate nix expressions and generate the .drv files.
|
|
Here we are not interested in building derivations, so evaluation is enough.
|
|
It can be used for one-shot expressions.
|
|
|
|
|
|
# 15.2. Fake it a little
|
|
|
|
It's useless from a nix view point, but I think it's useful for your own understanding.
|
|
Let's use PATH itself as NIX_PATH, and try to locate ping (or another binary if you don't have it).
|
|
|
|
```
|
|
$ nix-instantiate --eval -E '<ping>'
|
|
error: file `ping' was not found in the Nix search path (add it using $NIX_PATH or -I)
|
|
$ NIX_PATH=$PATH nix-instantiate --eval -E '<ping>'
|
|
/bin/ping
|
|
$ nix-instantiate -I /bin --eval -E '<ping>'
|
|
/bin/ping
|
|
```
|
|
|
|
Great. At first attempt nix obviously said could not be found anywhere in the search path.
|
|
Note that the [-I] option accepts a single directory.
|
|
Paths added with [-I] take precedence over NIX_PATH.
|
|
|
|
The NIX_PATH also accepts a different yet very handy syntax: "somename=somepath".
|
|
That is, instead of searching inside a directory for a name, we specify exactly the value of that name.
|
|
|
|
```
|
|
$ NIX_PATH="ping=/bin/ping" nix-instantiate --eval -E '<ping>'
|
|
/bin/ping
|
|
$ NIX_PATH="ping=/bin/foo" nix-instantiate --eval -E '<ping>'
|
|
error: file `ping' was not found in the Nix search path (add it using $N
|
|
```
|
|
|
|
Note in the second case how Nix checks whether the path exists or not.
|
|
|
|
|
|
# 15.3. The path to repository
|
|
|
|
You are out of curiosity, right?
|
|
|
|
```
|
|
$ nix-instantiate --eval -E '<nixpkgs>'
|
|
/home/nix/.nix-defexpr/channels/nixpkgs
|
|
$ echo $NIX_PATH
|
|
nixpkgs=/home/nix/.nix-defexpr/channels/nixpkgs
|
|
```
|
|
|
|
You may have a different path, depending on how you added channels etc..
|
|
Anyway that's the whole point.
|
|
The <nixpkgs> stranger that we used in our nix expressions, is referring to a path in the filesystem specified by NIX_PATH.
|
|
|
|
You can list that directory and realize it's simply a checkout of the nixpkgs repository at a specific commit (hint: .version-suffix).
|
|
|
|
!!! The NIX_PATH variable is exported by nix.sh, and that's the reason why I always asked you to source nix.sh at the beginning of my posts.
|
|
|
|
You may wonder: then I can also specify a different nixpkgs path to, e.g., a git checkout of nixpkgs?
|
|
Yes, you can and I encourage doing that.
|
|
We'll talk about this in the next pill.
|
|
|
|
Let's define a path for our repository, then!
|
|
Let's say all the default.nix, graphviz.nix etc. are under /home/nix/mypkgs:
|
|
|
|
```
|
|
$ export NIX_PATH=mypkgs=/home/nix/mypkgs:$NIX_PATH
|
|
$ nix-instantiate --eval '<mypkgs>'
|
|
{ graphviz = <code>; graphvizCore = <code>; hello = <code>; mkDerivation = <code>; }
|
|
```
|
|
|
|
Yes, nix-build also accepts paths with angular brackets.
|
|
We first evaluate the whole repository (default.nix) and then peek the graphviz attribute.
|
|
|
|
|
|
# 15.4. A big word about nix-env
|
|
|
|
The nix-env command is a little different than nix-instantiate and nix-build.
|
|
Whereas nix-instantiate and nix-build require a starting nix expression, nix-env does not.
|
|
|
|
You may be crippled by this concept at the beginning, you may think nix-env uses NIX_PATH to find the nixpkgs repository.
|
|
But that's not it.
|
|
|
|
The nix-env command uses ~/.nix-defexpr, which is also part of NIX_PATH by default, but that's only a coincidence.
|
|
If you empty NIX_PATH, nix-env will still be able to find derivations because of ~/.nix-defexpr.
|
|
|
|
So if you run nix-env -i graphviz inside your repository, it will install the nixpkgs one.
|
|
Same if you set NIX_PATH to point to your repository.
|
|
|
|
In order to specify an alternative to ~/.nix-defexpr it's possible to use the [-f] option:
|
|
|
|
```
|
|
$ nix-env -f '<mypkgs>' -i graphviz
|
|
warning: there are multiple derivations named `graphviz'; using the first one
|
|
replacing old `graphviz'
|
|
installing `graphviz'
|
|
```
|
|
|
|
Oh why did it say there's another derivation named graphviz?
|
|
Because both graphviz and graphvizCore attributes in our repository have the name "graphviz" for the derivation:
|
|
|
|
```
|
|
$ nix-env -f '<mypkgs>' -qaP
|
|
graphviz graphviz
|
|
graphvizCore graphviz
|
|
hello hello
|
|
```
|
|
|
|
By default nix-env parses all derivations and use the derivation names to interpret the command line.
|
|
So in this case "graphviz" matched two derivations.
|
|
Alternatively, like for nix-build, one can use [-A] to specify an attribute name instead of a derivation name:
|
|
|
|
```
|
|
$ nix-env -f '<mypkgs>' -i -A graphviz
|
|
replacing old `graphviz'
|
|
installing `graphviz'
|
|
```
|
|
|
|
This form, other than being more precise, it's also faster because nix-env does not have to parse all the derivations.
|
|
|
|
For completeness: you must install graphvizCore with [-A,] since without the [-A] switch it's ambiguous.
|
|
|
|
In summary, it may happen when playing with nix that nix-env peeks a different derivation than nix-build.
|
|
In such case you probably specified NIX_PATH, but nix-env is instead looking into ~/.nix-defexpr.
|
|
|
|
Why is nix-env having this different behavior?
|
|
I don't know specifically by myself either, but the answers could be:
|
|
* nix-env tries to be generic, thus it does not look for nixpkgs in NIX_PATH, rather it looks in ~/.nix-defexpr.
|
|
* nix-env is able to merge multiple trees in ~/.nix-defexpr by looking at all the possible derivations
|
|
|
|
It may also happen to you that you cannot match a derivation name when installing, because of the derivation name vs [-A] switch described above.
|
|
Maybe nix-env wanted to be more friendly in this case for default user setups.
|
|
|
|
It may or may not make sense for you, or it's like that for historical reasons, but that's how it works currently, unless somebody comes up with a better idea.
|
|
|
|
|
|
# 15.5. Conclusion
|
|
|
|
The NIX_PATH variable is the search path used by nix when using the angular brackets syntax.
|
|
It's possible to refer to "abstract" paths inside nix expressions and define the "concrete" path by means of NIX_PATH, or the usual [-I] flag in nix tools.
|
|
|
|
We've also explained some of the uncommon nix-env behaviors for newcomers.
|
|
The nix-env tool does not use NIX_PATH to search for packages, but rather for ~/.nix-defexpr.
|
|
Beware of that!
|
|
|
|
In general do not abuse NIX_PATH, when possible use relative paths when writing your own nix expressions.
|
|
Of course, in the case of <nixpkgs> in our repository, that's a perfectly fine usage of NIX_PATH.
|
|
Instead, inside our repository itself, refer to expressions with relative paths like ./hello.nix.
|