Add Nix idioms (file lambdas, callPackage, overrides)
These are not strictly speaking language features, but my intention for this document is that someone can - after reading it - navigate a large chunk of existing Nix code.
This commit is contained in:
parent
a2610a9b33
commit
bb02b01dd0
1 changed files with 99 additions and 6 deletions
|
@ -127,9 +127,9 @@ There are no global variables.
|
||||||
|
|
||||||
## Functions
|
## Functions
|
||||||
|
|
||||||
All functions in Nix are anonymous. This means that they are treated just like
|
All functions in Nix are anonymous lambdas. This means that they are treated
|
||||||
data. Giving them names is accomplished by assigning them to variables, or
|
just like data. Giving them names is accomplished by assigning them to
|
||||||
setting them as values in an attribute set (more on that below).
|
variables, or setting them as values in an attribute set (more on that below).
|
||||||
|
|
||||||
```
|
```
|
||||||
# simple function
|
# simple function
|
||||||
|
@ -401,9 +401,99 @@ general build logic is out of scope for this document.
|
||||||
|
|
||||||
# Nix Idioms
|
# Nix Idioms
|
||||||
|
|
||||||
TODO(tazjin): This section should contain information on various Nix idioms,
|
There are several idioms in Nix which are not technically part of the language
|
||||||
such as import headers, `callPackage`, fixed points (+ overrides / overlays) and
|
specification, but will commonly be encountered in the wild.
|
||||||
so on.
|
|
||||||
|
This section is an (incomplete) list of them.
|
||||||
|
|
||||||
|
## File lambdas
|
||||||
|
|
||||||
|
It is customary to start every file with a function header that receives the
|
||||||
|
files dependencies, instead of importing them directly in the file.
|
||||||
|
|
||||||
|
Sticking to this pattern lets users of your code easily change out, for example,
|
||||||
|
the specific version of `nixpkgs` that is used.
|
||||||
|
|
||||||
|
A common file header pattern would look like this:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ pkgs ? import <nixpkgs> {} }:
|
||||||
|
|
||||||
|
# ... 'pkgs' is then used in the code
|
||||||
|
```
|
||||||
|
|
||||||
|
In some sense, you might consider the function header of a file to be its "API".
|
||||||
|
|
||||||
|
## `callPackage`
|
||||||
|
|
||||||
|
Building on the previous pattern, there is a custom in nixpkgs of specifying the
|
||||||
|
dependencies of your file explicitly instead of accepting the entire package
|
||||||
|
set.
|
||||||
|
|
||||||
|
For example, a file containing build instructions for a tool that needs the
|
||||||
|
standard build environment and `libsvg` might start like this:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
# my-funky-program.nix
|
||||||
|
{ stdenv, libsvg }:
|
||||||
|
|
||||||
|
stdenv.mkDerivation { ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
Any time a file follows this header pattern it is probably meant to be imported
|
||||||
|
using a special function called `callPackage` which is part of the top-level
|
||||||
|
package set (as well as certain subsets, such as `haskellPackages`).
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ pkgs ? import <nixpkgs> {} }:
|
||||||
|
|
||||||
|
let my-funky-program = callPackage ./my-funky-program.nix {};
|
||||||
|
in # ... something happens with my-funky-program
|
||||||
|
```
|
||||||
|
|
||||||
|
The `callPackage` function looks at the expected arguments (via
|
||||||
|
`builtins.functionArgs`) and passes the appropriate keys from the set in which
|
||||||
|
it is defined as the values for each corresponding argument.
|
||||||
|
|
||||||
|
## Overrides / Overlays
|
||||||
|
|
||||||
|
One of the most powerful features of Nix is that the representation of all build
|
||||||
|
instructions as data means that they can easily be *overridden* to get a
|
||||||
|
different result.
|
||||||
|
|
||||||
|
For example, assuming there is a package `someProgram` which is built without
|
||||||
|
our favourite configuration flag (`--mimic-threaten-tag`) we might override it
|
||||||
|
like this:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
someProgram.overrideAttrs(old: {
|
||||||
|
configureFlags = old.configureFlags ++ ["--mimic-threaten-tag"];
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
This pattern has a variety of applications of varying complexity. The top-level
|
||||||
|
package set itself can have an `overlays` argument passed to it which may add
|
||||||
|
new packages to the imported set.
|
||||||
|
|
||||||
|
For a slightly more advanced example, assume that we want to import `<nixpkgs>`
|
||||||
|
but have the modification above be reflected in the imported package set:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let
|
||||||
|
overlay = (self: super: {
|
||||||
|
someProgram = super.someProgram.overrideAttrs(old: {
|
||||||
|
configureFlags = old.configureFlags ++ ["--mimic-threaten-tag"];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
in import <nixpkgs> { overlays = [ overlay ]; }
|
||||||
|
```
|
||||||
|
|
||||||
|
The overlay function receives two arguments, `self` and `super`. `self` is
|
||||||
|
the [fixed point][fp] of the overlay's evaluation, i.e. the package set
|
||||||
|
*including* the new packages and `super` is the "original" package set.
|
||||||
|
|
||||||
|
See the Nix manual sections [on overrides][] and [on overlays][] for more
|
||||||
|
details.
|
||||||
|
|
||||||
[currying]: https://en.wikipedia.org/wiki/Currying
|
[currying]: https://en.wikipedia.org/wiki/Currying
|
||||||
[builtins]: https://nixos.org/nix/manual/#ssec-builtins
|
[builtins]: https://nixos.org/nix/manual/#ssec-builtins
|
||||||
|
@ -414,3 +504,6 @@ so on.
|
||||||
[trivial builders]: https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/trivial-builders.nix
|
[trivial builders]: https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/trivial-builders.nix
|
||||||
[smkd]: https://nixos.org/nixpkgs/manual/#chap-stdenv
|
[smkd]: https://nixos.org/nixpkgs/manual/#chap-stdenv
|
||||||
[drv-manual]: https://nixos.org/nix/manual/#ssec-derivation
|
[drv-manual]: https://nixos.org/nix/manual/#ssec-derivation
|
||||||
|
[fp]: https://github.com/NixOS/nixpkgs/blob/master/lib/fixed-points.nix
|
||||||
|
[on overrides]: https://nixos.org/nixpkgs/manual/#sec-overrides
|
||||||
|
[on overlays]: https://nixos.org/nixpkgs/manual/#chap-overlays
|
||||||
|
|
Loading…
Add table
Reference in a new issue