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