tests: Add system installation test.
[jackhill/guix/guix.git] / gnu / packages.scm
CommitLineData
233e7676 1;;; GNU Guix --- Functional package management for GNU
7befee30 2;;; Copyright © 2012, 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
c2868b1e 3;;; Copyright © 2013 Mark H Weaver <mhw@netris.org>
7d193ec3 4;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
6caa4dfa 5;;; Copyright © 2016 Alex Kost <alezost@gmail.com>
fad155d4 6;;; Copyright © 2016 Mathieu Lirzin <mthl@gnu.org>
6b1891b0 7;;;
233e7676 8;;; This file is part of GNU Guix.
6b1891b0 9;;;
233e7676 10;;; GNU Guix is free software; you can redistribute it and/or modify it
6b1891b0
LC
11;;; under the terms of the GNU General Public License as published by
12;;; the Free Software Foundation; either version 3 of the License, or (at
13;;; your option) any later version.
14;;;
233e7676 15;;; GNU Guix is distributed in the hope that it will be useful, but
6b1891b0
LC
16;;; WITHOUT ANY WARRANTY; without even the implied warranty of
17;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;;; GNU General Public License for more details.
19;;;
20;;; You should have received a copy of the GNU General Public License
233e7676 21;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
6b1891b0 22
59a43334 23(define-module (gnu packages)
6b1891b0 24 #:use-module (guix packages)
98eb8cbe 25 #:use-module (guix ui)
800cdeef 26 #:use-module (guix utils)
958dd3ce 27 #:use-module (guix combinators)
95cd4971
LC
28 #:use-module ((guix build utils)
29 #:select ((package-name->name+version
30 . hyphen-separated-name->name+version)))
6b1891b0 31 #:use-module (ice-9 ftw)
c2868b1e 32 #:use-module (ice-9 vlist)
dc5669cd 33 #:use-module (ice-9 match)
6b1891b0 34 #:use-module (srfi srfi-1)
5e3b388b 35 #:use-module (srfi srfi-11)
6b1891b0 36 #:use-module (srfi srfi-26)
dbab5150
LC
37 #:use-module (srfi srfi-34)
38 #:use-module (srfi srfi-35)
800cdeef
LC
39 #:use-module (srfi srfi-39)
40 #:export (search-patch
25897079 41 search-patches
ac5aa288 42 search-bootstrap-binary
0492f4a2 43 %patch-path
0b3651bc 44 %bootstrap-binaries-path
c107b541 45 %package-module-path
7d193ec3 46
ba326ce4 47 fold-packages
7d193ec3 48
dc5669cd 49 find-packages-by-name
3f26bfc1 50 find-best-packages-by-name
7d193ec3
EB
51 find-newest-available-packages
52
84189ebc
LC
53 specification->package
54 specification->package+output))
6b1891b0
LC
55
56;;; Commentary:
57;;;
58;;; General utilities for the software distribution---i.e., the modules under
59a43334 59;;; (gnu packages ...).
6b1891b0
LC
60;;;
61;;; Code:
62
0b3651bc
LC
63;; By default, we store patches and bootstrap binaries alongside Guile
64;; modules. This is so that these extra files can be found without
65;; requiring a special setup, such as a specific installation directory
66;; and an extra environment variable. One advantage of this setup is
67;; that everything just works in an auto-compilation setting.
a9f60c42 68
a9f60c42 69(define %bootstrap-binaries-path
ac5aa288 70 (make-parameter
1ffa7090 71 (map (cut string-append <> "/gnu/packages/bootstrap")
0b3651bc 72 %load-path)))
ac5aa288 73
800cdeef 74(define (search-patch file-name)
dbab5150
LC
75 "Search the patch FILE-NAME. Raise an error if not found."
76 (or (search-path (%patch-path) file-name)
77 (raise (condition
78 (&message (message (format #f (_ "~a: patch not found")
79 file-name)))))))
800cdeef 80
25897079
AK
81(define-syntax-rule (search-patches file-name ...)
82 "Return the list of absolute file names corresponding to each
83FILE-NAME found in %PATCH-PATH."
84 (list (search-patch file-name) ...))
85
ac5aa288 86(define (search-bootstrap-binary file-name system)
dfba5489
LC
87 "Search the bootstrap binary FILE-NAME for SYSTEM. Raise an error if not
88found."
89 (or (search-path (%bootstrap-binaries-path)
90 (string-append system "/" file-name))
91 (raise (condition
92 (&message
93 (message
94 (format #f (_ "could not find bootstrap binary '~a' \
95for system '~a'")
96 file-name system)))))))
ac5aa288 97
84836a57
LC
98(define %distro-root-directory
99 ;; Absolute file name of the module hierarchy.
100 (dirname (search-path %load-path "guix.scm")))
6b1891b0 101
c107b541
LC
102(define %package-module-path
103 ;; Search path for package modules. Each item must be either a directory
104 ;; name or a pair whose car is a directory and whose cdr is a sub-directory
105 ;; to narrow the search.
8689901f
LC
106 (let* ((not-colon (char-set-complement (char-set #\:)))
107 (environment (string-tokenize (or (getenv "GUIX_PACKAGE_PATH") "")
108 not-colon)))
109 ;; Automatically add items from $GUIX_PACKAGE_PATH to Guile's search path.
110 (for-each (lambda (directory)
111 (set! %load-path (cons directory %load-path))
112 (set! %load-compiled-path
113 (cons directory %load-compiled-path)))
114 environment)
115
116 (make-parameter
117 (append environment `((,%distro-root-directory . "gnu/packages"))))))
c107b541 118
ee06af5b
LC
119(define %patch-path
120 ;; Define it after '%package-module-path' so that '%load-path' contains user
121 ;; directories, allowing patches in $GUIX_PACKAGE_PATH to be found.
122 (make-parameter
123 (map (lambda (directory)
124 (if (string=? directory %distro-root-directory)
125 (string-append directory "/gnu/packages/patches")
126 directory))
127 %load-path)))
128
84836a57 129(define* (scheme-files directory)
d95523fb
LC
130 "Return the list of Scheme files found under DIRECTORY, recursively. The
131returned list is sorted in alphabetical order."
132
133 ;; Sort entries so that 'fold-packages' works in a deterministic fashion
134 ;; regardless of details of the underlying file system.
135 (sort (file-system-fold (const #t) ; enter?
136 (lambda (path stat result) ; leaf
137 (if (string-suffix? ".scm" path)
138 (cons path result)
139 result))
140 (lambda (path stat result) ; down
141 result)
142 (lambda (path stat result) ; up
143 result)
144 (const #f) ; skip
145 (lambda (path stat errno result)
146 (warning (_ "cannot access `~a': ~a~%")
147 path (strerror errno))
148 result)
149 '()
150 directory
151 stat)
152 string<?))
6b1891b0 153
c107b541
LC
154(define file-name->module-name
155 (let ((not-slash (char-set-complement (char-set #\/))))
156 (lambda (file)
157 "Return the module name (a list of symbols) corresponding to FILE."
158 (map string->symbol
159 (string-tokenize (string-drop-right file 4) not-slash)))))
84836a57
LC
160
161(define* (package-modules directory #:optional sub-directory)
162 "Return the list of modules that provide packages for the distribution.
163Optionally, narrow the search to SUB-DIRECTORY."
164 (define prefix-len
165 (string-length directory))
166
167 (filter-map (lambda (file)
4ae7559f
LC
168 (let* ((file (substring file prefix-len))
169 (module (file-name->module-name file)))
170 (catch #t
171 (lambda ()
172 (resolve-interface module))
173 (lambda args
174 ;; Report the error, but keep going.
175 (warn-about-load-error module args)
176 #f))))
84836a57
LC
177 (scheme-files (if sub-directory
178 (string-append directory "/" sub-directory)
179 directory))))
6b1891b0 180
c107b541
LC
181(define* (all-package-modules #:optional (path (%package-module-path)))
182 "Return the list of package modules found in PATH, a list of directories to
183search."
184 (fold-right (lambda (spec result)
185 (match spec
186 ((? string? directory)
187 (append (package-modules directory) result))
188 ((directory . sub-directory)
189 (append (package-modules directory sub-directory)
190 result))))
191 '()
192 path))
193
ba326ce4
LC
194(define (fold-packages proc init)
195 "Call (PROC PACKAGE RESULT) for each available package, using INIT as
c2868b1e
MW
196the initial value of RESULT. It is guaranteed to never traverse the
197same package twice."
198 (identity ; discard second return value
199 (fold2 (lambda (module result seen)
200 (fold2 (lambda (var result seen)
201 (if (and (package? var)
202 (not (vhash-assq var seen)))
203 (values (proc var result)
204 (vhash-consq var #t seen))
205 (values result seen)))
206 result
207 seen
208 (module-map (lambda (sym var)
209 (false-if-exception (variable-ref var)))
210 module)))
211 init
212 vlist-null
c107b541 213 (all-package-modules))))
ba326ce4 214
9ffc1c00
LC
215(define find-packages-by-name
216 (let ((packages (delay
217 (fold-packages (lambda (p r)
218 (vhash-cons (package-name p) p r))
724311a2
LC
219 vlist-null)))
220 (version>? (lambda (p1 p2)
221 (version>? (package-version p1) (package-version p2)))))
9ffc1c00
LC
222 (lambda* (name #:optional version)
223 "Return the list of packages with the given NAME. If VERSION is not #f,
724311a2
LC
224then only return packages whose version is prefixed by VERSION, sorted in
225decreasing version order."
226 (let ((matching (sort (vhash-fold* cons '() name (force packages))
227 version>?)))
9ffc1c00
LC
228 (if version
229 (filter (lambda (package)
724311a2 230 (string-prefix? version (package-version package)))
9ffc1c00
LC
231 matching)
232 matching)))))
dc5669cd 233
3f26bfc1
LC
234(define find-newest-available-packages
235 (memoize
236 (lambda ()
237 "Return a vhash keyed by package names, and with
dc5669cd
MW
238associated values of the form
239
240 (newest-version newest-package ...)
241
242where the preferred package is listed first."
243
3f26bfc1
LC
244 ;; FIXME: Currently, the preferred package is whichever one
245 ;; was found last by 'fold-packages'. Find a better solution.
246 (fold-packages (lambda (p r)
247 (let ((name (package-name p))
248 (version (package-version p)))
249 (match (vhash-assoc name r)
250 ((_ newest-so-far . pkgs)
251 (case (version-compare version newest-so-far)
252 ((>) (vhash-cons name `(,version ,p) r))
253 ((=) (vhash-cons name `(,version ,p ,@pkgs) r))
254 ((<) r)))
255 (#f (vhash-cons name `(,version ,p) r)))))
256 vlist-null))))
257
258(define (find-best-packages-by-name name version)
259 "If version is #f, return the list of packages named NAME with the highest
260version numbers; otherwise, return the list of packages named NAME and at
261VERSION."
262 (if version
263 (find-packages-by-name name version)
264 (match (vhash-assoc name (find-newest-available-packages))
265 ((_ version pkgs ...) pkgs)
266 (#f '()))))
7d193ec3
EB
267
268\f
4ea44419
AK
269(define %sigint-prompt
270 ;; The prompt to jump to upon SIGINT.
271 (make-prompt-tag "interruptible"))
272
273(define (call-with-sigint-handler thunk handler)
274 "Call THUNK and return its value. Upon SIGINT, call HANDLER with the signal
275number in the context of the continuation of the call to this function, and
276return its return value."
277 (call-with-prompt %sigint-prompt
278 (lambda ()
279 (sigaction SIGINT
280 (lambda (signum)
281 (sigaction SIGINT SIG_DFL)
282 (abort-to-prompt %sigint-prompt signum)))
283 (dynamic-wind
284 (const #t)
285 thunk
286 (cut sigaction SIGINT SIG_DFL)))
287 (lambda (k signum)
288 (handler signum))))
289
fad155d4
ML
290\f
291;;;
292;;; Package specification.
293;;;
294
1b846da8 295(define* (%find-package spec name version #:key fallback?)
fad155d4
ML
296 (match (find-best-packages-by-name name version)
297 ((pkg . pkg*)
298 (unless (null? pkg*)
299 (warning (_ "ambiguous package specification `~a'~%") spec)
300 (warning (_ "choosing ~a from ~a~%")
301 (package-full-name pkg)
302 (location->string (package-location pkg))))
1b846da8 303 (when fallback?
7befee30
LC
304 (warning (_ "deprecated NAME-VERSION syntax; \
305use NAME@VERSION instead~%")))
fad155d4
ML
306 pkg)
307 (_
308 (if version
309 (leave (_ "~A: package not found for version ~a~%") name version)
efb107e0 310 (if (not fallback?)
1b846da8
ML
311 ;; XXX: Fallback to the older specification style with an hyphen
312 ;; between NAME and VERSION, for backward compatibility.
95cd4971
LC
313 (call-with-values
314 (lambda ()
315 (hyphen-separated-name->name+version name))
316 (cut %find-package spec <> <> #:fallback? #t))
efb107e0
LC
317
318 ;; The fallback case didn't find anything either, so bail out.
1b846da8 319 (leave (_ "~A: unknown package~%") name))))))
fad155d4 320
5e3b388b
CR
321(define (specification->package spec)
322 "Return a package matching SPEC. SPEC may be a package name, or a package
1b846da8 323name followed by an at-sign and a version number. If the version number is not
5e3b388b 324present, return the preferred newest version."
fad155d4
ML
325 (let-values (((name version) (package-name->name+version spec)))
326 (%find-package spec name version)))
84189ebc
LC
327
328(define* (specification->package+output spec #:optional (output "out"))
329 "Return the package and output specified by SPEC, or #f and #f; SPEC may
330optionally contain a version number and an output name, as in these examples:
331
332 guile
1b846da8 333 guile@2.0.9
84189ebc 334 guile:debug
1b846da8 335 guile@2.0.9:debug
84189ebc
LC
336
337If SPEC does not specify a version number, return the preferred newest
338version; if SPEC does not specify an output, return OUTPUT."
84189ebc
LC
339 (let-values (((name version sub-drv)
340 (package-specification->name+version+output spec output)))
fad155d4
ML
341 (match (%find-package spec name version)
342 (#f
343 (values #f #f))
344 (package
345 (if (member sub-drv (package-outputs package))
346 (values package sub-drv)
347 (leave (_ "package `~a' lacks output `~a'~%")
348 (package-full-name package)
349 sub-drv))))))