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.texi469
1 files changed, 429 insertions, 40 deletions
diff --git a/doc/guix-cookbook.texi b/doc/guix-cookbook.texi
index 66f94a0fe7..1b081a820e 100644
--- a/doc/guix-cookbook.texi
+++ b/doc/guix-cookbook.texi
@@ -58,6 +58,7 @@ Translation Project}.
 * Scheme tutorials::            Meet your new favorite language!
 * Packaging::                   Packaging tutorials
 * System Configuration::        Customizing the GNU System
+* Advanced package management:: Power to the users!
 
 * Acknowledgments::             Thanks!
 * GNU Free Documentation License::  The license of this document.
@@ -124,14 +125,14 @@ and @code{#f} stand for the booleans "true" and "false", respectively.
 
 Examples of valid expressions:
 
-@example scheme
+@lisp
 > "Hello World!"
 "Hello World!"
 > 17
 17
 > (display (string-append "Hello " "Guix" "\n"))
 "Hello Guix!"
-@end example
+@end lisp
 
 @item
 This last example is a function call nested in another function call.  When a
@@ -142,66 +143,66 @@ last evaluated expression as its return value.
 @item
 Anonymous functions are declared with the @code{lambda} term:
 
-@example scheme
+@lisp
 > (lambda (x) (* x x))
 #<procedure 120e348 at <unknown port>:24:0 (x)>
-@end example
+@end lisp
 
 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
+@lisp
 > ((lambda (x) (* x x)) 3)
 9
-@end example
+@end lisp
 
 @item
 Anything can be assigned a global name with @code{define}:
 
-@example scheme
+@lisp
 > (define a 3)
 > (define square (lambda (x) (* x x)))
 > (square a)
 9
-@end example
+@end lisp
 
 @item
 Procedures can be defined more concisely with the following syntax:
 
-@example scheme
+@lisp
 (define (square x) (* x x))
-@end example
+@end lisp
 
 @item
 A list structure can be created with the @code{list} procedure:
 
-@example scheme
+@lisp
 > (list 2 a 5 7)
 (2 3 5 7)
-@end example
+@end lisp
 
 @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
+@lisp
 > '(display (string-append "Hello " "Guix" "\n"))
 (display (string-append "Hello " "Guix" "\n"))
 > '(2 a 5 7)
 (2 a 5 7)
-@end example
+@end lisp
 
 @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
+@lisp
 > `(2 a 5 7 (2 ,a 5 ,(+ a 4)))
 (2 a 5 7 (2 3 5 7))
-@end example
+@end lisp
 
 Note that the above result is a list of mixed elements: numbers, symbols (here
 @code{a}) and the last element is a list itself.
@@ -209,7 +210,7 @@ Note that the above result is a list of mixed elements: numbers, symbols (here
 @item
 Multiple variables can be named locally with @code{let}:
 
-@example scheme
+@lisp
 > (define x 10)
 > (let ((x 2)
         (y 3))
@@ -219,17 +220,17 @@ Multiple variables can be named locally with @code{let}:
 10
 > y
 ERROR: In procedure module-lookup: Unbound variable: y
-@end example
+@end lisp
 
 Use @code{let*} to allow later variable declarations to refer to earlier
 definitions.
 
-@example scheme
+@lisp
 > (let* ((x 2)
          (y (* x 3)))
     (list x y))
 (2 6)
-@end example
+@end lisp
 
 @item
 The keyword syntax is @code{#:}; it is used to create unique identifiers.
@@ -243,12 +244,12 @@ Scheme treats @code{%} exactly the same as any other letter.
 @item
 Modules are created with @code{define-module}.  For instance
 
-@example scheme
+@lisp
 (define-module (guix build-system ruby)
   #:use-module (guix store)
   #:export (ruby-build
             ruby-build-system))
-@end example
+@end lisp
 
 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
@@ -342,7 +343,7 @@ 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
+@lisp
 (define-public hello
   (package
     (name "hello")
@@ -362,7 +363,7 @@ 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
+@end lisp
 
 As you can see, most of it is rather straightforward.  But let's review the
 fields together:
@@ -422,7 +423,7 @@ setup later; for now we will go the simplest route.
 
 Save the following to a file @file{my-hello.scm}.
 
-@example scheme
+@lisp
 (use-modules (guix packages)
              (guix download)
              (guix build-system gnu)
@@ -446,7 +447,7 @@ 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
+@end lisp
 
 We will explain the extra code in a moment.
 
@@ -563,7 +564,7 @@ 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
+@lisp
 (define* (make-linux-libre version hash supported-systems
                            #:key
                            ;; A function that takes an arch and a variant.
@@ -574,19 +575,19 @@ creates a package.
                            (extra-options %default-extra-linux-options)
                            (patches (list %boot-logo-patch)))
   ...)
-@end example
+@end lisp
 
 The current @code{linux-libre} package is for the 5.1.x series, and is
 declared like this:
 
-@example scheme
+@lisp
 (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
+@end lisp
 
 Any keys which are not assigned values inherit their default value from the
 @code{make-linux-libre} definition.  When comparing the two snippets above,
@@ -602,7 +603,7 @@ 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
+@lisp
 (let ((build  (assoc-ref %standard-phases 'build))
       (config (assoc-ref (or native-inputs inputs) "kconfig")))
 
@@ -613,13 +614,13 @@ the @code{make-linux-libre} package definition:
         (copy-file config ".config")
         (chmod ".config" #o666))
       (invoke "make" ,defconfig))
-@end example
+@end lisp
 
 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
+@lisp
 (define-public linux-libre/E2140
   (package
     (inherit linux-libre)
@@ -627,7 +628,7 @@ other package:
      `(("kconfig" ,(local-file "E2140.config"))
       ,@@(alist-delete "kconfig"
                       (package-native-inputs linux-libre))))))
