gnu: Add libdbusmenu.
[guix.git] / guix / self.scm
blob6d7569ec190f94a2c365adbbf0038988377f47fe
1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
3 ;;;
4 ;;; This file is part of GNU Guix.
5 ;;;
6 ;;; GNU Guix is free software; you can redistribute it and/or modify it
7 ;;; under the terms of the GNU General Public License as published by
8 ;;; the Free Software Foundation; either version 3 of the License, or (at
9 ;;; your option) any later version.
10 ;;;
11 ;;; GNU Guix is distributed in the hope that it will be useful, but
12 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ;;; GNU General Public License for more details.
15 ;;;
16 ;;; You should have received a copy of the GNU General Public License
17 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
19 (define-module (guix self)
20   #:use-module (guix config)
21   #:use-module (guix i18n)
22   #:use-module (guix modules)
23   #:use-module (guix gexp)
24   #:use-module (guix store)
25   #:use-module (guix monads)
26   #:use-module (guix discovery)
27   #:use-module (guix packages)
28   #:use-module (guix sets)
29   #:use-module (guix modules)
30   #:use-module ((guix build utils) #:select (find-files))
31   #:use-module ((guix build compile) #:select (%lightweight-optimizations))
32   #:use-module (srfi srfi-1)
33   #:use-module (srfi srfi-9)
34   #:use-module (srfi srfi-35)
35   #:use-module (ice-9 match)
36   #:export (make-config.scm
37             whole-package                     ;for internal use in 'guix pull'
38             compiled-guix
39             guix-derivation))
42 ;;;
43 ;;; Dependency handling.
44 ;;;
46 (define specification->package
47   ;; Use our own variant of that procedure because that of (gnu packages)
48   ;; would traverse all the .scm files, which is wasteful.
49   (let ((ref (lambda (module variable)
50                (module-ref (resolve-interface module) variable))))
51     (match-lambda
52       ("guile"      (ref '(gnu packages commencement) 'guile-final))
53       ("guile-json" (ref '(gnu packages guile) 'guile-json))
54       ("guile-ssh"  (ref '(gnu packages ssh)   'guile-ssh))
55       ("guile-git"  (ref '(gnu packages guile) 'guile-git))
56       ("guile-sqlite3" (ref '(gnu packages guile) 'guile-sqlite3))
57       ("guile-gcrypt"  (ref '(gnu packages gnupg) 'guile-gcrypt))
58       ("gnutls"     (ref '(gnu packages tls) 'gnutls))
59       ("zlib"       (ref '(gnu packages compression) 'zlib))
60       ("gzip"       (ref '(gnu packages compression) 'gzip))
61       ("bzip2"      (ref '(gnu packages compression) 'bzip2))
62       ("xz"         (ref '(gnu packages compression) 'xz))
63       ("po4a"       (ref '(gnu packages gettext) 'po4a))
64       ("gettext"       (ref '(gnu packages gettext) 'gettext-minimal))
65       (_            #f))))                        ;no such package
68 ;;;
69 ;;; Derivations.
70 ;;;
72 ;; Node in a DAG of build tasks.  Each node maps to a derivation, but it's
73 ;; easier to express things this way.
74 (define-record-type <node>
75   (node name modules source dependencies compiled)
76   node?
77   (name          node-name)                       ;string
78   (modules       node-modules)                    ;list of module names
79   (source        node-source)                     ;list of source files
80   (dependencies  node-dependencies)               ;list of nodes
81   (compiled      node-compiled))                  ;node -> lowerable object
83 ;; File mappings are essentially an alist as passed to 'imported-files'.
84 (define-record-type <file-mapping>
85   (file-mapping name alist)
86   file-mapping?
87   (name  file-mapping-name)
88   (alist file-mapping-alist))
90 (define-gexp-compiler (file-mapping-compiler (mapping <file-mapping>)
91                                              system target)
92   ;; Here we use 'imported-files', which can arrange to directly import all
93   ;; the files instead of creating a derivation, when possible.
94   (imported-files (map (match-lambda
95                          ((destination (? local-file? file))
96                           (cons destination
97                                 (local-file-absolute-file-name file)))
98                          ((destination source)
99                           (cons destination source))) ;silliness
100                        (file-mapping-alist mapping))
101                   #:name (file-mapping-name mapping)
102                   #:system system))
104 (define (node-source+compiled node)
105   "Return a \"bundle\" containing both the source code and object files for
106 NODE's modules, under their FHS directories: share/guile/site and lib/guile."
107   (define build
108     (with-imported-modules '((guix build utils))
109       #~(begin
110           (use-modules (guix build utils))
112           (define source
113             (string-append #$output "/share/guile/site/"
114                            (effective-version)))
116           (define object
117             (string-append #$output "/lib/guile/" (effective-version)
118                            "/site-ccache"))
120           (mkdir-p (dirname source))
121           (symlink #$(node-source node) source)
122           (mkdir-p (dirname object))
123           (symlink #$(node-compiled node) object))))
125   (computed-file (string-append (node-name node) "-modules")
126                  build))
128 (define (node-fold proc init nodes)
129   (let loop ((nodes nodes)
130              (visited (setq))
131              (result init))
132     (match nodes
133       (() result)
134       ((head tail ...)
135        (if (set-contains? visited head)
136            (loop tail visited result)
137            (loop tail (set-insert head visited)
138                  (proc head result)))))))
140 (define (node-modules/recursive nodes)
141   (node-fold (lambda (node modules)
142                (append (node-modules node) modules))
143              '()
144              nodes))
146 (define* (closure modules #:optional (except '()))
147   (source-module-closure modules
148                          #:select?
149                          (match-lambda
150                            (('guix 'config)
151                             #f)
152                            ((and module
153                                  (or ('guix _ ...) ('gnu _ ...)))
154                             (not (member module except)))
155                            (rest #f))))
157 (define module->import
158   ;; Return a file-name/file-like object pair for the specified module and
159   ;; suitable for 'imported-files'.
160   (match-lambda
161     ((module '=> thing)
162      (let ((file (module-name->file-name module)))
163        (list file thing)))
164     (module
165         (let ((file (module-name->file-name module)))
166           (list file
167                 (local-file (search-path %load-path file)))))))
169 (define* (scheme-node name modules #:optional (dependencies '())
170                       #:key (extra-modules '()) (extra-files '())
171                       (extensions '())
172                       parallel? guile-for-build)
173   "Return a node that builds the given Scheme MODULES, and depends on
174 DEPENDENCIES (a list of nodes).  EXTRA-MODULES is a list of additional modules
175 added to the source, and EXTRA-FILES is a list of additional files.
176 EXTENSIONS is a set of full-blown Guile packages (e.g., 'guile-json') that
177 must be present in the search path."
178   (let* ((modules (append extra-modules
179                           (closure modules
180                                    (node-modules/recursive dependencies))))
181          (module-files (map module->import modules))
182          (source (file-mapping (string-append name "-source")
183                                (append module-files extra-files))))
184     (node name modules source dependencies
185           (compiled-modules name source
186                             (map car module-files)
187                             (map node-source dependencies)
188                             (map node-compiled dependencies)
189                             #:extensions extensions
190                             #:parallel? parallel?
191                             #:guile-for-build guile-for-build))))
193 (define (file-imports directory sub-directory pred)
194   "List all the files matching PRED under DIRECTORY/SUB-DIRECTORY.  Return a
195 list of file-name/file-like objects suitable as inputs to 'imported-files'."
196   (map (lambda (file)
197          (list (string-drop file (+ 1 (string-length directory)))
198                (local-file file #:recursive? #t)))
199        (find-files (string-append directory "/" sub-directory) pred)))
201 (define* (file-append* item file #:key (recursive? #t))
202   "Return FILE within ITEM, which may be a file name or a file-like object.
203 When ITEM is a plain file name (a string), simply return a 'local-file'
204 record with the new file name."
205   (match item
206     ((? string?)
207      ;; This is the optimal case: we return a new "source".  Thus, a
208      ;; derivation that depends on this sub-directory does not depend on ITEM
209      ;; itself.
210      (local-file (string-append item "/" file)
211                  #:recursive? recursive?))
212     ;; TODO: Add 'local-file?' case.
213     (_
214      ;; In this case, anything that refers to the result also depends on ITEM,
215      ;; which isn't great.
216      (file-append item "/" file))))
218 (define* (locale-data source domain
219                       #:optional (directory domain))
220   "Return the locale data from 'po/DIRECTORY' in SOURCE, corresponding to
221 DOMAIN, a gettext domain."
222   (define gettext
223     (module-ref (resolve-interface '(gnu packages gettext))
224                 'gettext-minimal))
226   (define build
227     (with-imported-modules '((guix build utils))
228       #~(begin
229           (use-modules (guix build utils)
230                        (srfi srfi-26)
231                        (ice-9 match) (ice-9 ftw))
233           (define po-directory
234             #+(file-append* source (string-append "po/" directory)))
236           (define (compile language)
237             (let ((gmo (string-append #$output "/" language "/LC_MESSAGES/"
238                                       #$domain ".mo")))
239               (mkdir-p (dirname gmo))
240               (invoke #+(file-append gettext "/bin/msgfmt")
241                       "-c" "--statistics" "--verbose"
242                       "-o" gmo
243                       (string-append po-directory "/" language ".po"))))
245           (define (linguas)
246             ;; Return the list of languages.  Note: don't read 'LINGUAS'
247             ;; because it contains things like 'en@boldquot' that do not have
248             ;; a corresponding .po file.
249             (map (cut basename <> ".po")
250                  (scandir po-directory
251                           (cut string-suffix? ".po" <>))))
253           (for-each compile (linguas)))))
255   (computed-file (string-append "guix-locale-" domain)
256                  build))
258 (define (translate-texi-manuals source)
259   "Return the translated texinfo manuals built from SOURCE."
260   (define po4a
261     (specification->package "po4a"))
262   
263   (define gettext
264     (specification->package "gettext"))
266   (define glibc-utf8-locales
267     (module-ref (resolve-interface '(gnu packages base))
268                 'glibc-utf8-locales))
270   (define documentation
271     (file-append* source "doc"))
273   (define documentation-po
274     (file-append* source "po/doc"))
275   
276   (define build
277     (with-imported-modules '((guix build utils) (guix build po))
278       #~(begin
279           (use-modules (guix build utils) (guix build po)
280                        (ice-9 match) (ice-9 regex) (ice-9 textual-ports)
281                        (srfi srfi-1))
283           (mkdir #$output)
285           (copy-recursively #$documentation "."
286                             #:log (%make-void-port "w"))
288           (for-each
289             (lambda (file)
290               (copy-file file (basename file)))
291             (find-files #$documentation-po ".*.po$"))
293           (setenv "GUIX_LOCPATH"
294                   #+(file-append glibc-utf8-locales "/lib/locale"))
295           (setenv "PATH" #+(file-append gettext "/bin"))
296           (setenv "LC_ALL" "en_US.UTF-8")
297           (setlocale LC_ALL "en_US.UTF-8")
299           (define (translate-tmp-texi po source output)
300             "Translate Texinfo file SOURCE using messages from PO, and write
301 the result to OUTPUT."
302             (invoke #+(file-append po4a "/bin/po4a-translate")
303               "-M" "UTF-8" "-L" "UTF-8" "-k" "0" "-f" "texinfo"
304               "-m" source "-p" po "-l" output))
306           (define (make-ref-regex msgid end)
307             (make-regexp (string-append
308                            "ref\\{"
309                            (string-join (string-split (regexp-quote msgid) #\ )
310                                         "[ \n]+")
311                            end)))
313           (define (translate-cross-references content translations)
314             "Take CONTENT, a string representing a .texi file and translate any
315 cross-reference in it (@ref, @xref and @pxref) that have a translation in
316 TRANSLATIONS, an alist of msgid and msgstr."
317             (fold
318               (lambda (elem content)
319                 (match elem
320                   ((msgid . msgstr)
321                    ;; Empty translations and strings containing some special characters
322                    ;; cannot be the name of a section.
323                    (if (or (equal? msgstr "")
324                            (string-any (lambda (chr)
325                                          (member chr '(#\{ #\} #\( #\) #\newline #\,)))
326                                        msgid))
327                        content
328                        ;; Otherwise, they might be the name of a section, so we
329                        ;; need to translate any occurence in @(p?x?)ref{...}.
330                        (let ((regexp1 (make-ref-regex msgid ","))
331                              (regexp2 (make-ref-regex msgid "\\}")))
332                          (regexp-substitute/global
333                            #f regexp2
334                            (regexp-substitute/global
335                              #f regexp1 content 'pre "ref{" msgstr "," 'post)
336                            'pre "ref{" msgstr "}" 'post))))))
337               content translations))
338           
339           (define (translate-texi po lang)
340             "Translate the manual for one language LANG using the PO file."
341             (let ((translations (call-with-input-file po read-po-file)))
342               (translate-tmp-texi po "guix.texi"
343                                   (string-append "guix." lang ".texi.tmp"))
344               (translate-tmp-texi po "contributing.texi"
345                                   (string-append "contributing." lang ".texi.tmp"))
346               (let* ((texi-name (string-append "guix." lang ".texi"))
347                      (tmp-name (string-append texi-name ".tmp")))
348                 (with-output-to-file texi-name
349                   (lambda _
350                     (format #t "~a"
351                       (translate-cross-references
352                         (call-with-input-file tmp-name get-string-all)
353                         translations)))))
354               (let* ((texi-name (string-append "contributing." lang ".texi"))
355                      (tmp-name (string-append texi-name ".tmp")))
356                 (with-output-to-file texi-name
357                   (lambda _
358                     (format #t "~a"
359                       (translate-cross-references
360                         (call-with-input-file tmp-name get-string-all)
361                         translations)))))))
363           (for-each (lambda (po)
364                       (match (reverse (string-split po #\.))
365                         ((_ lang _ ...)
366                          (translate-texi po lang))))
367                     (find-files "." "^guix-manual\\.[a-z]{2}(_[A-Z]{2})?\\.po$"))
369           (for-each
370             (lambda (file)
371               (copy-file file (string-append #$output "/" file)))
372             (append
373               (find-files "." "contributing\\..*\\.texi$")
374               (find-files "." "guix\\..*\\.texi$"))))))
376   (computed-file "guix-translated-texinfo" build))
378 (define (info-manual source)
379   "Return the Info manual built from SOURCE."
380   (define texinfo
381     (module-ref (resolve-interface '(gnu packages texinfo))
382                 'texinfo))
384   (define graphviz
385     (module-ref (resolve-interface '(gnu packages graphviz))
386                 'graphviz))
388   (define glibc-utf8-locales
389     (module-ref (resolve-interface '(gnu packages base))
390                 'glibc-utf8-locales))
392   (define documentation
393     (file-append* source "doc"))
395   (define examples
396     (file-append* source "gnu/system/examples"))
398   (define build
399     (with-imported-modules '((guix build utils))
400       #~(begin
401           (use-modules (guix build utils))
403           (mkdir #$output)
405           ;; Create 'version.texi'.
406           ;; XXX: Can we use a more meaningful version string yet one that
407           ;; doesn't change at each commit?
408           (call-with-output-file "version.texi"
409             (lambda (port)
410               (let ((version "0.0-git"))
411                 (format port "
412 @set UPDATED 1 January 1970
413 @set UPDATED-MONTH January 1970
414 @set EDITION ~a
415 @set VERSION ~a\n" version version))))
417           ;; Copy configuration templates that the manual includes.
418           (for-each (lambda (template)
419                       (copy-file template
420                                  (string-append
421                                   "os-config-"
422                                   (basename template ".tmpl")
423                                   ".texi")))
424                     (find-files #$examples "\\.tmpl$"))
426           ;; Build graphs.
427           (mkdir-p (string-append #$output "/images"))
428           (for-each (lambda (dot-file)
429                       (invoke #+(file-append graphviz "/bin/dot")
430                               "-Tpng" "-Gratio=.9" "-Gnodesep=.005"
431                               "-Granksep=.00005" "-Nfontsize=9"
432                               "-Nheight=.1" "-Nwidth=.1"
433                               "-o" (string-append #$output "/images/"
434                                                   (basename dot-file ".dot")
435                                                   ".png")
436                               dot-file))
437                     (find-files (string-append #$documentation "/images")
438                                 "\\.dot$"))
440           ;; Copy other PNGs.
441           (for-each (lambda (png-file)
442                       (install-file png-file
443                                     (string-append #$output "/images")))
444                     (find-files (string-append #$documentation "/images")
445                                 "\\.png$"))
447           ;; Finally build the manual.  Copy it the Texinfo files to $PWD and
448           ;; add a symlink to the 'images' directory so that 'makeinfo' can
449           ;; see those images and produce image references in the Info output.
450           (copy-recursively #$documentation "."
451                             #:log (%make-void-port "w"))
452           (copy-recursively #+(translate-texi-manuals source) "."
453                             #:log (%make-void-port "w"))
454           (delete-file-recursively "images")
455           (symlink (string-append #$output "/images") "images")
457           ;; Provide UTF-8 locales needed by the 'xspara.c' code in makeinfo.
458           (setenv "GUIX_LOCPATH"
459                   #+(file-append glibc-utf8-locales "/lib/locale"))
461           (for-each (lambda (texi)
462                       (unless (string=? "guix.texi" texi)
463                         ;; Create 'version-LL.texi'.
464                         (let* ((base (basename texi ".texi"))
465                                (dot  (string-index base #\.))
466                                (tag  (string-drop base (+ 1 dot))))
467                           (symlink "version.texi"
468                                    (string-append "version-" tag ".texi"))))
470                       (invoke #+(file-append texinfo "/bin/makeinfo")
471                               texi "-I" #$documentation
472                               "-I" "."
473                               "-o" (string-append #$output "/"
474                                                   (basename texi ".texi")
475                                                   ".info")))
476                     (cons "guix.texi"
477                           (find-files "." "^guix\\.[a-z]{2}(_[A-Z]{2})?\\.texi$")))
479           ;; Compress Info files.
480           (setenv "PATH"
481                   #+(file-append (specification->package "gzip") "/bin"))
482           (for-each (lambda (file)
483                       (invoke "gzip" "-9n" file))
484                     (find-files #$output "\\.info(-[0-9]+)?$")))))
486   (computed-file "guix-manual" build))
488 (define* (guile-module-union things #:key (name "guix-module-union"))
489   "Return the union of the subset of THINGS (packages, computed files, etc.)
490 that provide Guile modules."
491   (define build
492     (with-imported-modules '((guix build union))
493       #~(begin
494           (use-modules (guix build union))
496           (define (modules directory)
497             (string-append directory "/share/guile/site"))
499           (define (objects directory)
500             (string-append directory "/lib/guile"))
502           (union-build #$output
503                        (filter (lambda (directory)
504                                  (or (file-exists? (modules directory))
505                                      (file-exists? (objects directory))))
506                                '#$things)
508                        #:log-port (%make-void-port "w")))))
510   (computed-file name build))
512 (define* (guix-command modules
513                        #:key source (dependencies '())
514                        guile (guile-version (effective-version)))
515   "Return the 'guix' command such that it adds MODULES and DEPENDENCIES in its
516 load path."
517   (define glibc-utf8-locales
518     (module-ref (resolve-interface '(gnu packages base))
519                 'glibc-utf8-locales))
521   (define module-directory
522     ;; To minimize the number of 'stat' calls needed to locate a module,
523     ;; create the union of all the module directories.
524     (guile-module-union (cons modules dependencies)))
526   (program-file "guix-command"
527                 #~(begin
528                     (set! %load-path
529                       (cons (string-append #$module-directory
530                                            "/share/guile/site/"
531                                            (effective-version))
532                             %load-path))
534                     (set! %load-compiled-path
535                       (cons (string-append #$module-directory
536                                            "/lib/guile/"
537                                            (effective-version)
538                                            "/site-ccache")
539                             %load-compiled-path))
541                     ;; To maximize the chances that locales are set up right
542                     ;; out-of-the-box, bundle "common" UTF-8 locales.
543                     (let ((locpath (getenv "GUIX_LOCPATH")))
544                       (setenv "GUIX_LOCPATH"
545                               (string-append (if locpath
546                                                  (string-append locpath ":")
547                                                  "")
548                                              #$(file-append glibc-utf8-locales
549                                                             "/lib/locale"))))
551                     (let ((guix-main (module-ref (resolve-interface '(guix ui))
552                                                  'guix-main)))
553                       #$(if source
554                             #~(begin
555                                 (bindtextdomain "guix"
556                                                 #$(locale-data source "guix"))
557                                 (bindtextdomain "guix-packages"
558                                                 #$(locale-data source
559                                                                "guix-packages"
560                                                                "packages")))
561                             #t)
563                       ;; XXX: It would be more convenient to change it to:
564                       ;;   (exit (apply guix-main (command-line)))
565                       (apply guix-main (command-line))))
566                 #:guile guile))
568 (define (miscellaneous-files source)
569   "Return data files taken from SOURCE."
570   (file-mapping "guix-misc"
571                 `(("etc/bash_completion.d/guix"
572                    ,(file-append* source "/etc/completion/bash/guix"))
573                   ("etc/bash_completion.d/guix-daemon"
574                    ,(file-append* source "/etc/completion/bash/guix-daemon"))
575                   ("share/zsh/site-functions/_guix"
576                    ,(file-append* source "/etc/completion/zsh/_guix"))
577                   ("share/fish/vendor_completions.d/guix.fish"
578                    ,(file-append* source "/etc/completion/fish/guix.fish"))
579                   ("share/guix/hydra.gnu.org.pub"
580                    ,(file-append* source
581                                   "/etc/substitutes/hydra.gnu.org.pub"))
582                   ("share/guix/berlin.guixsd.org.pub"
583                    ,(file-append* source
584                                   "/etc/substitutes/berlin.guixsd.org.pub"))
585                   ("share/guix/ci.guix.gnu.org.pub"  ;alias
586                    ,(file-append* source "/etc/substitutes/berlin.guixsd.org.pub"))
587                   ("share/guix/ci.guix.info.pub"  ;alias
588                    ,(file-append* source "/etc/substitutes/berlin.guixsd.org.pub")))))
590 (define* (whole-package name modules dependencies
591                         #:key
592                         (guile-version (effective-version))
593                         info daemon miscellany
594                         guile
595                         (command (guix-command modules
596                                                #:dependencies dependencies
597                                                #:guile guile
598                                                #:guile-version guile-version)))
599   "Return the whole Guix package NAME that uses MODULES, a derivation of all
600 the modules (under share/guile/site and lib/guile), and DEPENDENCIES, a list
601 of packages depended on.  COMMAND is the 'guix' program to use; INFO is the
602 Info manual."
603   (define (wrap daemon)
604     (program-file "guix-daemon"
605                   #~(begin
606                       (setenv "GUIX" #$command)
607                       (apply execl #$(file-append daemon "/bin/guix-daemon")
608                              "guix-daemon" (cdr (command-line))))))
610   (computed-file name
611                  (with-imported-modules '((guix build utils))
612                    #~(begin
613                        (use-modules (guix build utils))
615                        (define daemon
616                          #$(and daemon (wrap daemon)))
618                        (mkdir-p (string-append #$output "/bin"))
619                        (symlink #$command
620                                 (string-append #$output "/bin/guix"))
622                        (when daemon
623                          (symlink daemon
624                                   (string-append #$output "/bin/guix-daemon")))
626                        (let ((share (string-append #$output "/share"))
627                              (lib   (string-append #$output "/lib"))
628                              (info  #$info))
629                          (mkdir-p share)
630                          (symlink #$(file-append modules "/share/guile")
631                                   (string-append share "/guile"))
632                          (when info
633                            (symlink #$info (string-append share "/info")))
635                          (mkdir-p lib)
636                          (symlink #$(file-append modules "/lib/guile")
637                                   (string-append lib "/guile")))
639                        (when #$miscellany
640                          (copy-recursively #$miscellany #$output
641                                            #:log (%make-void-port "w")))))))
643 (define* (compiled-guix source #:key (version %guix-version)
644                         (pull-version 1)
645                         (name (string-append "guix-" version))
646                         (guile-version (effective-version))
647                         (guile-for-build (default-guile))
648                         (zlib (specification->package "zlib"))
649                         (gzip (specification->package "gzip"))
650                         (bzip2 (specification->package "bzip2"))
651                         (xz (specification->package "xz"))
652                         (guix (specification->package "guix")))
653   "Return a file-like object that contains a compiled Guix."
654   (define guile-json
655     (specification->package "guile-json"))
657   (define guile-ssh
658     (specification->package "guile-ssh"))
660   (define guile-git
661     (specification->package "guile-git"))
663   (define guile-sqlite3
664     (specification->package "guile-sqlite3"))
666   (define guile-gcrypt
667     (specification->package "guile-gcrypt"))
669   (define gnutls
670     (specification->package "gnutls"))
672   (define dependencies
673     (match (append-map (lambda (package)
674                          (cons (list "x" package)
675                                (package-transitive-propagated-inputs package)))
676                        (list guile-gcrypt gnutls guile-git guile-json
677                              guile-ssh guile-sqlite3))
678       (((labels packages _ ...) ...)
679        packages)))
681   (define *core-modules*
682     (scheme-node "guix-core"
683                  '((guix)
684                    (guix monad-repl)
685                    (guix packages)
686                    (guix download)
687                    (guix discovery)
688                    (guix profiles)
689                    (guix build-system gnu)
690                    (guix build-system trivial)
691                    (guix build profiles)
692                    (guix build gnu-build-system))
694                  ;; Provide a dummy (guix config) with the default version
695                  ;; number, storedir, etc.  This is so that "guix-core" is the
696                  ;; same across all installations and doesn't need to be
697                  ;; rebuilt when the version changes, which in turn means we
698                  ;; can have substitutes for it.
699                  #:extra-modules
700                  `(((guix config) => ,(make-config.scm)))
702                  ;; (guix man-db) is needed at build-time by (guix profiles)
703                  ;; but we don't need to compile it; not compiling it allows
704                  ;; us to avoid an extra dependency on guile-gdbm-ffi.
705                  #:extra-files
706                  `(("guix/man-db.scm" ,(local-file "../guix/man-db.scm"))
707                    ("guix/build/po.scm" ,(local-file "../guix/build/po.scm"))
708                    ("guix/store/schema.sql"
709                     ,(local-file "../guix/store/schema.sql")))
711                  #:extensions (list guile-gcrypt)
712                  #:guile-for-build guile-for-build))
714   (define *extra-modules*
715     (scheme-node "guix-extra"
716                  (filter-map (match-lambda
717                                (('guix 'scripts _ ..1) #f)
718                                (('guix 'man-db) #f)
719                                (name name))
720                              (scheme-modules* source "guix"))
721                  (list *core-modules*)
722                  #:extensions dependencies
723                  #:guile-for-build guile-for-build))
725   (define *core-package-modules*
726     (scheme-node "guix-packages-base"
727                  `((gnu packages)
728                    (gnu packages base))
729                  (list *core-modules* *extra-modules*)
730                  #:extensions dependencies
732                  ;; Add all the non-Scheme files here.  We must do it here so
733                  ;; that 'search-patches' & co. can find them.  Ideally we'd
734                  ;; keep them next to the .scm files that use them but it's
735                  ;; difficult to do (XXX).
736                  #:extra-files
737                  (file-imports source "gnu/packages"
738                                (lambda (file stat)
739                                  (and (eq? 'regular (stat:type stat))
740                                       (not (string-suffix? ".scm" file))
741                                       (not (string-suffix? ".go" file))
742                                       (not (string-prefix? ".#" file))
743                                       (not (string-suffix? "~" file)))))
744                  #:guile-for-build guile-for-build))
746   (define *package-modules*
747     (scheme-node "guix-packages"
748                  (scheme-modules* source "gnu/packages")
749                  (list *core-modules* *extra-modules* *core-package-modules*)
750                  #:extensions dependencies
751                  #:guile-for-build guile-for-build))
753   (define *system-modules*
754     (scheme-node "guix-system"
755                  `((gnu system)
756                    (gnu services)
757                    ,@(scheme-modules* source "gnu/bootloader")
758                    ,@(scheme-modules* source "gnu/system")
759                    ,@(scheme-modules* source "gnu/services"))
760                  (list *core-package-modules* *package-modules*
761                        *extra-modules* *core-modules*)
762                  #:extensions dependencies
763                  #:extra-files
764                  (append (file-imports source "gnu/system/examples"
765                                        (const #t))
767                          ;; All the installer code is on the build-side.
768                          (file-imports source "gnu/installer/"
769                                        (const #t))
770                          ;; Build-side code that we don't build.  Some of
771                          ;; these depend on guile-rsvg, the Shepherd, etc.
772                          (file-imports source "gnu/build" (const #t)))
773                  #:guile-for-build
774                  guile-for-build))
776   (define *cli-modules*
777     (scheme-node "guix-cli"
778                  (append (scheme-modules* source "/guix/scripts")
779                          `((gnu ci)))
780                  (list *core-modules* *extra-modules*
781                        *core-package-modules* *package-modules*
782                        *system-modules*)
783                  #:extensions dependencies
784                  #:guile-for-build guile-for-build))
786   (define *system-test-modules*
787     ;; Ship these modules mostly so (gnu ci) can discover them.
788     (scheme-node "guix-system-tests"
789                  `((gnu tests)
790                    ,@(scheme-modules* source "gnu/tests"))
791                  (list *core-package-modules* *package-modules*
792                        *extra-modules* *system-modules* *core-modules*
793                        *cli-modules*)           ;for (guix scripts pack), etc.
794                  #:extensions dependencies
795                  #:guile-for-build guile-for-build))
797   (define *config*
798     (scheme-node "guix-config"
799                  '()
800                  #:extra-modules
801                  `(((guix config)
802                     => ,(make-config.scm #:zlib zlib
803                                          #:gzip gzip
804                                          #:bzip2 bzip2
805                                          #:xz xz
806                                          #:package-name
807                                          %guix-package-name
808                                          #:package-version
809                                          version
810                                          #:bug-report-address
811                                          %guix-bug-report-address
812                                          #:home-page-url
813                                          %guix-home-page-url)))
814                  #:guile-for-build guile-for-build))
816   (define (built-modules node-subset)
817     (directory-union (string-append name "-modules")
818                      (append-map node-subset
820                                  ;; Note: *CONFIG* comes first so that it
821                                  ;; overrides the (guix config) module that
822                                  ;; comes with *CORE-MODULES*.
823                                  (list *config*
824                                        *cli-modules*
825                                        *system-test-modules*
826                                        *system-modules*
827                                        *package-modules*
828                                        *core-package-modules*
829                                        *extra-modules*
830                                        *core-modules*))
832                      ;; Silently choose the first entry upon collision so that
833                      ;; we choose *CONFIG*.
834                      #:resolve-collision 'first
836                      ;; When we do (add-to-store "utils.scm"), "utils.scm" must
837                      ;; be a regular file, not a symlink.  Thus, arrange so that
838                      ;; regular files appear as regular files in the final
839                      ;; output.
840                      #:copy? #t
841                      #:quiet? #t))
843   ;; Version 0 of 'guix pull' meant we'd just return Scheme modules.
844   ;; Version 1 is when we return the full package.
845   (cond ((= 1 pull-version)
846          ;; The whole package, with a standard file hierarchy.
847          (let* ((modules  (built-modules (compose list node-source+compiled)))
848                 (command  (guix-command modules
849                                         #:source source
850                                         #:dependencies dependencies
851                                         #:guile guile-for-build
852                                         #:guile-version guile-version)))
853            (whole-package name modules dependencies
854                           #:command command
855                           #:guile guile-for-build
857                           ;; Include 'guix-daemon'.  XXX: Here we inject an
858                           ;; older snapshot of guix-daemon, but that's a good
859                           ;; enough approximation for now.
860                           #:daemon (module-ref (resolve-interface
861                                                 '(gnu packages
862                                                       package-management))
863                                                'guix-daemon)
865                           #:info (info-manual source)
866                           #:miscellany (miscellaneous-files source)
867                           #:guile-version guile-version)))
868         ((= 0 pull-version)
869          ;; Legacy 'guix pull': return the .scm and .go files as one
870          ;; directory.
871          (built-modules (lambda (node)
872                           (list (node-source node)
873                                 (node-compiled node)))))
874         (else
875          ;; Unsupported 'guix pull' version.
876          #f)))
880 ;;; Generating (guix config).
883 (define %persona-variables
884   ;; (guix config) variables that define Guix's persona.
885   '(%guix-package-name
886     %guix-version
887     %guix-bug-report-address
888     %guix-home-page-url))
890 (define %config-variables
891   ;; (guix config) variables corresponding to Guix configuration.
892   (letrec-syntax ((variables (syntax-rules ()
893                                ((_)
894                                 '())
895                                ((_ variable rest ...)
896                                 (cons `(variable . ,variable)
897                                       (variables rest ...))))))
898     (variables %localstatedir %storedir %sysconfdir)))
900 (define* (make-config.scm #:key zlib gzip xz bzip2
901                           (package-name "GNU Guix")
902                           (package-version "0")
903                           (bug-report-address "bug-guix@gnu.org")
904                           (home-page-url "https://gnu.org/s/guix"))
906   ;; Hack so that Geiser is not confused.
907   (define defmod 'define-module)
909   (scheme-file "config.scm"
910                #~(;; The following expressions get spliced.
911                    (#$defmod (guix config)
912                      #:export (%guix-package-name
913                                %guix-version
914                                %guix-bug-report-address
915                                %guix-home-page-url
916                                %system
917                                %store-directory
918                                %state-directory
919                                %store-database-directory
920                                %config-directory
921                                %libz
922                                ;; TODO: %liblz
923                                %gzip
924                                %bzip2
925                                %xz))
927                    (define %system
928                      #$(%current-system))
930                    #$@(map (match-lambda
931                              ((name . value)
932                               #~(define-public #$name #$value)))
933                            %config-variables)
935                    (define %store-directory
936                      (or (and=> (getenv "NIX_STORE_DIR") canonicalize-path)
937                          %storedir))
939                    (define %state-directory
940                      ;; This must match `NIX_STATE_DIR' as defined in
941                      ;; `nix/local.mk'.
942                      (or (getenv "GUIX_STATE_DIRECTORY")
943                          (string-append %localstatedir "/guix")))
945                    (define %store-database-directory
946                      (or (getenv "GUIX_DATABASE_DIRECTORY")
947                          (string-append %state-directory "/db")))
949                    (define %config-directory
950                      ;; This must match `GUIX_CONFIGURATION_DIRECTORY' as
951                      ;; defined in `nix/local.mk'.
952                      (or (getenv "GUIX_CONFIGURATION_DIRECTORY")
953                          (string-append %sysconfdir "/guix")))
955                    (define %guix-package-name #$package-name)
956                    (define %guix-version #$package-version)
957                    (define %guix-bug-report-address #$bug-report-address)
958                    (define %guix-home-page-url #$home-page-url)
960                    (define %gzip
961                      #+(and gzip (file-append gzip "/bin/gzip")))
962                    (define %bzip2
963                      #+(and bzip2 (file-append bzip2 "/bin/bzip2")))
964                    (define %xz
965                      #+(and xz (file-append xz "/bin/xz")))
967                    (define %libz
968                      #+(and zlib
969                             (file-append zlib "/lib/libz"))))
971                ;; Guile 2.0 *requires* the 'define-module' to be at the
972                ;; top-level or the 'toplevel-ref' in the resulting .go file are
973                ;; made relative to a nonexistent anonymous module.
974                #:splice? #t))
978 ;;; Building.
981 (define* (compiled-modules name module-tree module-files
982                            #:optional
983                            (dependencies '())
984                            (dependencies-compiled '())
985                            #:key
986                            (extensions '())       ;full-blown Guile packages
987                            parallel?
988                            guile-for-build)
989   "Build all the MODULE-FILES from MODULE-TREE.  MODULE-FILES must be a list
990 like '(\"guix/foo.scm\" \"gnu/bar.scm\") and MODULE-TREE is the directory
991 containing MODULE-FILES and possibly other files as well."
992   ;; This is a non-monadic, enhanced version of 'compiled-file' from (guix
993   ;; gexp).
994   (define build
995     (with-imported-modules (source-module-closure
996                             '((guix build compile)
997                               (guix build utils)))
998       #~(begin
999           (use-modules (srfi srfi-26)
1000                        (ice-9 match)
1001                        (ice-9 format)
1002                        (ice-9 threads)
1003                        (guix build compile)
1004                        (guix build utils))
1006           (define (regular? file)
1007             (not (member file '("." ".."))))
1009           (define (report-load file total completed)
1010             (display #\cr)
1011             (format #t
1012                     "[~3@a/~3@a] loading...\t~5,1f% of ~d files"
1014                     ;; Note: Multiply TOTAL by two to account for the
1015                     ;; compilation phase that follows.
1016                     completed (* total 2)
1018                     (* 100. (/ completed total)) total)
1019             (force-output))
1021           (define (report-compilation file total completed)
1022             (display #\cr)
1023             (format #t "[~3@a/~3@a] compiling...\t~5,1f% of ~d files"
1025                     ;; Add TOTAL to account for the load phase that came
1026                     ;; before.
1027                     (+ total completed) (* total 2)
1029                     (* 100. (/ completed total)) total)
1030             (force-output))
1032           (define (process-directory directory files output)
1033             ;; Hide compilation warnings.
1034             (parameterize ((current-warning-port (%make-void-port "w")))
1035               (compile-files directory #$output files
1036                              #:workers (parallel-job-count)
1037                              #:report-load report-load
1038                              #:report-compilation report-compilation)))
1040           (setvbuf (current-output-port) 'line)
1041           (setvbuf (current-error-port) 'line)
1043           (set! %load-path (cons #+module-tree %load-path))
1044           (set! %load-path
1045             (append '#+dependencies
1046                     (map (lambda (extension)
1047                            (string-append extension "/share/guile/site/"
1048                                           (effective-version)))
1049                          '#+extensions)
1050                     %load-path))
1052           (set! %load-compiled-path
1053             (append '#+dependencies-compiled
1054                     (map (lambda (extension)
1055                            (string-append extension "/lib/guile/"
1056                                           (effective-version)
1057                                           "/site-ccache"))
1058                          '#+extensions)
1059                     %load-compiled-path))
1061           ;; Load the compiler modules upfront.
1062           (compile #f)
1064           (mkdir #$output)
1065           (chdir #+module-tree)
1066           (process-directory "." '#+module-files #$output)
1067           (newline))))
1069   (computed-file name build
1070                  #:guile guile-for-build
1071                  #:options
1072                  `(#:local-build? #f              ;allow substitutes
1074                    ;; Don't annoy people about _IONBF deprecation.
1075                    ;; Initialize 'terminal-width' in (system repl debug)
1076                    ;; to a large-enough value to make backtrace more
1077                    ;; verbose.
1078                    #:env-vars (("GUILE_WARN_DEPRECATED" . "no")
1079                                ("COLUMNS" . "200")))))
1083 ;;; Building.
1086 (define* (guix-derivation source version
1087                           #:optional (guile-version (effective-version))
1088                           #:key (pull-version 0))
1089   "Return, as a monadic value, the derivation to build the Guix from SOURCE
1090 for GUILE-VERSION.  Use VERSION as the version string.  PULL-VERSION specifies
1091 the version of the 'guix pull' protocol.  Return #f if this PULL-VERSION value
1092 is not supported."
1093   (define (shorten version)
1094     (if (and (string-every char-set:hex-digit version)
1095              (> (string-length version) 9))
1096         (string-take version 9)                   ;Git commit
1097         version))
1099   (define guile
1100     ;; When PULL-VERSION >= 1, produce a self-contained Guix and use Guile 2.2
1101     ;; unconditionally.
1102     (default-guile))
1104   (when (and (< pull-version 1)
1105              (not (string=? (package-version guile) guile-version)))
1106     ;; Guix < 0.15.0 has PULL-VERSION = 0, where the host Guile is reused and
1107     ;; can be any version.  When that happens and Guile is not current (e.g.,
1108     ;; it's Guile 2.0), just bail out.
1109     (raise (condition
1110             (&message
1111              (message "Guix is too old and cannot be upgraded")))))
1113   (mbegin %store-monad
1114     (set-guile-for-build guile)
1115     (let ((guix (compiled-guix source
1116                                #:version version
1117                                #:name (string-append "guix-"
1118                                                      (shorten version))
1119                                #:pull-version pull-version
1120                                #:guile-version (if (>= pull-version 1)
1121                                                    "2.2" guile-version)
1122                                #:guile-for-build guile)))
1123       (if guix
1124           (lower-object guix)
1125           (return #f)))))