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