1
0
Fork 0
mirror of https://github.com/NixOS/nix-pills synced 2024-09-18 03:50:12 -04:00

Support "note" sections, fix inter-links

This commit is contained in:
Noam Yorav-Raphael 2024-04-08 23:36:09 +03:00 committed by Jan Tojnar
parent 6af51f2b0a
commit f0099a3e28
24 changed files with 114 additions and 369 deletions

View file

@ -6,5 +6,11 @@ multilingual = false
src = "pills"
[output.html]
additional-css = ["custom.css"]
edit-url-template = "https://github.com/NixOS/nix-pills/tree/master/{path}"
git-repository-url = "https://github.com/NixOS/nix-pills"
[output.linkcheck]
follow-web-links = true
[output.epub]

18
custom.css Normal file
View file

@ -0,0 +1,18 @@
.info {
margin: 20px;
padding: 0 20px;
border-inline-start: 2px solid var(--links);
}
.info:before {
position: absolute;
width: 3rem;
height: 3rem;
margin-inline-start: calc(-1.5rem - 21px);
content: "ⓘ";
text-align: center;
background-color: var(--bg);
color: var(--links);
font-weight: bold;
font-size: 2rem;
}

View file

@ -8,6 +8,8 @@ For an up-to-date version, please visit <https://nixos.org/guides/nix-pills/>. A
If you encounter problems, please report them on the [nixos/nix-pills](https://github.com/NixOS/nix-pills/issues) issue tracker.
::: note
Commands prefixed with `#` have to be run as root, either requiring to login as root user or temporarily switching to it using `sudo` for example.
:::
<div class="info">
Note: Commands prefixed with `#` have to be run as root, either requiring to login as root user or temporarily switching to it using `sudo` for example.
</div>

View file

@ -1,10 +1,10 @@
# Install on Your Running System
Welcome to the second Nix pill. In the [first](#why-you-should-give-it-a-try) pill we briefly described Nix.
Welcome to the second Nix pill. In the [first](01-why-you-should-give-it-try.md) pill we briefly described Nix.
Now we\'ll install Nix on our running system and understand what changed in our system after the installation. **If you\'re using NixOS, Nix is already installed; you can skip to the [next](#enter-environment) pill.**
Now we\'ll install Nix on our running system and understand what changed in our system after the installation. **If you\'re using NixOS, Nix is already installed; you can skip to the [next](03-enter-environment.md) pill.**
For installation instructions, please refer to the Nix Reference Manual on [ Installing Nix](https://nixos.org/manual/nix/stable/installation/installation.html).
For installation instructions, please refer to the Nix Reference Manual on [ Installing Nix](https://nixos.org/manual/nix/stable/installation/installing-binary.html).
## Installation
@ -12,9 +12,11 @@ These articles are not a tutorial on *using* Nix. Instead, we\'re going to walk
The first thing to note: derivations in the Nix store refer to other derivations which are themselves in the Nix store. They don\'t use `libc` from our system or anywhere else. It\'s a self-contained store of all the software we need to bootstrap up to any particular package.
::: note
In a multi-user installation, such as the one used in NixOS, the store is owned by root and multiple users can install and build software through a Nix daemon. You can read more about multi-user installations here: <https://nixos.org/manual/nix/stable/installation/installing-binary.html#multi-user-installation>.
:::
<div class="info">
Note: In a multi-user installation, such as the one used in NixOS, the store is owned by root and multiple users can install and build software through a Nix daemon. You can read more about multi-user installations here: <https://nixos.org/manual/nix/stable/installation/installing-binary.html#multi-user-installation>.
</div>
## The beginnings of the Nix store
@ -40,13 +42,17 @@ Then there\'s a dependency relation from path to paths upon which they depend.
You can inspect the database by installing sqlite (`nix-env -iA sqlite -f '<nixpkgs>'`) and then running `sqlite3 /nix/var/nix/db/db.sqlite`.
::: note
If this is the first time you\'re using Nix after the initial installation, remember you must close and open your terminals first, so that your shell environment will be updated.
:::
<div class="info">
::: important
Never change `/nix/store` manually. If you do, then it will no longer be in sync with the sqlite db, unless you *really* know what you are doing.
:::
Note: If this is the first time you\'re using Nix after the initial installation, remember you must close and open your terminals first, so that your shell environment will be updated.
</div>
<div class="warning">
Important: Never change `/nix/store` manually. If you do, then it will no longer be in sync with the sqlite db, unless you *really* know what you are doing.
</div>
## The first profile

View file

@ -1,6 +1,6 @@
# Enter the Environment {#enter-environment}
Welcome to the third Nix pill. In the [second pill](#install-on-your-running-system) we installed Nix on our running system. Now we can finally play with it a little, these things also apply to NixOS users.
Welcome to the third Nix pill. In the [second pill](02-install-on-your-running.md) we installed Nix on our running system. Now we can finally play with it a little, these things also apply to NixOS users.
## Enter the environment
@ -166,7 +166,7 @@ The second option is to install Nix, thus creating a new generation:
## Channels
So where are we getting packages from? We said something about this already in the [second article](#install-on-your-running-system). There\'s a list of channels from which we get packages, although usually we use a single channel. The tool to manage channels is [nix-channel](https://nixos.org/manual/nix/stable/command-ref/nix-channel.html).
So where are we getting packages from? We said something about this already in the [second article](02-install-on-your-running.md). There\'s a list of channels from which we get packages, although usually we use a single channel. The tool to manage channels is [nix-channel](https://nixos.org/manual/nix/stable/command-ref/nix-channel.html).
$ nix-channel --list
nixpkgs http://nixos.org/channels/nixpkgs-unstable
@ -175,9 +175,11 @@ If you\'re using NixOS, you may not see any output from the above command (if yo
That\'s essentially the contents of `~/.nix-channels`.
::: note
`~/.nix-channels` is not a symlink to the nix store!
:::
<div class="info">
Note: `~/.nix-channels` is not a symlink to the nix store!
</div>
To update the channel run `nix-channel --update`. That will download the new Nix expressions (descriptions of the packages), create a new generation of the channels profile and unpack it under `~/.nix-defexpr/channels`.

View file

@ -1,6 +1,6 @@
# The Basics of the Language {#basics-of-language}
Welcome to the fourth Nix pill. In the [previous article](#enter-environment) we learned about Nix environments. We installed software as a user, managed their profile, switched between generations, and queried the Nix store. Those are the very basics of system administration using Nix.
Welcome to the fourth Nix pill. In the [previous article](03-enter-environment.md) we learned about Nix environments. We installed software as a user, managed their profile, switched between generations, and queried the Nix store. Those are the very basics of system administration using Nix.
The [Nix language](https://nixos.org/manual/nix/stable/expressions/expression-language.html) is used to write expressions that produce derivations. The [nix-build](https://nixos.org/manual/nix/stable/command-ref/nix-build.html) tool is used to build derivations from an expression. Even as a system administrator that wants to customize the installation, it\'s necessary to master Nix. Using Nix for your jobs means you get the features we saw in the previous articles for free.
@ -8,13 +8,17 @@ The syntax of Nix is quite unfamiliar, so looking at existing examples may lead
On the other hand, the same syntax is great for describing packages, so learning the language itself will pay off when writing package expressions.
::: important
In Nix, everything is an expression, there are no statements. This is common in functional languages.
:::
<div class="info">
::: important
Values in Nix are immutable.
:::
Important: In Nix, everything is an expression, there are no statements. This is common in functional languages.
</div>
<div class="info">
Important: Values in Nix are immutable.
</div>
## Value types

View file

@ -1,6 +1,6 @@
# Functions and Imports
Welcome to the fifth Nix pill. In the previous [fourth pill](#basics-of-language) we touched the Nix language for a moment. We introduced basic types and values of the Nix language, and basic expressions such as `if`, `with` and `let`. I invite you to re-read about these expressions and play with them in the repl.
Welcome to the fifth Nix pill. In the previous [fourth pill](04-basics-of-language.md) we touched the Nix language for a moment. We introduced basic types and values of the Nix language, and basic expressions such as `if`, `with` and `let`. I invite you to re-read about these expressions and play with them in the repl.
Functions help to build reusable components in a big repository like [nixpkgs](https://github.com/NixOS/nixpkgs/). The Nix manual has a [great explanation of functions](https://nixos.org/manual/nix/stable/expressions/language-constructs.html#functions). Let\'s go: pill on one hand, Nix manual on the other hand.
@ -25,7 +25,7 @@ We can store functions in variables.
As usual, please ignore the special syntax for assignments inside `nix repl`. So, we defined a function `x: x*2` that takes one parameter `x`, and returns `x*2`. This function is then assigned to the variable `double`. Finally we did our first function call: `double 3`.
[Big note:]{.underline} it\'s not like many other programming languages where you write `double(3)`. It really is `double 3`.
Big note: it\'s not like many other programming languages where you write `double(3)`. It really is `double 3`.
In summary: to call a function, name the variable, then space, then the argument. Nothing else to say, it\'s as easy as that.

View file

@ -1,6 +1,6 @@
# Our First Derivation
Welcome to the sixth Nix pill. In the previous [fifth pill](#functions-and-imports) we introduced functions and imports. Functions and imports are very simple concepts that allow for building complex abstractions and composition of modules to build a flexible Nix system.
Welcome to the sixth Nix pill. In the previous [fifth pill](05-functions-and-imports.md) we introduced functions and imports. Functions and imports are very simple concepts that allow for building complex abstractions and composition of modules to build a flexible Nix system.
In this post we finally arrived to writing a derivation. Derivations are the building blocks of a Nix system, from a file system view point. The Nix language is used to describe such derivations.
@ -49,9 +49,11 @@ Both drv paths and out paths are stored in the nix store as you can see.
What\'s in that `.drv` file? You can read it, but it\'s better to pretty print it:
::: note
If your version of nix doesn\'t have `nix derivation show`, use `nix show-derivation` instead.
:::
<div class="info">
Note: If your version of nix doesn't have `nix derivation show`, use `nix show-derivation` instead.
</div>
\<screen xmlns=\"http://docbook.org/ns/docbook\"\>\<prompt\>\$ \</prompt\>\<userinput\>nix derivation show /nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-\<emphasis\>myname.drv\</emphasis\>\</userinput\> \<computeroutput\>{ \"/nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv\": { \"outputs\": { \"out\": { \"path\": \"/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname\" } }, \"inputSrcs\": \[\], \"inputDrvs\": {}, \"platform\": \"mysystem\", \"builder\": \"mybuilder\", \"args\": \[\], \"env\": { \"builder\": \"mybuilder\", \"name\": \"myname\", \"out\": \"/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname\", \"system\": \"mysystem\" } } }\</computeroutput\>\</screen\>
@ -59,7 +61,7 @@ Ok, we can see there\'s an out path, but it does not exist yet. We never told Ni
Think, if Nix ever built the derivation just because we accessed it in Nix, we would have to wait a long time if it was, say, Firefox. That\'s why Nix let us know the path beforehand and kept evaluating the Nix expressions, but it\'s still empty because no build was ever made.
[Important]{.underline}: the hash of the out path is based solely on the input derivations in the current version of Nix, not on the contents of the build product. It\'s possible however to have [content-addressable](https://en.wikipedia.org/wiki/Content-addressable_storage) derivations for e.g. tarballs as we\'ll see later on.
Important: the hash of the out path is based solely on the input derivations in the current version of Nix, not on the contents of the build product. It\'s possible however to have [content-addressable](https://en.wikipedia.org/wiki/Content-addressable_storage) derivations for e.g. tarballs as we\'ll see later on.
Many things are empty in that `.drv`, however I\'ll write a summary of the [.drv format](http://nixos.org/~eelco/pubs/phd-thesis.pdf) for you:
@ -73,7 +75,7 @@ Many things are empty in that `.drv`, however I\'ll write a summary of the [.drv
That\'s it, the minimum necessary information to build our derivation.
[Important note]{.underline}: the environment variables passed to the builder are just those you see in the .drv plus some other Nix related configuration (number of cores, temp dir, \...). The builder will not inherit any variable from your running shell, otherwise builds would suffer from [non-determinism](https://wiki.debian.org/ReproducibleBuilds).
Important note: the environment variables passed to the builder are just those you see in the .drv plus some other Nix related configuration (number of cores, temp dir, \...). The builder will not inherit any variable from your running shell, otherwise builds would suffer from [non-determinism](https://wiki.debian.org/ReproducibleBuilds).
Back to our fake derivation.
@ -195,7 +197,7 @@ In the previous attempt we used a fake builder, `mybuilder` which obviously does
Another step forward, it executed the builder (bin/true), but the builder did not create the out path of course, it just exited with 0.
[Obvious note]{.underline}: every time we change the derivation, a new hash is created.
Obvious note: every time we change the derivation, a new hash is created.
Let\'s examine the new `.drv` now that we referred to another derivation:

View file

@ -2,7 +2,7 @@
## Introduction
Welcome to the seventh nix pill. In the previous [sixth pill](#our-first-derivation) we introduced the notion of derivation in the Nix language --- how to define a raw derivation and how to (try to) build it.
Welcome to the seventh nix pill. In the previous [sixth pill](06-our-first-derivation.md) we introduced the notion of derivation in the Nix language --- how to define a raw derivation and how to (try to) build it.
In this post we continue along the path, by creating a derivation that actually builds something. Then, we try to package a real program: we compile a simple C file and create a derivation out of it, given a blessed toolchain.
@ -57,7 +57,7 @@ In terms of autotools, `$out` will be the `--prefix` path. Yes, not the make `DE
We added something else to the derivation this time: the args attribute. Let\'s see how this changed the .drv compared to the previous pill: \<screen xmlns=\"http://docbook.org/ns/docbook\"\>\<prompt\>\$ \</prompt\>\<userinput\>nix derivation show /nix/store/i76pr1cz0za3i9r6xq518bqqvd2raspw-\<emphasis\>foo.drv\</emphasis\>\</userinput\> \<computeroutput\>{ \"/nix/store/i76pr1cz0za3i9r6xq518bqqvd2raspw-foo.drv\": { \"outputs\": { \"out\": { \"path\": \"/nix/store/gczb4qrag22harvv693wwnflqy7lx5pb-foo\" } }, \"inputSrcs\": \[ \"/nix/store/lb0n38r2b20r8rl1k45a7s4pj6ny22f7-builder.sh\" \], \"inputDrvs\": { \"/nix/store/hcgwbx42mcxr7ksnv0i1fg7kw6jvxshb-bash-4.4-p19.drv\": \[ \"out\" \] }, \"platform\": \"x86_64-linux\", \"builder\": \"/nix/store/q1g0rl8zfmz7r371fp5p42p4acmv297d-bash-4.4-p19/bin/bash\", \"args\": \[ \"/nix/store/lb0n38r2b20r8rl1k45a7s4pj6ny22f7-builder.sh\" \], \"env\": { \"builder\": \"/nix/store/q1g0rl8zfmz7r371fp5p42p4acmv297d-bash-4.4-p19/bin/bash\", \"name\": \"foo\", \"out\": \"/nix/store/gczb4qrag22harvv693wwnflqy7lx5pb-foo\", \"system\": \"x86_64-linux\" } } }\</computeroutput\>\</screen\> Much like the usual .drv, except that there\'s a list of arguments in there passed to the builder (bash) with `builder.sh`... In the nix store..? Nix automatically copies files or directories needed for the build into the store to ensure that they are not changed during the build process and that the deployment is stateless and independent of the building machine. `builder.sh` is not only in the arguments passed to the builder, it\'s also in the input derivations.
Given that `builder.sh` is a plain file, it has no .drv associated with it. The store path is computed based on the filename and on the hash of its contents. Store paths are covered in detail in [a later pill](#nix-store-paths).
Given that `builder.sh` is a plain file, it has no .drv associated with it. The store path is computed based on the filename and on the hash of its contents. Store paths are covered in detail in [a later pill](18-nix-store-paths.md).
## Packaging a simple C program
@ -118,7 +118,7 @@ Finally, it creates the symlink.
In the second line of `simple.nix`, we have an `import` function call. Recall that `import` accepts one argument, a nix file to load. In this case, the contents of the file evaluate to a function.
Afterwards, we call the function with the empty set. We saw this already in [the fifth pill](#functions-and-imports). To reiterate: `import <nixpkgs> {}` is calling two functions, not one. Reading it as `(import <nixpkgs>) {}` makes this clearer.
Afterwards, we call the function with the empty set. We saw this already in [the fifth pill](05-functions-and-imports.md). To reiterate: `import <nixpkgs> {}` is calling two functions, not one. Reading it as `(import <nixpkgs>) {}` makes this clearer.
The value returned by the nixpkgs function is a set; more specifically, it\'s a set of derivations. Calling `import <nixpkgs> {}` into a `let`-expression creates the local variable `pkgs` and brings it into scope. This has an effect similar to the `:l <nixpkgs>` we used in nix repl, in that it allows us to easily access derivations such as `bash`, `gcc`, and `coreutils`, but those derivations will have to be explicitly referred to as members of the `pkgs` set (e.g., `pkgs.bash` instead of just `bash`).

View file

@ -1,6 +1,6 @@
# Generic Builders
Welcome to the 8th Nix pill. In the previous [7th pill](#working-derivation) we successfully built a derivation. We wrote a builder script that compiled a C file and installed the binary under the nix store.
Welcome to the 8th Nix pill. In the previous [7th pill](07-working-derivation.md) we successfully built a derivation. We wrote a builder script that compiled a C file and installed the binary under the nix store.
In this post, we will generalize the builder script, write a Nix expression for [GNU hello world](https://www.gnu.org/software/hello/) and create a wrapper around the derivation built-in function.
@ -43,10 +43,8 @@ And the derivation hello.nix:
system = builtins.currentSystem;
}
:::: note
::: title
Nix on darwin
:::
<div class="info">
<h4>Nix on darwin</h4>
Darwin (i.e. macOS) builds typically use `clang` rather than `gcc` for a C compiler. We can adapt this early example for darwin by using this modified version of `hello.nix`:
@ -73,11 +71,11 @@ Darwin (i.e. macOS) builds typically use `clang` rather than `gcc` for a C compi
}
Later, we will show how Nix can automatically handle these differences. For now, please be just aware that changes similar to the above may be needed in what follows.
::::
</div>
Now build it with `nix-build hello.nix` and you can launch `result/bin/hello`. Nothing easier, but do we have to create a builder.sh for each package? Do we always have to pass the dependencies to the `derivation` function?
Please note the `--prefix=$out` we were talking about in the [previous pill](#working-derivation).
Please note the `--prefix=$out` we were talking about in the [previous pill](07-working-derivation.md).
## A generic builder
@ -192,7 +190,7 @@ Create `autotools.nix`:
in
derivation (defaultAttrs // attrs)
Ok now we have to remember a little about [Nix functions](#functions-and-imports). The whole nix expression of this `autotools.nix` file will evaluate to a function. This function accepts a parameter `pkgs`, then returns a function which accepts a parameter `attrs`.
Ok now we have to remember a little about [Nix functions](05-functions-and-imports.md). The whole nix expression of this `autotools.nix` file will evaluate to a function. This function accepts a parameter `pkgs`, then returns a function which accepts a parameter `attrs`.
The body of the function is simple, yet at first sight it might be hard to grasp:
@ -244,7 +242,7 @@ Out of this pill we managed to create a generic builder for autotools projects,
We are familiarizing ourselves with the way a Nix system grows up: it\'s about creating and composing derivations with the Nix language.
[Analogy]{.underline}: in C you create objects in the heap, and then you compose them inside new objects. Pointers are used to refer to other objects.
Analogy: in C you create objects in the heap, and then you compose them inside new objects. Pointers are used to refer to other objects.
In Nix you create derivations stored in the nix store, and then you compose them by creating new derivations. Store paths are used to refer to other derivations.

View file

@ -1,6 +1,6 @@
# Automatic Runtime Dependencies
Welcome to the 9th Nix pill. In the previous [8th pill](#generic-builders) we wrote a generic builder for autotools projects. We fed in build dependencies and a source tarball, and we received a Nix derivation as a result.
Welcome to the 9th Nix pill. In the previous [8th pill](08-generic-builders.md) we wrote a generic builder for autotools projects. We fed in build dependencies and a source tarball, and we received a Nix derivation as a result.
Today we stop by the GNU `hello` program to analyze build and runtime dependencies, and we enhance our builder to eliminate unnecessary runtime dependencies.
@ -106,7 +106,7 @@ Now, we rebuild `hello.nix`\...
and we see that `glibc` is a runtime dependency. This is exactly what we wanted.
The package is self-contained. This means that we can copy its closure onto another machine and we will be able to run it. Remember, only a very few components under the `/nix/store` are required to [run nix](#install-on-your-running-system). The `hello` binary will use the exact version of `glibc` library and interpreter referred to in the binary, rather than the system one:
The package is self-contained. This means that we can copy its closure onto another machine and we will be able to run it. Remember, only a very few components under the `/nix/store` are required to [run nix](02-install-on-your-running.md). The `hello` binary will use the exact version of `glibc` library and interpreter referred to in the binary, rather than the system one:
$ ldd result/bin/hello
linux-vdso.so.1 (0x00007fff11294000)

View file

@ -1,6 +1,6 @@
# Developing with `nix-shell`
Welcome to the 10th Nix pill. In the previous [9th pill](#automatic-runtime-dependencies) we saw one of the powerful features of Nix: automatic discovery of runtime dependencies. We also finalized the GNU `hello` package.
Welcome to the 10th Nix pill. In the previous [9th pill](09-automatic-runtime.md) we saw one of the powerful features of Nix: automatic discovery of runtime dependencies. We also finalized the GNU `hello` package.
In this pill, we will introduce the `nix-shell` tool and use it to hack on the GNU `hello` program. We will see how `nix-shell` gives us an isolated environment while we modify the source files of the project, similar to how `nix-build` gave us an isolated environment while building the derivation.

View file

@ -1,6 +1,6 @@
# The Garbage Collector {#garbage-collector}
Welcome to the 11th Nix pill. In the previous [10th pill](#developing-with-nix-shell), we drew a parallel between the isolated build environment provided by `nix-build` and the isolated development shell provided by `nix-shell`. Using `nix-shell` allowed us to debug, modify, and manually build software using an environment that is almost identical to the one provided by `nix-build`.
Welcome to the 11th Nix pill. In the previous [10th pill](10-developing-with-nix-shell.md), we drew a parallel between the isolated build environment provided by `nix-build` and the isolated development shell provided by `nix-shell`. Using `nix-shell` allowed us to debug, modify, and manually build software using an environment that is almost identical to the one provided by `nix-build`.
Today, we will stop focusing on packaging and instead look at a critical component of Nix: the garbage collector. When we use Nix tools, we are often building derivations. This includes `.drv` files as well as out paths. These artifacts go in the Nix store and take up space in our storage. Eventually we may wish to free up some space by removing derivations we no longer need. This is the focus of the 11th pill. By default, Nix takes a relatively conservative approach when automatically deciding which derivations are \"needed\". In this pill, we will also see a technique to conduct more destructive upgrade and deletion operations.
@ -63,7 +63,7 @@ Removing a GC root is simple. In our case, we delete the generation that refers
$ ls /nix/store/b3lxx3d3ggxcggvjw5n0m1ya1gcrmbyn-bsd-games-2.17
ls: cannot access /nix/store/b3lxx3d3ggxcggvjw5n0m1ya1gcrmbyn-bsd-games-2.17: No such file or directory
[Note]{.underline}: `nix-env --list-generations` does not rely on any particular metadata. It is able to list generations based solely on the file names under the profiles directory.
Note: `nix-env --list-generations` does not rely on any particular metadata. It is able to list generations based solely on the file names under the profiles directory.
Note that we removed the link from `/nix/var/nix/profiles`, not from `/nix/var/nix/gcroots`. In addition to the latter, Nix treats `/nix/var/nix/profiles` as a GC root. This is useful because it means that any profile and its generations are GC roots. Other paths are considered GC roots as well; for example, `/run/booted-system` on NixOS. The command `nix-store --gc --print-roots` prints all paths considered as GC roots when running the garbage collector.

View file

@ -1,6 +1,6 @@
# Package Repositories and the Inputs Design Pattern {#inputs-design-pattern}
Welcome to the 12th Nix pill. In the previous [11th pill](#garbage-collector), we stopped packaging and cleaned up the system with the garbage collector.
Welcome to the 12th Nix pill. In the previous [11th pill](11-garbage-collector.md), we stopped packaging and cleaned up the system with the garbage collector.
This time, we will resume packaging and improve different aspects of it. We will also demonstrate how to create a repository of multiple packages.

View file

@ -1,6 +1,6 @@
# Callpackage Design Pattern
Welcome to the 13th Nix pill. In the previous [12th pill](#inputs-design-pattern), we introduced the first basic design pattern for organizing a repository of software. In addition, we packaged graphviz so that we had two packages to bundle into an example repository.
Welcome to the 13th Nix pill. In the previous [12th pill](12-inputs-design-pattern.md), we introduced the first basic design pattern for organizing a repository of software. In addition, we packaged graphviz so that we had two packages to bundle into an example repository.
The next design pattern we will examine is called the `callPackage` pattern. This technique is extensively used in [nixpkgs](https://github.com/NixOS/nixpkgs), and it\'s the current de facto standard for importing packages in a repository. Its purpose is to reduce the duplication of identifiers between package derivation inputs and repository derivations.
@ -91,7 +91,7 @@ Let\'s dissect the above snippet:
In the snippet above, we\'ve also demonstrated that the `callPackage` call is equivalent to directly calling `add a b`.
We achieved most of what we wanted: to automatically call functions given a set of possible arguments. If an argument is not found within the set we used to call the function, then we receive an error (unless the function has variadic arguments denoted with `...`, as explained in the [5th pill](#functions-and-imports)).
We achieved most of what we wanted: to automatically call functions given a set of possible arguments. If an argument is not found within the set we used to call the function, then we receive an error (unless the function has variadic arguments denoted with `...`, as explained in the [5th pill](05-functions-and-imports.md)).
The last missing piece is allowing users to override some of the parameters. We may not want to always call functions with values taken from the big set. Thus, we add a third parameter which takes a set of overrides:

View file

@ -1,6 +1,6 @@
# Override Design Pattern
Welcome to the 14th Nix pill. In the previous [13th](#callpackage-design-pattern) pill, we introduced the `callPackage` pattern and used it to simplify the composition of software in a repository.
Welcome to the 14th Nix pill. In the previous [13th](13-callpackage-design-pattern.md) pill, we introduced the `callPackage` pattern and used it to simplify the composition of software in a repository.
The next design pattern is less necessary, but is useful in many cases and is a good exercise to learn more about Nix.
@ -20,7 +20,7 @@ Designing such utilities is not trivial in a functional language without static
## The override pattern
In [pill 12](#inputs-design-pattern) we introduced the inputs design pattern. We do not return a derivation picking dependencies directly from the repository; rather we declare the inputs and let the callers pass the necessary arguments.
In [pill 12](12-inputs-design-pattern.md) we introduced the inputs design pattern. We do not return a derivation picking dependencies directly from the repository; rather we declare the inputs and let the callers pass the necessary arguments.
In our repository we have a set of attributes that import the expressions of the packages and pass these arguments, getting back a derivation. Let\'s take for example the graphviz attribute:
@ -52,7 +52,7 @@ We would like to avoid specifying the nix expression again. Instead, we would li
The difference is obvious, as well as the advantages of this approach.
[Note:]{.underline} that `.override` is not a \"method\" in the OO sense as you may think. Nix is a functional language. The`.override` is simply an attribute of a set.
Note: that `.override` is not a \"method\" in the OO sense as you may think. Nix is a functional language. The`.override` is simply an attribute of a set.
## The override implementation

View file

@ -1,6 +1,6 @@
# Nix Search Paths
Welcome to the 15th Nix pill. In the previous [14th](#override-design-pattern) pill we have introduced the \"override\" pattern, useful for writing variants of derivations by passing different inputs.
Welcome to the 15th Nix pill. In the previous [14th](14-override-design-pattern.md) pill we have introduced the \"override\" pattern, useful for writing variants of derivations by passing different inputs.
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.

View file

@ -1,6 +1,6 @@
# Nixpkgs Parameters
Welcome to the 16th Nix pill. In the previous [15th](#nix-search-paths) pill we\'ve realized how nix finds expressions with the angular brackets syntax, so that we finally know where `<nixpkgs>` is located on our system.
Welcome to the 16th Nix pill. In the previous [15th](15-nix-search-paths.md) pill we\'ve realized how nix finds expressions with the angular brackets syntax, so that we finally know where `<nixpkgs>` is located on our system.
We can start diving into the [nixpkgs repository](https://github.com/NixOS/nixpkgs), through all the various tools and design patterns. Please note that also `nixpkgs` has its own manual, underlying the difference between the general `nix` language and the `nixpkgs` repository.

View file

@ -1,12 +1,12 @@
# Nixpkgs Overriding Packages
Welcome to the 17th Nix pill. In the previous [16th](#nixpkgs-parameters) pill we have started to dive into the [nixpkgs repository](http://github.com/NixOS/nixpkgs). `Nixpkgs` is a function, and we\'ve looked at some parameters like `system` and `config`.
Welcome to the 17th Nix pill. In the previous [16th](16-nixpkgs-parameters.md) pill we have started to dive into the [nixpkgs repository](http://github.com/NixOS/nixpkgs). `Nixpkgs` is a function, and we\'ve looked at some parameters like `system` and `config`.
Today we\'ll talk about a special attribute: `config.packageOverrides`. Overriding packages in a set with fixed point can be considered another design pattern in nixpkgs.
## Overriding a package
Recall the override design pattern from the [nix pill 14](#override-design-pattern). Instead of calling a function with parameters directly, we make the call (function + parameters) overridable.
Recall the override design pattern from the [nix pill 14](14-override-design-pattern.md). Instead of calling a function with parameters directly, we make the call (function + parameters) overridable.
We put the override function in the returned attribute set of the original function call.

View file

@ -1,6 +1,6 @@
# Nix Store Paths
Welcome to the 18th Nix pill. In the previous [17th](#nixpkgs-overriding-packages) pill we have scratched the surface of the `nixpkgs` repository structure. It is a set of packages, and it\'s possible to override such packages so that all other packages will use the overrides.
Welcome to the 18th Nix pill. In the previous [17th](17-nixpkgs-overriding-packages.md) pill we have scratched the surface of the `nixpkgs` repository structure. It is a set of packages, and it\'s possible to override such packages so that all other packages will use the overrides.
Before reading existing derivations, I\'d like to talk about store paths and how they are computed. In particular we are interested in fixed store paths that depend on an integrity hash (e.g. a sha256), which is usually applied to source tarballs.

View file

@ -1,6 +1,6 @@
# Fundamentals of Stdenv
Welcome to the 19th Nix pill. In the previous [18th](#nix-store-paths) pill we dived into the algorithm used by Nix to compute the store paths, and also introduced fixed-output store paths.
Welcome to the 19th Nix pill. In the previous [18th](18-nix-store-paths.md) pill we dived into the algorithm used by Nix to compute the store paths, and also introduced fixed-output store paths.
This time we will instead look into `nixpkgs`, in particular one of its core derivations: `stdenv`.
@ -39,7 +39,7 @@ How can it be? The package must be referring to those other packages somehow. In
## The setup file
Remember our generic `builder.sh` in [Pill 8](#generic-builders)? It sets up a basic `PATH`, unpacks the source and runs the usual autotools commands for us.
Remember our generic `builder.sh` in [Pill 8](08-generic-builders.md)? It sets up a basic `PATH`, unpacks the source and runs the usual autotools commands for us.
The [stdenv setup file](https://github.com/NixOS/nixpkgs/blob/master/pkgs/stdenv/generic/setup.sh) is exactly that. It sets up several environment variables like `PATH` and creates some helper bash functions to build a package. I invite you to read it.
@ -81,7 +81,7 @@ Let\'s write a `hello.nix` expression using this newly discovered `stdenv`:
src = ./hello-2.10.tar.gz;
}
Don\'t be scared by the `with` expression. It pulls the `nixpkgs` repository into scope, so we can directly use `stdenv`. It looks very similar to the hello expression in [Pill 8](#generic-builders).
Don\'t be scared by the `with` expression. It pulls the `nixpkgs` repository into scope, so we can directly use `stdenv`. It looks very similar to the hello expression in [Pill 8](08-generic-builders.md).
It builds, and runs fine:
@ -114,7 +114,7 @@ You can open [default-builder.sh](https://github.com/NixOS/nixpkgs/blob/master/p
source $stdenv/setup
genericBuild
It\'s what we did in [Pill 10](#developing-with-nix-shell) to make the derivations `nix-shell` friendly. When entering the shell, the setup file only sets up the environment without building anything. When doing `nix-build`, it actually runs the build process.
It\'s what we did in [Pill 10](10-developing-with-nix-shell.md) to make the derivations `nix-shell` friendly. When entering the shell, the setup file only sets up the environment without building anything. When doing `nix-build`, it actually runs the build process.
To get a clear understanding of the environment variables, look at the .drv of the hello derivation:

View file

@ -1,16 +1,18 @@
# Basic Dependencies and Hooks
Welcome to the 20th Nix pill. In the previous [19th](#fundamentals-of-stdenv) pill we introduced Nixpkgs\' stdenv, including `setup.sh` script, `default-builder.sh` helper script, and `stdenv.mkDerivation` builder. We focused on how stdenv is put together, and how it\'s used, and a bit about the phases of `genericBuild`.
Welcome to the 20th Nix pill. In the previous [19th](19-fundamentals-of-stdenv.md) pill we introduced Nixpkgs\' stdenv, including `setup.sh` script, `default-builder.sh` helper script, and `stdenv.mkDerivation` builder. We focused on how stdenv is put together, and how it\'s used, and a bit about the phases of `genericBuild`.
This time, we\'ll focus on the interaction of packages built with `stdenv.mkDerivation`. Packages need to depend on each other, of course. For this we have `buildInputs` and `propagatedBuildInputs` attributes. We\'ve also found that dependencies sometimes need to influence their dependents in ways the dependents can\'t or shouldn\'t predict. For this we have setup hooks and env hooks. Together, these 4 concepts support almost all build-time package interactions.
::: note
The complexity of the dependencies and hooks infrastructure has increased, over time, to support cross compilation. Once you learn the core concepts, you will be able to understand the extra complexity. As a starting point, you might want to refer to nixpkgs commit [6675f0a5](https://github.com/nixos/nixpkgs/tree/6675f0a52c0962042a1000c7f20e887d0d26ae25), the last version of stdenv without cross-compilation complexity.
:::
<div class="info">
Note: The complexity of the dependencies and hooks infrastructure has increased, over time, to support cross compilation. Once you learn the core concepts, you will be able to understand the extra complexity. As a starting point, you might want to refer to nixpkgs commit [6675f0a5](https://github.com/nixos/nixpkgs/tree/6675f0a52c0962042a1000c7f20e887d0d26ae25), the last version of stdenv without cross-compilation complexity.
</div>
## The `buildInputs` Attribute
For the simplest dependencies where the current package directly needs another, we use the `buildInputs` attribute. This is exactly the pattern used in our builder in [Pill 8](#generic-builders). To demo this, let\'s build GNU Hello, and then another package which provides a shell script that `exec`s it.
For the simplest dependencies where the current package directly needs another, we use the `buildInputs` attribute. This is exactly the pattern used in our builder in [Pill 8](08-generic-builders.html). To demo this, let\'s build GNU Hello, and then another package which provides a shell script that `exec`s it.
let
@ -213,7 +215,7 @@ This is strictly more general than any of the other mechanisms introduced in thi
## Environment Hooks
As a final convenience, we have environment hooks. Recall in [Pill 12](#inputs-design-pattern) how we created `NIX_CFLAGS_COMPILE` for `-I` flags and `NIX_LDFLAGS` for `-L` flags, in a similar manner to how we prepared the `PATH`. One point of ugliness was how anti-modular this was. It makes sense to build the `PATH` in a generic builder, because the `PATH` is used by the shell, and the generic builder is intrinsically tied to the shell. But `-I` and `-L` flags are only relevant to the C compiler. The stdenv isn\'t wedded to including a C compiler (though it does by default), and there are other compilers too which may take completely different flags.
As a final convenience, we have environment hooks. Recall in [Pill 12](12-inputs-design-pattern.md) how we created `NIX_CFLAGS_COMPILE` for `-I` flags and `NIX_LDFLAGS` for `-L` flags, in a similar manner to how we prepared the `PATH`. One point of ugliness was how anti-modular this was. It makes sense to build the `PATH` in a generic builder, because the `PATH` is used by the shell, and the generic builder is intrinsically tied to the shell. But `-I` and `-L` flags are only relevant to the C compiler. The stdenv isn\'t wedded to including a C compiler (though it does by default), and there are other compilers too which may take completely different flags.
As a first step, we can move that logic to a setup hook on the C compiler; indeed that\'s just what we do in CC Wrapper. [^2] But this pattern comes up fairly often, so somebody decided to add some helper support to reduce boilerplate.

View file

@ -22,30 +22,3 @@
- [Nix Store Paths](18-nix-store-paths.md)
- [Fundamentals of Stdenv](19-fundamentals-of-stdenv.md)
- [Basic Dependencies and Hooks](20-basic-dependencies-and-hooks.md)
```xml
<xi:include href="pills/01-why-you-should-give-it-try.xml" />
<xi:include href="pills/02-install-on-your-running.xml" />
<xi:include href="pills/03-enter-environment.xml" />
<xi:include href="pills/04-basics-of-language.xml" />
<xi:include href="pills/05-functions-and-imports.xml" />
<xi:include href="pills/06-our-first-derivation.xml" />
<xi:include href="pills/07-working-derivation.xml" />
<xi:include href="pills/08-generic-builders.xml" />
<xi:include href="pills/09-automatic-runtime.xml" />
<xi:include href="pills/10-developing-with-nix-shell.xml" />
<xi:include href="pills/11-garbage-collector.xml" />
<xi:include href="pills/12-inputs-design-pattern.xml" />
<xi:include href="pills/13-callpackage-design-pattern.xml" />
<xi:include href="pills/14-override-design-pattern.xml" />
<xi:include href="pills/15-nix-search-paths.xml" />
<xi:include href="pills/16-nixpkgs-parameters.xml" />
<xi:include href="pills/17-nixpkgs-overriding-packages.xml" />
<xi:include href="pills/18-nix-store-paths.xml" />
<xi:include href="pills/19-fundamentals-of-stdenv.xml" />
<xi:include href="pills/20-basic-dependencies-and-hooks.xml" />
```

268
style.css
View file

@ -1,268 +0,0 @@
/* Copied from http://bakefile.sourceforge.net/, which appears
licensed under the GNU GPL. */
/***************************************************************************
Basic headers and text:
***************************************************************************/
body
{
font-family: "Nimbus Sans L", sans-serif;
background: white;
margin: 2em 1em 2em 1em;
}
h1, h2, h3, h4
{
color: #005aa0;
}
h1 /* title */
{
font-size: 200%;
}
h2 /* chapters, appendices, subtitle */
{
font-size: 180%;
}
/* Extra space between chapters, appendices. */
div.chapter > div.titlepage h2, div.appendix > div.titlepage h2
{
margin-top: 1.5em;
}
div.section > div.titlepage h2 /* sections */
{
font-size: 150%;
margin-top: 1.5em;
}
h3 /* subsections */
{
font-size: 125%;
}
div.simplesect h2
{
font-size: 110%;
}
div.appendix h3
{
font-size: 150%;
margin-top: 1.5em;
}
div.refnamediv h2, div.refsynopsisdiv h2, div.refsection h2 /* refentry parts */
{
margin-top: 1.4em;
font-size: 125%;
}
div.refsection h3
{
font-size: 110%;
}
/***************************************************************************
Examples:
***************************************************************************/
div.example
{
border: 1px solid #b0b0b0;
padding: 6px 6px;
margin-left: 1.5em;
margin-right: 1.5em;
background: #f4f4f8;
border-radius: 0.4em;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
div.example p.title
{
margin-top: 0em;
}
div.example pre
{
box-shadow: none;
}
/***************************************************************************
Screen dumps:
***************************************************************************/
pre.screen, pre.programlisting
{
border: 1px solid #b0b0b0;
padding: 3px 3px;
margin-left: 1.5em;
margin-right: 1.5em;
color: #600000;
background: #f4f4f8;
font-family: monospace;
border-radius: 0.4em;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
div.example pre.programlisting
{
border: 0px;
padding: 0 0;
margin: 0 0 0 0;
}
/***************************************************************************
Notes, warnings etc:
***************************************************************************/
.note, .warning
{
border: 1px solid #b0b0b0;
padding: 3px 3px;
margin-left: 1.5em;
margin-right: 1.5em;
margin-bottom: 1em;
padding: 0.3em 0.3em 0.3em 0.3em;
background: #fffff5;
border-radius: 0.4em;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
div.note, div.warning
{
font-style: italic;
}
div.note h3, div.warning h3
{
color: red;
font-size: 100%;
padding-right: 0.5em;
display: inline;
}
div.note p, div.warning p
{
margin-bottom: 0em;
}
div.note h3 + p, div.warning h3 + p
{
display: inline;
}
div.note h3
{
color: blue;
font-size: 100%;
}
div.navfooter *
{
font-size: 90%;
}
/***************************************************************************
Links colors and highlighting:
***************************************************************************/
a { text-decoration: none; }
a:hover { text-decoration: underline; }
a:link { color: #0048b3; }
a:visited { color: #002a6a; }
/***************************************************************************
Table of contents:
***************************************************************************/
div.toc
{
font-size: 90%;
}
div.toc dl
{
margin-top: 0em;
margin-bottom: 0em;
}
/***************************************************************************
Special elements:
***************************************************************************/
tt, code
{
color: #400000;
}
.term
{
font-weight: bold;
}
div.variablelist dd p, div.glosslist dd p
{
margin-top: 0em;
}
div.variablelist dd, div.glosslist dd
{
margin-left: 1.5em;
}
div.glosslist dt
{
font-style: italic;
}
.varname
{
color: #400000;
}
span.command strong
{
font-weight: normal;
color: #400000;
}
div.calloutlist table
{
box-shadow: none;
}
table
{
border-collapse: collapse;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
table.simplelist
{
text-align: left;
color: #005aa0;
border: 0;
padding: 5px;
background: #fffff5;
font-weight: normal;
font-style: italic;
box-shadow: none;
margin-bottom: 1em;
}
div.navheader table, div.navfooter table {
box-shadow: none;
}