From 7bc46ecc34ceb042ff890e5d306d0a2a736e891d Mon Sep 17 00:00:00 2001 From: Ricardo Wurmus Date: Sun, 8 Sep 2019 14:35:44 +0200 Subject: [PATCH] doc: Add Guix Cookbook. * .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. --- .gitignore | 31 +- Makefile.am | 3 +- bootstrap | 12 +- doc/guix-cookbook.texi | 821 +++++++++++++++++++++++++++++++++++++++++ doc/local.mk | 9 +- po/doc/local.mk | 33 +- 6 files changed, 890 insertions(+), 19 deletions(-) create mode 100644 doc/guix-cookbook.texi diff --git a/.gitignore b/.gitignore index 93d2ec9801..38cde42fca 100644 --- a/.gitignore +++ b/.gitignore @@ -29,22 +29,23 @@ /doc/*.1 /doc/.dirstamp /doc/contributing.*.texi -/doc/guix.*.aux -/doc/guix.*.cp -/doc/guix.*.cps -/doc/guix.*.fn -/doc/guix.*.fns -/doc/guix.*.html -/doc/guix.*.info -/doc/guix.*.info-[0-9] -/doc/guix.*.ky -/doc/guix.*.pg -/doc/guix.*.toc -/doc/guix.*.t2p -/doc/guix.*.tp -/doc/guix.*.vr -/doc/guix.*.vrs +/doc/guix*.aux +/doc/guix*.cp +/doc/guix*.cps +/doc/guix*.fn +/doc/guix*.fns +/doc/guix*.html +/doc/guix*.info +/doc/guix*.info-[0-9] +/doc/guix*.ky +/doc/guix*.pg +/doc/guix*.toc +/doc/guix*.t2p +/doc/guix*.tp +/doc/guix*.vr +/doc/guix*.vrs /doc/guix.*.texi +/doc/guix-cookbook.*.texi /doc/guix.aux /doc/guix.cp /doc/guix.cps diff --git a/Makefile.am b/Makefile.am index 7e3b5c1070..93d18d7df6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -814,7 +814,8 @@ assert-no-store-file-names: $(AM_V_at)if grep -r --exclude=*.texi --exclude=*.info \ --exclude=*.info-[0-9] --exclude=*.dot \ --exclude=*.eps --exclude-dir=bootstrap \ - --exclude=guix-manual.pot --exclude=guix-manual.*.po \ + --exclude=guix-manual.pot --exclude=guix-manual.*.po \ + --exclude=guix-cookbook.pot --exclude=guix-cookbook.*.po \ --exclude=guix-prettify.el \ --exclude=ChangeLog* \ -E "$(storedir)/[a-z0-9]{32}-" $(distdir) ; \ diff --git a/bootstrap b/bootstrap index c0b5af7677..c9e7a084a1 100755 --- a/bootstrap +++ b/bootstrap @@ -4,7 +4,7 @@ set -e -x # Generate stubs for translations. -langs=`find po/doc -type f -name '*.po' \ +langs=`find po/doc -type f -name 'guix-manual*.po' \ | sed -e 's,guix-manual\.,,' \ | xargs -n 1 -I{} basename {} .po` for lang in ${langs}; do @@ -15,5 +15,15 @@ for lang in ${langs}; do touch "po/doc/guix-manual.${lang}.po" fi done +langs=`find po/doc -type f -name 'guix-cookbook*.po' \ + | sed -e 's,guix-manual\.,,' \ + | xargs -n 1 -I{} basename {} .po` +for lang in ${langs}; do + if [ ! -e "doc/guix-cookbook.${lang}.texi" ]; then + echo "@setfilename guix-cookbook.${lang}.info" > "doc/guix-cookbook.${lang}.texi" + # Ensure .po file is newer. + touch "po/doc/guix-cookbook.${lang}.po" + fi +done exec autoreconf -vfi 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)) +#: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 " [unknown] +gpg: aka "Sami Kerola (http://www.iki.fi/kerolasa/) " [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: diff --git a/doc/local.mk b/doc/local.mk index 336e961c4f..850612605b 100644 --- a/doc/local.mk +++ b/doc/local.mk @@ -26,7 +26,8 @@ info_TEXINFOS = %D%/guix.texi \ %D%/guix.es.texi \ %D%/guix.fr.texi \ %D%/guix.ru.texi \ - %D%/guix.zh_CN.texi + %D%/guix.zh_CN.texi \ + %D%/guix-cookbook.texi %C%_guix_TEXINFOS = \ %D%/contributing.texi \ @@ -108,6 +109,12 @@ $(srcdir)/%D%/guix.%.texi: po/doc/guix-manual.%.po $(srcdir)/%D%/contributing.%. -$(AM_V_POXREF)$(xref_command) -mv "$@.tmp" "$@" +$(srcdir)/%D%/guix-cookbook.%.texi: po/doc/guix-cookbook.%.po + -$(AM_V_PO4A)$(PO4A_TRANSLATE) $(PO4A_PARAMS) -m "%D%/guix-cookbook.texi" -p "$<" -l "$@.tmp" + -sed -i "s|guix-cookbook\.info|$$(basename "$@" | sed 's|texi$$|info|')|" "$@.tmp" + -$(AM_V_POXREF)$(xref_command) + -mv "$@.tmp" "$@" + $(srcdir)/%D%/contributing.%.texi: po/doc/guix-manual.%.po -$(AM_V_PO4A)$(PO4A_TRANSLATE) $(PO4A_PARAMS) -m "%D%/contributing.texi" -p "$<" -l "$@.tmp" -$(AM_V_POXREF)$(xref_command) diff --git a/po/doc/local.mk b/po/doc/local.mk index fb3c5aee03..f1a52615c1 100644 --- a/po/doc/local.mk +++ b/po/doc/local.mk @@ -23,9 +23,13 @@ DOC_PO_FILES= \ %D%/guix-manual.ru.po \ %D%/guix-manual.zh_CN.po +DOC_COOKBOOK_PO_FILES= + EXTRA_DIST = \ %D%/guix-manual.pot \ - $(DOC_PO_FILES) + %D%/guix-cookbook.pot \ + $(DOC_PO_FILES) \ + $(DOC_COOKBOOK_PO_FILES) POT_OPTIONS = --package-name "guix" --package-version "$(VERSION)" \ --copyright-holder "Ludovic Courtès" \ @@ -52,6 +56,27 @@ doc-po-update-%: exit 1; \ fi +doc-po-update-cookbook-%: + @lang=`echo "$@" | sed -e's/^doc-po-update-//'` ; \ + output="$(srcdir)/po/doc/guix-cookbook.$$lang.po" ; \ + input="$(srcdir)/po/doc/guix-cookbook.pot" ; \ + if test -f "$$output"; then \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $$output $$input"; \ + cd $(srcdir) \ + && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) "$$output" "$$input";; \ + *) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} "$$output" "$$input";; \ + esac; \ + }; \ + touch "$$output"; \ + else \ + echo "File $$output does not exist. If you are a translator, you can create it with 'msginit'." 1>&2; \ + exit 1; \ + fi + $(srcdir)/po/doc/%.pot-update: doc/%.texi $(AM_V_PO4A)$(PO4A_UPDATEPO) -M UTF-8 -f texinfo -m "$<" \ -p "$$(echo $@ | sed 's|-update||')" $(POT_OPTIONS) @@ -64,6 +89,7 @@ doc-pot-update: $(MAKE) $(srcdir)/po/doc/guix.pot-update; \ $(MAKE) $(srcdir)/po/doc/contributing.pot-update; \ done + $(MAKE) $(srcdir)/po/doc/guix-cookbook.pot-update; msgcat $(addprefix $(srcdir)/po/doc/, $(TMP_POT_FILES)) > $(srcdir)/po/doc/guix-manual.pot rm -f $(addprefix $(srcdir)/po/doc/, $(TMP_POT_FILES)) @@ -72,5 +98,10 @@ doc-po-update: doc-pot-update lang="`echo "$$f" | $(SED) -es'|.*/guix-manual\.\(.*\)\.po$$|\1|g'`"; \ $(MAKE) "doc-po-update-$$lang"; \ done + for f in $(DOC_COOKBOOK_PO_FILES); do \ + lang="`echo "$$f" | $(SED) -es'|.*/guix-cookbook\.\(.*\)\.po$$|\1|g'`"; \ + $(MAKE) "doc-po-update-cookbook-$$lang"; \ + done + .PHONY: doc-po-update doc-pot-update