summary refs log tree commit diff
path: root/doc/guix-cookbook.texi
diff options
context:
space:
mode:
Diffstat (limited to 'doc/guix-cookbook.texi')
-rw-r--r--doc/guix-cookbook.texi821
1 files changed, 821 insertions, 0 deletions
diff --git a/doc/guix-cookbook.texi b/doc/guix-cookbook.texi
new file mode 100644
index 0000000000..66f94a0fe7
--- /dev/null
+++ b/doc/guix-cookbook.texi
@@ -0,0 +1,821 @@
+\input texinfo
+@c -*-texinfo-*-
+
+@c %**start of header
+@setfilename guix-cookbook.info
+@documentencoding UTF-8
+@settitle GNU Guix Cookbook
+@c %**end of header
+
+@copying
+Copyright @copyright{} 2019 Ricardo Wurmus@*
+Copyright @copyright{} 2019 Efraim Flashner@*
+Copyright @copyright{} 2019 Pierre Neidhardt@*
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.3 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.  A
+copy of the license is included in the section entitled ``GNU Free
+Documentation License''.
+@end copying
+
+@dircategory System administration
+@direntry
+* Guix cookbook: (guix-cookbook).    Tutorials and examples for GNU Guix.
+@end direntry
+
+@titlepage
+@title GNU Guix Cookbook
+@subtitle Tutorials and examples for using the GNU Guix Functional Package Manager
+@author The GNU Guix Developers
+
+@page
+@vskip 0pt plus 1filll
+
+@insertcopying
+@end titlepage
+
+@contents
+
+@c *********************************************************************
+@node Top
+@top GNU Guix Cookbook
+
+This document presents tutorials and detailed examples for GNU@tie{}Guix, a
+functional package management tool written for the GNU system.  Please
+@pxref{Top,,, guix, GNU Guix reference manual} for details about the system,
+its API, and related concepts.
+
+@c TRANSLATORS: You can replace the following paragraph with information on
+@c how to join your own translation team and how to report issues with the
+@c translation.
+If you would like to translate this document in your native language, consider
+joining the @uref{https://translationproject.org/domain/guix-cookbook.html,
+Translation Project}.
+
+@menu
+* Scheme tutorials::            Meet your new favorite language!
+* Packaging::                   Packaging tutorials
+* System Configuration::        Customizing the GNU System
+
+* Acknowledgments::             Thanks!
+* GNU Free Documentation License::  The license of this document.
+* Concept Index::               Concepts.
+
+@detailmenu
+ --- The Detailed Node Listing ---
+
+Scheme tutorials
+
+* A Scheme Crash Course::       Learn the basics of Scheme
+
+Packaging
+
+* Packaging Tutorial::          Let's add a package to Guix!
+
+System Configuration
+
+* Customizing the Kernel::      Creating and using a custom Linux kernel
+
+
+@end detailmenu
+@end menu
+
+@c *********************************************************************
+@node Scheme tutorials
+@chapter Scheme tutorials
+
+GNU@tie{}Guix is written in the general purpose programming language Scheme,
+and many of its features can be accessed and manipulated programmatically.
+You can use Scheme to generate package definitions, to modify them, to build
+them, to deploy whole operating systems, etc.
+
+Knowing the basics of how to program in Scheme will unlock many of the
+advanced features Guix provides --- and you don't even need to be an
+experienced programmer to use them!
+
+Let's get started!
+
+@node A Scheme Crash Course
+@section A Scheme Crash Course
+
+@cindex Scheme, crash course
+
+Guix uses the Guile implementation of Scheme.  To start playing with the
+language, install it with @code{guix install guile} and start a
+@uref{https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop,
+REPL} by running @code{guile} from the command line.
+
+Alternatively you can also run @code{guix environment --ad-hoc guile -- guile}
+if you'd rather not have Guile installed in your user profile.
+
+In the following examples we use the @code{>} symbol to denote the REPL
+prompt, that is, the line reserved for user input.  @xref{Using Guile
+Interactively,,, guile, GNU Guile Reference Manual}) for more details on the
+REPL.
+
+@itemize
+@item
+Scheme syntax boils down to a tree of expressions (or @emph{s-expression} in
+Lisp lingo).  An expression can be a literal such as numbers and strings, or a
+compound which is a parenthesized list of compounds and literals.  @code{#t}
+and @code{#f} stand for the booleans "true" and "false", respectively.
+
+Examples of valid expressions:
+
+@example scheme
+> "Hello World!"
+"Hello World!"
+> 17
+17
+> (display (string-append "Hello " "Guix" "\n"))
+"Hello Guix!"
+@end example
+
+@item
+This last example is a function call nested in another function call.  When a
+parenthesized expression is evaluated, the first term is the function and the
+rest are the arguments passed to the function.  Every function returns the
+last evaluated expression as its return value.
+
+@item
+Anonymous functions are declared with the @code{lambda} term:
+
+@example scheme
+> (lambda (x) (* x x))
+#<procedure 120e348 at <unknown port>:24:0 (x)>
+@end example
+
+The above procedure returns the square of its argument.  Since everything is
+an expression, the @code{lambda} expression returns an anonymous procedure,
+which can in turn be applied to an argument:
+
+@example scheme
+> ((lambda (x) (* x x)) 3)
+9
+@end example
+
+@item
+Anything can be assigned a global name with @code{define}:
+
+@example scheme
+> (define a 3)
+> (define square (lambda (x) (* x x)))
+> (square a)
+9
+@end example
+
+@item
+Procedures can be defined more concisely with the following syntax:
+
+@example scheme
+(define (square x) (* x x))
+@end example
+
+@item
+A list structure can be created with the @code{list} procedure:
+
+@example scheme
+> (list 2 a 5 7)
+(2 3 5 7)
+@end example
+
+@item
+The @emph{quote} disables evaluation of a parenthesized expression: the first
+term is not called over the other terms.  Thus it effectively returns a list
+of terms.
+
+@example scheme
+> '(display (string-append "Hello " "Guix" "\n"))
+(display (string-append "Hello " "Guix" "\n"))
+> '(2 a 5 7)
+(2 a 5 7)
+@end example
+
+@item
+The @emph{quasiquote} disables evaluation of a parenthesized expression until
+a comma re-enables it.  Thus it provides us with fine-grained control over
+what is evaluated and what is not.
+
+@example scheme
+> `(2 a 5 7 (2 ,a 5 ,(+ a 4)))
+(2 a 5 7 (2 3 5 7))
+@end example
+
+Note that the above result is a list of mixed elements: numbers, symbols (here
+@code{a}) and the last element is a list itself.
+
+@item
+Multiple variables can be named locally with @code{let}:
+
+@example scheme
+> (define x 10)
+> (let ((x 2)
+        (y 3))
+    (list x y))
+(2 3)
+> x
+10
+> y
+ERROR: In procedure module-lookup: Unbound variable: y
+@end example
+
+Use @code{let*} to allow later variable declarations to refer to earlier
+definitions.
+
+@example scheme
+> (let* ((x 2)
+         (y (* x 3)))
+    (list x y))
+(2 6)
+@end example
+
+@item
+The keyword syntax is @code{#:}; it is used to create unique identifiers.
+@pxref{Keywords,,, guile, GNU Guile Reference Manual}.
+
+@item
+The percentage @code{%} is typically used for read-only global variables in
+the build stage.  Note that it is merely a convention, like @code{_} in C.
+Scheme treats @code{%} exactly the same as any other letter.
+
+@item
+Modules are created with @code{define-module}.  For instance
+
+@example scheme
+(define-module (guix build-system ruby)
+  #:use-module (guix store)
+  #:export (ruby-build
+            ruby-build-system))
+@end example
+
+defines the module @code{guix build-system ruby} which must be located in
+@file{guix/build-system/ruby.scm} somewhere in the Guile load path.  It
+depends on the @code{(guix store)} module and it exports two variables,
+@code{ruby-build} and @code{ruby-build-system}.
+@end itemize
+
+For a more detailed introduction, check out
+@uref{http://www.troubleshooters.com/codecorn/scheme_guile/hello.htm, Scheme
+at a Glance}, by Steve Litt.
+
+One of the reference Scheme books is the seminal ``Structure and
+Interpretation of Computer Programs'', by Harold Abelson and Gerald Jay
+Sussman, with Julie Sussman.  You'll find a
+@uref{https://mitpress.mit.edu/sites/default/files/sicp/index.html, free copy
+online}, together with
+@uref{https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/video-lectures/,
+videos of the lectures by the authors}.  The book is available in Texinfo
+format as the @code{sicp} Guix package.  Go ahead, run @code{guix install
+sicp} and start reading with @code{info sicp} (or with the Emacs Info reader).
+An @uref{https://sarabander.github.io/sicp/, unofficial ebook is also
+available}.
+
+You'll find more books, tutorials and other resources at
+@url{https://schemers.org/}.
+
+
+@c *********************************************************************
+@node Packaging
+@chapter Packaging
+
+@cindex packaging
+
+This chapter is dedicated to teaching you how to add packages to the
+collection of packages that come with GNU Guix.  This involves writing package
+definitions in Guile Scheme, organizing them in package modules, and building
+them.
+
+@menu
+* Packaging Tutorial::         A tutorial on how to add packages to Guix.
+@end menu
+
+@node Packaging Tutorial
+@section Packaging Tutorial
+
+GNU Guix stands out as the @emph{hackable} package manager, mostly because it
+uses @uref{https://www.gnu.org/software/guile/, GNU Guile}, a powerful
+high-level programming language, one of the
+@uref{https://en.wikipedia.org/wiki/Scheme_%28programming_language%29, Scheme}
+dialects from the
+@uref{https://en.wikipedia.org/wiki/Lisp_%28programming_language%29, Lisp family}.
+
+Package definitions are also written in Scheme, which empowers Guix in some
+very unique ways, unlike most other package managers that use shell scripts or
+simple languages.
+
+@itemize
+@item
+Use functions, structures, macros and all of Scheme expressiveness for your
+package definitions.
+
+@item
+Inheritance makes it easy to customize a package by inheriting from it and
+modifying only what is needed.
+ 
+@item
+Batch processing: the whole package collection can be parsed, filtered and
+processed.  Building a headless server with all graphical interfaces stripped
+out?  It's possible.  Want to rebuild everything from source using specific
+compiler optimization flags?  Pass the @code{#:make-flags "..."} argument to
+the list of packages.  It wouldn't be a stretch to think
+@uref{https://wiki.gentoo.org/wiki/USE_flag, Gentoo USE flags} here, but this
+goes even further: the changes don't have to be thought out beforehand by the
+packager, they can be @emph{programmed} by the user!
+@end itemize
+
+The following tutorial covers all the basics around package creation with Guix.
+It does not assume much knowledge of the Guix system nor of the Lisp language.
+The reader is only expected to be familiar with the command line and to have some
+basic programming knowledge.
+
+@subsection A "Hello World" package
+
+The “Defining Packages” section of the manual introduces the basics of Guix
+packaging (@pxref{Defining Packages,,, guix, GNU Guix Reference Manual}).  In
+the following section, we will partly go over those basics again.
+
+``GNU hello'' is a dummy project that serves as an idiomatic example for
+packaging.  It uses the GNU build system (@code{./configure && make && make
+install}).  Guix already provides a package definition which is a perfect
+example to start with.  You can look up its declaration with @code{guix edit
+hello} from the command line.  Let's see how it looks:
+
+@example scheme
+(define-public hello
+  (package
+    (name "hello")
+    (version "2.10")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "mirror://gnu/hello/hello-" version
+                                  ".tar.gz"))
+              (sha256
+               (base32
+                "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i"))))
+    (build-system gnu-build-system)
+    (synopsis "Hello, GNU world: An example GNU package")
+    (description
+     "GNU Hello prints the message \"Hello, world!\" and then exits.  It
+serves as an example of standard GNU coding practices.  As such, it supports
+command-line arguments, multiple languages, and so on.")
+    (home-page "https://www.gnu.org/software/hello/")
+    (license gpl3+)))
+@end example
+
+As you can see, most of it is rather straightforward.  But let's review the
+fields together:
+
+@table @samp
+@item name
+The project name.  Using Scheme conventions, we prefer to keep it
+lower case, without underscore and using dash-separated words.
+
+@item source
+This field contains a description of the source code origin.  The
+@code{origin} record contains these fields:
+
+@enumerate
+@item  The method, here @code{url-fetch} to download via HTTP/FTP, but other methods
+    exist, such as @code{git-fetch} for Git repositories.
+@item  The URI, which is typically some @code{https://} location for @code{url-fetch}.  Here
+    the special `mirror://gnu` refers to a set of well known locations, all of
+    which can be used by Guix to fetch the source, should some of them fail.
+@item  The @code{sha256} checksum of the requested file.  This is essential to ensure
+    the source is not corrupted.  Note that Guix works with base32 strings,
+    hence the call to the @code{base32} function.
+@end enumerate
+
+@item build-system
+
+This is where the power of abstraction provided by the Scheme language really
+shines: in this case, the @code{gnu-build-system} abstracts away the famous
+@code{./configure && make && make install} shell invocations.  Other build
+systems include the @code{trivial-build-system} which does not do anything and
+requires from the packager to program all the build steps, the
+@code{python-build-system}, the @code{emacs-build-system}, and many more
+(@pxref{Build Systems,,, guix, GNU Guix Reference Manual}).
+
+@item synopsis
+It should be a concise summary of what the package does.  For many packages a
+tagline from the project's home page can be used as the synopsis.
+
+@item description
+Same as for the synopsis, it's fine to re-use the project description from the
+homepage.  Note that Guix uses Texinfo syntax.
+
+@item home-page
+Use HTTPS if available.
+
+@item license
+See @code{guix/licenses.scm} in the project source for a full list of
+available licenses.
+@end table
+
+Time to build our first package!  Nothing fancy here for now: we will stick to a
+dummy "my-hello", a copy of the above declaration.
+
+As with the ritualistic "Hello World" taught with most programming languages,
+this will possibly be the most "manual" approach.  We will work out an ideal
+setup later; for now we will go the simplest route.
+
+Save the following to a file @file{my-hello.scm}.
+
+@example scheme
+(use-modules (guix packages)
+             (guix download)
+             (guix build-system gnu)
+             (guix licenses))
+
+(package
+  (name "my-hello")
+  (version "2.10")
+  (source (origin
+            (method url-fetch)
+            (uri (string-append "mirror://gnu/hello/hello-" version
+                                ".tar.gz"))
+            (sha256
+             (base32
+              "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i"))))
+  (build-system gnu-build-system)
+  (synopsis "Hello, Guix world: An example custom Guix package")
+  (description
+   "GNU Hello prints the message \"Hello, world!\" and then exits.  It
+serves as an example of standard GNU coding practices.  As such, it supports
+command-line arguments, multiple languages, and so on.")
+  (home-page "https://www.gnu.org/software/hello/")
+  (license gpl3+))
+@end example
+
+We will explain the extra code in a moment.
+
+Feel free to play with the different values of the various fields.  If you
+change the source, you'll need to update the checksum.  Indeed, Guix refuses to
+build anything if the given checksum does not match the computed checksum of the
+source code.  To obtain the correct checksum of the package declaration, we
+need to download the source, compute the sha256 checksum and convert it to
+base32.
+
+Thankfully, Guix can automate this task for us; all we need is to provide the
+URI:
+
+@c TRANSLATORS: This is example shell output.
+@example sh
+$ guix download mirror://gnu/hello/hello-2.10.tar.gz
+
+Starting download of /tmp/guix-file.JLYgL7
+From https://ftpmirror.gnu.org/gnu/hello/hello-2.10.tar.gz...
+following redirection to `https://mirror.ibcp.fr/pub/gnu/hello/hello-2.10.tar.gz'...
+ …10.tar.gz  709KiB                                 2.5MiB/s 00:00 [##################] 100.0%
+/gnu/store/hbdalsf5lpf01x4dcknwx6xbn6n5km6k-hello-2.10.tar.gz
+0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i
+@end example
+
+In this specific case the output tells us which mirror was chosen.
+If the result of the above command is not the same as in the above snippet,
+update your @code{my-hello} declaration accordingly.
+
+Note that GNU package tarballs come with an OpenPGP signature, so you
+should definitely check the signature of this tarball with `gpg` to
+authenticate it before going further:
+
+@c TRANSLATORS: This is example shell output.
+@example sh
+$ guix download mirror://gnu/hello/hello-2.10.tar.gz.sig
+
+Starting download of /tmp/guix-file.03tFfb
+From https://ftpmirror.gnu.org/gnu/hello/hello-2.10.tar.gz.sig...
+following redirection to `https://ftp.igh.cnrs.fr/pub/gnu/hello/hello-2.10.tar.gz.sig'...
+ ….tar.gz.sig  819B                                                                                                                       1.2MiB/s 00:00 [##################] 100.0%
+/gnu/store/rzs8wba9ka7grrmgcpfyxvs58mly0sx6-hello-2.10.tar.gz.sig
+0q0v86n3y38z17rl146gdakw9xc4mcscpk8dscs412j22glrv9jf
+$ gpg --verify /gnu/store/rzs8wba9ka7grrmgcpfyxvs58mly0sx6-hello-2.10.tar.gz.sig /gnu/store/hbdalsf5lpf01x4dcknwx6xbn6n5km6k-hello-2.10.tar.gz
+gpg: Signature made Sun 16 Nov 2014 01:08:37 PM CET
+gpg:                using RSA key A9553245FDE9B739
+gpg: Good signature from "Sami Kerola <kerolasa@@iki.fi>" [unknown]
+gpg:                 aka "Sami Kerola (http://www.iki.fi/kerolasa/) <kerolasa@@iki.fi>" [unknown]
+gpg: WARNING: This key is not certified with a trusted signature!
+gpg:          There is no indication that the signature belongs to the owner.
+Primary key fingerprint: 8ED3 96E3 7E38 D471 A005  30D3 A955 3245 FDE9 B739
+@end example
+
+You can then happily run
+
+@c TRANSLATORS: Do not translate this command
+@example sh
+$ guix package --install-from-file=my-hello.scm
+@end example
+
+You should now have @code{my-hello} in your profile!
+
+@c TRANSLATORS: Do not translate this command
+@example sh
+$ guix package --list-installed=my-hello
+my-hello	2.10	out
+/gnu/store/f1db2mfm8syb8qvc357c53slbvf1g9m9-my-hello-2.10
+@end example
+
+We've gone as far as we could without any knowledge of Scheme.  Before moving
+on to more complex packages, now is the right time to brush up on your Scheme
+knowledge.  @pxref{A Scheme Crash Course} to get up to speed.
+
+@c TODO: Continue the tutorial
+
+
+@c *********************************************************************
+@node System Configuration
+@chapter System Configuration
+
+Guix offers a flexible language for declaratively configuring your Guix
+System.  This flexibility can at times be overwhelming.  The purpose of this
+chapter is to demonstrate some advanced configuration concepts.
+
+@pxref{System Configuration,,, guix, GNU Guix Reference Manual} for a complete
+reference.
+
+@menu
+* Customizing the Kernel::     Creating and using a custom Linux kernel on Guix System.
+@end menu
+
+@node Customizing the Kernel
+@section Customizing the Kernel
+
+Guix is, at its core, a source based distribution with substitutes
+(@pxref{Substitutes,,, guix, GNU Guix Reference Manual}), and as such building
+packages from their source code is an expected part of regular package
+installations and upgrades.  Given this starting point, it makes sense that
+efforts are made to reduce the amount of time spent compiling packages, and
+recent changes and upgrades to the building and distribution of substitutes
+continues to be a topic of discussion within Guix.
+
+The kernel, while not requiring an overabundance of RAM to build, does take a
+rather long time on an average machine.  The official kernel configuration, as
+is the case with many GNU/Linux distributions, errs on the side of
+inclusiveness, and this is really what causes the build to take such a long
+time when the kernel is built from source.
+
+The Linux kernel, however, can also just be described as a regular old
+package, and as such can be customized just like any other package.  The
+procedure is a little bit different, although this is primarily due to the
+nature of how the package definition is written.
+
+The @code{linux-libre} kernel package definition is actually a procedure which
+creates a package.
+
+@example scheme
+(define* (make-linux-libre version hash supported-systems
+                           #:key
+                           ;; A function that takes an arch and a variant.
+                           ;; See kernel-config for an example.
+                           (extra-version #f)
+                           (configuration-file #f)
+                           (defconfig "defconfig")
+                           (extra-options %default-extra-linux-options)
+                           (patches (list %boot-logo-patch)))
+  ...)
+@end example
+
+The current @code{linux-libre} package is for the 5.1.x series, and is
+declared like this:
+
+@example scheme
+(define-public linux-libre
+  (make-linux-libre %linux-libre-version
+                    %linux-libre-hash
+                    '("x86_64-linux" "i686-linux" "armhf-linux" "aarch64-linux")
+                    #:patches %linux-libre-5.1-patches
+                    #:configuration-file kernel-config))
+@end example
+
+Any keys which are not assigned values inherit their default value from the
+@code{make-linux-libre} definition.  When comparing the two snippets above,
+you may notice that the code comment in the first doesn't actually refer to
+the @code{#:extra-version} keyword; it is actually for
+@code{#:configuration-file}.  Because of this, it is not actually easy to
+include a custom kernel configuration from the definition, but don't worry,
+there are other ways to work with what we do have.
+
+There are two ways to create a kernel with a custom kernel configuration.  The
+first is to provide a standard @file{.config} file during the build process by
+including an actual @file{.config} file as a native input to our custom
+kernel.  The following is a snippet from the custom @code{'configure} phase of
+the @code{make-linux-libre} package definition:
+
+@example scheme
+(let ((build  (assoc-ref %standard-phases 'build))
+      (config (assoc-ref (or native-inputs inputs) "kconfig")))
+
+  ;; Use a custom kernel configuration file or a default
+  ;; configuration file.
+  (if config
+      (begin
+        (copy-file config ".config")
+        (chmod ".config" #o666))
+      (invoke "make" ,defconfig))
+@end example
+
+Below is a sample kernel package.  The @code{linux-libre} package is nothing
+special and can be inherited from and have its fields overridden like any
+other package:
+
+@example scheme
+(define-public linux-libre/E2140
+  (package
+    (inherit linux-libre)
+    (native-inputs
+     `(("kconfig" ,(local-file "E2140.config"))
+      ,@@(alist-delete "kconfig"
+                      (package-native-inputs linux-libre))))))
+@end example
+
+In the same directory as the file defining @code{linux-libre-E2140} is a file
+named @file{E2140.config}, which is an actual kernel configuration file.  The
+@code{defconfig} keyword of @code{make-linux-libre} is left blank here, so the
+only kernel configuration in the package is the one which was included in the
+@code{native-inputs} field.
+
+The second way to create a custom kernel is to pass a new value to the
+@code{extra-options} keyword of the @code{make-linux-libre} procedure.  The
+@code{extra-options} keyword works with another function defined right below
+it:
+
+@example scheme
+(define %default-extra-linux-options
+  `(;; https://lists.gnu.org/archive/html/guix-devel/2014-04/msg00039.html
+   ("CONFIG_DEVPTS_MULTIPLE_INSTANCES" . #t)
+   ;; Modules required for initrd:
+   ("CONFIG_NET_9P" . m)
+   ("CONFIG_NET_9P_VIRTIO" . m)
+   ("CONFIG_VIRTIO_BLK" . m)
+   ("CONFIG_VIRTIO_NET" . m)
+   ("CONFIG_VIRTIO_PCI" . m)
+   ("CONFIG_VIRTIO_BALLOON" . m)
+   ("CONFIG_VIRTIO_MMIO" . m)
+   ("CONFIG_FUSE_FS" . m)
+   ("CONFIG_CIFS" . m)
+   ("CONFIG_9P_FS" . m)))
+
+(define (config->string options)
+  (string-join (map (match-lambda
+                      ((option . 'm)
+                       (string-append option "=m"))
+                      ((option . #t)
+                       (string-append option "=y"))
+                      ((option . #f)
+                       (string-append option "=n")))
+                    options)
+               "\n"))
+@end example
+
+And in the custom configure script from the `make-linux-libre` package:
+
+@example scheme
+;; Appending works even when the option wasn't in the
+;; file.  The last one prevails if duplicated.
+(let ((port (open-file ".config" "a"))
+      (extra-configuration ,(config->string extra-options)))
+  (display extra-configuration port)
+  (close-port port))
+
+(invoke "make" "oldconfig"))))
+@end example
+
+So by not providing a configuration-file the @file{.config} starts blank, and
+then we write into it the collection of flags that we want.  Here's another
+custom kernel:
+
+@example scheme
+(define %macbook41-full-config
+  (append %macbook41-config-options
+          %filesystems
+          %efi-support
+          %emulation
+          (@@@@ (gnu packages linux) %default-extra-linux-options)))
+
+(define-public linux-libre-macbook41
+  ;; XXX: Access the internal 'make-linux-libre' procedure, which is
+  ;; private and unexported, and is liable to change in the future.
+  ((@@@@ (gnu packages linux) make-linux-libre) (@@@@ (gnu packages linux) %linux-libre-version)
+                      (@@@@ (gnu packages linux) %linux-libre-hash)
+                      '("x86_64-linux")
+                      #:extra-version "macbook41"
+                      #:patches (@@@@ (gnu packages linux) %linux-libre-5.1-patches)
+                      #:extra-options %macbook41-config-options))
+@end example
+
+In the above example @code{%filesystems} is a collection of flags enabling
+different filesystem support, @code{%efi-support} enables EFI support and
+@code{%emulation} enables a x86_64-linux machine to act in 32-bit mode also.
+@code{%default-extra-linux-options} are the ones quoted above, which had to be
+added in since they were replaced in the @code{extra-options} keyword.
+
+This all sounds like it should be doable, but how does one even know which
+modules are required for a particular system?  Two places that can be helpful
+in trying to answer this question is the
+@uref{https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Kernel, Gentoo
+Handbook} and the
+@uref{https://www.kernel.org/doc/html/latest/admin-guide/README.html?highlight=localmodconfig,
+documentation from the kernel itself}.  From the kernel documentation, it
+seems that @code{make localmodconfig} is the command we want.
+
+In order to actually run @code{make localmodconfig} we first need to get and
+unpack the kernel source code:
+
+@example shell
+tar xf $(guix build linux-libre --source)
+@end example
+
+Once inside the directory containing the source code run @code{touch .config}
+to create an initial, empty @file{.config} to start with.  @code{make
+localmodconfig} works by seeing what you already have in @file{.config} and
+letting you know what you're missing.  If the file is blank then you're
+missing everything.  The next step is to run:
+
+@example shell
+guix environment linux-libre -- make localmodconfig
+@end example
+
+and note the output.  Do note that the @file{.config} file is still empty.
+The output generally contains two types of warnings.  The first start with
+"WARNING" and can actually be ignored in our case.  The second read:
+
+@example shell
+module pcspkr did not have configs CONFIG_INPUT_PCSPKR
+@end example
+
+For each of these lines, copy the @code{CONFIG_XXXX_XXXX} portion into the
+@file{.config} in the directory, and append @code{=m}, so in the end it looks
+like this:
+
+@example shell
+CONFIG_INPUT_PCSPKR=m
+CONFIG_VIRTIO=m
+@end example
+
+After copying all the configuration options, run @code{make localmodconfig}
+again to make sure that you don't have any output starting with "module".
+After all of these machine specific modules there are a couple more left that
+are also needed.  @code{CONFIG_MODULES} is necessary so that you can build and
+load modules separately and not have everything built into the kernel.
+@code{CONFIG_BLK_DEV_SD} is required for reading from hard drives.  It is
+possible that there are other modules which you will need.
+
+This post does not aim to be a guide to configuring your own kernel however,
+so if you do decide to build a custom kernel you'll have to seek out other
+guides to create a kernel which is just right for your needs.
+
+The second way to setup the kernel configuration makes more use of Guix's
+features and allows you to share configuration segments between different
+kernels.  For example, all machines using EFI to boot have a number of EFI
+configuration flags that they need.  It is likely that all the kernels will
+share a list of filesystems to support.  By using variables it is easier to
+see at a glance what features are enabled and to make sure you don't have
+features in one kernel but missing in another.
+
+Left undiscussed however, is Guix's initrd and its customization.  It is
+likely that you'll need to modify the initrd on a machine using a custom
+kernel, since certain modules which are expected to be built may not be
+available for inclusion into the initrd.
+
+@c *********************************************************************
+@node Acknowledgments
+@chapter Acknowledgments
+
+Guix is based on the @uref{https://nixos.org/nix/, Nix package manager},
+which was designed and
+implemented by Eelco Dolstra, with contributions from other people (see
+the @file{nix/AUTHORS} file in Guix.)  Nix pioneered functional package
+management, and promoted unprecedented features, such as transactional
+package upgrades and rollbacks, per-user profiles, and referentially
+transparent build processes.  Without this work, Guix would not exist.
+
+The Nix-based software distributions, Nixpkgs and NixOS, have also been
+an inspiration for Guix.
+
+GNU@tie{}Guix itself is a collective work with contributions from a
+number of people.  See the @file{AUTHORS} file in Guix for more
+information on these fine people.  The @file{THANKS} file lists people
+who have helped by reporting bugs, taking care of the infrastructure,
+providing artwork and themes, making suggestions, and more---thank you!
+
+This document includes adapted sections from articles that have previously
+been published on the Guix blog at @uref{https://guix.gnu.org/blog}.
+
+
+@c *********************************************************************
+@node GNU Free Documentation License
+@appendix GNU Free Documentation License
+@cindex license, GNU Free Documentation License
+@include fdl-1.3.texi
+
+@c *********************************************************************
+@node Concept Index
+@unnumbered Concept Index
+@printindex cp
+
+@bye
+
+@c Local Variables:
+@c ispell-local-dictionary: "american";
+@c End: