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