gexp: Slightly simplify 'gexp-inputs'.
[guix.git] / guix / gexp.scm
blob6f63afe6a6ace585b3511e289cf7ca331ce12a59
1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2014, 2015, 2016 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 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 (ice-9 match)
30   #:export (gexp
31             gexp?
32             with-imported-modules
34             gexp-input
35             gexp-input?
37             local-file
38             local-file?
39             local-file-file
40             local-file-absolute-file-name
41             local-file-name
42             local-file-recursive?
44             plain-file
45             plain-file?
46             plain-file-name
47             plain-file-content
49             computed-file
50             computed-file?
51             computed-file-name
52             computed-file-gexp
53             computed-file-options
55             program-file
56             program-file?
57             program-file-name
58             program-file-gexp
59             program-file-guile
61             scheme-file
62             scheme-file?
63             scheme-file-name
64             scheme-file-gexp
66             file-append
67             file-append?
68             file-append-base
69             file-append-suffix
71             gexp->derivation
72             gexp->file
73             gexp->script
74             text-file*
75             mixed-text-file
76             imported-files
77             imported-modules
78             compiled-modules
80             define-gexp-compiler
81             gexp-compiler?
82             lower-object
84             lower-inputs))
86 ;;; Commentary:
87 ;;;
88 ;;; This module implements "G-expressions", or "gexps".  Gexps are like
89 ;;; S-expressions (sexps), with two differences:
90 ;;;
91 ;;;   1. References (un-quotations) to derivations or packages in a gexp are
92 ;;;      replaced by the corresponding output file name; in addition, the
93 ;;;      'ungexp-native' unquote-like form allows code to explicitly refer to
94 ;;;      the native code of a given package, in case of cross-compilation;
95 ;;;
96 ;;;   2. Gexps embed information about the derivations they refer to.
97 ;;;
98 ;;; Gexps make it easy to write to files Scheme code that refers to store
99 ;;; items, or to write Scheme code to build derivations.
101 ;;; Code:
103 ;; "G expressions".
104 (define-record-type <gexp>
105   (make-gexp references modules proc)
106   gexp?
107   (references gexp-references)                    ;list of <gexp-input>
108   (modules    gexp-self-modules)                  ;list of module names
109   (proc       gexp-proc))                         ;procedure
111 (define (write-gexp gexp port)
112   "Write GEXP on PORT."
113   (display "#<gexp " port)
115   ;; Try to write the underlying sexp.  Now, this trick doesn't work when
116   ;; doing things like (ungexp-splicing (gexp ())) because GEXP's procedure
117   ;; tries to use 'append' on that, which fails with wrong-type-arg.
118   (false-if-exception
119    (write (apply (gexp-proc gexp)
120                  (gexp-references gexp))
121           port))
122   (format port " ~a>"
123           (number->string (object-address gexp) 16)))
125 (set-record-type-printer! <gexp> write-gexp)
129 ;;; Methods.
132 ;; Compiler for a type of objects that may be introduced in a gexp.
133 (define-record-type <gexp-compiler>
134   (gexp-compiler type lower expand)
135   gexp-compiler?
136   (type       gexp-compiler-type)                 ;record type descriptor
137   (lower      gexp-compiler-lower)
138   (expand     gexp-compiler-expand))              ;#f | DRV -> sexp
140 (define %gexp-compilers
141   ;; 'eq?' mapping of record type descriptor to <gexp-compiler>.
142   (make-hash-table 20))
144 (define (default-expander thing obj output)
145   "This is the default expander for \"things\" that appear in gexps.  It
146 returns its output file name of OBJ's OUTPUT."
147   (match obj
148     ((? derivation? drv)
149      (derivation->output-path drv output))
150     ((? string? file)
151      file)))
153 (define (register-compiler! compiler)
154   "Register COMPILER as a gexp compiler."
155   (hashq-set! %gexp-compilers
156               (gexp-compiler-type compiler) compiler))
158 (define (lookup-compiler object)
159   "Search for a compiler for OBJECT.  Upon success, return the three argument
160 procedure to lower it; otherwise return #f."
161   (and=> (hashq-ref %gexp-compilers (struct-vtable object))
162          gexp-compiler-lower))
164 (define (lookup-expander object)
165   "Search for an expander for OBJECT.  Upon success, return the three argument
166 procedure to expand it; otherwise return #f."
167   (and=> (hashq-ref %gexp-compilers (struct-vtable object))
168          gexp-compiler-expand))
170 (define* (lower-object obj
171                        #:optional (system (%current-system))
172                        #:key target)
173   "Return as a value in %STORE-MONAD the derivation or store item
174 corresponding to OBJ for SYSTEM, cross-compiling for TARGET if TARGET is true.
175 OBJ must be an object that has an associated gexp compiler, such as a
176 <package>."
177   (let ((lower (lookup-compiler obj)))
178     (lower obj system target)))
180 (define-syntax define-gexp-compiler
181   (syntax-rules (=> compiler expander)
182     "Define NAME as a compiler for objects matching PREDICATE encountered in
183 gexps.
185 In the simplest form of the macro, BODY must return a derivation for PARAM, an
186 object that matches PREDICATE, for SYSTEM and TARGET (the latter of which is
187 #f except when cross-compiling.)
189 The more elaborate form allows you to specify an expander:
191   (define-gexp-compiler something something?
192     compiler => (lambda (param system target) ...)
193     expander => (lambda (param drv output) ...))
195 The expander specifies how an object is converted to its sexp representation."
196     ((_ (name (param record-type) system target) body ...)
197      (define-gexp-compiler name record-type
198        compiler => (lambda (param system target) body ...)
199        expander => default-expander))
200     ((_ name record-type
201         compiler => compile
202         expander => expand)
203      (begin
204        (define name
205          (gexp-compiler record-type compile expand))
206        (register-compiler! name)))))
208 (define-gexp-compiler (derivation-compiler (drv <derivation>) system target)
209   ;; Derivations are the lowest-level representation, so this is the identity
210   ;; compiler.
211   (with-monad %store-monad
212     (return drv)))
216 ;;; File declarations.
219 ;; A local file name.  FILE is the file name the user entered, which can be a
220 ;; relative file name, and ABSOLUTE is a promise that computes its canonical
221 ;; absolute file name.  We keep it in a promise to compute it lazily and avoid
222 ;; repeated 'stat' calls.
223 (define-record-type <local-file>
224   (%%local-file file absolute name recursive? select?)
225   local-file?
226   (file       local-file-file)                    ;string
227   (absolute   %local-file-absolute-file-name)     ;promise string
228   (name       local-file-name)                    ;string
229   (recursive? local-file-recursive?)              ;Boolean
230   (select?    local-file-select?))                ;string stat -> Boolean
232 (define (true file stat) #t)
234 (define* (%local-file file promise #:optional (name (basename file))
235                       #:key recursive? (select? true))
236   ;; This intermediate procedure is part of our ABI, but the underlying
237   ;; %%LOCAL-FILE is not.
238   (%%local-file file promise name recursive? select?))
240 (define (absolute-file-name file directory)
241   "Return the canonical absolute file name for FILE, which lives in the
242 vicinity of DIRECTORY."
243   (canonicalize-path
244    (cond ((string-prefix? "/" file) file)
245          ((not directory) file)
246          ((string-prefix? "/" directory)
247           (string-append directory "/" file))
248          (else file))))
250 (define-syntax-rule (local-file file rest ...)
251   "Return an object representing local file FILE to add to the store; this
252 object can be used in a gexp.  If FILE is a relative file name, it is looked
253 up relative to the source file where this form appears.  FILE will be added to
254 the store under NAME--by default the base name of FILE.
256 When RECURSIVE? is true, the contents of FILE are added recursively; if FILE
257 designates a flat file and RECURSIVE? is true, its contents are added, and its
258 permission bits are kept.
260 When RECURSIVE? is true, call (SELECT?  FILE STAT) for each directory entry,
261 where FILE is the entry's absolute file name and STAT is the result of
262 'lstat'; exclude entries for which SELECT? does not return true.
264 This is the declarative counterpart of the 'interned-file' monadic procedure."
265   (%local-file file
266                (delay (absolute-file-name file (current-source-directory)))
267                rest ...))
269 (define (local-file-absolute-file-name file)
270   "Return the absolute file name for FILE, a <local-file> instance.  A
271 'system-error' exception is raised if FILE could not be found."
272   (force (%local-file-absolute-file-name file)))
274 (define-gexp-compiler (local-file-compiler (file <local-file>) system target)
275   ;; "Compile" FILE by adding it to the store.
276   (match file
277     (($ <local-file> file (= force absolute) name recursive? select?)
278      ;; Canonicalize FILE so that if it's a symlink, it is resolved.  Failing
279      ;; to do that, when RECURSIVE? is #t, we could end up creating a dangling
280      ;; symlink in the store, and when RECURSIVE? is #f 'add-to-store' would
281      ;; just throw an error, both of which are inconvenient.
282      (interned-file absolute name
283                     #:recursive? recursive? #:select? select?))))
285 (define-record-type <plain-file>
286   (%plain-file name content references)
287   plain-file?
288   (name        plain-file-name)                   ;string
289   (content     plain-file-content)                ;string
290   (references  plain-file-references))            ;list (currently unused)
292 (define (plain-file name content)
293   "Return an object representing a text file called NAME with the given
294 CONTENT (a string) to be added to the store.
296 This is the declarative counterpart of 'text-file'."
297   ;; XXX: For now just ignore 'references' because it's not clear how to use
298   ;; them in a declarative context.
299   (%plain-file name content '()))
301 (define-gexp-compiler (plain-file-compiler (file <plain-file>) system target)
302   ;; "Compile" FILE by adding it to the store.
303   (match file
304     (($ <plain-file> name content references)
305      (text-file name content references))))
307 (define-record-type <computed-file>
308   (%computed-file name gexp options)
309   computed-file?
310   (name       computed-file-name)                 ;string
311   (gexp       computed-file-gexp)                 ;gexp
312   (options    computed-file-options))             ;list of arguments
314 (define* (computed-file name gexp
315                         #:key (options '(#:local-build? #t)))
316   "Return an object representing the store item NAME, a file or directory
317 computed by GEXP.  OPTIONS is a list of additional arguments to pass
318 to 'gexp->derivation'.
320 This is the declarative counterpart of 'gexp->derivation'."
321   (%computed-file name gexp options))
323 (define-gexp-compiler (computed-file-compiler (file <computed-file>)
324                                               system target)
325   ;; Compile FILE by returning a derivation whose build expression is its
326   ;; gexp.
327   (match file
328     (($ <computed-file> name gexp options)
329      (apply gexp->derivation name gexp options))))
331 (define-record-type <program-file>
332   (%program-file name gexp guile)
333   program-file?
334   (name       program-file-name)                  ;string
335   (gexp       program-file-gexp)                  ;gexp
336   (guile      program-file-guile))                ;package
338 (define* (program-file name gexp #:key (guile #f))
339   "Return an object representing the executable store item NAME that runs
340 GEXP.  GUILE is the Guile package used to execute that script.
342 This is the declarative counterpart of 'gexp->script'."
343   (%program-file name gexp guile))
345 (define-gexp-compiler (program-file-compiler (file <program-file>)
346                                              system target)
347   ;; Compile FILE by returning a derivation that builds the script.
348   (match file
349     (($ <program-file> name gexp guile)
350      (gexp->script name gexp
351                    #:guile (or guile (default-guile))))))
353 (define-record-type <scheme-file>
354   (%scheme-file name gexp)
355   scheme-file?
356   (name       scheme-file-name)                  ;string
357   (gexp       scheme-file-gexp))                 ;gexp
359 (define* (scheme-file name gexp)
360   "Return an object representing the Scheme file NAME that contains GEXP.
362 This is the declarative counterpart of 'gexp->file'."
363   (%scheme-file name gexp))
365 (define-gexp-compiler (scheme-file-compiler (file <scheme-file>)
366                                             system target)
367   ;; Compile FILE by returning a derivation that builds the file.
368   (match file
369     (($ <scheme-file> name gexp)
370      (gexp->file name gexp))))
372 ;; Appending SUFFIX to BASE's output file name.
373 (define-record-type <file-append>
374   (%file-append base suffix)
375   file-append?
376   (base   file-append-base)                    ;<package> | <derivation> | ...
377   (suffix file-append-suffix))                 ;list of strings
379 (define (file-append base . suffix)
380   "Return a <file-append> object that expands to the concatenation of BASE and
381 SUFFIX."
382   (%file-append base suffix))
384 (define-gexp-compiler file-append-compiler <file-append>
385   compiler => (lambda (obj system target)
386                 (match obj
387                   (($ <file-append> base _)
388                    (lower-object base system #:target target))))
389   expander => (lambda (obj lowered output)
390                 (match obj
391                   (($ <file-append> base suffix)
392                    (let* ((expand (lookup-expander base))
393                           (base   (expand base lowered output)))
394                      (string-append base (string-concatenate suffix)))))))
398 ;;; Inputs & outputs.
401 ;; The input of a gexp.
402 (define-record-type <gexp-input>
403   (%gexp-input thing output native?)
404   gexp-input?
405   (thing     gexp-input-thing)       ;<package> | <origin> | <derivation> | ...
406   (output    gexp-input-output)      ;string
407   (native?   gexp-input-native?))    ;Boolean
409 (define (write-gexp-input input port)
410   (match input
411     (($ <gexp-input> thing output #f)
412      (format port "#<gexp-input ~s:~a>" thing output))
413     (($ <gexp-input> thing output #t)
414      (format port "#<gexp-input native ~s:~a>" thing output))))
416 (set-record-type-printer! <gexp-input> write-gexp-input)
418 (define* (gexp-input thing                        ;convenience procedure
419                      #:optional (output "out")
420                      #:key native?)
421   "Return a new <gexp-input> for the OUTPUT of THING; NATIVE? determines
422 whether this should be considered a \"native\" input or not."
423   (%gexp-input thing output native?))
425 ;; Reference to one of the derivation's outputs, for gexps used in
426 ;; derivations.
427 (define-record-type <gexp-output>
428   (gexp-output name)
429   gexp-output?
430   (name gexp-output-name))
432 (define (write-gexp-output output port)
433   (match output
434     (($ <gexp-output> name)
435      (format port "#<gexp-output ~a>" name))))
437 (set-record-type-printer! <gexp-output> write-gexp-output)
439 (define (gexp-modules gexp)
440   "Return the list of Guile module names GEXP relies on."
441   (delete-duplicates
442    (append (gexp-self-modules gexp)
443            (append-map (match-lambda
444                          (($ <gexp-input> (? gexp? exp))
445                           (gexp-modules exp))
446                          (($ <gexp-input> (lst ...))
447                           (append-map (lambda (item)
448                                         (if (gexp? item)
449                                             (gexp-modules item)
450                                             '()))
451                                       lst))
452                          (_
453                           '()))
454                        (gexp-references gexp)))))
456 (define* (lower-inputs inputs
457                        #:key system target)
458   "Turn any package from INPUTS into a derivation for SYSTEM; return the
459 corresponding input list as a monadic value.  When TARGET is true, use it as
460 the cross-compilation target triplet."
461   (with-monad %store-monad
462     (sequence %store-monad
463               (map (match-lambda
464                      (((? struct? thing) sub-drv ...)
465                       (mlet %store-monad ((drv (lower-object
466                                                 thing system #:target target)))
467                         (return `(,drv ,@sub-drv))))
468                      (input
469                       (return input)))
470                    inputs))))
472 (define* (lower-reference-graphs graphs #:key system target)
473   "Given GRAPHS, a list of (FILE-NAME INPUT ...) lists for use as a
474 #:reference-graphs argument, lower it such that each INPUT is replaced by the
475 corresponding derivation."
476   (match graphs
477     (((file-names . inputs) ...)
478      (mlet %store-monad ((inputs (lower-inputs inputs
479                                                #:system system
480                                                #:target target)))
481        (return (map cons file-names inputs))))))
483 (define* (lower-references lst #:key system target)
484   "Based on LST, a list of output names and packages, return a list of output
485 names and file names suitable for the #:allowed-references argument to
486 'derivation'."
487   (with-monad %store-monad
488     (define lower
489       (match-lambda
490        ((? string? output)
491         (return output))
492        (($ <gexp-input> thing output native?)
493         (mlet %store-monad ((drv (lower-object thing system
494                                                #:target (if native?
495                                                             #f target))))
496           (return (derivation->output-path drv output))))
497        (thing
498         (mlet %store-monad ((drv (lower-object thing system
499                                                #:target target)))
500           (return (derivation->output-path drv))))))
502     (sequence %store-monad (map lower lst))))
504 (define default-guile-derivation
505   ;; Here we break the abstraction by talking to the higher-level layer.
506   ;; Thus, do the resolution lazily to hide the circular dependency.
507   (let ((proc (delay
508                 (let ((iface (resolve-interface '(guix packages))))
509                   (module-ref iface 'default-guile-derivation)))))
510     (lambda (system)
511       ((force proc) system))))
513 (define* (gexp->derivation name exp
514                            #:key
515                            system (target 'current)
516                            hash hash-algo recursive?
517                            (env-vars '())
518                            (modules '())
519                            (module-path %load-path)
520                            (guile-for-build (%guile-for-build))
521                            (graft? (%graft?))
522                            references-graphs
523                            allowed-references disallowed-references
524                            leaked-env-vars
525                            local-build? (substitutable? #t)
526                            (script-name (string-append name "-builder")))
527   "Return a derivation NAME that runs EXP (a gexp) with GUILE-FOR-BUILD (a
528 derivation) on SYSTEM; EXP is stored in a file called SCRIPT-NAME.  When
529 TARGET is true, it is used as the cross-compilation target triplet for
530 packages referred to by EXP.
532 MODULES is deprecated in favor of 'with-imported-modules'.  Its meaning is to
533 make MODULES available in the evaluation context of EXP; MODULES is a list of
534 names of Guile modules searched in MODULE-PATH to be copied in the store,
535 compiled, and made available in the load path during the execution of
536 EXP---e.g., '((guix build utils) (guix build gnu-build-system)).
538 GRAFT? determines whether packages referred to by EXP should be grafted when
539 applicable.
541 When REFERENCES-GRAPHS is true, it must be a list of tuples of one of the
542 following forms:
544   (FILE-NAME PACKAGE)
545   (FILE-NAME PACKAGE OUTPUT)
546   (FILE-NAME DERIVATION)
547   (FILE-NAME DERIVATION OUTPUT)
548   (FILE-NAME STORE-ITEM)
550 The right-hand-side of each element of REFERENCES-GRAPHS is automatically made
551 an input of the build process of EXP.  In the build environment, each
552 FILE-NAME contains the reference graph of the corresponding item, in a simple
553 text format.
555 ALLOWED-REFERENCES must be either #f or a list of output names and packages.
556 In the latter case, the list denotes store items that the result is allowed to
557 refer to.  Any reference to another store item will lead to a build error.
558 Similarly for DISALLOWED-REFERENCES, which can list items that must not be
559 referenced by the outputs.
561 The other arguments are as for 'derivation'."
562   (define %modules
563     (delete-duplicates
564      (append modules (gexp-modules exp))))
565   (define outputs (gexp-outputs exp))
567   (define (graphs-file-names graphs)
568     ;; Return a list of (FILE-NAME . STORE-PATH) pairs made from GRAPHS.
569     (map (match-lambda
570           ;; TODO: Remove 'derivation?' special cases.
571            ((file-name (? derivation? drv))
572             (cons file-name (derivation->output-path drv)))
573            ((file-name (? derivation? drv) sub-drv)
574             (cons file-name (derivation->output-path drv sub-drv)))
575            ((file-name thing)
576             (cons file-name thing)))
577          graphs))
579   (mlet* %store-monad (;; The following binding forces '%current-system' and
580                        ;; '%current-target-system' to be looked up at >>=
581                        ;; time.
582                        (graft?    (set-grafting graft?))
584                        (system -> (or system (%current-system)))
585                        (target -> (if (eq? target 'current)
586                                       (%current-target-system)
587                                       target))
588                        (normals  (lower-inputs (gexp-inputs exp)
589                                                #:system system
590                                                #:target target))
591                        (natives  (lower-inputs (gexp-native-inputs exp)
592                                                #:system system
593                                                #:target #f))
594                        (inputs -> (append normals natives))
595                        (sexp     (gexp->sexp exp
596                                              #:system system
597                                              #:target target))
598                        (builder  (text-file script-name
599                                             (object->string sexp)))
600                        (modules  (if (pair? %modules)
601                                      (imported-modules %modules
602                                                        #:system system
603                                                        #:module-path module-path
604                                                        #:guile guile-for-build)
605                                      (return #f)))
606                        (compiled (if (pair? %modules)
607                                      (compiled-modules %modules
608                                                        #:system system
609                                                        #:module-path module-path
610                                                        #:guile guile-for-build)
611                                      (return #f)))
612                        (graphs   (if references-graphs
613                                      (lower-reference-graphs references-graphs
614                                                              #:system system
615                                                              #:target target)
616                                      (return #f)))
617                        (allowed  (if allowed-references
618                                      (lower-references allowed-references
619                                                        #:system system
620                                                        #:target target)
621                                      (return #f)))
622                        (disallowed (if disallowed-references
623                                        (lower-references disallowed-references
624                                                          #:system system
625                                                          #:target target)
626                                        (return #f)))
627                        (guile    (if guile-for-build
628                                      (return guile-for-build)
629                                      (default-guile-derivation system))))
630     (mbegin %store-monad
631       (set-grafting graft?)                       ;restore the initial setting
632       (raw-derivation name
633                       (string-append (derivation->output-path guile)
634                                      "/bin/guile")
635                       `("--no-auto-compile"
636                         ,@(if (pair? %modules)
637                               `("-L" ,(derivation->output-path modules)
638                                 "-C" ,(derivation->output-path compiled))
639                               '())
640                         ,builder)
641                       #:outputs outputs
642                       #:env-vars env-vars
643                       #:system system
644                       #:inputs `((,guile)
645                                  (,builder)
646                                  ,@(if modules
647                                        `((,modules) (,compiled) ,@inputs)
648                                        inputs)
649                                  ,@(match graphs
650                                      (((_ . inputs) ...) inputs)
651                                      (_ '())))
652                       #:hash hash #:hash-algo hash-algo #:recursive? recursive?
653                       #:references-graphs (and=> graphs graphs-file-names)
654                       #:allowed-references allowed
655                       #:disallowed-references disallowed
656                       #:leaked-env-vars leaked-env-vars
657                       #:local-build? local-build?
658                       #:substitutable? substitutable?))))
660 (define* (gexp-inputs exp #:key native?)
661   "Return the input list for EXP.  When NATIVE? is true, return only native
662 references; otherwise, return only non-native references."
663   (define (add-reference-inputs ref result)
664     (match ref
665       (($ <gexp-input> (? gexp? exp) _ #t)
666        (if native?
667            (append (gexp-inputs exp)
668                    (gexp-inputs exp #:native? #t)
669                    result)
670            result))
671       (($ <gexp-input> (? gexp? exp) _ #f)
672        (append (gexp-inputs exp #:native? native?)
673                result))
674       (($ <gexp-input> (? string? str))
675        (if (direct-store-path? str)
676            (cons `(,str) result)
677            result))
678       (($ <gexp-input> (? struct? thing) output n?)
679        (if (and (eqv? n? native?) (lookup-compiler thing))
680            ;; THING is a derivation, or a package, or an origin, etc.
681            (cons `(,thing ,output) result)
682            result))
683       (($ <gexp-input> (lst ...) output n?)
684        (if (eqv? native? n?)
685            (fold-right add-reference-inputs result
686                        ;; XXX: For now, automatically convert LST to a list of
687                        ;; gexp-inputs.
688                        (map (match-lambda
689                               ((? gexp-input? x) x)
690                               (x (%gexp-input x "out" (or n? native?))))
691                             lst))
692            result))
693       (_
694        ;; Ignore references to other kinds of objects.
695        result)))
697   (fold-right add-reference-inputs
698               '()
699               (gexp-references exp)))
701 (define gexp-native-inputs
702   (cut gexp-inputs <> #:native? #t))
704 (define (gexp-outputs exp)
705   "Return the outputs referred to by EXP as a list of strings."
706   (define (add-reference-output ref result)
707     (match ref
708       (($ <gexp-output> name)
709        (cons name result))
710       (($ <gexp-input> (? gexp? exp))
711        (append (gexp-outputs exp) result))
712       (($ <gexp-input> (lst ...) output native?)
713        ;; XXX: Automatically convert LST.
714        (add-reference-output (map (match-lambda
715                                    ((? gexp-input? x) x)
716                                    (x (%gexp-input x "out" native?)))
717                                   lst)
718                              result))
719       ((lst ...)
720        (fold-right add-reference-output result lst))
721       (_
722        result)))
724   (delete-duplicates
725    (add-reference-output (gexp-references exp) '())))
727 (define* (gexp->sexp exp #:key
728                      (system (%current-system))
729                      (target (%current-target-system)))
730   "Return (monadically) the sexp corresponding to EXP for the given OUTPUT,
731 and in the current monad setting (system type, etc.)"
732   (define* (reference->sexp ref #:optional native?)
733     (with-monad %store-monad
734       (match ref
735         (($ <gexp-output> output)
736          ;; Output file names are not known in advance but the daemon defines
737          ;; an environment variable for each of them at build time, so use
738          ;; that trick.
739          (return `((@ (guile) getenv) ,output)))
740         (($ <gexp-input> (? gexp? exp) output n?)
741          (gexp->sexp exp
742                      #:system system
743                      #:target (if (or n? native?) #f target)))
744         (($ <gexp-input> (refs ...) output n?)
745          (sequence %store-monad
746                    (map (lambda (ref)
747                           ;; XXX: Automatically convert REF to an gexp-input.
748                           (reference->sexp
749                            (if (gexp-input? ref)
750                                ref
751                                (%gexp-input ref "out" n?))
752                            (or n? native?)))
753                         refs)))
754         (($ <gexp-input> (? struct? thing) output n?)
755          (let ((target (if (or n? native?) #f target))
756                (expand (lookup-expander thing)))
757            (mlet %store-monad ((obj (lower-object thing system
758                                                   #:target target)))
759              ;; OBJ must be either a derivation or a store file name.
760              (return (expand thing obj output)))))
761         (($ <gexp-input> x)
762          (return x))
763         (x
764          (return x)))))
766   (mlet %store-monad
767       ((args (sequence %store-monad
768                        (map reference->sexp (gexp-references exp)))))
769     (return (apply (gexp-proc exp) args))))
771 (define (syntax-location-string s)
772   "Return a string representing the source code location of S."
773   (let ((props (syntax-source s)))
774     (if props
775         (let ((file   (assoc-ref props 'filename))
776               (line   (and=> (assoc-ref props 'line) 1+))
777               (column (assoc-ref props 'column)))
778           (if file
779               (simple-format #f "~a:~a:~a"
780                              file line column)
781               (simple-format #f "~a:~a" line column)))
782         "<unknown location>")))
784 (define-syntax-parameter current-imported-modules
785   ;; Current list of imported modules.
786   (identifier-syntax '()))
788 (define-syntax-rule (with-imported-modules modules body ...)
789   "Mark the gexps defined in BODY... as requiring MODULES in their execution
790 environment."
791   (syntax-parameterize ((current-imported-modules
792                          (identifier-syntax modules)))
793     body ...))
795 (define-syntax gexp
796   (lambda (s)
797     (define (collect-escapes exp)
798       ;; Return all the 'ungexp' present in EXP.
799       (let loop ((exp    exp)
800                  (result '()))
801         (syntax-case exp (ungexp
802                           ungexp-splicing
803                           ungexp-native
804                           ungexp-native-splicing)
805           ((ungexp _)
806            (cons exp result))
807           ((ungexp _ _)
808            (cons exp result))
809           ((ungexp-splicing _ ...)
810            (cons exp result))
811           ((ungexp-native _ ...)
812            (cons exp result))
813           ((ungexp-native-splicing _ ...)
814            (cons exp result))
815           ((exp0 exp ...)
816            (let ((result (loop #'exp0 result)))
817              (fold loop result #'(exp ...))))
818           (_
819            result))))
821     (define (escape->ref exp)
822       ;; Turn 'ungexp' form EXP into a "reference".
823       (syntax-case exp (ungexp ungexp-splicing
824                         ungexp-native ungexp-native-splicing
825                         output)
826         ((ungexp output)
827          #'(gexp-output "out"))
828         ((ungexp output name)
829          #'(gexp-output name))
830         ((ungexp thing)
831          #'(%gexp-input thing "out" #f))
832         ((ungexp drv-or-pkg out)
833          #'(%gexp-input drv-or-pkg out #f))
834         ((ungexp-splicing lst)
835          #'(%gexp-input lst "out" #f))
836         ((ungexp-native thing)
837          #'(%gexp-input thing "out" #t))
838         ((ungexp-native drv-or-pkg out)
839          #'(%gexp-input drv-or-pkg out #t))
840         ((ungexp-native-splicing lst)
841          #'(%gexp-input lst "out" #t))))
843     (define (substitute-ungexp exp substs)
844       ;; Given EXP, an 'ungexp' or 'ungexp-native' form, substitute it with
845       ;; the corresponding form in SUBSTS.
846       (match (assoc exp substs)
847         ((_ id)
848          id)
849         (_
850          #'(syntax-error "error: no 'ungexp' substitution"
851                          #'ref))))
853     (define (substitute-ungexp-splicing exp substs)
854       (syntax-case exp ()
855         ((exp rest ...)
856          (match (assoc #'exp substs)
857            ((_ id)
858             (with-syntax ((id id))
859               #`(append id
860                         #,(substitute-references #'(rest ...) substs))))
861            (_
862             #'(syntax-error "error: no 'ungexp-splicing' substitution"
863                             #'ref))))))
865     (define (substitute-references exp substs)
866       ;; Return a variant of EXP where all the cars of SUBSTS have been
867       ;; replaced by the corresponding cdr.
868       (syntax-case exp (ungexp ungexp-native
869                         ungexp-splicing ungexp-native-splicing)
870         ((ungexp _ ...)
871          (substitute-ungexp exp substs))
872         ((ungexp-native _ ...)
873          (substitute-ungexp exp substs))
874         (((ungexp-splicing _ ...) rest ...)
875          (substitute-ungexp-splicing exp substs))
876         (((ungexp-native-splicing _ ...) rest ...)
877          (substitute-ungexp-splicing exp substs))
878         ((exp0 exp ...)
879          #`(cons #,(substitute-references #'exp0 substs)
880                  #,(substitute-references #'(exp ...) substs)))
881         (x #''x)))
883     (syntax-case s (ungexp output)
884       ((_ exp)
885        (let* ((escapes (delete-duplicates (collect-escapes #'exp)))
886               (formals (generate-temporaries escapes))
887               (sexp    (substitute-references #'exp (zip escapes formals)))
888               (refs    (map escape->ref escapes)))
889          #`(make-gexp (list #,@refs)
890                       current-imported-modules
891                       (lambda #,formals
892                         #,sexp)))))))
896 ;;; Module handling.
899 (define %utils-module
900   ;; This file provides 'mkdir-p', needed to implement 'imported-files' and
901   ;; other primitives below.  Note: We give the file name relative to this
902   ;; file you are currently reading; 'search-path' could return a file name
903   ;; relative to the current working directory.
904   (local-file "build/utils.scm"
905               "build-utils.scm"))
907 (define* (imported-files files
908                          #:key (name "file-import")
909                          (system (%current-system))
910                          (guile (%guile-for-build)))
911   "Return a derivation that imports FILES into STORE.  FILES must be a list
912 of (FINAL-PATH . FILE-NAME) pairs; each FILE-NAME is read from the file
913 system, imported, and appears under FINAL-PATH in the resulting store path."
914   (define file-pair
915     (match-lambda
916      ((final-path . file-name)
917       (mlet %store-monad ((file (interned-file file-name
918                                                (basename final-path))))
919         (return (list final-path file))))))
921   (mlet %store-monad ((files (sequence %store-monad
922                                        (map file-pair files))))
923     (define build
924       (gexp
925        (begin
926          (primitive-load (ungexp %utils-module))  ;for 'mkdir-p'
927          (use-modules (ice-9 match))
929          (mkdir (ungexp output)) (chdir (ungexp output))
930          (for-each (match-lambda
931                     ((final-path store-path)
932                      (mkdir-p (dirname final-path))
933                      (symlink store-path final-path)))
934                    '(ungexp files)))))
936     ;; TODO: Pass FILES as an environment variable so that BUILD remains
937     ;; exactly the same regardless of FILES: less disk space, and fewer
938     ;; 'add-to-store' RPCs.
939     (gexp->derivation name build
940                       #:system system
941                       #:guile-for-build guile
942                       #:local-build? #t)))
944 (define* (imported-modules modules
945                            #:key (name "module-import")
946                            (system (%current-system))
947                            (guile (%guile-for-build))
948                            (module-path %load-path))
949   "Return a derivation that contains the source files of MODULES, a list of
950 module names such as `(ice-9 q)'.  All of MODULES must be in the MODULE-PATH
951 search path."
952   ;; TODO: Determine the closure of MODULES, build the `.go' files,
953   ;; canonicalize the source files through read/write, etc.
954   (let ((files (map (lambda (m)
955                       (let ((f (module->source-file-name m)))
956                         (cons f (search-path* module-path f))))
957                     modules)))
958     (imported-files files #:name name #:system system
959                     #:guile guile)))
961 (define* (compiled-modules modules
962                            #:key (name "module-import-compiled")
963                            (system (%current-system))
964                            (guile (%guile-for-build))
965                            (module-path %load-path))
966   "Return a derivation that builds a tree containing the `.go' files
967 corresponding to MODULES.  All the MODULES are built in a context where
968 they can refer to each other."
969   (mlet %store-monad ((modules (imported-modules modules
970                                                  #:system system
971                                                  #:guile guile
972                                                  #:module-path
973                                                  module-path)))
974     (define build
975       (gexp
976        (begin
977          (primitive-load (ungexp %utils-module))  ;for 'mkdir-p'
979          (use-modules (ice-9 ftw)
980                       (srfi srfi-26)
981                       (system base compile))
983          (define (regular? file)
984            (not (member file '("." ".."))))
986          (define (process-directory directory output)
987            (let ((entries (map (cut string-append directory "/" <>)
988                                (scandir directory regular?))))
989              (for-each (lambda (entry)
990                          (if (file-is-directory? entry)
991                              (let ((output (string-append output "/"
992                                                           (basename entry))))
993                                (mkdir-p output)
994                                (process-directory entry output))
995                              (let* ((base   (string-drop-right
996                                              (basename entry)
997                                              4)) ;.scm
998                                     (output (string-append output "/" base
999                                                            ".go")))
1000                                (compile-file entry
1001                                              #:output-file output
1002                                              #:opts
1003                                              %auto-compilation-options))))
1004                        entries)))
1006          (set! %load-path (cons (ungexp modules) %load-path))
1007          (mkdir (ungexp output))
1008          (chdir (ungexp modules))
1009          (process-directory "." (ungexp output)))))
1011     ;; TODO: Pass MODULES as an environment variable.
1012     (gexp->derivation name build
1013                       #:system system
1014                       #:guile-for-build guile
1015                       #:local-build? #t)))
1019 ;;; Convenience procedures.
1022 (define (default-guile)
1023   ;; Lazily resolve 'guile-final'.  This module must not refer to (gnu …)
1024   ;; modules directly, to avoid circular dependencies, hence this hack.
1025   (module-ref (resolve-interface '(gnu packages commencement))
1026               'guile-final))
1028 (define (load-path-expression modules)
1029   "Return as a monadic value a gexp that sets '%load-path' and
1030 '%load-compiled-path' to point to MODULES, a list of module names."
1031   (mlet %store-monad ((modules  (imported-modules modules))
1032                       (compiled (compiled-modules modules)))
1033     (return (gexp (eval-when (expand load eval)
1034                     (set! %load-path
1035                       (cons (ungexp modules) %load-path))
1036                     (set! %load-compiled-path
1037                       (cons (ungexp compiled)
1038                             %load-compiled-path)))))))
1040 (define* (gexp->script name exp
1041                        #:key (guile (default-guile)))
1042   "Return an executable script NAME that runs EXP using GUILE, with EXP's
1043 imported modules in its search path."
1044   (mlet %store-monad ((set-load-path
1045                        (load-path-expression (gexp-modules exp))))
1046     (gexp->derivation name
1047                       (gexp
1048                        (call-with-output-file (ungexp output)
1049                          (lambda (port)
1050                            ;; Note: that makes a long shebang.  When the store
1051                            ;; is /gnu/store, that fits within the 128-byte
1052                            ;; limit imposed by Linux, but that may go beyond
1053                            ;; when running tests.
1054                            (format port
1055                                    "#!~a/bin/guile --no-auto-compile~%!#~%"
1056                                    (ungexp guile))
1058                            (write '(ungexp set-load-path) port)
1059                            (write '(ungexp exp) port)
1060                            (chmod port #o555)))))))
1062 (define* (gexp->file name exp #:key (set-load-path? #t))
1063   "Return a derivation that builds a file NAME containing EXP.  When
1064 SET-LOAD-PATH? is true, emit code in the resulting file to set '%load-path'
1065 and '%load-compiled-path' to honor EXP's imported modules."
1066   (match (if set-load-path? (gexp-modules exp) '())
1067     (()                                           ;zero modules
1068      (gexp->derivation name
1069                        (gexp
1070                         (call-with-output-file (ungexp output)
1071                           (lambda (port)
1072                             (write '(ungexp exp) port))))
1073                        #:local-build? #t
1074                        #:substitutable? #f))
1075     ((modules ...)
1076      (mlet %store-monad ((set-load-path (load-path-expression modules)))
1077        (gexp->derivation name
1078                          (gexp
1079                           (call-with-output-file (ungexp output)
1080                             (lambda (port)
1081                               (write '(ungexp set-load-path) port)
1082                               (write '(ungexp exp) port))))
1083                          #:local-build? #t
1084                          #:substitutable? #f)))))
1086 (define* (text-file* name #:rest text)
1087   "Return as a monadic value a derivation that builds a text file containing
1088 all of TEXT.  TEXT may list, in addition to strings, objects of any type that
1089 can be used in a gexp: packages, derivations, local file objects, etc.  The
1090 resulting store file holds references to all these."
1091   (define builder
1092     (gexp (call-with-output-file (ungexp output "out")
1093             (lambda (port)
1094               (display (string-append (ungexp-splicing text)) port)))))
1096   (gexp->derivation name builder
1097                     #:local-build? #t
1098                     #:substitutable? #f))
1100 (define* (mixed-text-file name #:rest text)
1101   "Return an object representing store file NAME containing TEXT.  TEXT is a
1102 sequence of strings and file-like objects, as in:
1104   (mixed-text-file \"profile\"
1105                    \"export PATH=\" coreutils \"/bin:\" grep \"/bin\")
1107 This is the declarative counterpart of 'text-file*'."
1108   (define build
1109     (gexp (call-with-output-file (ungexp output "out")
1110             (lambda (port)
1111               (display (string-append (ungexp-splicing text)) port)))))
1113   (computed-file name build))
1117 ;;; Syntactic sugar.
1120 (eval-when (expand load eval)
1121   (define* (read-ungexp chr port #:optional native?)
1122     "Read an 'ungexp' or 'ungexp-splicing' form from PORT.  When NATIVE? is
1123 true, use 'ungexp-native' and 'ungexp-native-splicing' instead."
1124     (define unquote-symbol
1125       (match (peek-char port)
1126         (#\@
1127          (read-char port)
1128          (if native?
1129              'ungexp-native-splicing
1130              'ungexp-splicing))
1131         (_
1132          (if native?
1133              'ungexp-native
1134              'ungexp))))
1136     (match (read port)
1137       ((? symbol? symbol)
1138        (let ((str (symbol->string symbol)))
1139          (match (string-index-right str #\:)
1140            (#f
1141             `(,unquote-symbol ,symbol))
1142            (colon
1143             (let ((name   (string->symbol (substring str 0 colon)))
1144                   (output (substring str (+ colon 1))))
1145               `(,unquote-symbol ,name ,output))))))
1146       (x
1147        `(,unquote-symbol ,x))))
1149   (define (read-gexp chr port)
1150     "Read a 'gexp' form from PORT."
1151     `(gexp ,(read port)))
1153   ;; Extend the reader
1154   (read-hash-extend #\~ read-gexp)
1155   (read-hash-extend #\$ read-ungexp)
1156   (read-hash-extend #\+ (cut read-ungexp <> <> #t)))
1158 ;;; gexp.scm ends here