1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
4 ;;; This file is part of GNU Guix.
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.
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.
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 gexp)
20 #:use-module (guix store)
21 #:use-module (guix monads)
22 #:use-module (guix derivations)
23 #:use-module (guix grafts)
24 #:use-module (guix utils)
25 #:use-module (srfi srfi-1)
26 #:use-module (srfi srfi-9)
27 #:use-module (srfi srfi-9 gnu)
28 #:use-module (srfi srfi-26)
29 #:use-module (srfi srfi-34)
30 #:use-module (srfi srfi-35)
31 #:use-module (ice-9 match)
42 local-file-absolute-file-name
97 gexp-error-invalid-input))
101 ;;; This module implements "G-expressions", or "gexps". Gexps are like
102 ;;; S-expressions (sexps), with two differences:
104 ;;; 1. References (un-quotations) to derivations or packages in a gexp are
105 ;;; replaced by the corresponding output file name; in addition, the
106 ;;; 'ungexp-native' unquote-like form allows code to explicitly refer to
107 ;;; the native code of a given package, in case of cross-compilation;
109 ;;; 2. Gexps embed information about the derivations they refer to.
111 ;;; Gexps make it easy to write to files Scheme code that refers to store
112 ;;; items, or to write Scheme code to build derivations.
117 (define-record-type <gexp>
118 (make-gexp references modules proc)
120 (references gexp-references) ;list of <gexp-input>
121 (modules gexp-self-modules) ;list of module names
122 (proc gexp-proc)) ;procedure
124 (define (write-gexp gexp port)
125 "Write GEXP on PORT."
126 (display "#<gexp " port)
128 ;; Try to write the underlying sexp. Now, this trick doesn't work when
129 ;; doing things like (ungexp-splicing (gexp ())) because GEXP's procedure
130 ;; tries to use 'append' on that, which fails with wrong-type-arg.
132 (write (apply (gexp-proc gexp)
133 (gexp-references gexp))
136 (number->string (object-address gexp) 16)))
138 (set-record-type-printer! <gexp> write-gexp)
145 ;; Compiler for a type of objects that may be introduced in a gexp.
146 (define-record-type <gexp-compiler>
147 (gexp-compiler type lower expand)
149 (type gexp-compiler-type) ;record type descriptor
150 (lower gexp-compiler-lower)
151 (expand gexp-compiler-expand)) ;#f | DRV -> sexp
153 (define-condition-type &gexp-error &error
156 (define-condition-type &gexp-input-error &gexp-error
158 (input gexp-error-invalid-input))
161 (define %gexp-compilers
162 ;; 'eq?' mapping of record type descriptor to <gexp-compiler>.
163 (make-hash-table 20))
165 (define (default-expander thing obj output)
166 "This is the default expander for \"things\" that appear in gexps. It
167 returns its output file name of OBJ's OUTPUT."
170 (derivation->output-path drv output))
174 (define (register-compiler! compiler)
175 "Register COMPILER as a gexp compiler."
176 (hashq-set! %gexp-compilers
177 (gexp-compiler-type compiler) compiler))
179 (define (lookup-compiler object)
180 "Search for a compiler for OBJECT. Upon success, return the three argument
181 procedure to lower it; otherwise return #f."
182 (and=> (hashq-ref %gexp-compilers (struct-vtable object))
183 gexp-compiler-lower))
185 (define (lookup-expander object)
186 "Search for an expander for OBJECT. Upon success, return the three argument
187 procedure to expand it; otherwise return #f."
188 (and=> (hashq-ref %gexp-compilers (struct-vtable object))
189 gexp-compiler-expand))
191 (define* (lower-object obj
192 #:optional (system (%current-system))
194 "Return as a value in %STORE-MONAD the derivation or store item
195 corresponding to OBJ for SYSTEM, cross-compiling for TARGET if TARGET is true.
196 OBJ must be an object that has an associated gexp compiler, such as a
198 (match (lookup-compiler obj)
200 (raise (condition (&gexp-input-error (input obj)))))
202 (lower obj system target))))
204 (define-syntax define-gexp-compiler
205 (syntax-rules (=> compiler expander)
206 "Define NAME as a compiler for objects matching PREDICATE encountered in
209 In the simplest form of the macro, BODY must return a derivation for PARAM, an
210 object that matches PREDICATE, for SYSTEM and TARGET (the latter of which is
211 #f except when cross-compiling.)
213 The more elaborate form allows you to specify an expander:
215 (define-gexp-compiler something something?
216 compiler => (lambda (param system target) ...)
217 expander => (lambda (param drv output) ...))
219 The expander specifies how an object is converted to its sexp representation."
220 ((_ (name (param record-type) system target) body ...)
221 (define-gexp-compiler name record-type
222 compiler => (lambda (param system target) body ...)
223 expander => default-expander))
229 (gexp-compiler record-type compile expand))
230 (register-compiler! name)))))
232 (define-gexp-compiler (derivation-compiler (drv <derivation>) system target)
233 ;; Derivations are the lowest-level representation, so this is the identity
235 (with-monad %store-monad
240 ;;; File declarations.
243 ;; A local file name. FILE is the file name the user entered, which can be a
244 ;; relative file name, and ABSOLUTE is a promise that computes its canonical
245 ;; absolute file name. We keep it in a promise to compute it lazily and avoid
246 ;; repeated 'stat' calls.
247 (define-record-type <local-file>
248 (%%local-file file absolute name recursive? select?)
250 (file local-file-file) ;string
251 (absolute %local-file-absolute-file-name) ;promise string
252 (name local-file-name) ;string
253 (recursive? local-file-recursive?) ;Boolean
254 (select? local-file-select?)) ;string stat -> Boolean
256 (define (true file stat) #t)
258 (define* (%local-file file promise #:optional (name (basename file))
259 #:key recursive? (select? true))
260 ;; This intermediate procedure is part of our ABI, but the underlying
261 ;; %%LOCAL-FILE is not.
262 (%%local-file file promise name recursive? select?))
264 (define (absolute-file-name file directory)
265 "Return the canonical absolute file name for FILE, which lives in the
266 vicinity of DIRECTORY."
268 (cond ((string-prefix? "/" file) file)
269 ((not directory) file)
270 ((string-prefix? "/" directory)
271 (string-append directory "/" file))
274 (define-syntax local-file
276 "Return an object representing local file FILE to add to the store; this
277 object can be used in a gexp. If FILE is a relative file name, it is looked
278 up relative to the source file where this form appears. FILE will be added to
279 the store under NAME--by default the base name of FILE.
281 When RECURSIVE? is true, the contents of FILE are added recursively; if FILE
282 designates a flat file and RECURSIVE? is true, its contents are added, and its
283 permission bits are kept.
285 When RECURSIVE? is true, call (SELECT? FILE STAT) for each directory entry,
286 where FILE is the entry's absolute file name and STAT is the result of
287 'lstat'; exclude entries for which SELECT? does not return true.
289 This is the declarative counterpart of the 'interned-file' monadic procedure.
290 It is implemented as a macro to capture the current source directory where it
295 (delay (absolute-file-name file (current-source-directory)))
298 #'(syntax-error "missing file name"))
301 ;; XXX: We could return #'(lambda (file . rest) ...). However,
302 ;; (syntax-source #'id) is #f so (current-source-directory) would not
303 ;; work. Thus, simply forbid this form.
305 "'local-file' is a macro and cannot be used like this")))))
307 (define (local-file-absolute-file-name file)
308 "Return the absolute file name for FILE, a <local-file> instance. A
309 'system-error' exception is raised if FILE could not be found."
310 (force (%local-file-absolute-file-name file)))
312 (define-gexp-compiler (local-file-compiler (file <local-file>) system target)
313 ;; "Compile" FILE by adding it to the store.
315 (($ <local-file> file (= force absolute) name recursive? select?)
316 ;; Canonicalize FILE so that if it's a symlink, it is resolved. Failing
317 ;; to do that, when RECURSIVE? is #t, we could end up creating a dangling
318 ;; symlink in the store, and when RECURSIVE? is #f 'add-to-store' would
319 ;; just throw an error, both of which are inconvenient.
320 (interned-file absolute name
321 #:recursive? recursive? #:select? select?))))
323 (define-record-type <plain-file>
324 (%plain-file name content references)
326 (name plain-file-name) ;string
327 (content plain-file-content) ;string
328 (references plain-file-references)) ;list (currently unused)
330 (define (plain-file name content)
331 "Return an object representing a text file called NAME with the given
332 CONTENT (a string) to be added to the store.
334 This is the declarative counterpart of 'text-file'."
335 ;; XXX: For now just ignore 'references' because it's not clear how to use
336 ;; them in a declarative context.
337 (%plain-file name content '()))
339 (define-gexp-compiler (plain-file-compiler (file <plain-file>) system target)
340 ;; "Compile" FILE by adding it to the store.
342 (($ <plain-file> name content references)
343 (text-file name content references))))
345 (define-record-type <computed-file>
346 (%computed-file name gexp options)
348 (name computed-file-name) ;string
349 (gexp computed-file-gexp) ;gexp
350 (options computed-file-options)) ;list of arguments
352 (define* (computed-file name gexp
353 #:key (options '(#:local-build? #t)))
354 "Return an object representing the store item NAME, a file or directory
355 computed by GEXP. OPTIONS is a list of additional arguments to pass
356 to 'gexp->derivation'.
358 This is the declarative counterpart of 'gexp->derivation'."
359 (%computed-file name gexp options))
361 (define-gexp-compiler (computed-file-compiler (file <computed-file>)
363 ;; Compile FILE by returning a derivation whose build expression is its
366 (($ <computed-file> name gexp options)
367 (apply gexp->derivation name gexp options))))
369 (define-record-type <program-file>
370 (%program-file name gexp guile)
372 (name program-file-name) ;string
373 (gexp program-file-gexp) ;gexp
374 (guile program-file-guile)) ;package
376 (define* (program-file name gexp #:key (guile #f))
377 "Return an object representing the executable store item NAME that runs
378 GEXP. GUILE is the Guile package used to execute that script.
380 This is the declarative counterpart of 'gexp->script'."
381 (%program-file name gexp guile))
383 (define-gexp-compiler (program-file-compiler (file <program-file>)
385 ;; Compile FILE by returning a derivation that builds the script.
387 (($ <program-file> name gexp guile)
388 (gexp->script name gexp
389 #:guile (or guile (default-guile))))))
391 (define-record-type <scheme-file>
392 (%scheme-file name gexp)
394 (name scheme-file-name) ;string
395 (gexp scheme-file-gexp)) ;gexp
397 (define* (scheme-file name gexp)
398 "Return an object representing the Scheme file NAME that contains GEXP.
400 This is the declarative counterpart of 'gexp->file'."
401 (%scheme-file name gexp))
403 (define-gexp-compiler (scheme-file-compiler (file <scheme-file>)
405 ;; Compile FILE by returning a derivation that builds the file.
407 (($ <scheme-file> name gexp)
408 (gexp->file name gexp))))
410 ;; Appending SUFFIX to BASE's output file name.
411 (define-record-type <file-append>
412 (%file-append base suffix)
414 (base file-append-base) ;<package> | <derivation> | ...
415 (suffix file-append-suffix)) ;list of strings
417 (define (file-append base . suffix)
418 "Return a <file-append> object that expands to the concatenation of BASE and
420 (%file-append base suffix))
422 (define-gexp-compiler file-append-compiler <file-append>
423 compiler => (lambda (obj system target)
425 (($ <file-append> base _)
426 (lower-object base system #:target target))))
427 expander => (lambda (obj lowered output)
429 (($ <file-append> base suffix)
430 (let* ((expand (lookup-expander base))
431 (base (expand base lowered output)))
432 (string-append base (string-concatenate suffix)))))))
436 ;;; Inputs & outputs.
439 ;; The input of a gexp.
440 (define-record-type <gexp-input>
441 (%gexp-input thing output native?)
443 (thing gexp-input-thing) ;<package> | <origin> | <derivation> | ...
444 (output gexp-input-output) ;string
445 (native? gexp-input-native?)) ;Boolean
447 (define (write-gexp-input input port)
449 (($ <gexp-input> thing output #f)
450 (format port "#<gexp-input ~s:~a>" thing output))
451 (($ <gexp-input> thing output #t)
452 (format port "#<gexp-input native ~s:~a>" thing output))))
454 (set-record-type-printer! <gexp-input> write-gexp-input)
456 (define* (gexp-input thing ;convenience procedure
457 #:optional (output "out")
459 "Return a new <gexp-input> for the OUTPUT of THING; NATIVE? determines
460 whether this should be considered a \"native\" input or not."
461 (%gexp-input thing output native?))
463 ;; Reference to one of the derivation's outputs, for gexps used in
465 (define-record-type <gexp-output>
468 (name gexp-output-name))
470 (define (write-gexp-output output port)
472 (($ <gexp-output> name)
473 (format port "#<gexp-output ~a>" name))))
475 (set-record-type-printer! <gexp-output> write-gexp-output)
477 (define (gexp-modules gexp)
478 "Return the list of Guile module names GEXP relies on. If (gexp? GEXP) is
479 false, meaning that GEXP is a plain Scheme object, return the empty list."
482 (append (gexp-self-modules gexp)
483 (append-map (match-lambda
484 (($ <gexp-input> (? gexp? exp))
486 (($ <gexp-input> (lst ...))
487 (append-map (lambda (item)
494 (gexp-references gexp))))
495 '())) ;plain Scheme data type
497 (define* (lower-inputs inputs
499 "Turn any package from INPUTS into a derivation for SYSTEM; return the
500 corresponding input list as a monadic value. When TARGET is true, use it as
501 the cross-compilation target triplet."
502 (with-monad %store-monad
503 (sequence %store-monad
505 (((? struct? thing) sub-drv ...)
506 (mlet %store-monad ((drv (lower-object
507 thing system #:target target)))
508 (return `(,drv ,@sub-drv))))
513 (define* (lower-reference-graphs graphs #:key system target)
514 "Given GRAPHS, a list of (FILE-NAME INPUT ...) lists for use as a
515 #:reference-graphs argument, lower it such that each INPUT is replaced by the
516 corresponding derivation."
518 (((file-names . inputs) ...)
519 (mlet %store-monad ((inputs (lower-inputs inputs
522 (return (map cons file-names inputs))))))
524 (define* (lower-references lst #:key system target)
525 "Based on LST, a list of output names and packages, return a list of output
526 names and file names suitable for the #:allowed-references argument to
528 (with-monad %store-monad
533 (($ <gexp-input> thing output native?)
534 (mlet %store-monad ((drv (lower-object thing system
537 (return (derivation->output-path drv output))))
539 (mlet %store-monad ((drv (lower-object thing system
541 (return (derivation->output-path drv))))))
543 (sequence %store-monad (map lower lst))))
545 (define default-guile-derivation
546 ;; Here we break the abstraction by talking to the higher-level layer.
547 ;; Thus, do the resolution lazily to hide the circular dependency.
549 (let ((iface (resolve-interface '(guix packages))))
550 (module-ref iface 'default-guile-derivation)))))
552 ((force proc) system))))
554 (define* (gexp->derivation name exp
556 system (target 'current)
557 hash hash-algo recursive?
560 (module-path %load-path)
561 (guile-for-build (%guile-for-build))
564 allowed-references disallowed-references
566 local-build? (substitutable? #t)
568 (script-name (string-append name "-builder")))
569 "Return a derivation NAME that runs EXP (a gexp) with GUILE-FOR-BUILD (a
570 derivation) on SYSTEM; EXP is stored in a file called SCRIPT-NAME. When
571 TARGET is true, it is used as the cross-compilation target triplet for
572 packages referred to by EXP.
574 MODULES is deprecated in favor of 'with-imported-modules'. Its meaning is to
575 make MODULES available in the evaluation context of EXP; MODULES is a list of
576 names of Guile modules searched in MODULE-PATH to be copied in the store,
577 compiled, and made available in the load path during the execution of
578 EXP---e.g., '((guix build utils) (guix build gnu-build-system)).
580 GRAFT? determines whether packages referred to by EXP should be grafted when
583 When REFERENCES-GRAPHS is true, it must be a list of tuples of one of the
587 (FILE-NAME PACKAGE OUTPUT)
588 (FILE-NAME DERIVATION)
589 (FILE-NAME DERIVATION OUTPUT)
590 (FILE-NAME STORE-ITEM)
592 The right-hand-side of each element of REFERENCES-GRAPHS is automatically made
593 an input of the build process of EXP. In the build environment, each
594 FILE-NAME contains the reference graph of the corresponding item, in a simple
597 ALLOWED-REFERENCES must be either #f or a list of output names and packages.
598 In the latter case, the list denotes store items that the result is allowed to
599 refer to. Any reference to another store item will lead to a build error.
600 Similarly for DISALLOWED-REFERENCES, which can list items that must not be
601 referenced by the outputs.
603 DEPRECATION-WARNINGS determines whether to show deprecation warnings while
604 compiling modules. It can be #f, #t, or 'detailed.
606 The other arguments are as for 'derivation'."
609 (append modules (gexp-modules exp))))
610 (define outputs (gexp-outputs exp))
612 (define (graphs-file-names graphs)
613 ;; Return a list of (FILE-NAME . STORE-PATH) pairs made from GRAPHS.
615 ;; TODO: Remove 'derivation?' special cases.
616 ((file-name (? derivation? drv))
617 (cons file-name (derivation->output-path drv)))
618 ((file-name (? derivation? drv) sub-drv)
619 (cons file-name (derivation->output-path drv sub-drv)))
621 (cons file-name thing)))
624 (mlet* %store-monad (;; The following binding forces '%current-system' and
625 ;; '%current-target-system' to be looked up at >>=
627 (graft? (set-grafting graft?))
629 (system -> (or system (%current-system)))
630 (target -> (if (eq? target 'current)
631 (%current-target-system)
633 (normals (lower-inputs (gexp-inputs exp)
636 (natives (lower-inputs (gexp-native-inputs exp)
639 (inputs -> (append normals natives))
640 (sexp (gexp->sexp exp
643 (builder (text-file script-name
644 (object->string sexp)))
645 (modules (if (pair? %modules)
646 (imported-modules %modules
648 #:module-path module-path
649 #:guile guile-for-build)
651 (compiled (if (pair? %modules)
652 (compiled-modules %modules
654 #:module-path module-path
655 #:guile guile-for-build
656 #:deprecation-warnings
657 deprecation-warnings)
659 (graphs (if references-graphs
660 (lower-reference-graphs references-graphs
664 (allowed (if allowed-references
665 (lower-references allowed-references
669 (disallowed (if disallowed-references
670 (lower-references disallowed-references
674 (guile (if guile-for-build
675 (return guile-for-build)
676 (default-guile-derivation system))))
678 (set-grafting graft?) ;restore the initial setting
680 (string-append (derivation->output-path guile)
682 `("--no-auto-compile"
683 ,@(if (pair? %modules)
684 `("-L" ,(derivation->output-path modules)
685 "-C" ,(derivation->output-path compiled))
694 `((,modules) (,compiled) ,@inputs)
697 (((_ . inputs) ...) inputs)
699 #:hash hash #:hash-algo hash-algo #:recursive? recursive?
700 #:references-graphs (and=> graphs graphs-file-names)
701 #:allowed-references allowed
702 #:disallowed-references disallowed
703 #:leaked-env-vars leaked-env-vars
704 #:local-build? local-build?
705 #:substitutable? substitutable?))))
707 (define* (gexp-inputs exp #:key native?)
708 "Return the input list for EXP. When NATIVE? is true, return only native
709 references; otherwise, return only non-native references."
710 (define (add-reference-inputs ref result)
712 (($ <gexp-input> (? gexp? exp) _ #t)
714 (append (gexp-inputs exp)
715 (gexp-inputs exp #:native? #t)
718 (($ <gexp-input> (? gexp? exp) _ #f)
719 (append (gexp-inputs exp #:native? native?)
721 (($ <gexp-input> (? string? str))
722 (if (direct-store-path? str)
723 (cons `(,str) result)
725 (($ <gexp-input> (? struct? thing) output n?)
726 (if (and (eqv? n? native?) (lookup-compiler thing))
727 ;; THING is a derivation, or a package, or an origin, etc.
728 (cons `(,thing ,output) result)
730 (($ <gexp-input> (lst ...) output n?)
731 (fold-right add-reference-inputs result
732 ;; XXX: For now, automatically convert LST to a list of
733 ;; gexp-inputs. Inherit N?.
736 (%gexp-input (gexp-input-thing x)
737 (gexp-input-output x)
740 (%gexp-input x "out" n?)))
743 ;; Ignore references to other kinds of objects.
746 (fold-right add-reference-inputs
748 (gexp-references exp)))
750 (define gexp-native-inputs
751 (cut gexp-inputs <> #:native? #t))
753 (define (gexp-outputs exp)
754 "Return the outputs referred to by EXP as a list of strings."
755 (define (add-reference-output ref result)
757 (($ <gexp-output> name)
759 (($ <gexp-input> (? gexp? exp))
760 (append (gexp-outputs exp) result))
761 (($ <gexp-input> (lst ...) output native?)
762 ;; XXX: Automatically convert LST.
763 (add-reference-output (map (match-lambda
764 ((? gexp-input? x) x)
765 (x (%gexp-input x "out" native?)))
769 (fold-right add-reference-output result lst))
774 (add-reference-output (gexp-references exp) '())))
776 (define* (gexp->sexp exp #:key
777 (system (%current-system))
778 (target (%current-target-system)))
779 "Return (monadically) the sexp corresponding to EXP for the given OUTPUT,
780 and in the current monad setting (system type, etc.)"
781 (define* (reference->sexp ref #:optional native?)
782 (with-monad %store-monad
784 (($ <gexp-output> output)
785 ;; Output file names are not known in advance but the daemon defines
786 ;; an environment variable for each of them at build time, so use
788 (return `((@ (guile) getenv) ,output)))
789 (($ <gexp-input> (? gexp? exp) output n?)
792 #:target (if (or n? native?) #f target)))
793 (($ <gexp-input> (refs ...) output n?)
794 (sequence %store-monad
796 ;; XXX: Automatically convert REF to an gexp-input.
798 (if (gexp-input? ref)
800 (%gexp-input ref "out" n?))
803 (($ <gexp-input> (? struct? thing) output n?)
804 (let ((target (if (or n? native?) #f target))
805 (expand (lookup-expander thing)))
806 (mlet %store-monad ((obj (lower-object thing system
808 ;; OBJ must be either a derivation or a store file name.
809 (return (expand thing obj output)))))
816 ((args (sequence %store-monad
817 (map reference->sexp (gexp-references exp)))))
818 (return (apply (gexp-proc exp) args))))
820 (define (syntax-location-string s)
821 "Return a string representing the source code location of S."
822 (let ((props (syntax-source s)))
824 (let ((file (assoc-ref props 'filename))
825 (line (and=> (assoc-ref props 'line) 1+))
826 (column (assoc-ref props 'column)))
828 (simple-format #f "~a:~a:~a"
830 (simple-format #f "~a:~a" line column)))
831 "<unknown location>")))
833 (define-syntax-parameter current-imported-modules
834 ;; Current list of imported modules.
835 (identifier-syntax '()))
837 (define-syntax-rule (with-imported-modules modules body ...)
838 "Mark the gexps defined in BODY... as requiring MODULES in their execution
840 (syntax-parameterize ((current-imported-modules
841 (identifier-syntax modules)))
846 (define (collect-escapes exp)
847 ;; Return all the 'ungexp' present in EXP.
850 (syntax-case exp (ungexp
853 ungexp-native-splicing)
858 ((ungexp-splicing _ ...)
860 ((ungexp-native _ ...)
862 ((ungexp-native-splicing _ ...)
865 (let ((result (loop #'exp0 result)))
866 (loop #'exp result)))
870 (define (escape->ref exp)
871 ;; Turn 'ungexp' form EXP into a "reference".
872 (syntax-case exp (ungexp ungexp-splicing
873 ungexp-native ungexp-native-splicing
876 #'(gexp-output "out"))
877 ((ungexp output name)
878 #'(gexp-output name))
880 #'(%gexp-input thing "out" #f))
881 ((ungexp drv-or-pkg out)
882 #'(%gexp-input drv-or-pkg out #f))
883 ((ungexp-splicing lst)
884 #'(%gexp-input lst "out" #f))
885 ((ungexp-native thing)
886 #'(%gexp-input thing "out" #t))
887 ((ungexp-native drv-or-pkg out)
888 #'(%gexp-input drv-or-pkg out #t))
889 ((ungexp-native-splicing lst)
890 #'(%gexp-input lst "out" #t))))
892 (define (substitute-ungexp exp substs)
893 ;; Given EXP, an 'ungexp' or 'ungexp-native' form, substitute it with
894 ;; the corresponding form in SUBSTS.
895 (match (assoc exp substs)
899 (with-syntax ((exp exp))
900 #'(syntax-error "error: no 'ungexp' substitution" exp)))))
902 (define (substitute-ungexp-splicing exp substs)
905 (match (assoc #'exp substs)
907 (with-syntax ((id id))
909 #,(substitute-references #'(rest ...) substs))))
911 #'(syntax-error "error: no 'ungexp-splicing' substitution"
914 (define (substitute-references exp substs)
915 ;; Return a variant of EXP where all the cars of SUBSTS have been
916 ;; replaced by the corresponding cdr.
917 (syntax-case exp (ungexp ungexp-native
918 ungexp-splicing ungexp-native-splicing)
920 (substitute-ungexp exp substs))
921 ((ungexp-native _ ...)
922 (substitute-ungexp exp substs))
923 (((ungexp-splicing _ ...) rest ...)
924 (substitute-ungexp-splicing exp substs))
925 (((ungexp-native-splicing _ ...) rest ...)
926 (substitute-ungexp-splicing exp substs))
928 #`(cons #,(substitute-references #'exp0 substs)
929 #,(substitute-references #'exp substs)))
932 (syntax-case s (ungexp output)
934 (let* ((escapes (delete-duplicates (collect-escapes #'exp)))
935 (formals (generate-temporaries escapes))
936 (sexp (substitute-references #'exp (zip escapes formals)))
937 (refs (map escape->ref escapes)))
938 #`(make-gexp (list #,@refs)
939 current-imported-modules
948 (define %utils-module
949 ;; This file provides 'mkdir-p', needed to implement 'imported-files' and
950 ;; other primitives below. Note: We give the file name relative to this
951 ;; file you are currently reading; 'search-path' could return a file name
952 ;; relative to the current working directory.
953 (local-file "build/utils.scm"
956 (define* (imported-files files
957 #:key (name "file-import")
958 (system (%current-system))
959 (guile (%guile-for-build)))
960 "Return a derivation that imports FILES into STORE. FILES must be a list
961 of (FINAL-PATH . FILE) pairs. Each FILE is mapped to FINAL-PATH in the
962 resulting store path. FILE can be either a file name, or a file-like object,
963 as returned by 'local-file' for example."
966 ((final-path . (? string? file-name))
967 (mlet %store-monad ((file (interned-file file-name
968 (basename final-path))))
969 (return (list final-path file))))
970 ((final-path . file-like)
971 (mlet %store-monad ((file (lower-object file-like system)))
972 (return (list final-path file))))))
974 (mlet %store-monad ((files (sequence %store-monad
975 (map file-pair files))))
979 (primitive-load (ungexp %utils-module)) ;for 'mkdir-p'
980 (use-modules (ice-9 match))
982 (mkdir (ungexp output)) (chdir (ungexp output))
983 (for-each (match-lambda
984 ((final-path store-path)
985 (mkdir-p (dirname final-path))
986 (symlink store-path final-path)))
989 ;; TODO: Pass FILES as an environment variable so that BUILD remains
990 ;; exactly the same regardless of FILES: less disk space, and fewer
991 ;; 'add-to-store' RPCs.
992 (gexp->derivation name build
994 #:guile-for-build guile
997 (define* (imported-modules modules
998 #:key (name "module-import")
999 (system (%current-system))
1000 (guile (%guile-for-build))
1001 (module-path %load-path))
1002 "Return a derivation that contains the source files of MODULES, a list of
1003 module names such as `(ice-9 q)'. All of MODULES must be either names of
1004 modules to be found in the MODULE-PATH search path, or a module name followed
1005 by an arrow followed by a file-like object. For example:
1007 (imported-modules `((guix build utils)
1009 ((guix config) => ,(scheme-file …))))
1011 In this example, the first two modules are taken from MODULE-PATH, and the
1012 last one is created from the given <scheme-file> object."
1013 (mlet %store-monad ((files
1016 (((module ...) '=> file)
1018 (cons (module->source-file-name module)
1021 (let ((f (module->source-file-name module)))
1023 (cons f (search-path* module-path f))))))
1025 (imported-files files #:name name #:system system
1028 (define* (compiled-modules modules
1029 #:key (name "module-import-compiled")
1030 (system (%current-system))
1031 (guile (%guile-for-build))
1032 (module-path %load-path)
1033 (deprecation-warnings #f))
1034 "Return a derivation that builds a tree containing the `.go' files
1035 corresponding to MODULES. All the MODULES are built in a context where
1036 they can refer to each other."
1037 (mlet %store-monad ((modules (imported-modules modules
1045 (primitive-load (ungexp %utils-module)) ;for 'mkdir-p'
1047 (use-modules (ice-9 ftw)
1049 (system base compile))
1051 (define (regular? file)
1052 (not (member file '("." ".."))))
1054 (define (process-directory directory output)
1055 (let ((entries (map (cut string-append directory "/" <>)
1056 (scandir directory regular?))))
1057 (for-each (lambda (entry)
1058 (if (file-is-directory? entry)
1059 (let ((output (string-append output "/"
1062 (process-directory entry output))
1063 (let* ((base (string-drop-right
1066 (output (string-append output "/" base
1069 #:output-file output
1071 %auto-compilation-options))))
1074 (set! %load-path (cons (ungexp modules) %load-path))
1075 (mkdir (ungexp output))
1076 (chdir (ungexp modules))
1077 (process-directory "." (ungexp output)))))
1079 ;; TODO: Pass MODULES as an environment variable.
1080 (gexp->derivation name build
1082 #:guile-for-build guile
1085 (case deprecation-warnings
1087 '(("GUILE_WARN_DEPRECATED" . "no")))
1089 '(("GUILE_WARN_DEPRECATED" . "detailed")))
1095 ;;; Convenience procedures.
1098 (define (default-guile)
1099 ;; Lazily resolve 'guile-2.2' (not 'guile-final' because this is for
1100 ;; programs returned by 'program-file' and we don't want to keep references
1101 ;; to several Guile packages). This module must not refer to (gnu …)
1102 ;; modules directly, to avoid circular dependencies, hence this hack.
1103 (module-ref (resolve-interface '(gnu packages guile))
1106 (define (load-path-expression modules)
1107 "Return as a monadic value a gexp that sets '%load-path' and
1108 '%load-compiled-path' to point to MODULES, a list of module names."
1109 (mlet %store-monad ((modules (imported-modules modules))
1110 (compiled (compiled-modules modules)))
1111 (return (gexp (eval-when (expand load eval)
1113 (cons (ungexp modules) %load-path))
1114 (set! %load-compiled-path
1115 (cons (ungexp compiled)
1116 %load-compiled-path)))))))
1118 (define* (gexp->script name exp
1119 #:key (guile (default-guile)))
1120 "Return an executable script NAME that runs EXP using GUILE, with EXP's
1121 imported modules in its search path."
1122 (mlet %store-monad ((set-load-path
1123 (load-path-expression (gexp-modules exp))))
1124 (gexp->derivation name
1126 (call-with-output-file (ungexp output)
1128 ;; Note: that makes a long shebang. When the store
1129 ;; is /gnu/store, that fits within the 128-byte
1130 ;; limit imposed by Linux, but that may go beyond
1131 ;; when running tests.
1133 "#!~a/bin/guile --no-auto-compile~%!#~%"
1136 (write '(ungexp set-load-path) port)
1137 (write '(ungexp exp) port)
1138 (chmod port #o555)))))))
1140 (define* (gexp->file name exp #:key (set-load-path? #t))
1141 "Return a derivation that builds a file NAME containing EXP. When
1142 SET-LOAD-PATH? is true, emit code in the resulting file to set '%load-path'
1143 and '%load-compiled-path' to honor EXP's imported modules."
1144 (match (if set-load-path? (gexp-modules exp) '())
1146 (gexp->derivation name
1148 (call-with-output-file (ungexp output)
1150 (write '(ungexp exp) port))))
1152 #:substitutable? #f))
1154 (mlet %store-monad ((set-load-path (load-path-expression modules)))
1155 (gexp->derivation name
1157 (call-with-output-file (ungexp output)
1159 (write '(ungexp set-load-path) port)
1160 (write '(ungexp exp) port))))
1162 #:substitutable? #f)))))
1164 (define* (text-file* name #:rest text)
1165 "Return as a monadic value a derivation that builds a text file containing
1166 all of TEXT. TEXT may list, in addition to strings, objects of any type that
1167 can be used in a gexp: packages, derivations, local file objects, etc. The
1168 resulting store file holds references to all these."
1170 (gexp (call-with-output-file (ungexp output "out")
1172 (display (string-append (ungexp-splicing text)) port)))))
1174 (gexp->derivation name builder
1176 #:substitutable? #f))
1178 (define* (mixed-text-file name #:rest text)
1179 "Return an object representing store file NAME containing TEXT. TEXT is a
1180 sequence of strings and file-like objects, as in:
1182 (mixed-text-file \"profile\"
1183 \"export PATH=\" coreutils \"/bin:\" grep \"/bin\")
1185 This is the declarative counterpart of 'text-file*'."
1187 (gexp (call-with-output-file (ungexp output "out")
1189 (display (string-append (ungexp-splicing text)) port)))))
1191 (computed-file name build))
1193 (define (file-union name files)
1194 "Return a <computed-file> that builds a directory containing all of FILES.
1195 Each item in FILES must be a two-element list where the first element is the
1196 file name to use in the new directory, and the second element is a gexp
1197 denoting the target file. Here's an example:
1200 `((\"hosts\" ,(plain-file \"hosts\"
1201 \"127.0.0.1 localhost\"))
1202 (\"bashrc\" ,(plain-file \"bashrc\"
1203 \"alias ls='ls --color'\"))))
1205 This yields an 'etc' directory containing these two files."
1209 (mkdir (ungexp output))
1210 (chdir (ungexp output))
1216 ;; Stat the source to abort early if it does
1218 (stat (ungexp source))
1220 (symlink (ungexp source)
1221 (ungexp target))))))
1224 (define* (directory-union name things
1225 #:key (copy? #f) (quiet? #f))
1226 "Return a directory that is the union of THINGS, where THINGS is a list of
1227 file-like objects denoting directories. For example:
1229 (directory-union \"guile+emacs\" (list guile emacs))
1231 yields a directory that is the union of the 'guile' and 'emacs' packages.
1233 When HARD-LINKS? is true, create hard links instead of symlinks. When QUIET?
1234 is true, the derivation will not print anything."
1237 (gexp (lambda (old new)
1238 (if (file-is-directory? old)
1240 (copy-file old new))))
1245 (gexp (%make-void-port "w"))
1246 (gexp (current-error-port))))
1250 ;; Only one thing; return it.
1254 (with-imported-modules '((guix build union))
1256 (use-modules (guix build union))
1257 (union-build (ungexp output)
1260 #:log-port (ungexp log-port)
1261 #:symlink (ungexp symlink)))))))))
1265 ;;; Syntactic sugar.
1268 (eval-when (expand load eval)
1269 (define* (read-ungexp chr port #:optional native?)
1270 "Read an 'ungexp' or 'ungexp-splicing' form from PORT. When NATIVE? is
1271 true, use 'ungexp-native' and 'ungexp-native-splicing' instead."
1272 (define unquote-symbol
1273 (match (peek-char port)
1277 'ungexp-native-splicing
1286 (let ((str (symbol->string symbol)))
1287 (match (string-index-right str #\:)
1289 `(,unquote-symbol ,symbol))
1291 (let ((name (string->symbol (substring str 0 colon)))
1292 (output (substring str (+ colon 1))))
1293 `(,unquote-symbol ,name ,output))))))
1295 `(,unquote-symbol ,x))))
1297 (define (read-gexp chr port)
1298 "Read a 'gexp' form from PORT."
1299 `(gexp ,(read port)))
1301 ;; Extend the reader
1302 (read-hash-extend #\~ read-gexp)
1303 (read-hash-extend #\$ read-ungexp)
1304 (read-hash-extend #\+ (cut read-ungexp <> <> #t)))
1306 ;;; gexp.scm ends here