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