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