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