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