build-self: Spin only on TTYs.
[jackhill/guix/guix.git] / guix / self.scm
CommitLineData
eaae07ec
LC
1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2017, 2018 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/>.
18
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)
eaae07ec 29 #:use-module (guix modules)
45779fa6 30 #:use-module ((guix build utils) #:select (find-files))
eaae07ec
LC
31 #:use-module ((guix build compile) #:select (%lightweight-optimizations))
32 #:use-module (srfi srfi-1)
33 #:use-module (srfi srfi-9)
34 #:use-module (ice-9 match)
35 #:export (make-config.scm
8a0d9bc8 36 whole-package ;for internal use in 'guix pull'
eaae07ec
LC
37 compiled-guix
38 guix-derivation
39 reload-guix))
40
41\f
42;;;
43;;; Dependency handling.
44;;;
45
46(define* (false-if-wrong-guile package
47 #:optional (guile-version (effective-version)))
48 "Return #f if PACKAGE depends on the \"wrong\" major version of Guile (e.g.,
492.0 instead of 2.2), otherwise return PACKAGE."
50 (let ((guile (any (match-lambda
51 ((label (? package? dep) _ ...)
52 (and (string=? (package-name dep) "guile")
53 dep)))
54 (package-direct-inputs package))))
55 (and (or (not guile)
56 (string-prefix? guile-version
57 (package-version guile)))
58 package)))
59
60(define (package-for-guile guile-version . names)
61 "Return the package with one of the given NAMES that depends on
62GUILE-VERSION (\"2.0\" or \"2.2\"), or #f if none of the packages matches."
63 (let loop ((names names))
64 (match names
65 (()
66 #f)
67 ((name rest ...)
68 (match (specification->package name)
69 (#f
70 (loop rest))
71 ((? package? package)
a1639ae9 72 (or (false-if-wrong-guile package guile-version)
eaae07ec
LC
73 (loop rest))))))))
74
75(define specification->package
76 ;; Use our own variant of that procedure because that of (gnu packages)
77 ;; would traverse all the .scm files, which is wasteful.
78 (let ((ref (lambda (module variable)
79 (module-ref (resolve-interface module) variable))))
80 (match-lambda
81 ("guile" (ref '(gnu packages commencement) 'guile-final))
82 ("guile-json" (ref '(gnu packages guile) 'guile-json))
83 ("guile-ssh" (ref '(gnu packages ssh) 'guile-ssh))
84 ("guile-git" (ref '(gnu packages guile) 'guile-git))
d59e75f3 85 ("guile-sqlite3" (ref '(gnu packages guile) 'guile-sqlite3))
ca719424 86 ("guile-gcrypt" (ref '(gnu packages gnupg) 'guile-gcrypt))
108015df 87 ("gnutls" (ref '(gnu packages tls) 'gnutls))
eaae07ec
LC
88 ("zlib" (ref '(gnu packages compression) 'zlib))
89 ("gzip" (ref '(gnu packages compression) 'gzip))
90 ("bzip2" (ref '(gnu packages compression) 'bzip2))
91 ("xz" (ref '(gnu packages compression) 'xz))
e69dd844
LC
92 ("guile2.0-json" (ref '(gnu packages guile) 'guile2.0-json))
93 ("guile2.0-ssh" (ref '(gnu packages ssh) 'guile2.0-ssh))
94 ("guile2.0-git" (ref '(gnu packages guile) 'guile2.0-git))
d59e75f3 95 ;; XXX: No "guile2.0-sqlite3".
108015df 96 ("guile2.0-gnutls" (ref '(gnu packages tls) 'gnutls/guile-2.0))
e69dd844 97 (_ #f)))) ;no such package
eaae07ec
LC
98
99\f
100;;;
101;;; Derivations.
102;;;
103
104;; Node in a DAG of build tasks. Each node maps to a derivation, but it's
105;; easier to express things this way.
106(define-record-type <node>
107 (node name modules source dependencies compiled)
108 node?
109 (name node-name) ;string
110 (modules node-modules) ;list of module names
111 (source node-source) ;list of source files
112 (dependencies node-dependencies) ;list of nodes
113 (compiled node-compiled)) ;node -> lowerable object
114
f5db54ea
LC
115;; File mappings are essentially an alist as passed to 'imported-files'.
116(define-record-type <file-mapping>
117 (file-mapping name alist)
118 file-mapping?
119 (name file-mapping-name)
120 (alist file-mapping-alist))
121
122(define-gexp-compiler (file-mapping-compiler (mapping <file-mapping>)
123 system target)
124 ;; Here we use 'imported-files', which can arrange to directly import all
125 ;; the files instead of creating a derivation, when possible.
126 (imported-files (map (match-lambda
127 ((destination (? local-file? file))
128 (cons destination
129 (local-file-absolute-file-name file)))
130 ((destination source)
131 (cons destination source))) ;silliness
132 (file-mapping-alist mapping))
133 #:name (file-mapping-name mapping)
134 #:system system))
135
49c35bbb
LC
136(define (node-source+compiled node)
137 "Return a \"bundle\" containing both the source code and object files for
138NODE's modules, under their FHS directories: share/guile/site and lib/guile."
139 (define build
140 (with-imported-modules '((guix build utils))
141 #~(begin
142 (use-modules (guix build utils))
143
144 (define source
145 (string-append #$output "/share/guile/site/"
146 (effective-version)))
147
148 (define object
149 (string-append #$output "/lib/guile/" (effective-version)
150 "/site-ccache"))
151
152 (mkdir-p (dirname source))
153 (symlink #$(node-source node) source)
154 (mkdir-p (dirname object))
155 (symlink #$(node-compiled node) object))))
156
157 (computed-file (string-append (node-name node) "-modules")
158 build))
159
eaae07ec
LC
160(define (node-fold proc init nodes)
161 (let loop ((nodes nodes)
162 (visited (setq))
163 (result init))
164 (match nodes
165 (() result)
166 ((head tail ...)
167 (if (set-contains? visited head)
168 (loop tail visited result)
169 (loop tail (set-insert head visited)
170 (proc head result)))))))
171
172(define (node-modules/recursive nodes)
173 (node-fold (lambda (node modules)
174 (append (node-modules node) modules))
175 '()
176 nodes))
177
178(define* (closure modules #:optional (except '()))
179 (source-module-closure modules
180 #:select?
181 (match-lambda
182 (('guix 'config)
183 #f)
184 ((and module
185 (or ('guix _ ...) ('gnu _ ...)))
186 (not (member module except)))
187 (rest #f))))
188
189(define module->import
190 ;; Return a file-name/file-like object pair for the specified module and
191 ;; suitable for 'imported-files'.
192 (match-lambda
193 ((module '=> thing)
194 (let ((file (module-name->file-name module)))
195 (list file thing)))
196 (module
197 (let ((file (module-name->file-name module)))
198 (list file
199 (local-file (search-path %load-path file)))))))
200
201(define* (scheme-node name modules #:optional (dependencies '())
202 #:key (extra-modules '()) (extra-files '())
203 (extensions '())
204 parallel? guile-for-build)
205 "Return a node that builds the given Scheme MODULES, and depends on
206DEPENDENCIES (a list of nodes). EXTRA-MODULES is a list of additional modules
207added to the source, and EXTRA-FILES is a list of additional files.
208EXTENSIONS is a set of full-blown Guile packages (e.g., 'guile-json') that
209must be present in the search path."
210 (let* ((modules (append extra-modules
211 (closure modules
212 (node-modules/recursive dependencies))))
213 (module-files (map module->import modules))
f5db54ea
LC
214 (source (file-mapping (string-append name "-source")
215 (append module-files extra-files))))
eaae07ec 216 (node name modules source dependencies
8031b3fa
LC
217 (compiled-modules name source
218 (map car module-files)
eaae07ec
LC
219 (map node-source dependencies)
220 (map node-compiled dependencies)
221 #:extensions extensions
222 #:parallel? parallel?
223 #:guile-for-build guile-for-build))))
224
225(define (file-imports directory sub-directory pred)
226 "List all the files matching PRED under DIRECTORY/SUB-DIRECTORY. Return a
227list of file-name/file-like objects suitable as inputs to 'imported-files'."
228 (map (lambda (file)
229 (list (string-drop file (+ 1 (string-length directory)))
230 (local-file file #:recursive? #t)))
231 (find-files (string-append directory "/" sub-directory) pred)))
232
6cf502d1
LC
233(define* (file-append* item file #:key (recursive? #t))
234 "Return FILE within ITEM, which may be a file name or a file-like object.
235When ITEM is a plain file name (a string), simply return a 'local-file'
236record with the new file name."
9f1c3559
LC
237 (match item
238 ((? string?)
239 ;; This is the optimal case: we return a new "source". Thus, a
240 ;; derivation that depends on this sub-directory does not depend on ITEM
241 ;; itself.
6cf502d1
LC
242 (local-file (string-append item "/" file)
243 #:recursive? recursive?))
9f1c3559
LC
244 ;; TODO: Add 'local-file?' case.
245 (_
246 ;; In this case, anything that refers to the result also depends on ITEM,
247 ;; which isn't great.
6cf502d1 248 (file-append item "/" file))))
9f1c3559
LC
249
250(define* (locale-data source domain
251 #:optional (directory domain))
252 "Return the locale data from 'po/DIRECTORY' in SOURCE, corresponding to
253DOMAIN, a gettext domain."
254 (define gettext
255 (module-ref (resolve-interface '(gnu packages gettext))
256 'gettext-minimal))
257
258 (define build
259 (with-imported-modules '((guix build utils))
260 #~(begin
261 (use-modules (guix build utils)
262 (srfi srfi-26)
263 (ice-9 match) (ice-9 ftw))
264
265 (define po-directory
6cf502d1 266 #+(file-append* source (string-append "po/" directory)))
9f1c3559
LC
267
268 (define (compile language)
269 (let ((gmo (string-append #$output "/" language "/LC_MESSAGES/"
270 #$domain ".mo")))
271 (mkdir-p (dirname gmo))
272 (invoke #+(file-append gettext "/bin/msgfmt")
273 "-c" "--statistics" "--verbose"
274 "-o" gmo
275 (string-append po-directory "/" language ".po"))))
276
277 (define (linguas)
278 ;; Return the list of languages. Note: don't read 'LINGUAS'
279 ;; because it contains things like 'en@boldquot' that do not have
280 ;; a corresponding .po file.
281 (map (cut basename <> ".po")
282 (scandir po-directory
283 (cut string-suffix? ".po" <>))))
284
285 (for-each compile (linguas)))))
286
287 (computed-file (string-append "guix-locale-" domain)
288 build))
289
4554d4c8
LC
290(define (info-manual source)
291 "Return the Info manual built from SOURCE."
292 (define texinfo
293 (module-ref (resolve-interface '(gnu packages texinfo))
294 'texinfo))
295
296 (define graphviz
297 (module-ref (resolve-interface '(gnu packages graphviz))
298 'graphviz))
299
2d337760
LC
300 (define glibc-utf8-locales
301 (module-ref (resolve-interface '(gnu packages base))
302 'glibc-utf8-locales))
303
4554d4c8 304 (define documentation
6cf502d1 305 (file-append* source "doc"))
4554d4c8
LC
306
307 (define examples
6cf502d1 308 (file-append* source "gnu/system/examples"))
4554d4c8
LC
309
310 (define build
311 (with-imported-modules '((guix build utils))
312 #~(begin
313 (use-modules (guix build utils))
314
315 (mkdir #$output)
316
317 ;; Create 'version.texi'.
318 ;; XXX: Can we use a more meaningful version string yet one that
319 ;; doesn't change at each commit?
320 (call-with-output-file "version.texi"
321 (lambda (port)
cbe7387c 322 (let ((version "0.0-git"))
4554d4c8
LC
323 (format port "
324@set UPDATED 1 January 1970
325@set UPDATED-MONTH January 1970
326@set EDITION ~a
327@set VERSION ~a\n" version version))))
328
329 ;; Copy configuration templates that the manual includes.
330 (for-each (lambda (template)
331 (copy-file template
332 (string-append
333 "os-config-"
334 (basename template ".tmpl")
335 ".texi")))
336 (find-files #$examples "\\.tmpl$"))
337
338 ;; Build graphs.
339 (mkdir-p (string-append #$output "/images"))
340 (for-each (lambda (dot-file)
341 (invoke #+(file-append graphviz "/bin/dot")
342 "-Tpng" "-Gratio=.9" "-Gnodesep=.005"
343 "-Granksep=.00005" "-Nfontsize=9"
344 "-Nheight=.1" "-Nwidth=.1"
345 "-o" (string-append #$output "/images/"
346 (basename dot-file ".dot")
347 ".png")
348 dot-file))
349 (find-files (string-append #$documentation "/images")
350 "\\.dot$"))
351
352 ;; Copy other PNGs.
353 (for-each (lambda (png-file)
354 (install-file png-file
355 (string-append #$output "/images")))
356 (find-files (string-append #$documentation "/images")
357 "\\.png$"))
358
359 ;; Finally build the manual. Copy it the Texinfo files to $PWD and
360 ;; add a symlink to the 'images' directory so that 'makeinfo' can
361 ;; see those images and produce image references in the Info output.
362 (copy-recursively #$documentation "."
363 #:log (%make-void-port "w"))
364 (delete-file-recursively "images")
365 (symlink (string-append #$output "/images") "images")
366
2d337760
LC
367 ;; Provide UTF-8 locales needed by the 'xspara.c' code in makeinfo.
368 (setenv "GUIX_LOCPATH"
369 #+(file-append glibc-utf8-locales "/lib/locale"))
370
4554d4c8
LC
371 (for-each (lambda (texi)
372 (unless (string=? "guix.texi" texi)
373 ;; Create 'version-LL.texi'.
374 (let* ((base (basename texi ".texi"))
375 (dot (string-index base #\.))
376 (tag (string-drop base (+ 1 dot))))
377 (symlink "version.texi"
378 (string-append "version-" tag ".texi"))))
379
380 (invoke #+(file-append texinfo "/bin/makeinfo")
381 texi "-I" #$documentation
382 "-I" "."
383 "-o" (string-append #$output "/"
384 (basename texi ".texi")
385 ".info")))
386 (cons "guix.texi"
387 (find-files "." "^guix\\.[a-z]{2}\\.texi$"))))))
388
389 (computed-file "guix-manual" build))
390
49c35bbb
LC
391(define* (guile-module-union things #:key (name "guix-module-union"))
392 "Return the union of the subset of THINGS (packages, computed files, etc.)
393that provide Guile modules."
394 (define build
395 (with-imported-modules '((guix build union))
396 #~(begin
397 (use-modules (guix build union))
398
399 (define (modules directory)
400 (string-append directory "/share/guile/site"))
401
402 (define (objects directory)
403 (string-append directory "/lib/guile"))
404
405 (union-build #$output
406 (filter (lambda (directory)
407 (or (file-exists? (modules directory))
408 (file-exists? (objects directory))))
409 '#$things)
410
411 #:log-port (%make-void-port "w")))))
412
413 (computed-file name build))
414
415(define* (guix-command modules
a89faa3f 416 #:key source (dependencies '())
8970a886 417 guile (guile-version (effective-version)))
8a0d9bc8
LC
418 "Return the 'guix' command such that it adds MODULES and DEPENDENCIES in its
419load path."
49c35bbb
LC
420 (define module-directory
421 ;; To minimize the number of 'stat' calls needed to locate a module,
422 ;; create the union of all the module directories.
423 (guile-module-union (cons modules dependencies)))
f2d0a2cf 424
8a0d9bc8
LC
425 (program-file "guix-command"
426 #~(begin
427 (set! %load-path
49c35bbb
LC
428 (cons (string-append #$module-directory
429 "/share/guile/site/"
430 (effective-version))
431 %load-path))
8a0d9bc8 432
8a0d9bc8 433 (set! %load-compiled-path
49c35bbb
LC
434 (cons (string-append #$module-directory
435 "/lib/guile/"
436 (effective-version)
437 "/site-ccache")
a89faa3f 438 %load-compiled-path))
8a0d9bc8
LC
439
440 (let ((guix-main (module-ref (resolve-interface '(guix ui))
441 'guix-main)))
9f1c3559
LC
442 #$(if source
443 #~(begin
444 (bindtextdomain "guix"
445 #$(locale-data source "guix"))
446 (bindtextdomain "guix-packages"
447 #$(locale-data source
448 "guix-packages"
449 "packages")))
450 #t)
8a0d9bc8
LC
451
452 ;; XXX: It would be more convenient to change it to:
453 ;; (exit (apply guix-main (command-line)))
8970a886
LC
454 (apply guix-main (command-line))))
455 #:guile guile))
8a0d9bc8 456
e3744779
LC
457(define (miscellaneous-files source)
458 "Return data files taken from SOURCE."
459 (file-mapping "guix-misc"
460 `(("etc/bash_completion.d/guix"
461 ,(file-append* source "/etc/completion/bash/guix"))
462 ("etc/bash_completion.d/guix-daemon"
463 ,(file-append* source "/etc/completion/bash/guix-daemon"))
464 ("share/zsh/site-functions/_guix"
465 ,(file-append* source "/etc/completion/zsh/_guix"))
466 ("share/fish/vendor_completions.d/guix.fish"
467 ,(file-append* source "/etc/completion/fish/guix.fish"))
468 ("share/guix/hydra.gnu.org.pub"
469 ,(file-append* source
470 "/etc/substitutes/hydra.gnu.org.pub"))
471 ("share/guix/berlin.guixsd.org.pub"
6a837b60
LC
472 ,(file-append* source
473 "/etc/substitutes/berlin.guixsd.org.pub"))
474 ("share/guix/ci.guix.info.pub" ;alias
e3744779
LC
475 ,(file-append* source "/etc/substitutes/berlin.guixsd.org.pub")))))
476
8a0d9bc8 477(define* (whole-package name modules dependencies
9f1c3559
LC
478 #:key
479 (guile-version (effective-version))
e3744779 480 info daemon miscellany
8d3beb3a 481 guile
9f1c3559
LC
482 (command (guix-command modules
483 #:dependencies dependencies
8970a886 484 #:guile guile
9f1c3559 485 #:guile-version guile-version)))
8a0d9bc8 486 "Return the whole Guix package NAME that uses MODULES, a derivation of all
49c35bbb
LC
487the modules (under share/guile/site and lib/guile), and DEPENDENCIES, a list
488of packages depended on. COMMAND is the 'guix' program to use; INFO is the
489Info manual."
9f1c3559
LC
490 (computed-file name
491 (with-imported-modules '((guix build utils))
492 #~(begin
493 (use-modules (guix build utils))
e3744779 494
9f1c3559
LC
495 (mkdir-p (string-append #$output "/bin"))
496 (symlink #$command
497 (string-append #$output "/bin/guix"))
498
baed9236
LC
499 (when #$daemon
500 (symlink (string-append #$daemon "/bin/guix-daemon")
501 (string-append #$output "/bin/guix-daemon")))
502
49c35bbb
LC
503 (let ((share (string-append #$output "/share"))
504 (lib (string-append #$output "/lib"))
505 (info #$info))
506 (mkdir-p share)
507 (symlink #$(file-append modules "/share/guile")
508 (string-append share "/guile"))
4554d4c8 509 (when info
49c35bbb
LC
510 (symlink #$info (string-append share "/info")))
511
512 (mkdir-p lib)
513 (symlink #$(file-append modules "/lib/guile")
514 (string-append lib "/guile")))
a89faa3f 515
e3744779
LC
516 (when #$miscellany
517 (copy-recursively #$miscellany #$output
49c35bbb 518 #:log (%make-void-port "w")))))))
8a0d9bc8 519
eaae07ec 520(define* (compiled-guix source #:key (version %guix-version)
8a0d9bc8 521 (pull-version 1)
eaae07ec
LC
522 (name (string-append "guix-" version))
523 (guile-version (effective-version))
524 (guile-for-build (guile-for-build guile-version))
eaae07ec
LC
525 (zlib (specification->package "zlib"))
526 (gzip (specification->package "gzip"))
527 (bzip2 (specification->package "bzip2"))
528 (xz (specification->package "xz"))
529 (guix (specification->package "guix")))
530 "Return a file-like object that contains a compiled Guix."
531 (define guile-json
532 (package-for-guile guile-version
533 "guile-json"
eaae07ec
LC
534 "guile2.0-json"))
535
536 (define guile-ssh
537 (package-for-guile guile-version
538 "guile-ssh"
eaae07ec
LC
539 "guile2.0-ssh"))
540
541 (define guile-git
542 (package-for-guile guile-version
543 "guile-git"
544 "guile2.0-git"))
545
d59e75f3
LC
546 (define guile-sqlite3
547 (package-for-guile guile-version
548 "guile-sqlite3"
549 "guile2.0-sqlite3"))
550
ca719424
LC
551 (define guile-gcrypt
552 (package-for-guile guile-version
553 "guile-gcrypt"))
554
108015df
LC
555 (define gnutls
556 (package-for-guile guile-version
557 "gnutls" "guile2.0-gnutls"))
558
eaae07ec
LC
559 (define dependencies
560 (match (append-map (lambda (package)
561 (cons (list "x" package)
e13240f5 562 (package-transitive-propagated-inputs package)))
ca719424 563 (list guile-gcrypt gnutls guile-git guile-json
108015df 564 guile-ssh guile-sqlite3))
eaae07ec
LC
565 (((labels packages _ ...) ...)
566 packages)))
567
568 (define *core-modules*
569 (scheme-node "guix-core"
570 '((guix)
571 (guix monad-repl)
572 (guix packages)
573 (guix download)
574 (guix discovery)
575 (guix profiles)
576 (guix build-system gnu)
577 (guix build-system trivial)
578 (guix build profiles)
579 (guix build gnu-build-system))
580
581 ;; Provide a dummy (guix config) with the default version
582 ;; number, storedir, etc. This is so that "guix-core" is the
583 ;; same across all installations and doesn't need to be
584 ;; rebuilt when the version changes, which in turn means we
585 ;; can have substitutes for it.
586 #:extra-modules
ca719424 587 `(((guix config) => ,(make-config.scm)))
eaae07ec 588
8292f5a9
LC
589 ;; (guix man-db) is needed at build-time by (guix profiles)
590 ;; but we don't need to compile it; not compiling it allows
591 ;; us to avoid an extra dependency on guile-gdbm-ffi.
592 #:extra-files
3931c761
LC
593 `(("guix/man-db.scm" ,(local-file "../guix/man-db.scm"))
594 ("guix/store/schema.sql"
595 ,(local-file "../guix/store/schema.sql")))
8292f5a9 596
ca719424 597 #:extensions (list guile-gcrypt)
eaae07ec
LC
598 #:guile-for-build guile-for-build))
599
600 (define *extra-modules*
601 (scheme-node "guix-extra"
602 (filter-map (match-lambda
603 (('guix 'scripts _ ..1) #f)
8292f5a9 604 (('guix 'man-db) #f)
eaae07ec
LC
605 (name name))
606 (scheme-modules* source "guix"))
607 (list *core-modules*)
608 #:extensions dependencies
609 #:guile-for-build guile-for-build))
610
f2e66663
LC
611 (define *core-package-modules*
612 (scheme-node "guix-packages-base"
eaae07ec 613 `((gnu packages)
f2e66663 614 (gnu packages base))
eaae07ec
LC
615 (list *core-modules* *extra-modules*)
616 #:extensions dependencies
f2e66663
LC
617
618 ;; Add all the non-Scheme files here. We must do it here so
619 ;; that 'search-patches' & co. can find them. Ideally we'd
620 ;; keep them next to the .scm files that use them but it's
621 ;; difficult to do (XXX).
622 #:extra-files
eaae07ec
LC
623 (file-imports source "gnu/packages"
624 (lambda (file stat)
625 (and (eq? 'regular (stat:type stat))
626 (not (string-suffix? ".scm" file))
627 (not (string-suffix? ".go" file))
628 (not (string-prefix? ".#" file))
629 (not (string-suffix? "~" file)))))
630 #:guile-for-build guile-for-build))
631
f2e66663
LC
632 (define *package-modules*
633 (scheme-node "guix-packages"
634 (scheme-modules* source "gnu/packages")
635 (list *core-modules* *extra-modules* *core-package-modules*)
636 #:extensions dependencies
637 #:guile-for-build guile-for-build))
638
eaae07ec
LC
639 (define *system-modules*
640 (scheme-node "guix-system"
641 `((gnu system)
642 (gnu services)
643 ,@(scheme-modules* source "gnu/system")
644 ,@(scheme-modules* source "gnu/services"))
f2e66663
LC
645 (list *core-package-modules* *package-modules*
646 *extra-modules* *core-modules*)
eaae07ec
LC
647 #:extensions dependencies
648 #:extra-files
1458f768
LC
649 (append (file-imports source "gnu/system/examples"
650 (const #t))
651
652 ;; Build-side code that we don't build. Some of
653 ;; these depend on guile-rsvg, the Shepherd, etc.
654 (file-imports source "gnu/build" (const #t)))
eaae07ec
LC
655 #:guile-for-build
656 guile-for-build))
657
658 (define *cli-modules*
659 (scheme-node "guix-cli"
b5f8c2c8
LC
660 (append (scheme-modules* source "/guix/scripts")
661 `((gnu ci)))
f2e66663
LC
662 (list *core-modules* *extra-modules*
663 *core-package-modules* *package-modules*
eaae07ec
LC
664 *system-modules*)
665 #:extensions dependencies
666 #:guile-for-build guile-for-build))
667
668 (define *config*
669 (scheme-node "guix-config"
670 '()
671 #:extra-modules
672 `(((guix config)
ca719424 673 => ,(make-config.scm #:zlib zlib
eaae07ec
LC
674 #:gzip gzip
675 #:bzip2 bzip2
676 #:xz xz
eaae07ec
LC
677 #:package-name
678 %guix-package-name
679 #:package-version
680 version
681 #:bug-report-address
682 %guix-bug-report-address
683 #:home-page-url
684 %guix-home-page-url)))
685 #:guile-for-build guile-for-build))
686
a89faa3f 687 (define (built-modules node-subset)
8a0d9bc8 688 (directory-union (string-append name "-modules")
a89faa3f 689 (append-map node-subset
8a0d9bc8
LC
690
691 ;; Note: *CONFIG* comes first so that it
692 ;; overrides the (guix config) module that
693 ;; comes with *CORE-MODULES*.
694 (list *config*
695 *cli-modules*
696 *system-modules*
697 *package-modules*
698 *core-package-modules*
699 *extra-modules*
700 *core-modules*))
701
702 ;; Silently choose the first entry upon collision so that
703 ;; we choose *CONFIG*.
704 #:resolve-collision 'first
705
706 ;; When we do (add-to-store "utils.scm"), "utils.scm" must
707 ;; be a regular file, not a symlink. Thus, arrange so that
708 ;; regular files appear as regular files in the final
709 ;; output.
710 #:copy? #t
711 #:quiet? #t))
712
713 ;; Version 0 of 'guix pull' meant we'd just return Scheme modules.
714 ;; Version 1 is when we return the full package.
715 (cond ((= 1 pull-version)
716 ;; The whole package, with a standard file hierarchy.
49c35bbb
LC
717 (let* ((modules (built-modules (compose list node-source+compiled)))
718 (command (guix-command modules
a89faa3f
LC
719 #:source source
720 #:dependencies dependencies
8970a886 721 #:guile guile-for-build
a89faa3f
LC
722 #:guile-version guile-version)))
723 (whole-package name modules dependencies
9f1c3559 724 #:command command
8970a886 725 #:guile guile-for-build
baed9236
LC
726
727 ;; Include 'guix-daemon'. XXX: Here we inject an
728 ;; older snapshot of guix-daemon, but that's a good
729 ;; enough approximation for now.
730 #:daemon (module-ref (resolve-interface
731 '(gnu packages
732 package-management))
733 'guix-daemon)
734
4554d4c8 735 #:info (info-manual source)
e3744779 736 #:miscellany (miscellaneous-files source)
9f1c3559 737 #:guile-version guile-version)))
8a0d9bc8 738 ((= 0 pull-version)
a89faa3f
LC
739 ;; Legacy 'guix pull': return the .scm and .go files as one
740 ;; directory.
741 (built-modules (lambda (node)
742 (list (node-source node)
743 (node-compiled node)))))
8a0d9bc8
LC
744 (else
745 ;; Unsupported 'guix pull' version.
746 #f)))
eaae07ec
LC
747
748\f
749;;;
750;;; Generating (guix config).
751;;;
752
753(define %dependency-variables
754 ;; (guix config) variables corresponding to dependencies.
ca719424 755 '(%libz %xz %gzip %bzip2))
eaae07ec
LC
756
757(define %persona-variables
758 ;; (guix config) variables that define Guix's persona.
759 '(%guix-package-name
760 %guix-version
761 %guix-bug-report-address
762 %guix-home-page-url))
763
764(define %config-variables
45779fa6
LC
765 ;; (guix config) variables corresponding to Guix configuration.
766 (letrec-syntax ((variables (syntax-rules ()
767 ((_)
768 '())
769 ((_ variable rest ...)
770 (cons `(variable . ,variable)
771 (variables rest ...))))))
7af5c2a2 772 (variables %localstatedir %storedir %sysconfdir %system)))
eaae07ec 773
ca719424 774(define* (make-config.scm #:key zlib gzip xz bzip2
eaae07ec
LC
775 (package-name "GNU Guix")
776 (package-version "0")
777 (bug-report-address "bug-guix@gnu.org")
778 (home-page-url "https://gnu.org/s/guix"))
779
780 ;; Hack so that Geiser is not confused.
781 (define defmod 'define-module)
782
783 (scheme-file "config.scm"
eb72cdf0 784 #~(;; The following expressions get spliced.
eaae07ec
LC
785 (#$defmod (guix config)
786 #:export (%guix-package-name
787 %guix-version
788 %guix-bug-report-address
789 %guix-home-page-url
7af5c2a2
LC
790 %store-directory
791 %state-directory
792 %store-database-directory
793 %config-directory
eaae07ec
LC
794 %libz
795 %gzip
796 %bzip2
e8cb9c01 797 %xz))
eaae07ec 798
63cab418
LC
799 #$@(map (match-lambda
800 ((name . value)
801 #~(define-public #$name #$value)))
802 %config-variables)
803
7af5c2a2
LC
804 (define %store-directory
805 (or (and=> (getenv "NIX_STORE_DIR") canonicalize-path)
806 %storedir))
807
808 (define %state-directory
809 ;; This must match `NIX_STATE_DIR' as defined in
810 ;; `nix/local.mk'.
811 (or (getenv "NIX_STATE_DIR")
812 (string-append %localstatedir "/guix")))
813
814 (define %store-database-directory
815 (or (getenv "NIX_DB_DIR")
816 (string-append %state-directory "/db")))
817
818 (define %config-directory
819 ;; This must match `GUIX_CONFIGURATION_DIRECTORY' as
820 ;; defined in `nix/local.mk'.
821 (or (getenv "GUIX_CONFIGURATION_DIRECTORY")
822 (string-append %sysconfdir "/guix")))
823
63cab418
LC
824 (define %guix-package-name #$package-name)
825 (define %guix-version #$package-version)
826 (define %guix-bug-report-address #$bug-report-address)
827 (define %guix-home-page-url #$home-page-url)
828
63cab418
LC
829 (define %gzip
830 #+(and gzip (file-append gzip "/bin/gzip")))
831 (define %bzip2
832 #+(and bzip2 (file-append bzip2 "/bin/bzip2")))
833 (define %xz
834 #+(and xz (file-append xz "/bin/xz")))
835
63cab418
LC
836 (define %libz
837 #+(and zlib
e8cb9c01 838 (file-append zlib "/lib/libz"))))
eb72cdf0
LC
839
840 ;; Guile 2.0 *requires* the 'define-module' to be at the
e8cb9c01 841 ;; top-level or the 'toplevel-ref' in the resulting .go file are
eb72cdf0
LC
842 ;; made relative to a nonexistent anonymous module.
843 #:splice? #t))
eaae07ec
LC
844
845
846\f
847;;;
848;;; Building.
849;;;
850
8031b3fa 851(define* (compiled-modules name module-tree module-files
eaae07ec
LC
852 #:optional
853 (dependencies '())
854 (dependencies-compiled '())
855 #:key
856 (extensions '()) ;full-blown Guile packages
857 parallel?
858 guile-for-build)
8031b3fa
LC
859 "Build all the MODULE-FILES from MODULE-TREE. MODULE-FILES must be a list
860like '(\"guix/foo.scm\" \"gnu/bar.scm\") and MODULE-TREE is the directory
861containing MODULE-FILES and possibly other files as well."
eaae07ec
LC
862 ;; This is a non-monadic, enhanced version of 'compiled-file' from (guix
863 ;; gexp).
864 (define build
865 (with-imported-modules (source-module-closure
866 '((guix build compile)
867 (guix build utils)))
868 #~(begin
869 (use-modules (srfi srfi-26)
870 (ice-9 match)
871 (ice-9 format)
872 (ice-9 threads)
873 (guix build compile)
874 (guix build utils))
875
876 (define (regular? file)
877 (not (member file '("." ".."))))
878
879 (define (report-load file total completed)
880 (display #\cr)
881 (format #t
882 "loading...\t~5,1f% of ~d files" ;FIXME: i18n
883 (* 100. (/ completed total)) total)
884 (force-output))
885
886 (define (report-compilation file total completed)
887 (display #\cr)
888 (format #t "compiling...\t~5,1f% of ~d files" ;FIXME: i18n
889 (* 100. (/ completed total)) total)
890 (force-output))
891
8031b3fa
LC
892 (define (process-directory directory files output)
893 ;; Hide compilation warnings.
894 (parameterize ((current-warning-port (%make-void-port "w")))
895 (compile-files directory #$output files
896 #:workers (parallel-job-count)
897 #:report-load report-load
898 #:report-compilation report-compilation)))
eaae07ec
LC
899
900 (setvbuf (current-output-port) _IONBF)
901 (setvbuf (current-error-port) _IONBF)
902
903 (set! %load-path (cons #+module-tree %load-path))
904 (set! %load-path
905 (append '#+dependencies
906 (map (lambda (extension)
907 (string-append extension "/share/guile/site/"
908 (effective-version)))
909 '#+extensions)
910 %load-path))
911
912 (set! %load-compiled-path
913 (append '#+dependencies-compiled
914 (map (lambda (extension)
915 (string-append extension "/lib/guile/"
916 (effective-version)
917 "/site-ccache"))
918 '#+extensions)
919 %load-compiled-path))
920
921 ;; Load the compiler modules upfront.
922 (compile #f)
923
924 (mkdir #$output)
925 (chdir #+module-tree)
8031b3fa 926 (process-directory "." '#+module-files #$output)
69447b63 927 (newline))))
eaae07ec
LC
928
929 (computed-file name build
930 #:guile guile-for-build
931 #:options
932 `(#:local-build? #f ;allow substitutes
933
934 ;; Don't annoy people about _IONBF deprecation.
54be2b4d
LC
935 ;; Initialize 'terminal-width' in (system repl debug)
936 ;; to a large-enough value to make backtrace more
937 ;; verbose.
938 #:env-vars (("GUILE_WARN_DEPRECATED" . "no")
939 ("COLUMNS" . "200")))))
eaae07ec
LC
940
941\f
942;;;
943;;; Building.
944;;;
945
946(define (guile-for-build version)
947 "Return a derivation for Guile 2.0 or 2.2, whichever matches the currently
948running Guile."
949 (define canonical-package ;soft reference
950 (module-ref (resolve-interface '(gnu packages base))
951 'canonical-package))
952
953 (match version
eaae07ec
LC
954 ("2.2"
955 (canonical-package (module-ref (resolve-interface '(gnu packages guile))
2abd76e8 956 'guile-2.2)))
eaae07ec 957 ("2.0"
e69dd844
LC
958 (module-ref (resolve-interface '(gnu packages guile))
959 'guile-2.0))))
eaae07ec
LC
960
961(define* (guix-derivation source version
8a0d9bc8
LC
962 #:optional (guile-version (effective-version))
963 #:key (pull-version 0))
eaae07ec 964 "Return, as a monadic value, the derivation to build the Guix from SOURCE
8a0d9bc8
LC
965for GUILE-VERSION. Use VERSION as the version string. PULL-VERSION specifies
966the version of the 'guix pull' protocol. Return #f if this PULL-VERSION value
967is not supported."
eaae07ec
LC
968 (define (shorten version)
969 (if (and (string-every char-set:hex-digit version)
970 (> (string-length version) 9))
971 (string-take version 9) ;Git commit
972 version))
973
974 (define guile
099bb017
LC
975 ;; When PULL-VERSION >= 1, produce a self-contained Guix and use Guile 2.2
976 ;; unconditionally.
977 (guile-for-build (if (>= pull-version 1)
978 "2.2"
979 guile-version)))
eaae07ec
LC
980
981 (mbegin %store-monad
982 (set-guile-for-build guile)
8a0d9bc8
LC
983 (let ((guix (compiled-guix source
984 #:version version
985 #:name (string-append "guix-"
986 (shorten version))
987 #:pull-version pull-version
099bb017 988 #:guile-version (if (>= pull-version 1)
d02bb02f 989 "2.2" guile-version)
8a0d9bc8
LC
990 #:guile-for-build guile)))
991 (if guix
992 (lower-object guix)
993 (return #f)))))