* .gitignore: Update ignore list. * Makefile.am (assert-no-store-file-names): Exclude the cookbook. * bootstrap: Generate po files for cookbook translations. * doc/guix-cookbook.texi: New file. * doc/local.mk (info_TEXINFOS): Add it; add a rule to build cookbook translations. * po/doc/local.mk (DOC_COOKBOOK_PO_FILES): New variable. (EXTRA_DIST): Add cookbook pot file and po files. (doc-po-update-cookbook-%): New target. (doc-pot-update): Also update cookbook pot file. (doc-po-update): Also update cookbook po files.
		
			
				
	
	
		
			821 lines
		
	
	
	
		
			30 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			821 lines
		
	
	
	
		
			30 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| \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:
 |