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