-@end example
+@end lisp
 
 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
@@ -640,7 +641,7 @@ The second way to create a custom kernel is to pass a new value to the
 @code{extra-options} keyword works with another function defined right below
 it:
 
-@example scheme
+@lisp
 (define %default-extra-linux-options
   `(;; https://lists.gnu.org/archive/html/guix-devel/2014-04/msg00039.html
    ("CONFIG_DEVPTS_MULTIPLE_INSTANCES" . #t)
@@ -666,11 +667,11 @@ it:
                        (string-append option "=n")))
                     options)
                "\n"))
-@end example
+@end lisp
 
 And in the custom configure script from the `make-linux-libre` package:
 
-@example scheme
+@lisp
 ;; Appending works even when the option wasn't in the
 ;; file.  The last one prevails if duplicated.
 (let ((port (open-file ".config" "a"))
@@ -679,13 +680,13 @@ And in the custom configure script from the `make-linux-libre` package:
   (close-port port))
 
 (invoke "make" "oldconfig"))))
-@end example
+@end lisp
 
 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
+@lisp
 (define %macbook41-full-config
   (append %macbook41-config-options
           %filesystems
@@ -702,7 +703,7 @@ custom kernel:
                       #:extra-version "macbook41"
                       #:patches (@@@@ (gnu packages linux) %linux-libre-5.1-patches)
                       #:extra-options %macbook41-config-options))
-@end example
+@end lisp
 
 In the above example @code{%filesystems} is a collection of flags enabling
 different filesystem support, @code{%efi-support} enables EFI support and
@@ -779,6 +780,394 @@ kernel, since certain modules which are expected to be built may not be
 available for inclusion into the initrd.
 
 @c *********************************************************************
+@node Advanced package management
+@chapter Advanced package management
+
+Guix is a functional package manager that offers many features beyond
+what more traditional package managers can do.  To the uninitiated,
+those features might not have obvious use cases at first.  The purpose
+of this chapter is to demonstrate some advanced package management
+concepts.
+
+@pxref{Package Management,,, guix, GNU Guix Reference Manual} for a complete
+reference.
+
+@menu
+* Guix Profiles in Practice::     Strategies for multiple profiles and manifests.
+@end menu
+
+@node Guix Profiles in Practice
+@section Guix Profiles in Practice
+
+Guix provides a very useful feature that may be quite foreign to newcomers:
+@emph{profiles}.  They are a way to group package installations together and all users
+on a same system are free to use as many profiles as they want.
+
+Whether you're a developer or not, you may find that multiple profiles bring you
+great power and flexibility.  While they shift the paradigm somewhat compared to
+@emph{traditional package managers}, they are very convenient to use once you've
+understood how to set them up.
+
+If you are familiar with Python's @samp{virtualenv}, you can think of a profile as a
+kind of universal @samp{virtualenv} that can hold any kind of software whatsoever, not
+just Python software.  Furthermore, profiles are self-sufficient: they capture
+all the runtime dependencies which guarantees that all programs within a profile
+will always work at any point in time.
+
+Multiple profiles have many benefits:
+
+@itemize
+@item
+Clean semantic separation of the various packages a user needs for different contexts.
+
+@item
+Multiple profiles can be made available into the environment either on login
+or within a dedicated shell.
+
+@item
+Profiles can be loaded on demand.  For instance, the user can use multiple
+shells, each of them running different profiles.
+
+@item
+Isolation: Programs from one profile will not use programs from the other, and
+they user can even install different versions of the same programs to the two
+profiles without conflict.
+
+@item
+Deduplication: Profiles share dependencies that happens to be the exact same.
+This makes multiple profiles storage-efficient.
+
+@item
+Reproducible: when used with declarative manifests, a profile can be fully
+specified by the Guix commit that was active when it was set up.  This means
+that the exact same profile can be @uref{https://guix.gnu.org/blog/2018/multi-dimensional-transactions-and-rollbacks-oh-my/, set up anywhere, anytime}, with just the
+commit information.  See the section on @ref{Reproducible profiles}.
+
+@item
+Easier upgrades and maintenance: Multiple profiles make it easy to keep
+package listings at hand and make upgrades completely friction-less.
+@end itemize
+
+Concretely, here follows some typical profiles:
+
+@itemize
+@item
+The dependencies of a project you are working on.
+
+@item
+Your favourite programming language libraries.
+
+@item
+Laptop-specific programs (like @samp{powertop}) that you don't need on a desktop.
+
+@item
+@TeX{}live (this one can be really useful when you need to install just one
+package for this one document you've just received over email).
+
+@item
+Games.
+@end itemize
+
+Let's dive in the set up!
+
+@node Basic setup with manifests
+@subsection Basic setup with manifests
+
+A Guix profile can be set up @emph{via} a so-called @emph{manifest specification} that looks like
+this:
+
+@lisp
+(specifications->manifest
+  '("package-1"
+    ;; Version 1.3 of package-2.
+    "package-2@@1.3"
+    ;; The "lib" output of package-3.
+    "package-3:lib"
+    ; ...
+    "package-N"))
+@end lisp
+
+@pxref{Invoking guix package,,, guix, GNU Guix Reference Manual}, for
+the syntax details.
+
+We can create a manifest specification per profile and install them this way:
+
+@example
+GUIX_EXTRA_PROFILES=$HOME/.guix-extra-profiles
+mkdir -p "$GUIX_EXTRA_PROFILES"/my-project # if it does not exist yet
+guix package --manifest=/path/to/guix-my-project-manifest.scm --profile="$GUIX_EXTRA_PROFILES"/my-project/my-project
+@end example
+
+Here we set an arbitrary variable @samp{GUIX_EXTRA_PROFILES} to point to the directory
+where we will store our profiles in the rest of this article.
+
+Placing all your profiles in a single directory, with each profile getting its
+own sub-directory, is somewhat cleaner.  This way, each sub-directory will
+contain all the symlinks for precisely one profile.  Besides, "looping over
+profiles" becomes obvious from any programming language (e.g. a shell script) by
+simply looping over the sub-directories of @samp{$GUIX_EXTRA_PROFILES}.
+
+Note that it's also possible to loop over the output of
+
+@example
+guix package --list-profiles
+@end example
+
+although you'll probably have to filter out @samp{~/.config/guix/current}.
+
+To enable all profiles on login, add this to your @samp{~/.bash_profile} (or similar):
+
+@example
+for i in $GUIX_EXTRA_PROFILES/*; do
+  profile=$i/$(basename "$i")
+  if [ -f "$profile"/etc/profile ]; then
+    GUIX_PROFILE="$profile"
+    . "$GUIX_PROFILE"/etc/profile
+  fi
+  unset profile
+done
+@end example
+
+Note to Guix System users: the above reflects how your default profile
+@samp{~/.guix-profile} is activated from @samp{/etc/profile}, that latter being loaded by
+@samp{~/.bashrc} by default.
+
+You can obviously choose to only enable a subset of them:
+
+@example
+for i in "$GUIX_EXTRA_PROFILES"/my-project-1 "$GUIX_EXTRA_PROFILES"/my-project-2; do
+  profile=$i/$(basename "$i")
+  if [ -f "$profile"/etc/profile ]; then
+    GUIX_PROFILE="$profile"
+    . "$GUIX_PROFILE"/etc/profile
+  fi
+  unset profile
+done
+@end example
+
+When a profile is off, it's straightforward to enable it for an individual shell
+without "polluting" the rest of the user session:
+
+@example
+GUIX_PROFILE="path/to/my-project" ; . "$GUIX_PROFILE"/etc/profile
+@end example
+
+The key to enabling a profile is to @emph{source} its @samp{etc/profile} file.  This file
+contains shell code that exports the right environment variables necessary to
+activate the software contained in the profile.  It is built automatically by
+Guix and meant to be sourced.
+It contains the same variables you would get if you ran:
+
+@example
+guix package --search-paths=prefix --profile=$my_profile"
+@end example
+
+Once again, see (@pxref{Invoking guix package,,, guix, GNU Guix Reference Manual})
+for the command line options.
+
+To upgrade a profile, simply install the manifest again:
+
+@example
+guix package -m /path/to/guix-my-project-manifest.scm -p "$GUIX_EXTRA_PROFILES"/my-project/my-project
+@end example
+
+To upgrade all profiles, it's easy enough to loop over them.  For instance,
+assuming your manifest specifications are stored in
+@samp{~/.guix-manifests/guix-$profile-manifest.scm}, with @samp{$profile} being the name
+of the profile (e.g. "project1"), you could do the following in Bourne shell:
+
+@example
+for profile in "$GUIX_EXTRA_PROFILES"/*; do
+  guix package --profile="$profile" --manifest="$HOME/.guix-manifests/guix-$profile-manifest.scm"
+done
+@end example
+
+Each profile has its own generations:
+
+@example
+guix package -p "$GUIX_EXTRA_PROFILES"/my-project/my-project --list-generations
+@end example
+
+You can roll-back to any generation of a given profile:
+
+@example
+guix package -p "$GUIX_EXTRA_PROFILES"/my-project/my-project --switch-generations=17
+@end example
+
+@node Required packages
+@subsection Required packages
+
+Activating a profile essentially boils down to exporting a bunch of
+environmental variables.  This is the role of the @samp{etc/profile} within the
+profile.
+
+@emph{Note: Only the environmental variables of the packages that consume them will
+be set.}
+
+For instance, @samp{MANPATH} won't be set if there is no consumer application for man
+pages within the profile.  So if you need to transparently access man pages once
+the profile is loaded, you've got two options:
+
+@itemize
+@item
+Either export the variable manually, e.g.
+@example
+export MANPATH=/path/to/profile$@{MANPATH:+:@}$MANPATH"
+@end example
+
+@item
+Or include @samp{man-db} to the profile manifest.
+@end itemize
+
+The same is true for @samp{INFOPATH} (you can install @samp{info-reader}),
+@samp{PKG_CONFIG_PATH} (install @samp{pkg-config}), etc.
+
+@node Default profile
+@subsection Default profile
+
+What about the default profile that Guix keeps in @samp{~/.guix-profile}?
+
+You can assign it the role you want.  Typically you would install the manifest
+of the packages you want to use all the time.
+
+Alternatively, you could keep it "manifest-less" for throw-away packages
+that you would just use for a couple of days.
+This way makes it convenient to run
+
+@example
+guix install package-foo
+guix upgrade package-bar
+@end example
+
+without having to specify the path to a profile.
+
+@node The benefits of manifests
+@subsection The benefits of manifests
+
+Manifests are a convenient way to keep your package lists around and, say,
+to synchronize them across multiple machines using a version control system.
+
+A common complaint about manifests is that they can be slow to install when they
+contain large number of packages.  This is especially cumbersome when you just
+want get an upgrade for one package within a big manifest.
+
+This is one more reason to use multiple profiles, which happen to be just
+perfect to break down manifests into multiple sets of semantically connected
+packages.  Using multiple, small profiles provides more flexibility and
+usability.
+
+Manifests come with multiple benefits.  In particular, they ease maintenance:
+
+@itemize
+@item
+When a profile is set up from a manifest, the manifest itself is
+self-sufficient to keep a "package listing" around and reinstall the profile
+later or on a different system.  For ad-hoc profiles, we would need to
+generate a manifest specification manually and maintain the package versions
+for the packages that don't use the default version.
+
+@item
+@code{guix package --upgrade} always tries to update the packages that have
+propagated inputs, even if there is nothing to do.  Guix manifests remove this
+problem.
+
+@item
+When partially upgrading a profile, conflicts may arise (due to diverging
+dependencies between the updated and the non-updated packages) and they can be
+annoying to resolve manually.  Manifests remove this problem altogether since
+all packages are always upgraded at once.
+
+@item
+As mentioned above, manifests allow for reproducible profiles, while the
+imperative @code{guix install}, @code{guix upgrade}, etc. do not, since they produce
+different profiles every time even when they hold the same packages.  See
+@uref{https://issues.guix.gnu.org/issue/33285, the related discussion on the matter}.
+
+@item
+Manifest specifications are usable by other @samp{guix} commands.  For example, you
+can run @code{guix weather -m manifest.scm} to see how many substitutes are
+available, which can help you decide whether you want to try upgrading today
+or wait a while.  Another example: you can run @code{guix pack -m manifest.scm} to
+create a pack containing all the packages in the manifest (and their
+transitive references).
+
+@item
+Finally, manifests have a Scheme representation, the @samp{<manifest>} record type.
+They can be manipulated in Scheme and passed to the various Guix @uref{https://en.wikipedia.org/wiki/Api, APIs}.
+@end itemize
+
+It's important to understand that while manifests can be used to declare
+profiles, they are not strictly equivalent: profiles have the side effect that
+they "pin" packages in the store, which prevents them from being
+garbage-collected (@pxref{Invoking guix gc,,, guix, GNU Guix Reference Manual})
+and ensures that they will still be available at any point in
+the future.
+
+Let's take an example:
+
+@enumerate
+@item
+We have an environment for hacking on a project for which there isn't a Guix
+package yet.  We build the environment using a manifest, and then run @code{guix
+   environment -m manifest.scm}.  So far so good.
+
+@item
+Many weeks pass and we have run a couple of @code{guix pull} in the mean time.
+Maybe a dependency from our manifest has been updated; or we may have run
+@code{guix gc} and some packages needed by our manifest have been
+garbage-collected.
+
+@item
+Eventually, we set to work on that project again, so we run @code{guix environment
+   -m manifest.scm}.  But now we have to wait for Guix to build and install
+stuff!
+@end enumerate
+
+Ideally, we could spare the rebuild time.  And indeed we can, all we need is to
+install the manifest to a profile and use @code{GUIX_PROFILE=/the/profile;
+. "$GUIX_PROFILE"/etc/profile} as explained above: this guarantees that our
+hacking environment will be available at all times.
+
+@emph{Security warning:} While keeping old profiles around can be convenient, keep in
+mind that outdated packages may not have received the latest security fixes.
+
+@node Reproducible profiles
+@subsection Reproducible profiles
+
+To reproduce a profile bit-for-bit, we need two pieces of information:
+
+@itemize
+@item
+a manifest,
+@item
+a Guix channel specification.
+@end itemize
+
+Indeed, manifests alone might not be enough: different Guix versions (or
+different channels) can produce different outputs for a given manifest.
+
+You can output the Guix channel specification with @samp{guix describe
+--format=channels}.
+Save this to a file, say @samp{channel-specs.scm}.
+
+On another computer, you can use the channel specification file and the manifest
+to reproduce the exact same profile:
+
+@example
+GUIX_EXTRA_PROFILES=$HOME/.guix-extra-profiles
+GUIX_EXTRA=$HOME/.guix-extra
+
+mkdir "$GUIX_EXTRA"/my-project
+guix pull --channels=channel-specs.scm --profile "$GUIX_EXTRA/my-project/guix"
+
+mkdir -p "$GUIX_EXTRA_PROFILES/my-project"
+"$GUIX_EXTRA"/my-project/guix/bin/guix package --manifest=/path/to/guix-my-project-manifest.scm --profile="$GUIX_EXTRA_PROFILES"/my-project/my-project
+@end example
+
+It's safe to delete the Guix channel profile you've just installed with the
+channel specification, the project profile does not depend on it.
+
+@c *********************************************************************
 @node Acknowledgments
 @chapter Acknowledgments