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