[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Dissecting Guix -- blog post series
From: |
Mekeor Melire |
Subject: |
Re: Dissecting Guix -- blog post series |
Date: |
Sat, 10 Dec 2022 21:25:49 +0000 |
2022-12-08 18:24 paren@disroot.org:
> Some of you may have seen on IRC that I've been writing a post for the Guix
> blog that I hope will form the first part of a series. This series aims to
> dissect the internals of Guix, from bottom to top.
Great, I'm looking forward to read it! Especially, personally, I'm eager for
the rather fundamental concepts of Guix (and Nix).
> Perhaps they could go in the cookbook once the series is done?
Yes, I personally think the content should be published at two places at the
same time: OTOH, it should either be incorporated into either the manual or the
cookbook; and OTOH, it should be published as a blog-post. The blog-post should
also link to the respective section of the manual or cookbook in a preamble.
> * Dissecting Guix, Part 1: Derivations
> * Dissecting Guix, Part 2: The Humble G-Expression
> * Dissecting Guix, Part 3: Packages
> * Dissecting Guix, Part 4: Monads
> * Dissecting Guix, Part 5: Profiles and Search Paths
> * Dissecting Guix, Part 6: Goings-On in the Build Container
> * Dissecting Guix, Part 7: Record Types
> * Dissecting Guix, Part 8: Substitutes and Grafts
> * Dissecting Guix, Part 9: Cross-Compilation
I think it'd also be fine to come up with the titles during the process of
writing as sometimes that process itself is insightful. E.g. I could imagine
parts 2 and 4 to collapse. Maybe, maybe not, you'll see.
> * Dissecting Guix, Part 10: Services
>
> Walks you through the process of creating a service, and thouroughly explains
> system configuration.
How'd this part differ from section "12.18 Defining Services" of the manual?
> * Dissecting Guix, Part 11: Home Services
> * Dissecting Guix, Part 12: Writing a Subcommand
> * Dissecting Guix, Part 13: Lending a Hand
>
> How to edit the Guix source code and submit patches to be reviewed by the
> lovely Guix community!
How'd this part differ from sections 22 and "22.6 Submitting Patches" from the
manual?
Now, as for the actual article. Firstly, I added some comments below. Secondly,
I created a "patch" suggesting some changes.
By the way, the text does not seem to strictly fill columns at a certain line
width. So I did not bother to fill columns in the "patch".
> title: Dissecting Guix, Part 1: Derivations and Derivation
> date: TBC
> author: (
> tags: Dissecting Guix, Functional package management, Programming interfaces,
> Scheme API
> ---
> To a new user, Guix's functional architecture can seem quite alien, and
> possibly offputting. With a combination of extensive `#guix`-querying,
> determined manual-reading, and plenty of source-perusing, they may
> eventually figure out how everything fits together by themselves, but this
> can be frustrating and often takes a fairly long time.
>
> However, once you peel back the layers, the "Nix way" is actually rather
> elegant, if perhaps not as simple as the mutable, imperative style
> implemented by the likes of [`dpkg`](https://wiki.debian.org/dpkg) and,
> [`pacman`](https://wiki.archlinux.org/title/pacman). This series of blog
> posts will cover basic Guix concepts, taking a "ground-up" approach by
> dealing with lower-level concepts first, and hopefully make those months of
> information-gathering unnecessary.
>
> Before we dig in to Guix-specific concepts, we'll need to learn about one
> inherited from [Nix](https://nixos.org), the original functional package
> manager and the inspiration for Guix; the idea of a _derivation_ and its
> corresponding _store items_.
>
> These concepts were originally described by Eelco Dolstra, the author of Nix,
> in their [PhD thesis](https://edolstra.github.io/pubs/phd-thesis.pdf); see
> _§ 2.1 The Nix store_ and _§ 2.4 Store Derivations_.
>
> # Store Items
>
> As you almost certainly know, everything that Guix builds is stored in the
> _store_, which is almost always the `/gnu/store` directory. It's the job of
> the
> [`guix-daemon`](https://guix.gnu.org/manual/en/html_node/Invoking-guix_002ddaemon.html)
> to manage the store and build things. If you run
> [`guix build
> PKG`](https://guix.gnu.org/manual/en/html_node/Invoking-guix-build.html),
> `PKG` will be built or downloaded from a substitute server if available, and
> a path to an item in the store will be displayed.
>
> ```
> $ guix build irssi
> /gnu/store/v5pd69j3hjs1fck4b5p9hd91wc8yf5qx-irssi-1.4.3
> ```
>
> This item contains the final result of building [`irssi`](https://irssi.org).
> Let's peek inside:
>
> ```
> $ ls $(guix build irssi)
> bin/ etc/ include/ lib/ share/
> $ ls $(guix build irssi)/bin
> irssi*
> ```
>
> `irssi` is quite a simple package. What about a more complex one, like
> [`glib`](https://docs.gtk.org/glib)?
>
> ```
> $ guix build glib
> /gnu/store/bx8qq76idlmjrlqf1faslsq6zjc6f426-glib-2.73.3-bin
> /gnu/store/j65bhqwr7qq7l77nj0ahmk1f1ilnjr3a-glib-2.73.3-debug
> /gnu/store/3pn4ll6qakgfvfpc4mw89qrrbsgj3jf3-glib-2.73.3-doc
> /gnu/store/dvsk6x7d26nmwsqhnzws4iirb6dhhr1d-glib-2.73.3
> /gnu/store/4c8ycz501n2d0xdi4blahvnbjhd5hpa8-glib-2.73.3-static
> ```
>
> `glib` produces five `/gnu/store` items, because it's possible for a package
> to produce multiple
> [outputs](https://guix.gnu.org/manual/en/html_node/Packages-with-Multiple-Outputs.html).
> Each output can be referred to separately, by prefixing a package's name with
> `:OUTPUT` where supported. For example, this
> [`guix
> install`](https://guix.gnu.org/manual/en/html_node/Invoking-guix-package.html)
> invocation will add `glib`'s `bin` output to your profile:
>
> ```
> $ guix install glib:bin
> ```
>
> The default output is `out`, so when you pass `glib` by itself to that
> command, it will actually install `glib:out` to the profile.
>
> `guix build` also provides the `--source` flag, which produces the store
> item corresponding to the given package's downloaded source code.
>
> ```
> $ guix build --source irssi
> /gnu/store/cflbi4nbak0v9xbyc43lamzl4a539hhb-irssi-1.4.3.tar.xz
> $ guix build --source glib
> /gnu/store/d22wzjq3xm3q8hwnhbgk2xd3ph7lb6ay-glib-2.73.3.tar.xz
> ```
>
> But how does Guix know how to build these store outputs in the first place?
> That's where derivations come in.
>
> # `.drv` Files
>
> You've probably seen these being printed by the Guix CLI now and again.
> Derivations, represented in the daemon's eyes by `.drv` files, contain
> instructions for building store items. We can retrieve the paths of
> these `.drv` files with the `guix build --derivations` command:
>
> ```
> $ guix build --derivations irssi
> /gnu/store/zcgmhac8r4kdj2s6bcvcmhh4k35qvihx-irssi-1.4.3.drv
> ```
>
> `guix build` can actually also accept derivation paths as an argument, in
> lieu of a package, like so:
>
> ```
> $ guix build /gnu/store/zcgmhac8r4kdj2s6bcvcmhh4k35qvihx-irssi-1.4.3.drv
> /gnu/store/v5pd69j3hjs1fck4b5p9hd91wc8yf5qx-irssi-1.4.3
> ```
>
> Let's look inside this derivation file.
>
> ```
> Derive([("out","/gnu/store/v5pd69j3hjs1fck4b5p9hd91wc8yf5qx-irssi-1.4.3","","")],[("/gnu/store/9mv9xg4kyj4h1cvsgrw7b9x34y8yppph-glib-2.70.2.drv",["out"]),("/gnu/store/baqpbl4wck7nkxrbyc9nlhma7kq5dyfl-guile-2.0.14.drv",["out"]),("/gnu/store/bfirgq65ndhf63nn4q6vlkbha9zd931q-openssl-1.1.1l.drv",["out"]),("/gnu/store/gjwpqzvfhz13shix6a6cs2hjc18pj7wy-module-import-compiled.drv",["out"]),("/gnu/store/ij8651x4yh53hhcn6qw2644nhh2s8kcn-glib-2.70.2.drv",["out"]),("/gnu/store/jg2vv6yc2yqzi3qzs82dxvqmi5k21lhy-irssi-1.4.3.drv",["out"]),("/gnu/store/qggpjl9g6ic3cq09qrwkm0dfsdjf7pyr-glibc-utf8-locales-2.33.drv",["out"]),("/gnu/store/zafabw13yyhz93jwrcz7axak1kn1f2cx-openssl-1.1.1s.drv",["out"])],["/gnu/store/af18nrrsk98c5a71h3fifnxg1zi5mx7y-module-import","/gnu/store/qnrwmby5cwqdqxyiv1ga6azvakmdvgl7-irssi-1.4.3-builder"],"x86_64-linux","/gnu/store/hnr4r2d0h0xarx52i6jq9gvsrlc3q81a-guile-2.0.14/bin/guile",["--no-auto-compile","-L","/gnu/store/af18nrrsk98c5a71h3fifnxg1zi5mx7y-module-import","-C","/gnu/store/6rkkvvb7pl1l9ng8vvywvwf357vhm3va-module-import-compiled","/gnu/store/qnrwmby5cwqdqxyiv1ga6azvakmdvgl7-irssi-1.4.3-builder"],[("allowSubstitutes","0"),("guix
> properties","((type . graft) (graft (count .
> 2)))"),("out","/gnu/store/v5pd69j3hjs1fck4b5p9hd91wc8yf5qx-irssi-1.4.3"),("preferLocalBuild","1")])
> ```
>
> It's... not exactly human-readable. We could try to format it and break
> it down, but it'd still be pretty hard to understand, since `.drv` files
> contain no labels for the "arguments" or any other human-readable indicators.
> Instead, we're going to explore derivations in a Guile REPL.
>
> # Exploring Guix Interactively
>
> Before we continue, we'll want to start a REPL, so that we can try out
> the Guix Guile API interactively. To run a REPL in the terminal, simply
> [call `guix
> repl`](https://guix.gnu.org/manual/devel/en/html_node/Using-Guix-Interactively.html).
>
> If you're using Emacs, you can instead install
> [Geiser](https://nongnu.org/geiser),
> which provides a comfortable Emacs UI for various Lisp REPLs, invoke
> `guix repl --listen=tcp:37146 &`, and type `M-x geiser-connect RET RET RET` to
> connect to the running Guile instance.
This approach did not work nicely for me. In particular, the last command made
Emacs freeze (even with and 'emacs -Q'). And then, when evaluating the first
code block below, i.e. the module-import, I got the warning "Unknown meta
command: geiser-no-values". That's why, in the "patch", I suggest to simply run
'M-x geiser RET' which works just fine.
(I guess this is due to the fact that "Geiser invokes geiser-guile-binary with
certain flags": <https://gitlab.com/emacs-guix/emacs-guix/-/issues/16>.)
> There are a few Guix modules we'll need. Run this Scheme code to import
> them:
>
> ```scheme
> (use-modules (guix derivations)
> (guix gexp)
> (guix packages)
> (guix store)
> (gnu packages glib)
> (gnu packages irc))
> ```
>
> We now have access to the store, G-expression, package, and derivation
> APIs, along with the `irssi` and `glib` `<package>` objects.
>
> # Creating a `<derivation>`
>
> The Guix API for derivations revolves around the `<derivation>` record,
> which is the Scheme representation of that whole block of text surrounded by
> `Derive(...)`. If we look in `guix/derivations.scm`, we can see that it's
> defined like this:
>
> ```scheme
> (define-immutable-record-type <derivation>
> (make-derivation outputs inputs sources system builder args env-vars
> file-name)
> derivation?
> (outputs derivation-outputs) ; list of name/<derivation-output> pairs
> (inputs derivation-inputs) ; list of <derivation-input>
> (sources derivation-sources) ; list of store paths
> (system derivation-system) ; string
> (builder derivation-builder) ; store path
> (args derivation-builder-arguments) ; list of strings
> (env-vars derivation-builder-environment-vars) ; list of name/value pairs
> (file-name derivation-file-name)) ; the .drv file name
> ```
>
> With the exception of `file-name`, each of those fields corresponds to
> an "argument" in the `Derive(...)` form. Before we can examine them,
> though, we need to figure out how to _lower_ that `irssi` `<package>`
> object into a derivation.
>
> The procedure we use to turn a high-level object like `<package>` into a
> derivation is called `lower-object`; more on that in a future post.
> However, this doesn't produce a derivation:
>
> ```scheme
> (pk (lower-object irssi))
> ;;; (#<procedure 7fe17c7af540 at guix/store.scm:1994:2 (state)>)
> ```
>
> `pk` is an abbreviation for the procedure `peek`, which takes the given
> object, writes a representation of it to the output, and returns it.
> It's especially handy when you want to view an intermediate value in a
> complex expression.
>
> The returned object is a procedure that needs to be evaluated in the
> context of a store connection. We do this by first using `with-store`
> to connect to the store and bind the connection to a name, then wrapping
> the `lower-object` call with `run-with-store`:
>
> ```scheme
> (define irssi-drv
> (pk (with-store %store
> (run-with-store %store
> (lower-object irssi)))))
> ;;; (#<derivation /gnu/store/zcgmhac8r4kdj2s6bcvcmhh4k35qvihx-irssi-1.4.3.drv
> => /gnu/store/v5pd69j3hjs1fck4b5p9hd91wc8yf5qx-irssi-1.4.3 7fe1902b6140>)
>
> (define glib-drv
> (pk (with-store %store
> (run-with-store %store
> (lower-object glib)))))
> ;;; (#<derivation /gnu/store/81qqs7xah2ln39znrji4r6xj85zi15bi-glib-2.70.2.drv
> => /gnu/store/lp7k9ygvpwxgxjvmf8bix8d2aar0azr7-glib-2.70.2-bin
> /gnu/store/22mkp8cr6rxg6w8br9q8dbymf51b44m8-glib-2.70.2-debug
> /gnu/store/a6qb5arvir4vm1zlkp4chnl7d8qzzd7x-glib-2.70.2
> /gnu/store/y4ak268dcdwkc6lmqfk9g1dgk2jr9i34-glib-2.70.2-static 7fe17ca13b90>)
> ```
>
> And we have liftoff! Now we've got two `<derivation>` records to play
> with.
>
> # Exploring `<derivation>`
I suggest to use subheadings within this chapter because otherwise readers
loose the overview.
> The first "argument" in the `.drv` file is `outputs`, which tells the
> Guix daemon about the outputs that this build can produce:
>
> ```scheme
> (define irssi-outputs
> (pk (derivation-outputs irssi-drv)))
> ;;; ((("out" . #<<derivation-output> path:
> "/gnu/store/v5pd69j3hjs1fck4b5p9hd91wc8yf5qx-irssi-1.4.3" hash-algo: #f hash:
> #f recursive?: #f>)))
>
> (pk (assoc-ref irssi-outputs "out"))
>
> (define glib-outputs
> (pk (derivation-outputs glib-drv)))
> ;;; ((("bin" . #<<derivation-output> path:
> "/gnu/store/lp7k9ygvpwxgxjvmf8bix8d2aar0azr7-glib-2.70.2-bin" hash-algo: #f
> hash: #f recursive?: #f>) ("debug" . #<<derivation-output> path:
> "/gnu/store/22mkp8cr6rxg6w8br9q8dbymf51b44m8-glib-2.70.2-debug" hash-algo: #f
> hash: #f recursive?: #f>) ("out" . #<<derivation-output> path:
> "/gnu/store/a6qb5arvir4vm1zlkp4chnl7d8qzzd7x-glib-2.70.2" hash-algo: #f hash:
> #f recursive?: #f>) ("static" . #<<derivation-output> path:
> "/gnu/store/y4ak268dcdwkc6lmqfk9g1dgk2jr9i34-glib-2.70.2-static" hash-algo:
> #f hash: #f recursive?: #f>)))
>
> (pk (assoc-ref glib-outputs "bin"))
> ;;; (#<<derivation-output> path:
> "/gnu/store/lp7k9ygvpwxgxjvmf8bix8d2aar0azr7-glib-2.70.2-bin" hash-algo: #f
> hash: #f recursive?: #f>)
> ```
>
> It's a simple association list mapping output names to `<derivation-output>`
> records, and it's equivalent to the first "argument" in the `.drv` file:
>
> ```
> [ ("out", "/gnu/store/v5pd69j3hjs1fck4b5p9hd91wc8yf5qx-irssi-1.4.3", "", "")
> ]
> ```
>
> The `hash-algo` and `hash` fields are for storing the content hash and the
> algorithm used with that hash for what we term a _fixed-output derivation_,
> which is essentially a derivation where we know what the hash of the content
> will be in advance. For instance, `origin`s produce fixed-output derivations:
>
> ```scheme
> (define irssi-src-drv
> (pk (with-store %store
> (run-with-store %store
> (lower-object (package-source irssi))))))
> ;;; (#<derivation
> /gnu/store/mcz3vzq7lwwaqjb8dy7cd69lvmi6d241-irssi-1.4.3.tar.xz.drv =>
> /gnu/store/cflbi4nbak0v9xbyc43lamzl4a539hhb-irssi-1.4.3.tar.xz 7fe17b3c8d70>)
>
> (define irssi-src-outputs
> (pk (derivation-outputs irssi-src-drv)))
> ;;; ((("out" . #<<derivation-output> path:
> "/gnu/store/cflbi4nbak0v9xbyc43lamzl4a539hhb-irssi-1.4.3.tar.xz" hash-algo:
> sha256 hash: #vu8(185 63 113 82 35 163 34 230 127 66 182 26 8 165 18 174 41
> 227 75 212 165 61 127 34 55 102 102 10 170 90 4 52) recursive?: #f>)))
>
> (pk (assoc-ref irssi-src-outputs "out"))
> ;;; (#<<derivation-output> path:
> "/gnu/store/cflbi4nbak0v9xbyc43lamzl4a539hhb-irssi-1.4.3.tar.xz" hash-algo:
> sha256 hash: #vu8(185 63 113 82 35 163 34 230 127 66 182 26 8 165 18 174 41
> 227 75 212 165 61 127 34 55 102 102 10 170 90 4 52) recursive?: #f>)
> ```
>
> Note how the `hash` and `hash-algo` now have values.
>
> Perceptive readers may note that the `<derivation-output>` has four fields,
> whereas the tuple in the `.drv` file only has three (minus the label). If
> we read the source for `write-derivation`, we can see that the `recursive?`
> field is serialised by prefixing the `hash-algo` with `r:` if it's true:
>
> ```scheme
> ;;; guix/derivations.scm:630:2
>
> (define (write-output output port)
> (match output
> ((name . ($ <derivation-output> path hash-algo hash recursive?))
> (write-tuple (list name path
> (if hash-algo
> (string-append (if recursive? "r:" "")
> (symbol->string hash-algo))
> "")
> (or (and=> hash bytevector->base16-string)
> ""))
> write-escaped-string
> port))))
> ```
>
> The purpose of `recursive?` is difficult to explain, and is out of scope for
> this post.
If the purpose is out of scope, then we should not dive in that deeply.
Especially, I'd suggest skip the code snippet.
> The next field is `inputs`, which corresponds to, you guessed it, the
> second pseudo-"argument" in the `.drv` file format:
>
> ```
> [ ("/gnu/store/9mv9xg4kyj4h1cvsgrw7b9x34y8yppph-glib-2.70.2.drv", ["out"]),
> ("/gnu/store/baqpbl4wck7nkxrbyc9nlhma7kq5dyfl-guile-2.0.14.drv", ["out"]),
> ("/gnu/store/bfirgq65ndhf63nn4q6vlkbha9zd931q-openssl-1.1.1l.drv", ["out"]),
> ("/gnu/store/gjwpqzvfhz13shix6a6cs2hjc18pj7wy-module-import-compiled.drv",
> ["out"]),
> ("/gnu/store/ij8651x4yh53hhcn6qw2644nhh2s8kcn-glib-2.70.2.drv", ["out"]),
> ("/gnu/store/jg2vv6yc2yqzi3qzs82dxvqmi5k21lhy-irssi-1.4.3.drv", ["out"]),
> ("/gnu/store/qggpjl9g6ic3cq09qrwkm0dfsdjf7pyr-glibc-utf8-locales-2.33.drv",
> ["out"]),
> ("/gnu/store/zafabw13yyhz93jwrcz7axak1kn1f2cx-openssl-1.1.1s.drv", ["out"])
> ]
> ```
>
> Here, each tuple specifies a derivation that needs to be built before this
> derivation can be built, and the outputs of the derivation that the build
> process of this derivation uses. Let's grab us the Scheme equivalent:
>
> ```scheme
> (define irssi-inputs
> (pk (derivation-inputs irssi-drv)))
> ;;; [a fairly large amount of output]
>
> (pk (car irssi-inputs))
> ;;; (#<<derivation-input> drv: #<derivation
> /gnu/store/9mv9xg4kyj4h1cvsgrw7b9x34y8yppph-glib-2.70.2.drv =>
> /gnu/store/2jj2mxn6wfrcw7i85nywk71mmqbnhzps-glib-2.70.2 7fe1902b6640>
> sub-derivations: ("out")>)
> ```
>
> Unlike `derivation-outputs`, `derivation-inputs` maps 1:1 to the `.drv`
> form; the `drv` field is a `<derivation>` to be built, and the
> `sub-derivations` field is a list of outputs.
>
> The other pseudo-"arguments" are pretty simple; none of them involve new
Here you write "pretty simple". Later you also write "self-explanatory" and
"obviously". I suggest to let the reader decide what's simple.
> records. The third is `derivation-sources`, which contains a list of
> all store items used in the build which aren't themselves built using
> derivations, whereas `derivation-inputs` contains the dependencies
> which are.
>
> This list usually just contains the path to the Guile _build script_ that
> realises the store items when run, which we'll examine in a later post, and
> the path to a directory containing extra modules to add to the build script's
> `%load-path`, called `/gnu/store/...-module-import`.
>
> The next "argument" is self-explanatory: `derivation-system`, which specifies
> the Nix system we're building for. Next is `derivation-builder`, pointing to
> the `guile` executable that runs the script; and the second-to-last is
> `derivation-args`, which is a list of arguments to pass to
> `derivation-builder`.
> Note how we use `-L` and `-C` to extend the Guile `%load-path` and
> `%load-compiled-path` to include the `module-import` and
> `module-import-compiled`
> directories:
>
> ```scheme
> (pk (derivation-system irssi-drv))
> ;;; ("x86_64-linux")
>
> (pk (derivation-builder irrsi-drv))
> ;;; ("/gnu/store/hnr4r2d0h0xarx52i6jq9gvsrlc3q81a-guile-2.0.14/bin/guile")
>
> (pk (derivation-builder-arguments irrsi-drv))
> ;;; (("--no-auto-compile" "-L"
> "/gnu/store/af18nrrsk98c5a71h3fifnxg1zi5mx7y-module-import" "-C"
> "/gnu/store/6rkkvvb7pl1l9ng8vvywvwf357vhm3va-module-import-compiled"
> "/gnu/store/qnrwmby5cwqdqxyiv1ga6azvakmdvgl7-irssi-1.4.3-builder"))
> ```
>
> The final "argument" contains a list of environment variables to set before
> we start the build process:
>
> ```scheme
> (pk (derivation-builder-environment-vars irssi-drv))
> ;;; ((("allowSubstitutes" . "0") ("guix properties" . "((type . graft) (graft
> (count . 2)))") ("out" .
> "/gnu/store/v5pd69j3hjs1fck4b5p9hd91wc8yf5qx-irssi-1.4.3")
> ("preferLocalBuild" . "1")))
> ```
>
> Obviously, the last record field, `derivation-file-name`, simply allows you to
Before this point, the record fields have been called '"argument"'s all the
time. I think it's not nice style to carry on a quoted term through many
paragraphs like this. Let's simply write "record field" all the time, instead.
> retrieve the path to the `.drv` file in Scheme, and so isn't
> represented in a serialised derivation. Speaking of serialisation, to
> convert between the `.drv` text format and the Scheme `<derivation>`
> record, you can use `write-derivation`, `read-derivation`, and
> `read-derivation-from-file`.
I think an example for invoking read-derivation-from-file would round up this
tutorial really nicely because it'd close the circle between .drv-files and
<derivation>-objects.
> # Conclusion
>
> Derivations are one of Guix's most important concepts, but are fairly easy to
> understand once you get past the obtuse `.drv` file format. They provide the
> Guix daemon with the initial instructions that it uses to build store items
> like packages, origins, and other file-likes such as `computed-file` and
> `local-file`, which will be discussed in a future post!
Here, in the conclusion, IMHO, there could be another brief listing of all
fields of a derivation.
> #### About GNU Guix
>
> [GNU Guix](https://guix.gnu.org) is a transactional package manager and
> an advanced distribution of the GNU system that [respects user
> freedom](https://www.gnu.org/distros/free-system-distribution-guidelines.html).
> Guix can be used on top of any system running the Hurd or the Linux
> kernel, or it can be used as a standalone operating system distribution
> for i686, x86_64, ARMv7, AArch64 and POWER9 machines.
>
> In addition to standard package management features, Guix supports
> transactional upgrades and roll-backs, unprivileged package management,
> per-user profiles, and garbage collection. When used as a standalone
> GNU/Linux distribution, Guix offers a declarative, stateless approach to
> operating system configuration management. Guix is highly customizable
> and hackable through [Guile](https://www.gnu.org/software/guile)
> programming interfaces and extensions to the
> [Scheme](http://schemers.org) language.
0001-many-different-rather-small-changes.patch
Description: Text Data
0000-initialize-markdown.patch
Description: Text Data
Re: Dissecting Guix -- blog post series,
Mekeor Melire <=
[PATCH guix-artwork v2] website: posts: Add Dissecting Guix, Part 1: Derivations., (, 2022/12/12
[PATCH guix-artwork v3] website: posts: Add Dissecting Guix, Part 1: Derivations., (, 2022/12/12
[PATCH guix-artwork v4] website: posts: Add Dissecting Guix, Part 1: Derivations., (, 2022/12/17