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