gnu: Use 'glibc-utf8-locales-final' in the default patching inputs.
[jackhill/guix/guix.git] / guix / packages.scm
CommitLineData
233e7676 1;;; GNU Guix --- Functional package management for GNU
e87f0591 2;;; Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
a193b824 3;;; Copyright © 2014 Mark H Weaver <mhw@netris.org>
e3ce5d70 4;;;
233e7676 5;;; This file is part of GNU Guix.
e3ce5d70 6;;;
233e7676 7;;; GNU Guix is free software; you can redistribute it and/or modify it
e3ce5d70
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
e3ce5d70
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/>.
e3ce5d70
LC
19
20(define-module (guix packages)
21 #:use-module (guix utils)
c0cd1b3e 22 #:use-module (guix records)
e3ce5d70 23 #:use-module (guix store)
e87f0591 24 #:use-module (guix monads)
ff40e9b7 25 #:use-module (guix gexp)
ddc29a78 26 #:use-module (guix base32)
d510ab46 27 #:use-module (guix derivations)
e3ce5d70 28 #:use-module (guix build-system)
cf87cc89 29 #:use-module (guix gexp)
e3ce5d70 30 #:use-module (ice-9 match)
c37a74bd 31 #:use-module (ice-9 vlist)
062c6927 32 #:use-module (srfi srfi-1)
946b72c9 33 #:use-module (srfi srfi-9 gnu)
05962f29 34 #:use-module (srfi srfi-11)
a63062b5 35 #:use-module (srfi srfi-26)
d36622dc
LC
36 #:use-module (srfi srfi-34)
37 #:use-module (srfi srfi-35)
cd52703a
LC
38 #:re-export (%current-system
39 %current-target-system)
ff352cfb 40 #:export (origin
90c68be8
LC
41 origin?
42 origin-uri
43 origin-method
44 origin-sha256
45 origin-file-name
ac10e0e1
LC
46 origin-patches
47 origin-patch-flags
48 origin-patch-inputs
49 origin-patch-guile
f9cc8971
LC
50 origin-snippet
51 origin-modules
52 origin-imported-modules
e4c245f8 53 base32
e3ce5d70 54
a18eda27
LC
55 <search-path-specification>
56 search-path-specification
57 search-path-specification?
58 search-path-specification->sexp
59
e3ce5d70
LC
60 package
61 package?
62 package-name
63 package-version
2847050a 64 package-full-name
e3ce5d70
LC
65 package-source
66 package-build-system
67 package-arguments
68 package-inputs
69 package-native-inputs
062c6927 70 package-propagated-inputs
e3ce5d70 71 package-outputs
a18eda27 72 package-native-search-paths
e3ce5d70 73 package-search-paths
05962f29 74 package-replacement
d45122f5 75 package-synopsis
e3ce5d70 76 package-description
e3ce5d70 77 package-license
52bda18a 78 package-home-page
4e097f86 79 package-supported-systems
e3ce5d70 80 package-maintainers
062c6927 81 package-properties
35f3c5f5 82 package-location
d66c7096 83 package-field-location
e3ce5d70 84
7d193ec3 85 package-direct-inputs
a3d73f59 86 package-transitive-inputs
9c1edabd
LC
87 package-transitive-target-inputs
88 package-transitive-native-inputs
113aef68 89 package-transitive-propagated-inputs
7c3c0374 90 package-transitive-supported-systems
e3ce5d70
LC
91 package-source-derivation
92 package-derivation
d36622dc 93 package-cross-derivation
d510ab46 94 package-output
05962f29 95 package-grafts
d36622dc 96
4e097f86
LC
97 %supported-systems
98
d36622dc 99 &package-error
07783858 100 package-error?
d36622dc
LC
101 package-error-package
102 &package-input-error
07783858 103 package-input-error?
9b222abe
LC
104 package-error-invalid-input
105 &package-cross-build-system-error
0d5a559f
LC
106 package-cross-build-system-error?
107
108 package->bag
d3d337d2 109 bag->derivation
0d5a559f
LC
110 bag-transitive-inputs
111 bag-transitive-host-inputs
112 bag-transitive-build-inputs
e87f0591
LC
113 bag-transitive-target-inputs
114
115 default-guile
ff40e9b7 116 default-guile-derivation
e87f0591
LC
117 set-guile-for-build
118 package-file
119 package->derivation
120 package->cross-derivation
121 origin->derivation))
e3ce5d70
LC
122
123;;; Commentary:
124;;;
125;;; This module provides a high-level mechanism to define packages in a
126;;; Guix-based distribution.
127;;;
128;;; Code:
129
90c68be8
LC
130;; The source of a package, such as a tarball URL and fetcher---called
131;; "origin" to avoid name clash with `package-source', `source', etc.
132(define-record-type* <origin>
133 origin make-origin
134 origin?
135 (uri origin-uri) ; string
9b5b5c17 136 (method origin-method) ; procedure
90c68be8 137 (sha256 origin-sha256) ; bytevector
ac10e0e1 138 (file-name origin-file-name (default #f)) ; optional file name
6b1f9721
LC
139
140 ;; Patches are delayed so that the 'search-patch' calls are made lazily,
141 ;; which reduces I/O on startup and allows patch-not-found errors to be
142 ;; gracefully handled at run time.
143 (patches origin-patches ; list of file names
144 (default '()) (delayed))
145
f9cc8971 146 (snippet origin-snippet (default #f)) ; sexp or #f
ac10e0e1
LC
147 (patch-flags origin-patch-flags ; list of strings
148 (default '("-p1")))
1d9bc459
LC
149
150 ;; Patching requires Guile, GNU Patch, and a few more. These two fields are
151 ;; used to specify these dependencies when needed.
ac10e0e1
LC
152 (patch-inputs origin-patch-inputs ; input list or #f
153 (default #f))
f9cc8971
LC
154 (modules origin-modules ; list of module names
155 (default '()))
156 (imported-modules origin-imported-modules ; list of module names
157 (default '()))
1d9bc459 158 (patch-guile origin-patch-guile ; package or #f
ac10e0e1 159 (default #f)))
e3ce5d70 160
f1096964
LC
161(define (print-origin origin port)
162 "Write a concise representation of ORIGIN to PORT."
163 (match origin
164 (($ <origin> uri method sha256 file-name patches)
165 (simple-format port "#<origin ~s ~a ~s ~a>"
166 uri (bytevector->base32-string sha256)
6b1f9721 167 (force patches)
f1096964
LC
168 (number->string (object-address origin) 16)))))
169
170(set-record-type-printer! <origin> print-origin)
171
e4c245f8
LC
172(define-syntax base32
173 (lambda (s)
174 "Return the bytevector corresponding to the given Nix-base32
175representation."
176 (syntax-case s ()
177 ((_ str)
178 (string? (syntax->datum #'str))
aba326f7 179 ;; A literal string: do the conversion at expansion time.
e4c245f8
LC
180 (with-syntax ((bv (nix-base32-string->bytevector
181 (syntax->datum #'str))))
aba326f7
LC
182 #''bv))
183 ((_ str)
184 #'(nix-base32-string->bytevector str)))))
e4c245f8 185
a18eda27
LC
186;; The specification of a search path.
187(define-record-type* <search-path-specification>
188 search-path-specification make-search-path-specification
189 search-path-specification?
7b21fe53
LC
190 (variable search-path-specification-variable) ;string
191 (files search-path-specification-files) ;list of strings
192 (separator search-path-specification-separator ;string
193 (default ":"))
194 (file-type search-path-specification-file-type ;symbol
195 (default 'directory))
196 (file-pattern search-path-specification-file-pattern ;#f | string
197 (default #f)))
a18eda27
LC
198
199(define (search-path-specification->sexp spec)
200 "Return an sexp representing SPEC, a <search-path-specification>. The sexp
201corresponds to the arguments expected by `set-path-environment-variable'."
202 (match spec
7b21fe53
LC
203 (($ <search-path-specification> variable files separator type pattern)
204 `(,variable ,files ,separator ,type ,pattern))))
d36622dc 205
4e097f86
LC
206(define %supported-systems
207 ;; This is the list of system types that are supported. By default, we
208 ;; expect all packages to build successfully here.
209 '("x86_64-linux" "i686-linux" "mips64el-linux"))
210
a18eda27 211;; A package.
e3ce5d70
LC
212(define-record-type* <package>
213 package make-package
214 package?
215 (name package-name) ; string
216 (version package-version) ; string
90c68be8 217 (source package-source) ; <origin> instance
e3ce5d70 218 (build-system package-build-system) ; build system
64fddd74 219 (arguments package-arguments ; arguments for the build method
21c203a5 220 (default '()) (thunked))
062c6927 221
e3ce5d70 222 (inputs package-inputs ; input packages or derivations
dd6b9a37 223 (default '()) (thunked))
062c6927 224 (propagated-inputs package-propagated-inputs ; same, but propagated
9d97a1b3 225 (default '()) (thunked))
e3ce5d70 226 (native-inputs package-native-inputs ; native input packages/derivations
a7dc055b 227 (default '()) (thunked))
c9d01150
LC
228 (self-native-input? package-self-native-input? ; whether to use itself as
229 ; a native input when cross-
230 (default #f)) ; compiling
062c6927 231
e3ce5d70
LC
232 (outputs package-outputs ; list of strings
233 (default '("out")))
a18eda27
LC
234
235 ; lists of
236 ; <search-path-specification>,
237 ; for native and cross
238 ; inputs
239 (native-search-paths package-native-search-paths (default '()))
240 (search-paths package-search-paths (default '()))
05962f29
LC
241 (replacement package-replacement ; package | #f
242 (default #f) (thunked))
e3ce5d70 243
d45122f5
LC
244 (synopsis package-synopsis) ; one-line description
245 (description package-description) ; one or two paragraphs
1fb78cb2 246 (license package-license)
45753b65 247 (home-page package-home-page)
4e097f86
LC
248 (supported-systems package-supported-systems ; list of strings
249 (default %supported-systems))
35f3c5f5 250 (maintainers package-maintainers (default '()))
45753b65 251
062c6927
LC
252 (properties package-properties (default '())) ; alist for anything else
253
35f3c5f5
LC
254 (location package-location
255 (default (and=> (current-source-location)
256 source-properties->location))))
e3ce5d70 257
946b72c9
LC
258(set-record-type-printer! <package>
259 (lambda (package port)
260 (let ((loc (package-location package))
261 (format simple-format))
2e1bafb0 262 (format port "#<package ~a-~a ~a~a>"
946b72c9
LC
263 (package-name package)
264 (package-version package)
2e1bafb0
LC
265 (if loc
266 (format #f "~a:~a "
267 (location-file loc)
268 (location-line loc))
269 "")
946b72c9
LC
270 (number->string (object-address
271 package)
272 16)))))
273
d66c7096 274(define (package-field-location package field)
f903dc05
LC
275 "Return the source code location of the definition of FIELD for PACKAGE, or
276#f if it could not be determined."
277 (define (goto port line column)
278 (unless (and (= (port-column port) (- column 1))
279 (= (port-line port) (- line 1)))
280 (unless (eof-object? (read-char port))
281 (goto port line column))))
d66c7096
LC
282
283 (match (package-location package)
284 (($ <location> file line column)
285 (catch 'system
286 (lambda ()
0b8749b7
LC
287 ;; In general we want to keep relative file names for modules.
288 (with-fluids ((%file-port-name-canonicalization 'relative))
289 (call-with-input-file (search-path %load-path file)
290 (lambda (port)
291 (goto port line column)
292 (match (read port)
293 (('package inits ...)
294 (let ((field (assoc field inits)))
295 (match field
296 ((_ value)
297 ;; Put the `or' here, and not in the first argument of
298 ;; `and=>', to work around a compiler bug in 2.0.5.
299 (or (and=> (source-properties value)
300 source-properties->location)
301 (and=> (source-properties field)
302 source-properties->location)))
303 (_
304 #f))))
305 (_
306 #f))))))
d66c7096 307 (lambda _
f903dc05 308 #f)))
d66c7096
LC
309 (_ #f)))
310
d36622dc
LC
311
312;; Error conditions.
313
314(define-condition-type &package-error &error
315 package-error?
316 (package package-error-package))
317
318(define-condition-type &package-input-error &package-error
319 package-input-error?
320 (input package-error-invalid-input))
321
9b222abe
LC
322(define-condition-type &package-cross-build-system-error &package-error
323 package-cross-build-system-error?)
324
d36622dc 325
2847050a
LC
326(define (package-full-name package)
327 "Return the full name of PACKAGE--i.e., `NAME-VERSION'."
328 (string-append (package-name package) "-" (package-version package)))
329
ac10e0e1
LC
330(define (%standard-patch-inputs)
331 (let ((ref (lambda (module var)
332 (module-ref (resolve-interface module) var))))
333 `(("tar" ,(ref '(gnu packages base) 'tar))
334 ("xz" ,(ref '(gnu packages compression) 'xz))
335 ("bzip2" ,(ref '(gnu packages compression) 'bzip2))
336 ("gzip" ,(ref '(gnu packages compression) 'gzip))
337 ("lzip" ,(ref '(gnu packages compression) 'lzip))
9cca706c 338 ("patch" ,(ref '(gnu packages base) 'patch))
ec3b1c57
LC
339 ("locales" ,(ref '(gnu packages commencement)
340 'glibc-utf8-locales-final)))))
ac10e0e1 341
1d9bc459 342(define (default-guile)
e87f0591
LC
343 "Return the default Guile package used to run the build code of
344derivations."
bdb36958 345 (let ((distro (resolve-interface '(gnu packages commencement))))
1d9bc459 346 (module-ref distro 'guile-final)))
ac10e0e1 347
ff40e9b7
LC
348(define* (default-guile-derivation #:optional (system (%current-system)))
349 "Return the derivation for SYSTEM of the default Guile package used to run
350the build code of derivation."
351 (package->derivation (default-guile) system
352 #:graft? #f))
353
cf87cc89 354(define* (patch-and-repack source patches
ac10e0e1 355 #:key
cf87cc89 356 (inputs (%standard-patch-inputs))
f9cc8971 357 (snippet #f)
ac10e0e1 358 (flags '("-p1"))
f9cc8971
LC
359 (modules '())
360 (imported-modules '())
ac10e0e1
LC
361 (guile-for-build (%guile-for-build))
362 (system (%current-system)))
f9cc8971
LC
363 "Unpack SOURCE (a derivation or store path), apply all of PATCHES, and
364repack the tarball using the tools listed in INPUTS. When SNIPPET is true,
365it must be an s-expression that will run from within the directory where
366SOURCE was unpacked, after all of PATCHES have been applied. MODULES and
367IMPORTED-MODULES specify modules to use/import for use by SNIPPET."
368 (define source-file-name
369 ;; SOURCE is usually a derivation, but it could be a store file.
370 (if (derivation? source)
371 (derivation->output-path source)
372 source))
373
cf87cc89
LC
374 (define (lookup-input name)
375 (match (assoc-ref inputs name)
376 ((package) package)
377 (#f #f)))
378
ac10e0e1 379 (define decompression-type
f9cc8971
LC
380 (cond ((string-suffix? "gz" source-file-name) "gzip")
381 ((string-suffix? "bz2" source-file-name) "bzip2")
382 ((string-suffix? "lz" source-file-name) "lzip")
383 (else "xz")))
ac10e0e1
LC
384
385 (define original-file-name
f9cc8971
LC
386 ;; Remove the store prefix plus the slash, hash, and hyphen.
387 (let* ((sans (string-drop source-file-name
388 (+ (string-length (%store-prefix)) 1)))
389 (dash (string-index sans #\-)))
390 (string-drop sans (+ 1 dash))))
ac10e0e1 391
3ca00bb5
LC
392 (define (numeric-extension? file-name)
393 ;; Return true if FILE-NAME ends with digits.
857ecb3d
LC
394 (and=> (file-extension file-name)
395 (cut string-every char-set:hex-digit <>)))
3ca00bb5
LC
396
397 (define (tarxz-name file-name)
398 ;; Return a '.tar.xz' file name based on FILE-NAME.
399 (let ((base (if (numeric-extension? file-name)
400 original-file-name
401 (file-sans-extension file-name))))
402 (string-append base
403 (if (equal? (file-extension base) "tar")
404 ".xz"
405 ".tar.xz"))))
406
cf87cc89
LC
407 (define instantiate-patch
408 (match-lambda
409 ((? string? patch)
410 (interned-file patch #:recursive? #t))
411 ((? origin? patch)
412 (origin->derivation patch system))))
413
414 (mlet %store-monad ((tar -> (lookup-input "tar"))
415 (xz -> (lookup-input "xz"))
416 (patch -> (lookup-input "patch"))
417 (locales -> (lookup-input "locales"))
418 (decomp -> (lookup-input decompression-type))
419 (patches (sequence %store-monad
420 (map instantiate-patch patches))))
421 (define build
422 #~(begin
423 (use-modules (ice-9 ftw)
424 (srfi srfi-1)
425 (guix build utils))
426
427 (define (apply-patch patch)
428 (format (current-error-port) "applying '~a'...~%" patch)
429
430 ;; Use '--force' so that patches that do not apply perfectly are
431 ;; rejected.
432 (zero? (system* (string-append #$patch "/bin/patch")
433 "--force" #$@flags "--input" patch)))
434
435 (define (first-file directory)
436 ;; Return the name of the first file in DIRECTORY.
437 (car (scandir directory
438 (lambda (name)
439 (not (member name '("." "..")))))))
440
441 ;; Encoding/decoding errors shouldn't be silent.
442 (fluid-set! %default-port-conversion-strategy 'error)
443
444 (when #$locales
445 ;; First of all, install a UTF-8 locale so that UTF-8 file names
446 ;; are correctly interpreted. During bootstrap, LOCALES is #f.
447 (setenv "LOCPATH" (string-append #$locales "/lib/locale"))
448 (setlocale LC_ALL "en_US.UTF-8"))
449
450 (setenv "PATH" (string-append #$xz "/bin" ":"
451 #$decomp "/bin"))
452
453 ;; SOURCE may be either a directory or a tarball.
454 (and (if (file-is-directory? #$source)
455 (let* ((store (or (getenv "NIX_STORE") "/gnu/store"))
456 (len (+ 1 (string-length store)))
457 (base (string-drop #$source len))
458 (dash (string-index base #\-))
459 (directory (string-drop base (+ 1 dash))))
460 (mkdir directory)
461 (copy-recursively #$source directory)
462 #t)
463 (zero? (system* (string-append #$tar "/bin/tar")
464 "xvf" #$source)))
465 (let ((directory (first-file ".")))
466 (format (current-error-port)
467 "source is under '~a'~%" directory)
468 (chdir directory)
469
470 (and (every apply-patch '#$patches)
471 #$@(if snippet
472 #~((let ((module (make-fresh-user-module)))
473 (module-use-interfaces! module
474 (map resolve-interface
475 '#$modules))
476 ((@ (system base compile) compile)
477 '#$snippet
478 #:to 'value
479 #:opts %auto-compilation-options
480 #:env module)))
481 #~())
482
483 (begin (chdir "..") #t)
484 (zero? (system* (string-append #$tar "/bin/tar")
485 "cvfa" #$output directory)))))))
486
487 (let ((name (tarxz-name original-file-name))
488 (modules (delete-duplicates (cons '(guix build utils) modules))))
489 (gexp->derivation name build
490 #:graft? #f
491 #:system system
492 #:modules modules
493 #:guile-for-build guile-for-build))))
ac10e0e1 494
113aef68
LC
495(define (transitive-inputs inputs)
496 (let loop ((inputs inputs)
a3d73f59
LC
497 (result '()))
498 (match inputs
499 (()
500 (delete-duplicates (reverse result))) ; XXX: efficiency
501 (((and i (name (? package? p) sub ...)) rest ...)
502 (let ((t (map (match-lambda
503 ((dep-name derivation ...)
504 (cons (string-append name "/" dep-name)
505 derivation)))
506 (package-propagated-inputs p))))
507 (loop (append t rest)
508 (append t (cons i result)))))
509 ((input rest ...)
510 (loop rest (cons input result))))))
511
7d193ec3
EB
512(define (package-direct-inputs package)
513 "Return all the direct inputs of PACKAGE---i.e, its direct inputs along
514with their propagated inputs."
515 (append (package-native-inputs package)
516 (package-inputs package)
517 (package-propagated-inputs package)))
518
113aef68
LC
519(define (package-transitive-inputs package)
520 "Return the transitive inputs of PACKAGE---i.e., its direct inputs along
521with their propagated inputs, recursively."
7d193ec3 522 (transitive-inputs (package-direct-inputs package)))
113aef68 523
9c1edabd
LC
524(define (package-transitive-target-inputs package)
525 "Return the transitive target inputs of PACKAGE---i.e., its direct inputs
526along with their propagated inputs, recursively. This only includes inputs
527for the target system, and not native inputs."
528 (transitive-inputs (append (package-inputs package)
529 (package-propagated-inputs package))))
530
531(define (package-transitive-native-inputs package)
532 "Return the transitive native inputs of PACKAGE---i.e., its direct inputs
533along with their propagated inputs, recursively. This only includes inputs
534for the host system (\"native inputs\"), and not target inputs."
535 (transitive-inputs (package-native-inputs package)))
536
113aef68
LC
537(define (package-transitive-propagated-inputs package)
538 "Return the propagated inputs of PACKAGE, and their propagated inputs,
539recursively."
540 (transitive-inputs (package-propagated-inputs package)))
541
a193b824
MW
542(define-syntax define-memoized/v
543 (lambda (form)
544 "Define a memoized single-valued unary procedure with docstring.
545The procedure argument is compared to cached keys using `eqv?'."
546 (syntax-case form ()
547 ((_ (proc arg) docstring body body* ...)
548 (string? (syntax->datum #'docstring))
549 #'(define proc
550 (let ((cache (make-hash-table)))
551 (define (proc arg)
552 docstring
553 (match (hashv-get-handle cache arg)
554 ((_ . value)
555 value)
556 (_
557 (let ((result (let () body body* ...)))
558 (hashv-set! cache arg result)
559 result))))
560 proc))))))
c37a74bd 561
a193b824 562(define-memoized/v (package-transitive-supported-systems package)
7c3c0374
LC
563 "Return the intersection of the systems supported by PACKAGE and those
564supported by its dependencies."
a193b824
MW
565 (fold (lambda (input systems)
566 (match input
567 ((label (? package? p) . _)
568 (lset-intersection
569 string=? systems (package-transitive-supported-systems p)))
570 (_
571 systems)))
572 (package-supported-systems package)
573 (package-direct-inputs package)))
7c3c0374 574
0d5a559f
LC
575(define (bag-transitive-inputs bag)
576 "Same as 'package-transitive-inputs', but applied to a bag."
577 (transitive-inputs (append (bag-build-inputs bag)
578 (bag-host-inputs bag)
579 (bag-target-inputs bag))))
580
581(define (bag-transitive-build-inputs bag)
582 "Same as 'package-transitive-native-inputs', but applied to a bag."
583 (transitive-inputs (bag-build-inputs bag)))
584
585(define (bag-transitive-host-inputs bag)
586 "Same as 'package-transitive-target-inputs', but applied to a bag."
587 (transitive-inputs (bag-host-inputs bag)))
588
589(define (bag-transitive-target-inputs bag)
590 "Return the \"target inputs\" of BAG, recursively."
591 (transitive-inputs (bag-target-inputs bag)))
592
a2ebaddd
LC
593\f
594;;;
595;;; Package derivations.
596;;;
597
598(define %derivation-cache
599 ;; Package to derivation-path mapping.
e4588af9 600 (make-weak-key-hash-table 100))
a2ebaddd 601
e509d152
LC
602(define (cache package system thunk)
603 "Memoize the return values of THUNK as the derivation of PACKAGE on
604SYSTEM."
bce7526f
LC
605 ;; FIXME: This memoization should be associated with the open store, because
606 ;; otherwise it breaks when switching to a different store.
e509d152
LC
607 (let ((vals (call-with-values thunk list)))
608 ;; Use `hashq-set!' instead of `hash-set!' because `hash' returns the
609 ;; same value for all structs (as of Guile 2.0.6), and because pointer
610 ;; equality is sufficient in practice.
8dcec914
LC
611 (hashq-set! %derivation-cache package
612 `((,system ,@vals)
613 ,@(or (hashq-ref %derivation-cache package)
614 '())))
e509d152
LC
615 (apply values vals)))
616
617(define-syntax-rule (cached package system body ...)
618 "Memoize the result of BODY for the arguments PACKAGE and SYSTEM.
619Return the cached result when available."
8dcec914
LC
620 (let ((thunk (lambda () body ...))
621 (key system))
e509d152
LC
622 (match (hashq-ref %derivation-cache package)
623 ((alist (... ...))
8dcec914 624 (match (assoc-ref alist key)
e509d152
LC
625 ((vals (... ...))
626 (apply values vals))
627 (#f
8dcec914 628 (cache package key thunk))))
e509d152 629 (#f
8dcec914 630 (cache package key thunk)))))
a2ebaddd 631
a63062b5
LC
632(define* (expand-input store package input system #:optional cross-system)
633 "Expand INPUT, an input tuple, such that it contains only references to
634derivation paths or store paths. PACKAGE is only used to provide contextual
635information in exceptions."
592ef6c8
LC
636 (define (intern file)
637 ;; Add FILE to the store. Set the `recursive?' bit to #t, so that
638 ;; file permissions are preserved.
a9ebd9ef 639 (add-to-store store (basename file) #t "sha256" file))
592ef6c8 640
a63062b5
LC
641 (define derivation
642 (if cross-system
05962f29
LC
643 (cut package-cross-derivation store <> cross-system system
644 #:graft? #f)
645 (cut package-derivation store <> system #:graft? #f)))
a63062b5
LC
646
647 (match input
648 (((? string? name) (? package? package))
649 (list name (derivation package)))
650 (((? string? name) (? package? package)
651 (? string? sub-drv))
652 (list name (derivation package)
653 sub-drv))
654 (((? string? name)
655 (and (? string?) (? derivation-path?) drv))
656 (list name drv))
657 (((? string? name)
658 (and (? string?) (? file-exists? file)))
659 ;; Add FILE to the store. When FILE is in the sub-directory of a
660 ;; store path, it needs to be added anyway, so it can be used as a
661 ;; source.
662 (list name (intern file)))
663 (((? string? name) (? origin? source))
664 (list name (package-source-derivation store source system)))
665 (x
666 (raise (condition (&package-input-error
667 (package package)
668 (input x)))))))
592ef6c8 669
0d5a559f
LC
670(define* (package->bag package #:optional
671 (system (%current-system))
05962f29
LC
672 (target (%current-target-system))
673 #:key (graft? (%graft?)))
0d5a559f
LC
674 "Compile PACKAGE into a bag for SYSTEM, possibly cross-compiled to TARGET,
675and return it."
676 ;; Bind %CURRENT-SYSTEM and %CURRENT-TARGET-SYSTEM so that thunked field
677 ;; values can refer to it.
678 (parameterize ((%current-system system)
679 (%current-target-system target))
05962f29
LC
680 (match (if graft?
681 (or (package-replacement package) package)
682 package)
0d5a559f
LC
683 (($ <package> name version source build-system
684 args inputs propagated-inputs native-inputs self-native-input?
685 outputs)
05962f29 686 (or (make-bag build-system (string-append name "-" version)
d3d337d2 687 #:system system
0d5a559f
LC
688 #:target target
689 #:source source
690 #:inputs (append (inputs)
691 (propagated-inputs))
692 #:outputs outputs
693 #:native-inputs `(,@(if (and target self-native-input?)
694 `(("self" ,package))
695 '())
696 ,@(native-inputs))
697 #:arguments (args))
698 (raise (if target
699 (condition
700 (&package-cross-build-system-error
701 (package package)))
702 (condition
703 (&package-error
704 (package package))))))))))
705
05962f29
LC
706(define (input-graft store system)
707 "Return a procedure that, given an input referring to a package with a
708graft, returns a pair with the original derivation and the graft's derivation,
709and returns #f for other inputs."
710 (match-lambda
711 ((label (? package? package) sub-drv ...)
712 (let ((replacement (package-replacement package)))
713 (and replacement
714 (let ((orig (package-derivation store package system
715 #:graft? #f))
716 (new (package-derivation store replacement system)))
717 (graft
718 (origin orig)
719 (replacement new)
720 (origin-output (match sub-drv
721 (() "out")
722 ((output) output)))
723 (replacement-output origin-output))))))
724 (x
725 #f)))
726
727(define (input-cross-graft store target system)
728 "Same as 'input-graft', but for cross-compilation inputs."
729 (match-lambda
730 ((label (? package? package) sub-drv ...)
731 (let ((replacement (package-replacement package)))
732 (and replacement
733 (let ((orig (package-cross-derivation store package target system
734 #:graft? #f))
735 (new (package-cross-derivation store replacement
736 target system)))
737 (graft
738 (origin orig)
739 (replacement new)
740 (origin-output (match sub-drv
741 (() "out")
742 ((output) output)))
743 (replacement-output origin-output))))))
744 (_
745 #f)))
746
747(define* (bag-grafts store bag)
748 "Return the list of grafts applicable to BAG. Each graft is a <graft>
749record."
750 (let ((target (bag-target bag))
751 (system (bag-system bag)))
752 (define native-grafts
753 (filter-map (input-graft store system)
754 (append (bag-transitive-build-inputs bag)
755 (bag-transitive-target-inputs bag)
756 (if target
757 '()
758 (bag-transitive-host-inputs bag)))))
759
760 (define target-grafts
761 (if target
762 (filter-map (input-cross-graft store target system)
763 (bag-transitive-host-inputs bag))
764 '()))
765
766 (append native-grafts target-grafts)))
767
768(define* (package-grafts store package
769 #:optional (system (%current-system))
770 #:key target)
771 "Return the list of grafts applicable to PACKAGE as built for SYSTEM and
772TARGET."
773 (let* ((package (or (package-replacement package) package))
774 (bag (package->bag package system target)))
775 (bag-grafts store bag)))
776
d3d337d2
LC
777(define* (bag->derivation store bag
778 #:optional context)
779 "Return the derivation to build BAG for SYSTEM. Optionally, CONTEXT can be
780a package object describing the context in which the call occurs, for improved
781error reporting."
782 (if (bag-target bag)
783 (bag->cross-derivation store bag)
784 (let* ((system (bag-system bag))
785 (inputs (bag-transitive-inputs bag))
786 (input-drvs (map (cut expand-input store context <> system)
787 inputs))
788 (paths (delete-duplicates
789 (append-map (match-lambda
790 ((_ (? package? p) _ ...)
791 (package-native-search-paths
792 p))
793 (_ '()))
794 inputs))))
795
796 (apply (bag-build bag)
797 store (bag-name bag) input-drvs
798 #:search-paths paths
799 #:outputs (bag-outputs bag) #:system system
800 (bag-arguments bag)))))
801
802(define* (bag->cross-derivation store bag
803 #:optional context)
804 "Return the derivation to build BAG, which is actually a cross build.
805Optionally, CONTEXT can be a package object denoting the context of the call.
806This is an internal procedure."
807 (let* ((system (bag-system bag))
808 (target (bag-target bag))
809 (host (bag-transitive-host-inputs bag))
810 (host-drvs (map (cut expand-input store context <> system target)
811 host))
812 (target* (bag-transitive-target-inputs bag))
813 (target-drvs (map (cut expand-input store context <> system)
814 target*))
815 (build (bag-transitive-build-inputs bag))
816 (build-drvs (map (cut expand-input store context <> system)
817 build))
818 (all (append build target* host))
819 (paths (delete-duplicates
820 (append-map (match-lambda
821 ((_ (? package? p) _ ...)
822 (package-search-paths p))
823 (_ '()))
824 all)))
825 (npaths (delete-duplicates
826 (append-map (match-lambda
827 ((_ (? package? p) _ ...)
828 (package-native-search-paths
829 p))
830 (_ '()))
831 all))))
832
833 (apply (bag-build bag)
834 store (bag-name bag)
835 #:native-drvs build-drvs
836 #:target-drvs (append host-drvs target-drvs)
837 #:search-paths paths
838 #:native-search-paths npaths
839 #:outputs (bag-outputs bag)
840 #:system system #:target target
841 (bag-arguments bag))))
842
a63062b5 843(define* (package-derivation store package
05962f29
LC
844 #:optional (system (%current-system))
845 #:key (graft? (%graft?)))
59688fc4
LC
846 "Return the <derivation> object of PACKAGE for SYSTEM."
847
e509d152
LC
848 ;; Compute the derivation and cache the result. Caching is important
849 ;; because some derivations, such as the implicit inputs of the GNU build
850 ;; system, will be queried many, many times in a row.
05962f29
LC
851 (cached package (cons system graft?)
852 (let* ((bag (package->bag package system #f #:graft? graft?))
853 (drv (bag->derivation store bag package)))
854 (if graft?
855 (match (bag-grafts store bag)
856 (()
857 drv)
858 (grafts
859 (let ((guile (package-derivation store (default-guile)
860 system #:graft? #f)))
861 (graft-derivation store (bag-name bag) drv grafts
862 #:system system
863 #:guile guile))))
864 drv))))
e3ce5d70 865
9c1edabd 866(define* (package-cross-derivation store package target
05962f29
LC
867 #:optional (system (%current-system))
868 #:key (graft? (%graft?)))
9c1edabd
LC
869 "Cross-build PACKAGE for TARGET (a GNU triplet) from host SYSTEM (a Guix
870system identifying string)."
05962f29
LC
871 (cached package (list system target graft?)
872 (let* ((bag (package->bag package system target #:graft? graft?))
873 (drv (bag->derivation store bag package)))
874 (if graft?
875 (match (bag-grafts store bag)
876 (()
877 drv)
878 (grafts
879 (graft-derivation store (bag-name bag) drv grafts
880 #:system system
881 #:guile
882 (package-derivation store (default-guile)
883 system #:graft? #f))))
884 drv))))
d510ab46 885
de8bcdae
LC
886(define* (package-output store package
887 #:optional (output "out") (system (%current-system)))
d510ab46
LC
888 "Return the output path of PACKAGE's OUTPUT for SYSTEM---where OUTPUT is the
889symbolic output name, such as \"out\". Note that this procedure calls
890`package-derivation', which is costly."
59688fc4
LC
891 (let ((drv (package-derivation store package system)))
892 (derivation->output-path drv output)))
e87f0591
LC
893
894\f
895;;;
896;;; Monadic interface.
897;;;
898
899(define (set-guile-for-build guile)
900 "This monadic procedure changes the Guile currently used to run the build
901code of derivations to GUILE, a package object."
902 (lambda (store)
903 (let ((guile (package-derivation store guile)))
4e190c28 904 (values (%guile-for-build guile) store))))
e87f0591
LC
905
906(define* (package-file package
907 #:optional file
908 #:key
909 system (output "out") target)
910 "Return as a monadic value the absolute file name of FILE within the
911OUTPUT directory of PACKAGE. When FILE is omitted, return the name of the
912OUTPUT directory of PACKAGE. When TARGET is true, use it as a
913cross-compilation target triplet."
914 (lambda (store)
915 (define compute-derivation
916 (if target
917 (cut package-cross-derivation <> <> target <>)
918 package-derivation))
919
920 (let* ((system (or system (%current-system)))
921 (drv (compute-derivation store package system))
922 (out (derivation->output-path drv output)))
4e190c28
LC
923 (values (if file
924 (string-append out "/" file)
925 out)
926 store))))
e87f0591
LC
927
928(define package->derivation
929 (store-lift package-derivation))
930
931(define package->cross-derivation
932 (store-lift package-cross-derivation))
933
ff40e9b7
LC
934(define-gexp-compiler (package-compiler (package package?) system target)
935 ;; Compile PACKAGE to a derivation for SYSTEM, optionally cross-compiled for
936 ;; TARGET. This is used when referring to a package from within a gexp.
937 (if target
938 (package->cross-derivation package target system)
939 (package->derivation package system)))
940
f220a838
LC
941(define* (origin->derivation source
942 #:optional (system (%current-system)))
943 "When SOURCE is an <origin> object, return its derivation for SYSTEM. When
944SOURCE is a file name, return either the interned file name (if SOURCE is
945outside of the store) or SOURCE itself (if SOURCE is already a store item.)"
946 (match source
6b1f9721 947 (($ <origin> uri method sha256 name (= force ()) #f)
f220a838
LC
948 ;; No patches, no snippet: this is a fixed-output derivation.
949 (method uri 'sha256 sha256 name #:system system))
6b1f9721 950 (($ <origin> uri method sha256 name (= force (patches ...)) snippet
f220a838
LC
951 (flags ...) inputs (modules ...) (imported-modules ...)
952 guile-for-build)
953 ;; Patches and/or a snippet.
954 (mlet %store-monad ((source (method uri 'sha256 sha256 name
955 #:system system))
956 (guile (package->derivation (or guile-for-build
957 (default-guile))
958 system
959 #:graft? #f)))
cf87cc89
LC
960 (patch-and-repack source patches
961 #:inputs inputs
962 #:snippet snippet
963 #:flags flags
964 #:system system
965 #:modules modules
966 #:imported-modules modules
967 #:guile-for-build guile)))
f220a838
LC
968 ((and (? string?) (? direct-store-path?) file)
969 (with-monad %store-monad
970 (return file)))
971 ((? string? file)
972 (interned-file file (basename file)
973 #:recursive? #t))))
974
ff40e9b7
LC
975(define-gexp-compiler (origin-compiler (origin origin?) system target)
976 ;; Compile ORIGIN to a derivation for SYSTEM. This is used when referring
977 ;; to an origin from within a gexp.
978 (origin->derivation origin system))
979
f220a838
LC
980(define package-source-derivation
981 (store-lower origin->derivation))