guix: refresh: Add --list-dependent option.
[jackhill/guix/guix.git] / guix / packages.scm
CommitLineData
233e7676 1;;; GNU Guix --- Functional package management for GNU
9b5b5c17 2;;; Copyright © 2012, 2013, 2014 Ludovic Courtès <ludo@gnu.org>
e3ce5d70 3;;;
233e7676 4;;; This file is part of GNU Guix.
e3ce5d70 5;;;
233e7676 6;;; GNU Guix is free software; you can redistribute it and/or modify it
e3ce5d70
LC
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
233e7676 11;;; GNU Guix is distributed in the hope that it will be useful, but
e3ce5d70
LC
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
233e7676 17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
e3ce5d70
LC
18
19(define-module (guix packages)
20 #:use-module (guix utils)
c0cd1b3e 21 #:use-module (guix records)
e3ce5d70 22 #:use-module (guix store)
ddc29a78 23 #:use-module (guix base32)
d510ab46 24 #:use-module (guix derivations)
e3ce5d70
LC
25 #:use-module (guix build-system)
26 #:use-module (ice-9 match)
062c6927 27 #:use-module (srfi srfi-1)
946b72c9 28 #:use-module (srfi srfi-9 gnu)
a63062b5 29 #:use-module (srfi srfi-26)
d36622dc
LC
30 #:use-module (srfi srfi-34)
31 #:use-module (srfi srfi-35)
cd52703a
LC
32 #:re-export (%current-system
33 %current-target-system)
ff352cfb 34 #:export (origin
90c68be8
LC
35 origin?
36 origin-uri
37 origin-method
38 origin-sha256
39 origin-file-name
ac10e0e1
LC
40 origin-patches
41 origin-patch-flags
42 origin-patch-inputs
43 origin-patch-guile
f9cc8971
LC
44 origin-snippet
45 origin-modules
46 origin-imported-modules
e4c245f8 47 base32
e3ce5d70 48
a18eda27
LC
49 <search-path-specification>
50 search-path-specification
51 search-path-specification?
52 search-path-specification->sexp
53
e3ce5d70
LC
54 package
55 package?
56 package-name
57 package-version
2847050a 58 package-full-name
e3ce5d70
LC
59 package-source
60 package-build-system
61 package-arguments
62 package-inputs
63 package-native-inputs
062c6927 64 package-propagated-inputs
e3ce5d70 65 package-outputs
a18eda27 66 package-native-search-paths
e3ce5d70 67 package-search-paths
d45122f5 68 package-synopsis
e3ce5d70 69 package-description
e3ce5d70 70 package-license
52bda18a 71 package-home-page
e3ce5d70
LC
72 package-platforms
73 package-maintainers
062c6927 74 package-properties
35f3c5f5 75 package-location
d66c7096 76 package-field-location
e3ce5d70 77
7d193ec3 78 package-direct-inputs
a3d73f59 79 package-transitive-inputs
9c1edabd
LC
80 package-transitive-target-inputs
81 package-transitive-native-inputs
113aef68 82 package-transitive-propagated-inputs
e3ce5d70
LC
83 package-source-derivation
84 package-derivation
d36622dc 85 package-cross-derivation
d510ab46 86 package-output
d36622dc
LC
87
88 &package-error
07783858 89 package-error?
d36622dc
LC
90 package-error-package
91 &package-input-error
07783858 92 package-input-error?
9b222abe
LC
93 package-error-invalid-input
94 &package-cross-build-system-error
95 package-cross-build-system-error?))
e3ce5d70
LC
96
97;;; Commentary:
98;;;
99;;; This module provides a high-level mechanism to define packages in a
100;;; Guix-based distribution.
101;;;
102;;; Code:
103
90c68be8
LC
104;; The source of a package, such as a tarball URL and fetcher---called
105;; "origin" to avoid name clash with `package-source', `source', etc.
106(define-record-type* <origin>
107 origin make-origin
108 origin?
109 (uri origin-uri) ; string
9b5b5c17 110 (method origin-method) ; procedure
90c68be8 111 (sha256 origin-sha256) ; bytevector
ac10e0e1
LC
112 (file-name origin-file-name (default #f)) ; optional file name
113 (patches origin-patches (default '())) ; list of file names
f9cc8971 114 (snippet origin-snippet (default #f)) ; sexp or #f
ac10e0e1
LC
115 (patch-flags origin-patch-flags ; list of strings
116 (default '("-p1")))
1d9bc459
LC
117
118 ;; Patching requires Guile, GNU Patch, and a few more. These two fields are
119 ;; used to specify these dependencies when needed.
ac10e0e1
LC
120 (patch-inputs origin-patch-inputs ; input list or #f
121 (default #f))
f9cc8971
LC
122 (modules origin-modules ; list of module names
123 (default '()))
124 (imported-modules origin-imported-modules ; list of module names
125 (default '()))
1d9bc459 126 (patch-guile origin-patch-guile ; package or #f
ac10e0e1 127 (default #f)))
e3ce5d70 128
f1096964
LC
129(define (print-origin origin port)
130 "Write a concise representation of ORIGIN to PORT."
131 (match origin
132 (($ <origin> uri method sha256 file-name patches)
133 (simple-format port "#<origin ~s ~a ~s ~a>"
134 uri (bytevector->base32-string sha256)
135 patches
136 (number->string (object-address origin) 16)))))
137
138(set-record-type-printer! <origin> print-origin)
139
e4c245f8
LC
140(define-syntax base32
141 (lambda (s)
142 "Return the bytevector corresponding to the given Nix-base32
143representation."
144 (syntax-case s ()
145 ((_ str)
146 (string? (syntax->datum #'str))
aba326f7 147 ;; A literal string: do the conversion at expansion time.
e4c245f8
LC
148 (with-syntax ((bv (nix-base32-string->bytevector
149 (syntax->datum #'str))))
aba326f7
LC
150 #''bv))
151 ((_ str)
152 #'(nix-base32-string->bytevector str)))))
e4c245f8 153
a18eda27
LC
154;; The specification of a search path.
155(define-record-type* <search-path-specification>
156 search-path-specification make-search-path-specification
157 search-path-specification?
158 (variable search-path-specification-variable)
159 (directories search-path-specification-directories)
160 (separator search-path-specification-separator (default ":")))
161
162(define (search-path-specification->sexp spec)
163 "Return an sexp representing SPEC, a <search-path-specification>. The sexp
164corresponds to the arguments expected by `set-path-environment-variable'."
165 (match spec
166 (($ <search-path-specification> variable directories separator)
167 `(,variable ,directories ,separator))))
d36622dc 168
a18eda27 169;; A package.
e3ce5d70
LC
170(define-record-type* <package>
171 package make-package
172 package?
173 (name package-name) ; string
174 (version package-version) ; string
90c68be8 175 (source package-source) ; <origin> instance
e3ce5d70 176 (build-system package-build-system) ; build system
64fddd74 177 (arguments package-arguments ; arguments for the build method
21c203a5 178 (default '()) (thunked))
062c6927 179
e3ce5d70 180 (inputs package-inputs ; input packages or derivations
dd6b9a37 181 (default '()) (thunked))
062c6927 182 (propagated-inputs package-propagated-inputs ; same, but propagated
9d97a1b3 183 (default '()) (thunked))
e3ce5d70 184 (native-inputs package-native-inputs ; native input packages/derivations
a7dc055b 185 (default '()) (thunked))
c9d01150
LC
186 (self-native-input? package-self-native-input? ; whether to use itself as
187 ; a native input when cross-
188 (default #f)) ; compiling
062c6927 189
e3ce5d70
LC
190 (outputs package-outputs ; list of strings
191 (default '("out")))
a18eda27
LC
192
193 ; lists of
194 ; <search-path-specification>,
195 ; for native and cross
196 ; inputs
197 (native-search-paths package-native-search-paths (default '()))
198 (search-paths package-search-paths (default '()))
e3ce5d70 199
d45122f5
LC
200 (synopsis package-synopsis) ; one-line description
201 (description package-description) ; one or two paragraphs
1fb78cb2 202 (license package-license)
45753b65 203 (home-page package-home-page)
e3ce5d70 204 (platforms package-platforms (default '()))
35f3c5f5 205 (maintainers package-maintainers (default '()))
45753b65 206
062c6927
LC
207 (properties package-properties (default '())) ; alist for anything else
208
35f3c5f5
LC
209 (location package-location
210 (default (and=> (current-source-location)
211 source-properties->location))))
e3ce5d70 212
946b72c9
LC
213(set-record-type-printer! <package>
214 (lambda (package port)
215 (let ((loc (package-location package))
216 (format simple-format))
217 (format port "#<package ~a-~a ~a:~a ~a>"
218 (package-name package)
219 (package-version package)
220 (location-file loc)
221 (location-line loc)
222 (number->string (object-address
223 package)
224 16)))))
225
d66c7096 226(define (package-field-location package field)
f903dc05
LC
227 "Return the source code location of the definition of FIELD for PACKAGE, or
228#f if it could not be determined."
229 (define (goto port line column)
230 (unless (and (= (port-column port) (- column 1))
231 (= (port-line port) (- line 1)))
232 (unless (eof-object? (read-char port))
233 (goto port line column))))
d66c7096
LC
234
235 (match (package-location package)
236 (($ <location> file line column)
237 (catch 'system
238 (lambda ()
0b8749b7
LC
239 ;; In general we want to keep relative file names for modules.
240 (with-fluids ((%file-port-name-canonicalization 'relative))
241 (call-with-input-file (search-path %load-path file)
242 (lambda (port)
243 (goto port line column)
244 (match (read port)
245 (('package inits ...)
246 (let ((field (assoc field inits)))
247 (match field
248 ((_ value)
249 ;; Put the `or' here, and not in the first argument of
250 ;; `and=>', to work around a compiler bug in 2.0.5.
251 (or (and=> (source-properties value)
252 source-properties->location)
253 (and=> (source-properties field)
254 source-properties->location)))
255 (_
256 #f))))
257 (_
258 #f))))))
d66c7096 259 (lambda _
f903dc05 260 #f)))
d66c7096
LC
261 (_ #f)))
262
d36622dc
LC
263
264;; Error conditions.
265
266(define-condition-type &package-error &error
267 package-error?
268 (package package-error-package))
269
270(define-condition-type &package-input-error &package-error
271 package-input-error?
272 (input package-error-invalid-input))
273
9b222abe
LC
274(define-condition-type &package-cross-build-system-error &package-error
275 package-cross-build-system-error?)
276
d36622dc 277
2847050a
LC
278(define (package-full-name package)
279 "Return the full name of PACKAGE--i.e., `NAME-VERSION'."
280 (string-append (package-name package) "-" (package-version package)))
281
ac10e0e1
LC
282(define (%standard-patch-inputs)
283 (let ((ref (lambda (module var)
284 (module-ref (resolve-interface module) var))))
285 `(("tar" ,(ref '(gnu packages base) 'tar))
286 ("xz" ,(ref '(gnu packages compression) 'xz))
287 ("bzip2" ,(ref '(gnu packages compression) 'bzip2))
288 ("gzip" ,(ref '(gnu packages compression) 'gzip))
289 ("lzip" ,(ref '(gnu packages compression) 'lzip))
290 ("patch" ,(ref '(gnu packages base) 'patch)))))
291
1d9bc459
LC
292(define (default-guile)
293 "Return the default Guile package for SYSTEM."
294 (let ((distro (resolve-interface '(gnu packages base))))
295 (module-ref distro 'guile-final)))
ac10e0e1 296
f9cc8971 297(define* (patch-and-repack store source patches
ac10e0e1 298 #:key
f9cc8971
LC
299 (inputs '())
300 (snippet #f)
ac10e0e1 301 (flags '("-p1"))
f9cc8971
LC
302 (modules '())
303 (imported-modules '())
ac10e0e1
LC
304 (guile-for-build (%guile-for-build))
305 (system (%current-system)))
f9cc8971
LC
306 "Unpack SOURCE (a derivation or store path), apply all of PATCHES, and
307repack the tarball using the tools listed in INPUTS. When SNIPPET is true,
308it must be an s-expression that will run from within the directory where
309SOURCE was unpacked, after all of PATCHES have been applied. MODULES and
310IMPORTED-MODULES specify modules to use/import for use by SNIPPET."
311 (define source-file-name
312 ;; SOURCE is usually a derivation, but it could be a store file.
313 (if (derivation? source)
314 (derivation->output-path source)
315 source))
316
ac10e0e1 317 (define decompression-type
f9cc8971
LC
318 (cond ((string-suffix? "gz" source-file-name) "gzip")
319 ((string-suffix? "bz2" source-file-name) "bzip2")
320 ((string-suffix? "lz" source-file-name) "lzip")
321 (else "xz")))
ac10e0e1
LC
322
323 (define original-file-name
f9cc8971
LC
324 ;; Remove the store prefix plus the slash, hash, and hyphen.
325 (let* ((sans (string-drop source-file-name
326 (+ (string-length (%store-prefix)) 1)))
327 (dash (string-index sans #\-)))
328 (string-drop sans (+ 1 dash))))
ac10e0e1 329
3ca00bb5
LC
330 (define (numeric-extension? file-name)
331 ;; Return true if FILE-NAME ends with digits.
857ecb3d
LC
332 (and=> (file-extension file-name)
333 (cut string-every char-set:hex-digit <>)))
3ca00bb5
LC
334
335 (define (tarxz-name file-name)
336 ;; Return a '.tar.xz' file name based on FILE-NAME.
337 (let ((base (if (numeric-extension? file-name)
338 original-file-name
339 (file-sans-extension file-name))))
340 (string-append base
341 (if (equal? (file-extension base) "tar")
342 ".xz"
343 ".tar.xz"))))
344
ac10e0e1
LC
345 (define patch-inputs
346 (map (lambda (number patch)
347 (list (string-append "patch" (number->string number))
348 (add-to-store store (basename patch) #t
349 "sha256" patch)))
350 (iota (length patches))
351
352 patches))
353
354 (define builder
355 `(begin
356 (use-modules (ice-9 ftw)
3ca00bb5
LC
357 (srfi srfi-1)
358 (guix build utils))
ac10e0e1
LC
359
360 (let ((out (assoc-ref %outputs "out"))
361 (xz (assoc-ref %build-inputs "xz"))
362 (decomp (assoc-ref %build-inputs ,decompression-type))
363 (source (assoc-ref %build-inputs "source"))
364 (tar (string-append (assoc-ref %build-inputs "tar")
365 "/bin/tar"))
366 (patch (string-append (assoc-ref %build-inputs "patch")
367 "/bin/patch")))
368 (define (apply-patch input)
369 (let ((patch* (assoc-ref %build-inputs input)))
370 (format (current-error-port) "applying '~a'...~%" patch*)
371 (zero? (system* patch "--batch" ,@flags "--input" patch*))))
372
3ca00bb5
LC
373 (define (first-file directory)
374 ;; Return the name of the first file in DIRECTORY.
375 (car (scandir directory
376 (lambda (name)
377 (not (member name '("." "..")))))))
378
ac10e0e1
LC
379 (setenv "PATH" (string-append xz "/bin" ":"
380 decomp "/bin"))
3ca00bb5
LC
381
382 ;; SOURCE may be either a directory or a tarball.
383 (and (if (file-is-directory? source)
8be3b8a3 384 (let* ((store (or (getenv "NIX_STORE") "/gnu/store"))
3ca00bb5
LC
385 (len (+ 1 (string-length store)))
386 (base (string-drop source len))
387 (dash (string-index base #\-))
388 (directory (string-drop base (+ 1 dash))))
389 (mkdir directory)
390 (copy-recursively source directory)
391 #t)
392 (zero? (system* tar "xvf" source)))
393 (let ((directory (first-file ".")))
ac10e0e1
LC
394 (format (current-error-port)
395 "source is under '~a'~%" directory)
396 (chdir directory)
f9cc8971 397
ac10e0e1 398 (and (every apply-patch ',(map car patch-inputs))
f9cc8971
LC
399
400 ,@(if snippet
401 `((let ((module (make-fresh-user-module)))
402 (module-use-interfaces! module
403 (map resolve-interface
404 ',modules))
405 (module-define! module '%build-inputs
406 %build-inputs)
407 (module-define! module '%outputs %outputs)
408 ((@ (system base compile) compile)
409 ',snippet
410 #:to 'value
411 #:opts %auto-compilation-options
412 #:env module)))
413 '())
414
ac10e0e1
LC
415 (begin (chdir "..") #t)
416 (zero? (system* tar "cvfa" out directory))))))))
417
418
3ca00bb5
LC
419 (let ((name (tarxz-name original-file-name))
420 (inputs (filter-map (match-lambda
421 ((name (? package? p))
422 (and (member name (cons decompression-type
423 '("tar" "xz" "patch")))
424 (list name
425 (package-derivation store p
426 system)))))
427 (or inputs (%standard-patch-inputs))))
428 (modules (delete-duplicates (cons '(guix build utils) modules))))
ac10e0e1 429
3ca00bb5 430 (build-expression->derivation store name builder
dd1a5a15
LC
431 #:inputs `(("source" ,source)
432 ,@inputs
433 ,@patch-inputs)
434 #:system system
3ca00bb5 435 #:modules modules
ac10e0e1
LC
436 #:guile-for-build guile-for-build)))
437
b642e4b8
LC
438(define* (package-source-derivation store source
439 #:optional (system (%current-system)))
440 "Return the derivation path for SOURCE, a package source, for SYSTEM."
e3ce5d70 441 (match source
f9cc8971
LC
442 (($ <origin> uri method sha256 name () #f)
443 ;; No patches, no snippet: this is a fixed-output derivation.
b642e4b8 444 (method store uri 'sha256 sha256 name
7357138b 445 #:system system))
f9cc8971
LC
446 (($ <origin> uri method sha256 name (patches ...) snippet
447 (flags ...) inputs (modules ...) (imported-modules ...)
448 guile-for-build)
449 ;; Patches and/or a snippet.
ac10e0e1 450 (let ((source (method store uri 'sha256 sha256 name
1d9bc459
LC
451 #:system system))
452 (guile (match (or guile-for-build (%guile-for-build)
453 (default-guile))
454 ((? package? p)
455 (package-derivation store p system))
456 ((? derivation? drv)
457 drv))))
f9cc8971
LC
458 (patch-and-repack store source patches
459 #:inputs inputs
460 #:snippet snippet
ac10e0e1
LC
461 #:flags flags
462 #:system system
f9cc8971
LC
463 #:modules modules
464 #:imported-modules modules
1d9bc459 465 #:guile-for-build guile)))
f80594cc 466 ((and (? string?) (? direct-store-path?) file)
7357138b
LC
467 file)
468 ((? string? file)
469 (add-to-store store (basename file) #t "sha256" file))))
e3ce5d70 470
113aef68
LC
471(define (transitive-inputs inputs)
472 (let loop ((inputs inputs)
a3d73f59
LC
473 (result '()))
474 (match inputs
475 (()
476 (delete-duplicates (reverse result))) ; XXX: efficiency
477 (((and i (name (? package? p) sub ...)) rest ...)
478 (let ((t (map (match-lambda
479 ((dep-name derivation ...)
480 (cons (string-append name "/" dep-name)
481 derivation)))
482 (package-propagated-inputs p))))
483 (loop (append t rest)
484 (append t (cons i result)))))
485 ((input rest ...)
486 (loop rest (cons input result))))))
487
7d193ec3
EB
488(define (package-direct-inputs package)
489 "Return all the direct inputs of PACKAGE---i.e, its direct inputs along
490with their propagated inputs."
491 (append (package-native-inputs package)
492 (package-inputs package)
493 (package-propagated-inputs package)))
494
113aef68
LC
495(define (package-transitive-inputs package)
496 "Return the transitive inputs of PACKAGE---i.e., its direct inputs along
497with their propagated inputs, recursively."
7d193ec3 498 (transitive-inputs (package-direct-inputs package)))
113aef68 499
9c1edabd
LC
500(define (package-transitive-target-inputs package)
501 "Return the transitive target inputs of PACKAGE---i.e., its direct inputs
502along with their propagated inputs, recursively. This only includes inputs
503for the target system, and not native inputs."
504 (transitive-inputs (append (package-inputs package)
505 (package-propagated-inputs package))))
506
507(define (package-transitive-native-inputs package)
508 "Return the transitive native inputs of PACKAGE---i.e., its direct inputs
509along with their propagated inputs, recursively. This only includes inputs
510for the host system (\"native inputs\"), and not target inputs."
511 (transitive-inputs (package-native-inputs package)))
512
113aef68
LC
513(define (package-transitive-propagated-inputs package)
514 "Return the propagated inputs of PACKAGE, and their propagated inputs,
515recursively."
516 (transitive-inputs (package-propagated-inputs package)))
517
a2ebaddd
LC
518\f
519;;;
520;;; Package derivations.
521;;;
522
523(define %derivation-cache
524 ;; Package to derivation-path mapping.
e4588af9 525 (make-weak-key-hash-table 100))
a2ebaddd 526
e509d152
LC
527(define (cache package system thunk)
528 "Memoize the return values of THUNK as the derivation of PACKAGE on
529SYSTEM."
530 (let ((vals (call-with-values thunk list)))
531 ;; Use `hashq-set!' instead of `hash-set!' because `hash' returns the
532 ;; same value for all structs (as of Guile 2.0.6), and because pointer
533 ;; equality is sufficient in practice.
534 (hashq-set! %derivation-cache package `((,system ,@vals)))
535 (apply values vals)))
536
537(define-syntax-rule (cached package system body ...)
538 "Memoize the result of BODY for the arguments PACKAGE and SYSTEM.
539Return the cached result when available."
540 (let ((thunk (lambda () body ...)))
541 (match (hashq-ref %derivation-cache package)
542 ((alist (... ...))
543 (match (assoc-ref alist system)
544 ((vals (... ...))
545 (apply values vals))
546 (#f
547 (cache package system thunk))))
548 (#f
549 (cache package system thunk)))))
a2ebaddd 550
a63062b5
LC
551(define* (expand-input store package input system #:optional cross-system)
552 "Expand INPUT, an input tuple, such that it contains only references to
553derivation paths or store paths. PACKAGE is only used to provide contextual
554information in exceptions."
592ef6c8
LC
555 (define (intern file)
556 ;; Add FILE to the store. Set the `recursive?' bit to #t, so that
557 ;; file permissions are preserved.
a9ebd9ef 558 (add-to-store store (basename file) #t "sha256" file))
592ef6c8 559
a63062b5
LC
560 (define derivation
561 (if cross-system
562 (cut package-cross-derivation store <> cross-system system)
563 (cut package-derivation store <> system)))
564
565 (match input
566 (((? string? name) (? package? package))
567 (list name (derivation package)))
568 (((? string? name) (? package? package)
569 (? string? sub-drv))
570 (list name (derivation package)
571 sub-drv))
572 (((? string? name)
573 (and (? string?) (? derivation-path?) drv))
574 (list name drv))
575 (((? string? name)
576 (and (? string?) (? file-exists? file)))
577 ;; Add FILE to the store. When FILE is in the sub-directory of a
578 ;; store path, it needs to be added anyway, so it can be used as a
579 ;; source.
580 (list name (intern file)))
581 (((? string? name) (? origin? source))
582 (list name (package-source-derivation store source system)))
583 (x
584 (raise (condition (&package-input-error
585 (package package)
586 (input x)))))))
592ef6c8 587
a63062b5
LC
588(define* (package-derivation store package
589 #:optional (system (%current-system)))
59688fc4
LC
590 "Return the <derivation> object of PACKAGE for SYSTEM."
591
e509d152
LC
592 ;; Compute the derivation and cache the result. Caching is important
593 ;; because some derivations, such as the implicit inputs of the GNU build
594 ;; system, will be queried many, many times in a row.
595 (cached package system
21c203a5
LC
596
597 ;; Bind %CURRENT-SYSTEM so that thunked field values can refer
598 ;; to it.
9c1edabd
LC
599 (parameterize ((%current-system system)
600 (%current-target-system #f))
21c203a5
LC
601 (match package
602 (($ <package> name version source (= build-system-builder builder)
603 args inputs propagated-inputs native-inputs self-native-input?
604 outputs)
a18eda27 605 (let* ((inputs (package-transitive-inputs package))
a63062b5
LC
606 (input-drvs (map (cut expand-input
607 store package <> system)
608 inputs))
a18eda27
LC
609 (paths (delete-duplicates
610 (append-map (match-lambda
611 ((_ (? package? p) _ ...)
612 (package-native-search-paths
613 p))
614 (_ '()))
615 inputs))))
21c203a5
LC
616
617 (apply builder
618 store (package-full-name package)
619 (and source
620 (package-source-derivation store source system))
a18eda27
LC
621 input-drvs
622 #:search-paths paths
21c203a5
LC
623 #:outputs outputs #:system system
624 (args))))))))
e3ce5d70 625
9c1edabd 626(define* (package-cross-derivation store package target
a63062b5 627 #:optional (system (%current-system)))
9c1edabd
LC
628 "Cross-build PACKAGE for TARGET (a GNU triplet) from host SYSTEM (a Guix
629system identifying string)."
630 (cached package (cons system target)
631
632 ;; Bind %CURRENT-SYSTEM so that thunked field values can refer
633 ;; to it.
634 (parameterize ((%current-system system)
635 (%current-target-system target))
636 (match package
637 (($ <package> name version source
638 (= build-system-cross-builder builder)
639 args inputs propagated-inputs native-inputs self-native-input?
640 outputs)
9b222abe
LC
641 (unless builder
642 (raise (condition
643 (&package-cross-build-system-error
644 (package package)))))
645
9c1edabd
LC
646 (let* ((inputs (package-transitive-target-inputs package))
647 (input-drvs (map (cut expand-input
648 store package <>
649 system target)
650 inputs))
651 (host (append (if self-native-input?
652 `(("self" ,package))
653 '())
654 (package-transitive-native-inputs package)))
655 (host-drvs (map (cut expand-input
656 store package <> system)
657 host))
658 (all (append host inputs))
659 (paths (delete-duplicates
660 (append-map (match-lambda
661 ((_ (? package? p) _ ...)
662 (package-search-paths p))
663 (_ '()))
664 all)))
665 (npaths (delete-duplicates
666 (append-map (match-lambda
667 ((_ (? package? p) _ ...)
668 (package-native-search-paths
669 p))
670 (_ '()))
671 all))))
672
673 (apply builder
674 store (package-full-name package) target
675 (and source
676 (package-source-derivation store source system))
677 input-drvs host-drvs
678 #:search-paths paths
679 #:native-search-paths npaths
680 #:outputs outputs #:system system
681 (args))))))))
d510ab46 682
de8bcdae
LC
683(define* (package-output store package
684 #:optional (output "out") (system (%current-system)))
d510ab46
LC
685 "Return the output path of PACKAGE's OUTPUT for SYSTEM---where OUTPUT is the
686symbolic output name, such as \"out\". Note that this procedure calls
687`package-derivation', which is costly."
59688fc4
LC
688 (let ((drv (package-derivation store package system)))
689 (derivation->output-path drv output)))