diff --git a/book.toml b/book.toml index cf49e33..b0432db 100644 --- a/book.toml +++ b/book.toml @@ -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] diff --git a/custom.css b/custom.css new file mode 100644 index 0000000..9a336ae --- /dev/null +++ b/custom.css @@ -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; +} \ No newline at end of file diff --git a/pills/00-preface.md b/pills/00-preface.md index d08ba24..f1f03c9 100644 --- a/pills/00-preface.md +++ b/pills/00-preface.md @@ -8,6 +8,8 @@ For an up-to-date version, please visit . 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. -::: +
+ +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. + +
diff --git a/pills/02-install-on-your-running.md b/pills/02-install-on-your-running.md index 05d5b4e..bae39db 100644 --- a/pills/02-install-on-your-running.md +++ b/pills/02-install-on-your-running.md @@ -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: . -::: +
+ +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: . + +
## 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 ''`) 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. -::: +
-::: 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. + +
+ +
+ +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. + +
## The first profile diff --git a/pills/03-enter-environment.md b/pills/03-enter-environment.md index da67708..44a90f9 100644 --- a/pills/03-enter-environment.md +++ b/pills/03-enter-environment.md @@ -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! -::: +
+ +Note: `~/.nix-channels` is not a symlink to the nix store! + +
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`. diff --git a/pills/04-basics-of-language.md b/pills/04-basics-of-language.md index fbcfece..46ce04d 100644 --- a/pills/04-basics-of-language.md +++ b/pills/04-basics-of-language.md @@ -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. -::: +
-::: important -Values in Nix are immutable. -::: +Important: In Nix, everything is an expression, there are no statements. This is common in functional languages. + +
+ +
+ +Important: Values in Nix are immutable. + +
## Value types diff --git a/pills/05-functions-and-imports.md b/pills/05-functions-and-imports.md index bdda418..a92e6ed 100644 --- a/pills/05-functions-and-imports.md +++ b/pills/05-functions-and-imports.md @@ -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. diff --git a/pills/06-our-first-derivation.md b/pills/06-our-first-derivation.md index 1316759..a4c281d 100644 --- a/pills/06-our-first-derivation.md +++ b/pills/06-our-first-derivation.md @@ -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. -::: +
+ +Note: If your version of nix doesn't have `nix derivation show`, use `nix show-derivation` instead. + +
\\\$ \\nix derivation show /nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-\myname.drv\\ \{ \"/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\" } } }\\ @@ -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: diff --git a/pills/07-working-derivation.md b/pills/07-working-derivation.md index d6791f4..d73d662 100644 --- a/pills/07-working-derivation.md +++ b/pills/07-working-derivation.md @@ -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: \\\$ \\nix derivation show /nix/store/i76pr1cz0za3i9r6xq518bqqvd2raspw-\foo.drv\\ \{ \"/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\" } } }\\ 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 {}` is calling two functions, not one. Reading it as `(import ) {}` 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 {}` is calling two functions, not one. Reading it as `(import ) {}` makes this clearer. The value returned by the nixpkgs function is a set; more specifically, it\'s a set of derivations. Calling `import {}` into a `let`-expression creates the local variable `pkgs` and brings it into scope. This has an effect similar to the `:l ` 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`). diff --git a/pills/08-generic-builders.md b/pills/08-generic-builders.md index cbe92a3..3e41d74 100644 --- a/pills/08-generic-builders.md +++ b/pills/08-generic-builders.md @@ -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 -::: +
+

Nix on darwin

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. -:::: +
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. diff --git a/pills/09-automatic-runtime.md b/pills/09-automatic-runtime.md index 8cfb98a..f51b6d7 100644 --- a/pills/09-automatic-runtime.md +++ b/pills/09-automatic-runtime.md @@ -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) diff --git a/pills/10-developing-with-nix-shell.md b/pills/10-developing-with-nix-shell.md index d81d0a9..e86660a 100644 --- a/pills/10-developing-with-nix-shell.md +++ b/pills/10-developing-with-nix-shell.md @@ -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. diff --git a/pills/11-garbage-collector.md b/pills/11-garbage-collector.md index f667537..87867d7 100644 --- a/pills/11-garbage-collector.md +++ b/pills/11-garbage-collector.md @@ -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. diff --git a/pills/12-inputs-design-pattern.md b/pills/12-inputs-design-pattern.md index 19b2a3d..0c0880d 100644 --- a/pills/12-inputs-design-pattern.md +++ b/pills/12-inputs-design-pattern.md @@ -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. diff --git a/pills/13-callpackage-design-pattern.md b/pills/13-callpackage-design-pattern.md index 6b556b2..40569c5 100644 --- a/pills/13-callpackage-design-pattern.md +++ b/pills/13-callpackage-design-pattern.md @@ -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: diff --git a/pills/14-override-design-pattern.md b/pills/14-override-design-pattern.md index 6eb41ac..10d9259 100644 --- a/pills/14-override-design-pattern.md +++ b/pills/14-override-design-pattern.md @@ -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 diff --git a/pills/15-nix-search-paths.md b/pills/15-nix-search-paths.md index 0f7cbb7..34d0d1a 100644 --- a/pills/15-nix-search-paths.md +++ b/pills/15-nix-search-paths.md @@ -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. diff --git a/pills/16-nixpkgs-parameters.md b/pills/16-nixpkgs-parameters.md index 47a10f1..01f102a 100644 --- a/pills/16-nixpkgs-parameters.md +++ b/pills/16-nixpkgs-parameters.md @@ -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 `` 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 `` 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. diff --git a/pills/17-nixpkgs-overriding-packages.md b/pills/17-nixpkgs-overriding-packages.md index f3793c2..daf7bee 100644 --- a/pills/17-nixpkgs-overriding-packages.md +++ b/pills/17-nixpkgs-overriding-packages.md @@ -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. diff --git a/pills/18-nix-store-paths.md b/pills/18-nix-store-paths.md index 9e177ca..cb94807 100644 --- a/pills/18-nix-store-paths.md +++ b/pills/18-nix-store-paths.md @@ -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. diff --git a/pills/19-fundamentals-of-stdenv.md b/pills/19-fundamentals-of-stdenv.md index 289e619..7a90bac 100644 --- a/pills/19-fundamentals-of-stdenv.md +++ b/pills/19-fundamentals-of-stdenv.md @@ -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: diff --git a/pills/20-basic-dependencies-and-hooks.md b/pills/20-basic-dependencies-and-hooks.md index 17a28ed..3f347c1 100644 --- a/pills/20-basic-dependencies-and-hooks.md +++ b/pills/20-basic-dependencies-and-hooks.md @@ -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. -::: +
+ +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. + +
## 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. diff --git a/pills/SUMMARY.md b/pills/SUMMARY.md index fb7641d..a3e5ec3 100644 --- a/pills/SUMMARY.md +++ b/pills/SUMMARY.md @@ -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 - - - - - - - - - - - - - - - - - - - - -``` - diff --git a/style.css b/style.css deleted file mode 100644 index e329eb4..0000000 --- a/style.css +++ /dev/null @@ -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; -}