tests: Adjust to Shepherd error message change.
[jackhill/guix/guix.git] / guix / derivations.scm
CommitLineData
233e7676 1;;; GNU Guix --- Functional package management for GNU
35b5ca78 2;;; Copyright © 2012, 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
77d3cf08 3;;;
233e7676 4;;; This file is part of GNU Guix.
77d3cf08 5;;;
233e7676 6;;; GNU Guix is free software; you can redistribute it and/or modify it
77d3cf08
LC
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;;;
233e7676 11;;; GNU Guix is distributed in the hope that it will be useful, but
77d3cf08
LC
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
233e7676 17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
77d3cf08
LC
18
19(define-module (guix derivations)
20 #:use-module (srfi srfi-1)
21 #:use-module (srfi srfi-9)
07c86312 22 #:use-module (srfi srfi-9 gnu)
77d3cf08 23 #:use-module (srfi srfi-26)
f304c9c2
LC
24 #:use-module (srfi srfi-34)
25 #:use-module (srfi srfi-35)
77d3cf08
LC
26 #:use-module (rnrs io ports)
27 #:use-module (rnrs bytevectors)
28 #:use-module (ice-9 match)
29 #:use-module (ice-9 rdelim)
e387ab7c 30 #:use-module (ice-9 vlist)
69f90f5c 31 #:use-module (guix store)
26bbbb95 32 #:use-module (guix utils)
958dd3ce 33 #:use-module (guix combinators)
e87f0591 34 #:use-module (guix monads)
72626a71 35 #:use-module (guix hash)
ddc29a78 36 #:use-module (guix base32)
969df974 37 #:use-module (guix records)
ed3592a9 38 #:use-module (guix sets)
9a20830e
LC
39 #:export (<derivation>
40 derivation?
77d3cf08
LC
41 derivation-outputs
42 derivation-inputs
43 derivation-sources
44 derivation-system
7ce7361b 45 derivation-builder
77d3cf08
LC
46 derivation-builder-arguments
47 derivation-builder-environment-vars
6a446d56 48 derivation-file-name
9a20830e
LC
49 derivation-prerequisites
50 derivation-prerequisites-to-build
77d3cf08 51
9a20830e 52 <derivation-output>
77d3cf08
LC
53 derivation-output?
54 derivation-output-path
55 derivation-output-hash-algo
56 derivation-output-hash
36bbbbd1 57 derivation-output-recursive?
77d3cf08 58
9a20830e 59 <derivation-input>
77d3cf08
LC
60 derivation-input?
61 derivation-input-path
62 derivation-input-sub-derivations
dd36b51b 63 derivation-input-output-paths
3681db5d 64 valid-derivation-input?
77d3cf08 65
f304c9c2
LC
66 &derivation-error
67 derivation-error?
68 derivation-error-derivation
69 &derivation-missing-output-error
70 derivation-missing-output-error?
71 derivation-missing-output
72
e786293e 73 derivation-name
0b6af195 74 derivation-output-names
77d3cf08 75 fixed-output-derivation?
fc93e309
LC
76 offloadable-derivation?
77 substitutable-derivation?
e9651e39 78 substitution-oracle
341c6fdd
LC
79 derivation-hash
80
81 read-derivation
26bbbb95 82 write-derivation
59688fc4
LC
83 derivation->output-path
84 derivation->output-paths
de4c3f26 85 derivation-path->output-path
7244a5f7 86 derivation-path->output-paths
d9085c23 87 derivation
969df974 88
e387ab7c 89 map-derivation
d9085c23 90
01d8ac64 91 build-derivations
e87f0591 92 built-derivations
e87f0591 93
d26e1967
LC
94 file-search-error?
95 file-search-error-file-name
96 file-search-error-search-path
9d8100f4 97
d26e1967 98 search-path*
6985335f 99 module->source-file-name
aa72d9af 100 build-expression->derivation)
e87f0591
LC
101
102 ;; Re-export it from here for backward compatibility.
01d8ac64 103 #:re-export (%guile-for-build))
77d3cf08 104
f304c9c2
LC
105;;;
106;;; Error conditions.
107;;;
108
109(define-condition-type &derivation-error &nix-error
110 derivation-error?
111 (derivation derivation-error-derivation))
112
113(define-condition-type &derivation-missing-output-error &derivation-error
114 derivation-missing-output-error?
115 (output derivation-missing-output))
116
77d3cf08
LC
117;;;
118;;; Nix derivations, as implemented in Nix's `derivations.cc'.
119;;;
120
121(define-record-type <derivation>
6a446d56
LC
122 (make-derivation outputs inputs sources system builder args env-vars
123 file-name)
77d3cf08
LC
124 derivation?
125 (outputs derivation-outputs) ; list of name/<derivation-output> pairs
126 (inputs derivation-inputs) ; list of <derivation-input>
127 (sources derivation-sources) ; list of store paths
128 (system derivation-system) ; string
129 (builder derivation-builder) ; store path
130 (args derivation-builder-arguments) ; list of strings
6a446d56
LC
131 (env-vars derivation-builder-environment-vars) ; list of name/value pairs
132 (file-name derivation-file-name)) ; the .drv file name
77d3cf08
LC
133
134(define-record-type <derivation-output>
36bbbbd1 135 (make-derivation-output path hash-algo hash recursive?)
77d3cf08
LC
136 derivation-output?
137 (path derivation-output-path) ; store path
138 (hash-algo derivation-output-hash-algo) ; symbol | #f
36bbbbd1
LC
139 (hash derivation-output-hash) ; bytevector | #f
140 (recursive? derivation-output-recursive?)) ; Boolean
77d3cf08
LC
141
142(define-record-type <derivation-input>
143 (make-derivation-input path sub-derivations)
144 derivation-input?
145 (path derivation-input-path) ; store path
146 (sub-derivations derivation-input-sub-derivations)) ; list of strings
147
07c86312
LC
148(set-record-type-printer! <derivation>
149 (lambda (drv port)
150 (format port "#<derivation ~a => ~a ~a>"
151 (derivation-file-name drv)
152 (string-join
153 (map (match-lambda
154 ((_ . output)
155 (derivation-output-path output)))
156 (derivation-outputs drv)))
157 (number->string (object-address drv) 16))))
158
e786293e
LC
159(define (derivation-name drv)
160 "Return the base name of DRV."
161 (let ((base (store-path-package-name (derivation-file-name drv))))
162 (string-drop-right base 4)))
163
0b6af195
LC
164(define (derivation-output-names drv)
165 "Return the names of the outputs of DRV."
166 (match (derivation-outputs drv)
167 (((names . _) ...)
168 names)))
169
77d3cf08
LC
170(define (fixed-output-derivation? drv)
171 "Return #t if DRV is a fixed-output derivation, such as the result of a
172download with a fixed hash (aka. `fetchurl')."
173 (match drv
174 (($ <derivation>
99e17dc9 175 (("out" . ($ <derivation-output> _ (? symbol?) (? bytevector?)))))
77d3cf08
LC
176 #t)
177 (_ #f)))
178
97507ebe
LC
179(define (derivation-input<? input1 input2)
180 "Compare INPUT1 and INPUT2, two <derivation-input>."
181 (string<? (derivation-input-path input1)
182 (derivation-input-path input2)))
183
dd36b51b
LC
184(define (derivation-input-output-paths input)
185 "Return the list of output paths corresponding to INPUT, a
186<derivation-input>."
187 (match input
188 (($ <derivation-input> path sub-drvs)
189 (map (cut derivation-path->output-path path <>)
190 sub-drvs))))
191
3681db5d
LC
192(define (valid-derivation-input? store input)
193 "Return true if INPUT is valid--i.e., if all the outputs it requests are in
194the store."
195 (every (cut valid-path? store <>)
196 (derivation-input-output-paths input)))
197
97507ebe
LC
198(define (coalesce-duplicate-inputs inputs)
199 "Return a list of inputs, such that when INPUTS contains the same DRV twice,
200they are coalesced, with their sub-derivations merged. This is needed because
201Nix itself keeps only one of them."
202 (fold (lambda (input result)
203 (match input
204 (($ <derivation-input> path sub-drvs)
205 ;; XXX: quadratic
206 (match (find (match-lambda
207 (($ <derivation-input> p s)
208 (string=? p path)))
209 result)
210 (#f
211 (cons input result))
212 ((and dup ($ <derivation-input> _ sub-drvs2))
213 ;; Merge DUP with INPUT.
214 (let ((sub-drvs (delete-duplicates
215 (append sub-drvs sub-drvs2))))
216 (cons (make-derivation-input path
217 (sort sub-drvs string<?))
218 (delq dup result))))))))
219 '()
220 inputs))
221
3681db5d
LC
222(define* (derivation-prerequisites drv #:optional (cut? (const #f)))
223 "Return the list of derivation-inputs required to build DRV, recursively.
224
225CUT? is a predicate that is passed a derivation-input and returns true to
226eliminate the given input and its dependencies from the search. An example of
227search a predicate is 'valid-derivation-input?'; when it is used as CUT?, the
228result is the set of prerequisites of DRV not already in valid."
ed3592a9
LC
229 (let loop ((drv drv)
230 (result '())
231 (input-set (set)))
3681db5d
LC
232 (let ((inputs (remove (lambda (input)
233 (or (set-contains? input-set input)
234 (cut? input)))
9a20830e 235 (derivation-inputs drv))))
ed3592a9
LC
236 (fold2 loop
237 (append inputs result)
238 (fold set-insert input-set inputs)
239 (map (lambda (i)
240 (call-with-input-file (derivation-input-path i)
241 read-derivation))
242 inputs)))))
9a20830e 243
fc93e309
LC
244(define (offloadable-derivation? drv)
245 "Return true if DRV can be offloaded, false otherwise."
246 (match (assoc "preferLocalBuild"
247 (derivation-builder-environment-vars drv))
248 (("preferLocalBuild" . "1") #f)
249 (_ #t)))
250
4a6aeb67
LC
251(define (substitutable-derivation? drv)
252 "Return #t if DRV can be substituted."
253 (match (assoc "allowSubstitutes"
254 (derivation-builder-environment-vars drv))
255 (("allowSubstitutes" . value)
256 (string=? value "1"))
257 (_ #t)))
fc93e309 258
e9651e39
LC
259(define (derivation-output-paths drv sub-drvs)
260 "Return the output paths of outputs SUB-DRVS of DRV."
261 (match drv
262 (($ <derivation> outputs)
263 (map (lambda (sub-drv)
264 (derivation-output-path (assoc-ref outputs sub-drv)))
265 sub-drvs))))
266
58c08df0
LC
267(define* (substitution-oracle store drv
268 #:key (mode (build-mode normal)))
e9651e39
LC
269 "Return a one-argument procedure that, when passed a store file name,
270returns #t if it's substitutable and #f otherwise. The returned procedure
1eabf4ec
LC
271knows about all substitutes for all the derivations listed in DRV, *except*
272those that are already valid (that is, it won't bother checking whether an
273item is substitutable if it's already on disk); it also knows about their
274prerequisites, unless they are themselves substitutable.
e9651e39
LC
275
276Creating a single oracle (thus making a single 'substitutable-paths' call) and
277reusing it is much more efficient than calling 'has-substitutes?' or similar
278repeatedly, because it avoids the costs associated with launching the
279substituter many times."
c7d1d88f
LC
280 (define valid?
281 (cut valid-path? store <>))
282
c3a450fb
LC
283 (define valid-input?
284 (cut valid-derivation-input? store <>))
285
286 (define (dependencies drv)
287 ;; Skip prerequisite sub-trees of DRV whose root is valid. This allows us
288 ;; to ask the substituter for just as much as needed, instead of asking it
289 ;; for the whole world, which can be significantly faster when substitute
290 ;; info is not already in cache.
291 (append-map derivation-input-output-paths
292 (derivation-prerequisites drv valid-input?)))
293
e9651e39 294 (let* ((paths (delete-duplicates
b59df243
LC
295 (concatenate
296 (fold (lambda (drv result)
297 (let ((self (match (derivation->output-paths drv)
298 (((names . paths) ...)
299 paths))))
58c08df0
LC
300 (cond ((eqv? mode (build-mode check))
301 (cons (dependencies drv) result))
302 ((every valid? self)
303 result)
304 (else
305 (cons* self (dependencies drv) result)))))
b59df243
LC
306 '()
307 drv))))
c06d140c
LC
308 (subst (list->set (substitutable-paths store paths))))
309 (cut set-contains? subst <>)))
e9651e39 310
784bb1f3 311(define* (derivation-prerequisites-to-build store drv
dd36b51b 312 #:key
58c08df0 313 (mode (build-mode normal))
dd36b51b 314 (outputs
0b6af195 315 (derivation-output-names drv))
e9651e39
LC
316 (substitutable?
317 (substitution-oracle store
58c08df0
LC
318 (list drv)
319 #:mode mode)))
dd36b51b
LC
320 "Return two values: the list of derivation-inputs required to build the
321OUTPUTS of DRV and not already available in STORE, recursively, and the list
e9651e39
LC
322of required store paths that can be substituted. SUBSTITUTABLE? must be a
323one-argument procedure similar to that returned by 'substitution-oracle'."
784bb1f3
LC
324 (define built?
325 (cut valid-path? store <>))
326
9a20830e 327 (define input-built?
dd36b51b
LC
328 (compose (cut any built? <>) derivation-input-output-paths))
329
330 (define input-substitutable?
331 ;; Return true if and only if all of SUB-DRVS are subsitutable. If at
332 ;; least one is missing, then everything must be rebuilt.
333 (compose (cut every substitutable? <>) derivation-input-output-paths))
784bb1f3 334
58c08df0
LC
335 (define (derivation-built? drv* sub-drvs)
336 ;; In 'check' mode, assume that DRV is not built.
337 (and (not (and (eqv? mode (build-mode check))
338 (eq? drv* drv)))
339 (every built? (derivation-output-paths drv* sub-drvs))))
dd36b51b
LC
340
341 (define (derivation-substitutable? drv sub-drvs)
d2d0514b
LC
342 (and (substitutable-derivation? drv)
343 (every substitutable? (derivation-output-paths drv sub-drvs))))
dd36b51b
LC
344
345 (let loop ((drv drv)
346 (sub-drvs outputs)
347 (build '())
348 (substitute '()))
349 (cond ((derivation-built? drv sub-drvs)
350 (values build substitute))
351 ((derivation-substitutable? drv sub-drvs)
352 (values build
353 (append (derivation-output-paths drv sub-drvs)
354 substitute)))
355 (else
d2d0514b
LC
356 (let ((build (if (substitutable-derivation? drv)
357 build
358 (cons (make-derivation-input
359 (derivation-file-name drv) sub-drvs)
360 build)))
361 (inputs (remove (lambda (i)
dd36b51b
LC
362 (or (member i build) ; XXX: quadratic
363 (input-built? i)
364 (input-substitutable? i)))
365 (derivation-inputs drv))))
366 (fold2 loop
367 (append inputs build)
368 (append (append-map (lambda (input)
369 (if (and (not (input-built? input))
370 (input-substitutable? input))
371 (derivation-input-output-paths
372 input)
373 '()))
374 (derivation-inputs drv))
375 substitute)
376 (map (lambda (i)
377 (call-with-input-file (derivation-input-path i)
378 read-derivation))
379 inputs)
380 (map derivation-input-sub-derivations inputs)))))))
9a20830e 381
d0840e4a
LC
382(define (%read-derivation drv-port)
383 ;; Actually read derivation from DRV-PORT.
77d3cf08
LC
384
385 (define comma (string->symbol ","))
386
387 (define (ununquote x)
388 (match x
389 (('unquote x) (ununquote x))
390 ((x ...) (map ununquote x))
391 (_ x)))
392
393 (define (outputs->alist x)
394 (fold-right (lambda (output result)
395 (match output
396 ((name path "" "")
397 (alist-cons name
36bbbbd1 398 (make-derivation-output path #f #f #f)
77d3cf08
LC
399 result))
400 ((name path hash-algo hash)
401 ;; fixed-output
36bbbbd1
LC
402 (let* ((rec? (string-prefix? "r:" hash-algo))
403 (algo (string->symbol
404 (if rec?
405 (string-drop hash-algo 2)
406 hash-algo)))
407 (hash (base16-string->bytevector hash)))
77d3cf08 408 (alist-cons name
36bbbbd1
LC
409 (make-derivation-output path algo
410 hash rec?)
77d3cf08
LC
411 result)))))
412 '()
413 x))
414
415 (define (make-input-drvs x)
416 (fold-right (lambda (input result)
417 (match input
418 ((path (sub-drvs ...))
419 (cons (make-derivation-input path sub-drvs)
420 result))))
421 '()
422 x))
423
df7bbd38
LC
424 ;; The contents of a derivation are typically ASCII, but choosing
425 ;; UTF-8 allows us to take the fast path for Guile's `scm_getc'.
426 (set-port-encoding! drv-port "UTF-8")
427
77d3cf08
LC
428 (let loop ((exp (read drv-port))
429 (result '()))
430 (match exp
431 ((? eof-object?)
432 (let ((result (reverse result)))
433 (match result
434 (('Derive ((outputs ...) (input-drvs ...)
435 (input-srcs ...)
436 (? string? system)
437 (? string? builder)
438 ((? string? args) ...)
439 ((var value) ...)))
440 (make-derivation (outputs->alist outputs)
441 (make-input-drvs input-drvs)
442 input-srcs
443 system builder args
6a446d56
LC
444 (fold-right alist-cons '() var value)
445 (port-filename drv-port)))
77d3cf08
LC
446 (_
447 (error "failed to parse derivation" drv-port result)))))
448 ((? (cut eq? <> comma))
449 (loop (read drv-port) result))
450 (_
451 (loop (read drv-port)
452 (cons (ununquote exp) result))))))
453
d0840e4a
LC
454(define read-derivation
455 (let ((cache (make-weak-value-hash-table 200)))
456 (lambda (drv-port)
457 "Read the derivation from DRV-PORT and return the corresponding
458<derivation> object."
459 ;; Memoize that operation because `%read-derivation' is quite expensive,
460 ;; and because the same argument is read more than 15 times on average
461 ;; during something like (package-derivation s gdb).
462 (let ((file (and=> (port-filename drv-port) basename)))
463 (or (and file (hash-ref cache file))
464 (let ((drv (%read-derivation drv-port)))
465 (hash-set! cache file drv)
466 drv))))))
467
d8085599
LC
468(define-inlinable (write-sequence lst write-item port)
469 ;; Write each element of LST with WRITE-ITEM to PORT, separating them with a
470 ;; comma.
471 (match lst
472 (()
473 #t)
474 ((prefix (... ...) last)
475 (for-each (lambda (item)
476 (write-item item port)
477 (display "," port))
478 prefix)
479 (write-item last port))))
480
481(define-inlinable (write-list lst write-item port)
482 ;; Write LST as a derivation list to PORT, using WRITE-ITEM to write each
483 ;; element.
484 (display "[" port)
485 (write-sequence lst write-item port)
486 (display "]" port))
487
488(define-inlinable (write-tuple lst write-item port)
489 ;; Same, but write LST as a tuple.
490 (display "(" port)
491 (write-sequence lst write-item port)
492 (display ")" port))
493
77d3cf08
LC
494(define (write-derivation drv port)
495 "Write the ATerm-like serialization of DRV to PORT. See Section 2.4 of
496Eelco Dolstra's PhD dissertation for an overview of a previous version of
497that form."
aaa848f3
LC
498
499 ;; Make sure we're using the faster implementation.
500 (define format simple-format)
501
d8085599
LC
502 (define (write-string-list lst)
503 (write-list lst write port))
77d3cf08 504
d8085599
LC
505 (define (write-output output port)
506 (match output
36bbbbd1 507 ((name . ($ <derivation-output> path hash-algo hash recursive?))
d8085599 508 (write-tuple (list name path
36bbbbd1
LC
509 (if hash-algo
510 (string-append (if recursive? "r:" "")
511 (symbol->string hash-algo))
512 "")
d8085599
LC
513 (or (and=> hash bytevector->base16-string)
514 ""))
515 write
516 port))))
517
518 (define (write-input input port)
519 (match input
520 (($ <derivation-input> path sub-drvs)
521 (display "(" port)
522 (write path port)
523 (display "," port)
97507ebe 524 (write-string-list sub-drvs)
d8085599
LC
525 (display ")" port))))
526
527 (define (write-env-var env-var port)
528 (match env-var
529 ((name . value)
530 (display "(" port)
531 (write name port)
532 (display "," port)
533 (write value port)
534 (display ")" port))))
535
97507ebe 536 ;; Assume all the lists we are writing are already sorted.
77d3cf08
LC
537 (match drv
538 (($ <derivation> outputs inputs sources
539 system builder args env-vars)
540 (display "Derive(" port)
97507ebe 541 (write-list outputs write-output port)
77d3cf08 542 (display "," port)
97507ebe 543 (write-list inputs write-input port)
77d3cf08 544 (display "," port)
97507ebe 545 (write-string-list sources)
77d3cf08 546 (format port ",~s,~s," system builder)
d8085599 547 (write-string-list args)
77d3cf08 548 (display "," port)
97507ebe 549 (write-list env-vars write-env-var port)
77d3cf08
LC
550 (display ")" port))))
551
be4e38fb
LC
552(define derivation->string
553 (memoize
554 (lambda (drv)
555 "Return the external representation of DRV as a string."
556 (with-fluids ((%default-port-encoding "UTF-8"))
557 (call-with-output-string
558 (cut write-derivation drv <>))))))
559
59688fc4 560(define* (derivation->output-path drv #:optional (output "out"))
f304c9c2
LC
561 "Return the store path of its output OUTPUT. Raise a
562'&derivation-missing-output-error' condition if OUTPUT is not an output of
563DRV."
564 (let ((output* (assoc-ref (derivation-outputs drv) output)))
565 (if output*
566 (derivation-output-path output*)
567 (raise (condition (&derivation-missing-output-error
568 (derivation drv)
569 (output output)))))))
59688fc4
LC
570
571(define (derivation->output-paths drv)
572 "Return the list of name/path pairs of the outputs of DRV."
573 (map (match-lambda
574 ((name . output)
575 (cons name (derivation-output-path output))))
576 (derivation-outputs drv)))
577
aaa848f3
LC
578(define derivation-path->output-path
579 ;; This procedure is called frequently, so memoize it.
580 (memoize
581 (lambda* (path #:optional (output "out"))
6f58d582 582 "Read the derivation from PATH (`/gnu/store/xxx.drv'), and return the store
de4c3f26 583path of its output OUTPUT."
d0dc4907
LC
584 (derivation->output-path (call-with-input-file path read-derivation)
585 output))))
de4c3f26 586
7244a5f7 587(define (derivation-path->output-paths path)
6f58d582 588 "Read the derivation from PATH (`/gnu/store/xxx.drv'), and return the
7244a5f7 589list of name/path pairs of its outputs."
59688fc4 590 (derivation->output-paths (call-with-input-file path read-derivation)))
7244a5f7 591
de4c3f26
LC
592\f
593;;;
594;;; Derivation primitive.
595;;;
596
26bbbb95
LC
597(define (compressed-hash bv size) ; `compressHash'
598 "Given the hash stored in BV, return a compressed version thereof that fits
599in SIZE bytes."
600 (define new (make-bytevector size 0))
601 (define old-size (bytevector-length bv))
602 (let loop ((i 0))
603 (if (= i old-size)
604 new
605 (let* ((j (modulo i size))
606 (o (bytevector-u8-ref new j)))
607 (bytevector-u8-set! new j
608 (logxor o (bytevector-u8-ref bv i)))
609 (loop (+ 1 i))))))
77d3cf08 610
1391dcb0
LC
611(define derivation-path->base16-hash
612 (memoize
613 (lambda (file)
614 "Return a string containing the base16 representation of the hash of the
615derivation at FILE."
616 (call-with-input-file file
617 (compose bytevector->base16-string
618 derivation-hash
619 read-derivation)))))
620
de4c3f26
LC
621(define derivation-hash ; `hashDerivationModulo' in derivations.cc
622 (memoize
623 (lambda (drv)
624 "Return the hash of DRV, modulo its fixed-output inputs, as a bytevector."
625 (match drv
626 (($ <derivation> ((_ . ($ <derivation-output> path
36bbbbd1
LC
627 (? symbol? hash-algo) (? bytevector? hash)
628 (? boolean? recursive?)))))
de4c3f26 629 ;; A fixed-output derivation.
77d3cf08 630 (sha256
de4c3f26 631 (string->utf8
36bbbbd1
LC
632 (string-append "fixed:out:"
633 (if recursive? "r:" "")
634 (symbol->string hash-algo)
749c6567
LC
635 ":" (bytevector->base16-string hash)
636 ":" path))))
de4c3f26
LC
637 (($ <derivation> outputs inputs sources
638 system builder args env-vars)
639 ;; A regular derivation: replace the path of each input with that
640 ;; input's hash; return the hash of serialization of the resulting
561eaf71
LC
641 ;; derivation.
642 (let* ((inputs (map (match-lambda
643 (($ <derivation-input> path sub-drvs)
1391dcb0 644 (let ((hash (derivation-path->base16-hash path)))
561eaf71
LC
645 (make-derivation-input hash sub-drvs))))
646 inputs))
97507ebe
LC
647 (drv (make-derivation outputs
648 (sort (coalesce-duplicate-inputs inputs)
649 derivation-input<?)
650 sources
6a446d56
LC
651 system builder args env-vars
652 #f)))
b0fad8a2
LC
653
654 ;; XXX: At this point this remains faster than `port-sha256', because
655 ;; the SHA256 port's `write' method gets called for every single
656 ;; character.
de4c3f26 657 (sha256
be4e38fb 658 (string->utf8 (derivation->string drv)))))))))
77d3cf08 659
26bbbb95
LC
660(define (store-path type hash name) ; makeStorePath
661 "Return the store path for NAME/HASH/TYPE."
662 (let* ((s (string-append type ":sha256:"
663 (bytevector->base16-string hash) ":"
664 (%store-prefix) ":" name))
665 (h (sha256 (string->utf8 s)))
666 (c (compressed-hash h 20)))
667 (string-append (%store-prefix) "/"
668 (bytevector->nix-base32-string c) "-"
669 name)))
670
671(define (output-path output hash name) ; makeOutputPath
672 "Return an output path for OUTPUT (the name of the output as a string) of
673the derivation called NAME with hash HASH."
674 (store-path (string-append "output:" output) hash
675 (if (string=? output "out")
676 name
677 (string-append name "-" output))))
678
36bbbbd1
LC
679(define (fixed-output-path output hash-algo hash recursive? name)
680 "Return an output path for the fixed output OUTPUT defined by HASH of type
681HASH-ALGO, of the derivation NAME. RECURSIVE? has the same meaning as for
682'add-to-store'."
683 (if (and recursive? (eq? hash-algo 'sha256))
684 (store-path "source" hash name)
685 (let ((tag (string-append "fixed:" output ":"
686 (if recursive? "r:" "")
687 (symbol->string hash-algo) ":"
688 (bytevector->base16-string hash) ":")))
689 (store-path (string-append "output:" output)
690 (sha256 (string->utf8 tag))
691 name))))
692
a987d2c0
LC
693(define* (derivation store name builder args
694 #:key
695 (system (%current-system)) (env-vars '())
696 (inputs '()) (outputs '("out"))
2096ef47 697 hash hash-algo recursive?
35b5ca78
LC
698 references-graphs
699 allowed-references disallowed-references
4a6aeb67
LC
700 leaked-env-vars local-build?
701 (substitutable? #t))
59688fc4 702 "Build a derivation with the given arguments, and return the resulting
2096ef47 703<derivation> object. When HASH and HASH-ALGO are given, a
59688fc4 704fixed-output derivation is created---i.e., one whose result is known in
36bbbbd1
LC
705advance, such as a file download. If, in addition, RECURSIVE? is true, then
706that fixed output may be an executable file or a directory and HASH must be
707the hash of an archive containing this output.
5b0c9d16 708
858e9282 709When REFERENCES-GRAPHS is true, it must be a list of file name/store path
5b0c9d16 710pairs. In that case, the reference graph of each store path is exported in
1909431c
LC
711the build environment in the corresponding file, in a simple text format.
712
b53be755 713When ALLOWED-REFERENCES is true, it must be a list of store items or outputs
35b5ca78
LC
714that the derivation's outputs may refer to. Likewise, DISALLOWED-REFERENCES,
715if true, must be a list of things the outputs may not refer to.
b53be755 716
c0468155
LC
717When LEAKED-ENV-VARS is true, it must be a list of strings denoting
718environment variables that are allowed to \"leak\" from the daemon's
719environment to the build environment. This is only applicable to fixed-output
720derivations--i.e., when HASH is true. The main use is to allow variables such
721as \"http_proxy\" to be passed to derivations that download files.
722
1909431c
LC
723When LOCAL-BUILD? is true, declare that the derivation is not a good candidate
724for offloading and should rather be built locally. This is the case for small
4a6aeb67
LC
725derivations where the costs of data transfers would outweigh the benefits.
726
727When SUBSTITUTABLE? is false, declare that substitutes of the derivation's
728output should not be used."
26bbbb95
LC
729 (define (add-output-paths drv)
730 ;; Return DRV with an actual store path for each of its output and the
731 ;; corresponding environment variable.
732 (match drv
733 (($ <derivation> outputs inputs sources
734 system builder args env-vars)
735 (let* ((drv-hash (derivation-hash drv))
736 (outputs (map (match-lambda
d9085c23 737 ((output-name . ($ <derivation-output>
36bbbbd1
LC
738 _ algo hash rec?))
739 (let ((path (if hash
740 (fixed-output-path output-name
741 algo hash
742 rec? name)
743 (output-path output-name
744 drv-hash name))))
d9085c23
LC
745 (cons output-name
746 (make-derivation-output path algo
36bbbbd1 747 hash rec?)))))
d9085c23 748 outputs)))
26bbbb95
LC
749 (make-derivation outputs inputs sources system builder args
750 (map (match-lambda
751 ((name . value)
752 (cons name
753 (or (and=> (assoc-ref outputs name)
754 derivation-output-path)
755 value))))
6a446d56
LC
756 env-vars)
757 #f)))))
26bbbb95 758
5b0c9d16
LC
759 (define (user+system-env-vars)
760 ;; Some options are passed to the build daemon via the env. vars of
761 ;; derivations (urgh!). We hide that from our API, but here is the place
762 ;; where we kludgify those options.
b53be755
LC
763 (let ((env-vars `(,@(if local-build?
764 `(("preferLocalBuild" . "1"))
765 '())
4a6aeb67
LC
766 ,@(if (not substitutable?)
767 `(("allowSubstitutes" . "0"))
768 '())
b53be755
LC
769 ,@(if allowed-references
770 `(("allowedReferences"
771 . ,(string-join allowed-references)))
772 '())
35b5ca78
LC
773 ,@(if disallowed-references
774 `(("disallowedReferences"
775 . ,(string-join disallowed-references)))
776 '())
c0468155
LC
777 ,@(if leaked-env-vars
778 `(("impureEnvVars"
779 . ,(string-join leaked-env-vars)))
780 '())
b53be755 781 ,@env-vars)))
1909431c
LC
782 (match references-graphs
783 (((file . path) ...)
784 (let ((value (map (cut string-append <> " " <>)
785 file path)))
786 ;; XXX: This all breaks down if an element of FILE or PATH contains
787 ;; white space.
788 `(("exportReferencesGraph" . ,(string-join value " "))
789 ,@env-vars)))
790 (#f
791 env-vars))))
5b0c9d16
LC
792
793 (define (env-vars-with-empty-outputs env-vars)
26bbbb95 794 ;; Return a variant of ENV-VARS where each OUTPUTS is associated with an
561eaf71 795 ;; empty string, even outputs that do not appear in ENV-VARS.
26bbbb95
LC
796 (let ((e (map (match-lambda
797 ((name . val)
798 (if (member name outputs)
799 (cons name "")
800 (cons name val))))
801 env-vars)))
561eaf71
LC
802 (fold (lambda (output-name env-vars)
803 (if (assoc output-name env-vars)
804 env-vars
805 (append env-vars `((,output-name . "")))))
806 e
807 outputs)))
26bbbb95 808
6a446d56
LC
809 (define (set-file-name drv file)
810 ;; Set FILE as the 'file-name' field of DRV.
811 (match drv
812 (($ <derivation> outputs inputs sources system builder
813 args env-vars)
814 (make-derivation outputs inputs sources system builder
815 args env-vars file))))
816
97507ebe
LC
817 (define input->derivation-input
818 (match-lambda
819 (((? derivation? drv))
820 (make-derivation-input (derivation-file-name drv) '("out")))
821 (((? derivation? drv) sub-drvs ...)
822 (make-derivation-input (derivation-file-name drv) sub-drvs))
823 (((? direct-store-path? input))
824 (make-derivation-input input '("out")))
825 (((? direct-store-path? input) sub-drvs ...)
826 (make-derivation-input input sub-drvs))
827 ((input . _)
828 (let ((path (add-to-store store (basename input)
829 #t "sha256" input)))
830 (make-derivation-input path '())))))
831
832 ;; Note: lists are sorted alphabetically, to conform with the behavior of
833 ;; C++ `std::map' in Nix itself.
834
26bbbb95
LC
835 (let* ((outputs (map (lambda (name)
836 ;; Return outputs with an empty path.
837 (cons name
36bbbbd1
LC
838 (make-derivation-output "" hash-algo
839 hash recursive?)))
97507ebe
LC
840 (sort outputs string<?)))
841 (inputs (sort (coalesce-duplicate-inputs
842 (map input->derivation-input
843 (delete-duplicates inputs)))
844 derivation-input<?))
845 (env-vars (sort (env-vars-with-empty-outputs
846 (user+system-env-vars))
847 (lambda (e1 e2)
848 (string<? (car e1) (car e2)))))
26bbbb95
LC
849 (drv-masked (make-derivation outputs
850 (filter (compose derivation-path?
851 derivation-input-path)
852 inputs)
853 (filter-map (lambda (i)
854 (let ((p (derivation-input-path i)))
855 (and (not (derivation-path? p))
856 p)))
857 inputs)
6a446d56 858 system builder args env-vars #f))
26bbbb95 859 (drv (add-output-paths drv-masked)))
de4c3f26 860
6a446d56 861 (let ((file (add-text-to-store store (string-append name ".drv")
be4e38fb 862 (derivation->string drv)
97507ebe 863 (map derivation-input-path inputs))))
59688fc4
LC
864 (set-file-name drv file))))
865
e387ab7c
LC
866(define* (map-derivation store drv mapping
867 #:key (system (%current-system)))
868 "Given MAPPING, a list of pairs of derivations, return a derivation based on
869DRV where all the 'car's of MAPPING have been replaced by its 'cdr's,
870recursively."
871 (define (substitute str initial replacements)
872 (fold (lambda (path replacement result)
873 (string-replace-substring result path
874 replacement))
875 str
876 initial replacements))
877
878 (define (substitute-file file initial replacements)
879 (define contents
880 (with-fluids ((%default-port-encoding #f))
881 (call-with-input-file file get-string-all)))
882
883 (let ((updated (substitute contents initial replacements)))
884 (if (string=? updated contents)
885 file
886 ;; XXX: permissions aren't preserved.
887 (add-text-to-store store (store-path-package-name file)
888 updated))))
889
890 (define input->output-paths
891 (match-lambda
a716e36d 892 (((? derivation? drv))
e387ab7c 893 (list (derivation->output-path drv)))
a716e36d 894 (((? derivation? drv) sub-drvs ...)
e387ab7c 895 (map (cut derivation->output-path drv <>)
a716e36d
LC
896 sub-drvs))
897 ((file)
898 (list file))))
e387ab7c
LC
899
900 (let ((mapping (fold (lambda (pair result)
901 (match pair
a716e36d 902 (((? derivation? orig) . replacement)
e387ab7c 903 (vhash-cons (derivation-file-name orig)
a716e36d
LC
904 replacement result))
905 ((file . replacement)
906 (vhash-cons file replacement result))))
e387ab7c
LC
907 vlist-null
908 mapping)))
909 (define rewritten-input
910 ;; Rewrite the given input according to MAPPING, and return an input
911 ;; in the format used in 'derivation' calls.
912 (memoize
913 (lambda (input loop)
914 (match input
915 (($ <derivation-input> path (sub-drvs ...))
916 (match (vhash-assoc path mapping)
a716e36d 917 ((_ . (? derivation? replacement))
e387ab7c 918 (cons replacement sub-drvs))
a716e36d
LC
919 ((_ . replacement)
920 (list replacement))
e387ab7c
LC
921 (#f
922 (let* ((drv (loop (call-with-input-file path read-derivation))))
923 (cons drv sub-drvs)))))))))
924
925 (let loop ((drv drv))
926 (let* ((inputs (map (cut rewritten-input <> loop)
927 (derivation-inputs drv)))
928 (initial (append-map derivation-input-output-paths
929 (derivation-inputs drv)))
930 (replacements (append-map input->output-paths inputs))
931
932 ;; Sources typically refer to the output directories of the
933 ;; original inputs, INITIAL. Rewrite them by substituting
934 ;; REPLACEMENTS.
a716e36d
LC
935 (sources (map (lambda (source)
936 (match (vhash-assoc source mapping)
937 ((_ . replacement)
938 replacement)
939 (#f
940 (substitute-file source
941 initial replacements))))
e387ab7c
LC
942 (derivation-sources drv)))
943
944 ;; Now augment the lists of initials and replacements.
945 (initial (append (derivation-sources drv) initial))
946 (replacements (append sources replacements))
947 (name (store-path-package-name
948 (string-drop-right (derivation-file-name drv)
949 4))))
950 (derivation store name
951 (substitute (derivation-builder drv)
952 initial replacements)
953 (map (cut substitute <> initial replacements)
954 (derivation-builder-arguments drv))
955 #:system system
956 #:env-vars (map (match-lambda
957 ((var . value)
958 `(,var
959 . ,(substitute value initial
960 replacements))))
961 (derivation-builder-environment-vars drv))
962 #:inputs (append (map list sources) inputs)
0b6af195 963 #:outputs (derivation-output-names drv)
e387ab7c
LC
964 #:hash (match (derivation-outputs drv)
965 ((($ <derivation-output> _ algo hash))
966 hash)
967 (_ #f))
968 #:hash-algo (match (derivation-outputs drv)
969 ((($ <derivation-output> _ algo hash))
970 algo)
971 (_ #f)))))))
972
59688fc4
LC
973\f
974;;;
975;;; Store compatibility layer.
976;;;
977
a8d65643
LC
978(define* (build-derivations store derivations
979 #:optional (mode (build-mode normal)))
980 "Build DERIVATIONS, a list of <derivation> objects or .drv file names, using
981the specified MODE."
01d8ac64
LC
982 (build-things store (map (match-lambda
983 ((? string? file) file)
984 ((and drv ($ <derivation>))
985 (derivation-file-name drv)))
a8d65643
LC
986 derivations)
987 mode))
d9085c23
LC
988
989\f
990;;;
991;;; Guile-based builders.
992;;;
993
d9024884
LC
994(define (parent-directories file-name)
995 "Return the list of parent dirs of FILE-NAME, in the order in which an
996`mkdir -p' implementation would make them."
997 (let ((not-slash (char-set-complement (char-set #\/))))
998 (reverse
999 (fold (lambda (dir result)
1000 (match result
1001 (()
1002 (list dir))
1003 ((prev _ ...)
1004 (cons (string-append prev "/" dir)
1005 result))))
1006 '()
1007 (remove (cut string=? <> ".")
1008 (string-tokenize (dirname file-name) not-slash))))))
1009
aa72d9af 1010(define* (imported-files store files ;deprecated
b272c474
LC
1011 #:key (name "file-import")
1012 (system (%current-system))
1013 (guile (%guile-for-build)))
99634e3f
LC
1014 "Return a derivation that imports FILES into STORE. FILES must be a list
1015of (FINAL-PATH . FILE-NAME) pairs; each FILE-NAME is read from the file
1016system, imported, and appears under FINAL-PATH in the resulting store path."
99634e3f
LC
1017 (let* ((files (map (match-lambda
1018 ((final-path . file-name)
2acb2cb6 1019 (list final-path
a9ebd9ef 1020 (add-to-store store (basename final-path) #f
99634e3f
LC
1021 "sha256" file-name))))
1022 files))
1023 (builder
1024 `(begin
1025 (mkdir %output) (chdir %output)
1026 ,@(append-map (match-lambda
2acb2cb6 1027 ((final-path store-path)
d9024884 1028 (append (match (parent-directories final-path)
99634e3f
LC
1029 (() '())
1030 ((head ... tail)
1031 (append (map (lambda (d)
1032 `(false-if-exception
1033 (mkdir ,d)))
1034 head)
224f7ad6
LC
1035 `((or (file-exists? ,tail)
1036 (mkdir ,tail))))))
99634e3f
LC
1037 `((symlink ,store-path ,final-path)))))
1038 files))))
dd1a5a15
LC
1039 (build-expression->derivation store name builder
1040 #:system system
1041 #:inputs files
6ce206cb
LC
1042 #:guile-for-build guile
1043 #:local-build? #t)))
99634e3f 1044
d26e1967
LC
1045;; The "file not found" error condition.
1046(define-condition-type &file-search-error &error
1047 file-search-error?
1048 (file file-search-error-file-name)
1049 (path file-search-error-search-path))
1050
8601d0dd
LC
1051(define search-path*
1052 ;; A memoizing version of 'search-path' so 'imported-modules' does not end
1053 ;; up looking for the same files over and over again.
d26e1967
LC
1054 (memoize (lambda (path file)
1055 "Search for FILE in PATH and memoize the result. Raise a
1056'&file-search-error' condition if it could not be found."
1057 (or (search-path path file)
1058 (raise (condition
1059 (&file-search-error (file file)
1060 (path path))))))))
8601d0dd 1061
6985335f
LC
1062(define (module->source-file-name module)
1063 "Return the file name corresponding to MODULE, a Guile module name (a list
1064of symbols.)"
1065 (string-append (string-join (map symbol->string module) "/")
1066 ".scm"))
1067
aa72d9af 1068(define* (%imported-modules store modules ;deprecated
e87f0591
LC
1069 #:key (name "module-import")
1070 (system (%current-system))
1071 (guile (%guile-for-build))
1072 (module-path %load-path))
3eb98237 1073 "Return a derivation that contains the source files of MODULES, a list of
8dcb0c55 1074module names such as `(ice-9 q)'. All of MODULES must be in the MODULE-PATH
3eb98237
LC
1075search path."
1076 ;; TODO: Determine the closure of MODULES, build the `.go' files,
1077 ;; canonicalize the source files through read/write, etc.
1078 (let ((files (map (lambda (m)
6985335f 1079 (let ((f (module->source-file-name m)))
8601d0dd 1080 (cons f (search-path* module-path f))))
3eb98237 1081 modules)))
b272c474
LC
1082 (imported-files store files #:name name #:system system
1083 #:guile guile)))
3eb98237 1084
aa72d9af 1085(define* (%compiled-modules store modules ;deprecated
e87f0591
LC
1086 #:key (name "module-import-compiled")
1087 (system (%current-system))
1088 (guile (%guile-for-build))
1089 (module-path %load-path))
d9024884
LC
1090 "Return a derivation that builds a tree containing the `.go' files
1091corresponding to MODULES. All the MODULES are built in a context where
1092they can refer to each other."
e87f0591
LC
1093 (let* ((module-drv (%imported-modules store modules
1094 #:system system
1095 #:guile guile
1096 #:module-path module-path))
59688fc4 1097 (module-dir (derivation->output-path module-drv))
d9024884
LC
1098 (files (map (lambda (m)
1099 (let ((f (string-join (map symbol->string m)
1100 "/")))
1101 (cons (string-append f ".go")
1102 (string-append module-dir "/" f ".scm"))))
1103 modules)))
1104 (define builder
1105 `(begin
1106 (use-modules (system base compile))
1107 (let ((out (assoc-ref %outputs "out")))
1108 (mkdir out)
1109 (chdir out))
1110
1111 (set! %load-path
1112 (cons ,module-dir %load-path))
1113
1114 ,@(map (match-lambda
1115 ((output . input)
1116 (let ((make-parent-dirs (map (lambda (dir)
1117 `(unless (file-exists? ,dir)
1118 (mkdir ,dir)))
1119 (parent-directories output))))
1120 `(begin
1121 ,@make-parent-dirs
1122 (compile-file ,input
1123 #:output-file ,output
1124 #:opts %auto-compilation-options)))))
1125 files)))
1126
dd1a5a15
LC
1127 (build-expression->derivation store name builder
1128 #:inputs `(("modules" ,module-drv))
1129 #:system system
6ce206cb
LC
1130 #:guile-for-build guile
1131 #:local-build? #t)))
3eb98237 1132
aa72d9af 1133(define* (build-expression->derivation store name exp ;deprecated
dd1a5a15
LC
1134 #:key
1135 (system (%current-system))
1136 (inputs '())
1137 (outputs '("out"))
36bbbbd1 1138 hash hash-algo recursive?
4c1eddf7 1139 (env-vars '())
6dd7787c 1140 (modules '())
9c629a27 1141 guile-for-build
1909431c 1142 references-graphs
63a42824 1143 allowed-references
35b5ca78 1144 disallowed-references
4a6aeb67 1145 local-build? (substitutable? #t))
874e6874
LC
1146 "Return a derivation that executes Scheme expression EXP as a builder
1147for derivation NAME. INPUTS must be a list of (NAME DRV-PATH SUB-DRV)
1148tuples; when SUB-DRV is omitted, \"out\" is assumed. MODULES is a list
1149of names of Guile modules from the current search path to be copied in
1150the store, compiled, and made available in the load path during the
1151execution of EXP.
1152
1153EXP is evaluated in an environment where %OUTPUT is bound to the main
1154output path, %OUTPUTS is bound to a list of output/path pairs, and where
1155%BUILD-INPUTS is bound to an alist of string/output-path pairs made from
1156INPUTS. Optionally, ENV-VARS is a list of string pairs specifying the
1157name and value of environment variables visible to the builder. The
1158builder terminates by passing the result of EXP to `exit'; thus, when
1159EXP returns #f, the build is considered to have failed.
6dd7787c
LC
1160
1161EXP is built using GUILE-FOR-BUILD (a derivation). When GUILE-FOR-BUILD is
9c629a27
LC
1162omitted or is #f, the value of the `%guile-for-build' fluid is used instead.
1163
63a42824 1164See the `derivation' procedure for the meaning of REFERENCES-GRAPHS,
35b5ca78 1165ALLOWED-REFERENCES, DISALLOWED-REFERENCES, LOCAL-BUILD?, and SUBSTITUTABLE?."
b272c474
LC
1166 (define guile-drv
1167 (or guile-for-build (%guile-for-build)))
1168
d9085c23 1169 (define guile
59688fc4 1170 (string-append (derivation->output-path guile-drv)
d9085c23
LC
1171 "/bin/guile"))
1172
0d56a551
LC
1173 (define module-form?
1174 (match-lambda
a987d2c0
LC
1175 (((or 'define-module 'use-modules) _ ...) #t)
1176 (_ #f)))
0d56a551 1177
7bdd1f0e
LC
1178 (define source-path
1179 ;; When passed an input that is a source, return its path; otherwise
1180 ;; return #f.
1181 (match-lambda
59688fc4
LC
1182 ((_ (? derivation?) _ ...)
1183 #f)
7bdd1f0e
LC
1184 ((_ path _ ...)
1185 (and (not (derivation-path? path))
1186 path))))
1187
d9085c23 1188 (let* ((prologue `(begin
0d56a551
LC
1189 ,@(match exp
1190 ((_ ...)
1191 ;; Module forms must appear at the top-level so
1192 ;; that any macros they export can be expanded.
1193 (filter module-form? exp))
1194 (_ `(,exp)))
1195
d9085c23 1196 (define %output (getenv "out"))
9bc07f4d
LC
1197 (define %outputs
1198 (map (lambda (o)
1199 (cons o (getenv o)))
1200 ',outputs))
d9085c23
LC
1201 (define %build-inputs
1202 ',(map (match-lambda
2acb2cb6
LC
1203 ((name drv . rest)
1204 (let ((sub (match rest
1205 (() "out")
1206 ((x) x))))
1207 (cons name
59688fc4
LC
1208 (cond
1209 ((derivation? drv)
1210 (derivation->output-path drv sub))
1211 ((derivation-path? drv)
1212 (derivation-path->output-path drv
1213 sub))
1214 (else drv))))))
d44bc84b
LC
1215 inputs))
1216
d9024884
LC
1217 ,@(if (null? modules)
1218 '()
1219 ;; Remove our own settings.
1220 '((unsetenv "GUILE_LOAD_COMPILED_PATH")))
1221
d44bc84b
LC
1222 ;; Guile sets it, but remove it to avoid conflicts when
1223 ;; building Guile-using packages.
1224 (unsetenv "LD_LIBRARY_PATH")))
d9085c23
LC
1225 (builder (add-text-to-store store
1226 (string-append name "-guile-builder")
0bb1aa9e
LC
1227
1228 ;; Explicitly use UTF-8 for determinism,
1229 ;; and also because UTF-8 output is faster.
1230 (with-fluids ((%default-port-encoding
1231 "UTF-8"))
1232 (call-with-output-string
1233 (lambda (port)
1234 (write prologue port)
1235 (write
1236 `(exit
1237 ,(match exp
1238 ((_ ...)
1239 (remove module-form? exp))
1240 (_ `(,exp))))
1241 port))))
7bdd1f0e
LC
1242
1243 ;; The references don't really matter
1244 ;; since the builder is always used in
1245 ;; conjunction with the drv that needs
1246 ;; it. For clarity, we add references
1247 ;; to the subset of INPUTS that are
1248 ;; sources, avoiding references to other
1249 ;; .drv; otherwise, BUILDER's hash would
1250 ;; depend on those, even if they are
1251 ;; fixed-output.
1252 (filter-map source-path inputs)))
1253
d9024884 1254 (mod-drv (and (pair? modules)
e87f0591
LC
1255 (%imported-modules store modules
1256 #:guile guile-drv
1257 #:system system)))
3eb98237 1258 (mod-dir (and mod-drv
59688fc4 1259 (derivation->output-path mod-drv)))
d9024884 1260 (go-drv (and (pair? modules)
e87f0591
LC
1261 (%compiled-modules store modules
1262 #:guile guile-drv
1263 #:system system)))
d9024884 1264 (go-dir (and go-drv
59688fc4 1265 (derivation->output-path go-drv))))
a987d2c0 1266 (derivation store name guile
3eb98237
LC
1267 `("--no-auto-compile"
1268 ,@(if mod-dir `("-L" ,mod-dir) '())
1269 ,builder)
d9024884 1270
a987d2c0
LC
1271 #:system system
1272
1273 #:inputs `((,(or guile-for-build (%guile-for-build)))
1274 (,builder)
1275 ,@(map cdr inputs)
1276 ,@(if mod-drv `((,mod-drv) (,go-drv)) '()))
1277
d9024884
LC
1278 ;; When MODULES is non-empty, shamelessly clobber
1279 ;; $GUILE_LOAD_COMPILED_PATH.
a987d2c0
LC
1280 #:env-vars (if go-dir
1281 `(("GUILE_LOAD_COMPILED_PATH" . ,go-dir)
1282 ,@(alist-delete "GUILE_LOAD_COMPILED_PATH"
1283 env-vars))
1284 env-vars)
1285
9bc07f4d 1286 #:hash hash #:hash-algo hash-algo
36bbbbd1 1287 #:recursive? recursive?
9c629a27 1288 #:outputs outputs
1909431c 1289 #:references-graphs references-graphs
63a42824 1290 #:allowed-references allowed-references
35b5ca78 1291 #:disallowed-references disallowed-references
4a6aeb67
LC
1292 #:local-build? local-build?
1293 #:substitutable? substitutable?)))
e87f0591
LC
1294
1295\f
1296;;;
1297;;; Monadic interface.
1298;;;
1299
1300(define built-derivations
1301 (store-lift build-derivations))