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