summary refs log tree commit diff
path: root/doc/guix-cookbook.texi
blob: 1b081a820ed3acfc4ddd30f29afdebd21b8d802c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
\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
* Advanced package management:: Power to the users!

* 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:

@lisp
> "Hello World!"
"Hello World!"
> 17
17
> (display (string-append "Hello " "Guix" "\n"))
"Hello Guix!"
@end lisp

@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:

@lisp
> (lambda (x) (* x x))
#<procedure 120e348 at <unknown port>:24:0 (x)>
@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:

@lisp
> ((lambda (x) (* x x)) 3)
9
@end lisp

@item
Anything can be assigned a global name with @code{define}:

@lisp
> (define a 3)
> (define square (lambda (x) (* x x)))
> (square a)
9
@end lisp

@item
Procedures can be defined more concisely with the following syntax:

@lisp
(define (square x) (* x x))
@end lisp

@item
A list structure can be created with the @code{list} procedure:

@lisp
> (list 2 a 5 7)
(2 3 5 7)
@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.

@lisp
> '(display (string-append "Hello " "Guix" "\n"))
(display (string-append "Hello " "Guix" "\n"))
> '(2 a 5 7)
(2 a 5 7)
@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.

@lisp
> `(2 a 5 7 (2 ,a 5 ,(+ a 4)))
(2 a 5 7 (2 3 5 7))
@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.

@item
Multiple variables can be named locally with @code{let}:

@lisp
> (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 lisp

Use @code{let*} to allow later variable declarations to refer to earlier
definitions.

@lisp
> (let* ((x 2)
         (y (* x 3)))
    (list x y))
(2 6)
@end lisp

@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

@lisp
(define-module (guix build-system ruby)
  #:use-module (guix store)
  #:export (ruby-build
            ruby-build-system))
@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
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:

@lisp
(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 lisp

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}.

@lisp
(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 lisp

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.

@lisp
(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 lisp

The current @code{linux-libre} package is for the 5.1.x series, and is
declared like this:

@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 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,
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:

@lisp
(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 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:

@lisp
(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 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
@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:

@lisp
(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 lisp

And in the custom configure script from the `make-linux-libre` package:

@lisp
;; 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 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:

@lisp
(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 lisp

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 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

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: