From 25f17b5f5b20e869ac666e7079885ed3952878b8 Mon Sep 17 00:00:00 2001 From: Fernando Ayats Date: Tue, 17 Sep 2024 16:10:16 +0200 Subject: [PATCH] tuto 2 content --- src/components/NixTuto.astro | 16 +++ .../blog/nix-tuto-1/{index.md => index.mdx} | 13 ++- .../blog/nix-tuto-2/{index.md => index.mdx} | 101 ++++++++++++++++-- src/content/blog/nix-tuto-2/pkg-config.nix | 23 ++++ .../blog/nix-tuto-3/{index.md => index.mdx} | 4 +- .../blog/nix-tuto-4/{index.md => index.mdx} | 2 +- 6 files changed, 142 insertions(+), 17 deletions(-) create mode 100644 src/components/NixTuto.astro rename src/content/blog/nix-tuto-1/{index.md => index.mdx} (99%) rename src/content/blog/nix-tuto-2/{index.md => index.mdx} (72%) create mode 100644 src/content/blog/nix-tuto-2/pkg-config.nix rename src/content/blog/nix-tuto-3/{index.md => index.mdx} (55%) rename src/content/blog/nix-tuto-4/{index.md => index.mdx} (93%) diff --git a/src/components/NixTuto.astro b/src/components/NixTuto.astro new file mode 100644 index 0000000..1f581d5 --- /dev/null +++ b/src/components/NixTuto.astro @@ -0,0 +1,16 @@ +--- +--- + diff --git a/src/content/blog/nix-tuto-1/index.md b/src/content/blog/nix-tuto-1/index.mdx similarity index 99% rename from src/content/blog/nix-tuto-1/index.md rename to src/content/blog/nix-tuto-1/index.mdx index ea3e9af..3853042 100644 --- a/src/content/blog/nix-tuto-1/index.md +++ b/src/content/blog/nix-tuto-1/index.mdx @@ -11,10 +11,9 @@ slug: nix-tuto-1 This is part 1 of a tutorial series that covers all of Nix. You can find the rest here: -- Part 1: Language basics -- Part 2: Derivations -- Part 3: Module system -- Part 4: Integration +import NixTuto from "../../../components/NixTuto.astro"; + + In this part of the tutorial I want to set the base upon we will build the rest of our knowledge of Nix. We will cover the syntax of the language itself, the @@ -736,7 +735,7 @@ about this. Or you might want to read ahead because of curiosity. ### Merging attribute sets I decided to skip the merging operator `//` when talking about attrsets. It -takes two attrsets, and inserts the keys from the right-hand side into the +takes two attrsets, and inserts the keys from the right-hand side into the left-hand side. Notice that this definition is very specific to what it does: **it does not try to merge any child attrsets**. Looking at an example: @@ -788,8 +787,8 @@ that are best (or only) implemented with recursion. The nixpkgs' lib also offers `lib.fix`, which has a simple definition: ```nix -fix = - f: +fix = + f: let x = f x; in diff --git a/src/content/blog/nix-tuto-2/index.md b/src/content/blog/nix-tuto-2/index.mdx similarity index 72% rename from src/content/blog/nix-tuto-2/index.md rename to src/content/blog/nix-tuto-2/index.mdx index 5e9e3d1..7611c31 100644 --- a/src/content/blog/nix-tuto-2/index.md +++ b/src/content/blog/nix-tuto-2/index.mdx @@ -2,13 +2,19 @@ title: "The Nix lectures, part 2: Derivations" pubDate: 2024-09-16T07:07:01Z draft: true -summary: FIXME +summary: | + From builtins.derivation to stdenv.mkDerivation, and the language-specific + builders. All you need to know to start packaging software with Nix. slug: nix-tuto-2 --- This is part 2 of a tutorial series that covers all of Nix. We covered language basics in the first part, and in this post we will cover derivations. +import NixTuto from "../../../components/NixTuto.astro"; + + + ## builtins.derivation This is the primitive that Nix uses to define derivations. You will probably @@ -22,7 +28,7 @@ of `builtins.derivation`. > useful when you want to use a current Nix binary to evaluate some nixpkgs from > *many* years ago. -`builtins.derivation` is a function that takes an attrset with some +`builtins.derivation` is a function that takes an attrset with some **known keys**, and the rest are set as environment variables. You can check the reference documentation in the [nix manual](https://nix.dev/manual/nix/stable/language/derivations). A simple invocation might look like this: @@ -93,7 +99,7 @@ build system, Nix also implements a *sandbox* that is used during builds. This sandbox only allows access to: - `/bin/sh` -- to be able to bootstrap everything. -- `/nix/store` -- deliberate use of other programs in the store +- `/nix/store` -- deliberate use of other programs in the store is not concerning because of the cryptographic hashes. - "Private" versions of `/proc`, `/dev`, etc. - Private PID, mount, etc. namespaces. @@ -128,6 +134,36 @@ built-in to the language itself, with the `outputHash*` options: # got: sha256-3FWguG761jOvjXDVGi2BkN+hLCUurMCBzeF4m0AEr4A= ``` +### Building derivations + +Nix is an expression-based language, and every nix file must return a single +value. If it returns a derivation, instead of `nix eval`, you use `nix build` to +tell the nix-daemon to build the derivation for you. + +`nix build` takes an "installable", which can follow the different types: + +- `-f [filename.nix] [attribute]` +- `[flake.nix]#[flake output]` +- `--expr "literal nix expression"` + +When using `-f`, instead of returning a derivation, you can return an attrset of +derivations, which you select with the name: + +```nix +# filename.nix +{ + foo = builtins.derivation { ... }; + bar = builtins.derivation { ... }; +} + +# $ nix build -f ./filename.nix foo +``` + +Some of the flags you should know about are: + +- `-L` or `--print-build-logs` -- to make Nix print the build logs. +- `--keep-failed` -- put the working directory somewhere after failing a build. + ## stdenv @@ -225,21 +261,72 @@ in pkgs.stdenv.mkDerivation { # ... patches = [ - ./my.patch + ./my.patch ]; - postPatch = '' + postPatch = '' # this runs after the standard patchPhase, which applies `patches` ''; - buildPhase = '' + buildPhase = '' # completely change the build phase ''; - postBuild = '' + postBuild = '' # this won't run # if you want, you can add `runHook preBuild` and `runHook postBuild` # to your custom buildPhase ''; } ``` + +Many phases also have some configuration. For example, you can control +`unpackPhase` by setting the env variable `dontUnpack`. Refer to the manual for +specifics of each phase. + +The default behavior of the stdenv for `buildPhase` and `installPhase` is `make` + +`make install`. If you have a simple C program, then you don't need anything +else. But you probably don't, so let's keep dissecting stdenv. + + +### Dependencies + +The different types of dependencies can be a complex topic. It gets messy when +handling cross-compilation, because you must not mix the different architecures +(e.g. using an x86_64 GCC to build an ARM64 binary). + +In Nix, you will use 2 kind of dependencies: + +- `nativeBuildInputs` -- packages that are needed on the **build** machine. + - For example: GCC, make, pkg-config, etc (*usually* programs). +- `buildInputs` -- packages that are needed on the machine that **runs** the +package. + - For example: libc, QT, zlib, etc (*usually* libraries). + +By default, Nix doesn't check that the dependencies do respect this difference, +unless you use `strictDeps = true;` + +### Hooks + +One of the difference of `nativeBuildInputs`, is that they may contain some bash +code that is sourced by the bash builder. The hook will only be executed if the +package is in `nativeBuildInputs`. + +Hooks augment the capabilities of `mkDerivation`, depending on the package. +Usually, they are executed for the program to be able to function properly. This +is best shown by using the example of the hook of `pkg-config`. + +`pkg-config` is a program that allows use to find the path to libraries. This is +essential in Nix, because there is no global library path. However, how do we +transmit to `pkg-config`, that the packages in `buildInputs` are available? The +hook is what "glues" everything together. For `pkg-config`, its hook will export +`PKG_CONFIG_PATH`, which is used by the CLI: + +```nix file: "pkg-config.nix" + +# $ nix build -f ./pkg-config.nix -L +# with-pkg-config> PKG_CONFIG_PATH:/nix/store/0w4q8asq9sn56dl0sxp1m8gk4vy2ygs8-zlib-1.3.1-dev/lib/pkgconfig +# with-pkg-config> zlib zlib - zlib compression library +``` + +### Compiler wrappers diff --git a/src/content/blog/nix-tuto-2/pkg-config.nix b/src/content/blog/nix-tuto-2/pkg-config.nix new file mode 100644 index 0000000..1cda388 --- /dev/null +++ b/src/content/blog/nix-tuto-2/pkg-config.nix @@ -0,0 +1,23 @@ +# pkg-config.nix +let + pkgs = import {}; +in + pkgs.stdenv.mkDerivation { + name = "with-pkg-config"; + src = null; + dontUnpack = true; + + nativeBuildInputs = [ + pkgs.pkg-config + ]; + + buildInputs = [ + pkgs.zlib + ]; + + buildPhase = '' + echo "PKG_CONFIG_PATH:$PKG_CONFIG_PATH" + pkg-config --list-all + printenv + ''; + } diff --git a/src/content/blog/nix-tuto-3/index.md b/src/content/blog/nix-tuto-3/index.mdx similarity index 55% rename from src/content/blog/nix-tuto-3/index.md rename to src/content/blog/nix-tuto-3/index.mdx index c646969..33456ea 100644 --- a/src/content/blog/nix-tuto-3/index.md +++ b/src/content/blog/nix-tuto-3/index.mdx @@ -1,9 +1,9 @@ --- -title: "The Nix lectures, part 3: Module system" +title: "The Nix lectures, part 3: NixOS and module system" pubDate: 2024-09-16T07:08:21Z draft: true summary: FIXME slug: nix-tuto-3 --- -## hello +## TODO diff --git a/src/content/blog/nix-tuto-4/index.md b/src/content/blog/nix-tuto-4/index.mdx similarity index 93% rename from src/content/blog/nix-tuto-4/index.md rename to src/content/blog/nix-tuto-4/index.mdx index 054989e..feac1b4 100644 --- a/src/content/blog/nix-tuto-4/index.md +++ b/src/content/blog/nix-tuto-4/index.mdx @@ -6,4 +6,4 @@ summary: FIXME slug: nix-tuto-4 --- -## hello +## TODO