packages: Re-export `%current-target-system'.
[jackhill/guix/guix.git] / guix / packages.scm
CommitLineData
233e7676 1;;; GNU Guix --- Functional package management for GNU
aba326f7 2;;; Copyright © 2012, 2013 Ludovic Courtès <ludo@gnu.org>
e3ce5d70 3;;;
233e7676 4;;; This file is part of GNU Guix.
e3ce5d70 5;;;
233e7676 6;;; GNU Guix is free software; you can redistribute it and/or modify it
e3ce5d70
LC
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
233e7676 11;;; GNU Guix is distributed in the hope that it will be useful, but
e3ce5d70
LC
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
233e7676 17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
e3ce5d70
LC
18
19(define-module (guix packages)
20 #:use-module (guix utils)
c0cd1b3e 21 #:use-module (guix records)
e3ce5d70 22 #:use-module (guix store)
ddc29a78 23 #:use-module (guix base32)
d510ab46 24 #:use-module (guix derivations)
e3ce5d70
LC
25 #:use-module (guix build-system)
26 #:use-module (ice-9 match)
062c6927 27 #:use-module (srfi srfi-1)
946b72c9 28 #:use-module (srfi srfi-9 gnu)
d510ab46 29 #:use-module (srfi srfi-11)
a63062b5 30 #:use-module (srfi srfi-26)
d36622dc
LC
31 #:use-module (srfi srfi-34)
32 #:use-module (srfi srfi-35)
cd52703a
LC
33 #:re-export (%current-system
34 %current-target-system)
ff352cfb 35 #:export (origin
90c68be8
LC
36 origin?
37 origin-uri
38 origin-method
39 origin-sha256
40 origin-file-name
e4c245f8 41 base32
e3ce5d70 42
a18eda27
LC
43 <search-path-specification>
44 search-path-specification
45 search-path-specification?
46 search-path-specification->sexp
47
e3ce5d70
LC
48 package
49 package?
50 package-name
51 package-version
2847050a 52 package-full-name
e3ce5d70
LC
53 package-source
54 package-build-system
55 package-arguments
56 package-inputs
57 package-native-inputs
062c6927 58 package-propagated-inputs
e3ce5d70 59 package-outputs
a18eda27 60 package-native-search-paths
e3ce5d70 61 package-search-paths
d45122f5 62 package-synopsis
e3ce5d70 63 package-description
e3ce5d70 64 package-license
52bda18a 65 package-home-page
e3ce5d70
LC
66 package-platforms
67 package-maintainers
062c6927 68 package-properties
35f3c5f5 69 package-location
d66c7096 70 package-field-location
e3ce5d70 71
a3d73f59 72 package-transitive-inputs
9c1edabd
LC
73 package-transitive-target-inputs
74 package-transitive-native-inputs
113aef68 75 package-transitive-propagated-inputs
e3ce5d70
LC
76 package-source-derivation
77 package-derivation
d36622dc 78 package-cross-derivation
d510ab46 79 package-output
d36622dc
LC
80
81 &package-error
07783858 82 package-error?
d36622dc
LC
83 package-error-package
84 &package-input-error
07783858 85 package-input-error?
d36622dc 86 package-error-invalid-input))
e3ce5d70
LC
87
88;;; Commentary:
89;;;
90;;; This module provides a high-level mechanism to define packages in a
91;;; Guix-based distribution.
92;;;
93;;; Code:
94
90c68be8
LC
95;; The source of a package, such as a tarball URL and fetcher---called
96;; "origin" to avoid name clash with `package-source', `source', etc.
97(define-record-type* <origin>
98 origin make-origin
99 origin?
100 (uri origin-uri) ; string
101 (method origin-method) ; symbol
102 (sha256 origin-sha256) ; bytevector
103 (file-name origin-file-name (default #f))) ; optional file name
e3ce5d70 104
e4c245f8
LC
105(define-syntax base32
106 (lambda (s)
107 "Return the bytevector corresponding to the given Nix-base32
108representation."
109 (syntax-case s ()
110 ((_ str)
111 (string? (syntax->datum #'str))
aba326f7 112 ;; A literal string: do the conversion at expansion time.
e4c245f8
LC
113 (with-syntax ((bv (nix-base32-string->bytevector
114 (syntax->datum #'str))))
aba326f7
LC
115 #''bv))
116 ((_ str)
117 #'(nix-base32-string->bytevector str)))))
e4c245f8 118
a18eda27
LC
119;; The specification of a search path.
120(define-record-type* <search-path-specification>
121 search-path-specification make-search-path-specification
122 search-path-specification?
123 (variable search-path-specification-variable)
124 (directories search-path-specification-directories)
125 (separator search-path-specification-separator (default ":")))
126
127(define (search-path-specification->sexp spec)
128 "Return an sexp representing SPEC, a <search-path-specification>. The sexp
129corresponds to the arguments expected by `set-path-environment-variable'."
130 (match spec
131 (($ <search-path-specification> variable directories separator)
132 `(,variable ,directories ,separator))))
d36622dc 133
a18eda27 134;; A package.
e3ce5d70
LC
135(define-record-type* <package>
136 package make-package
137 package?
138 (name package-name) ; string
139 (version package-version) ; string
90c68be8 140 (source package-source) ; <origin> instance
e3ce5d70 141 (build-system package-build-system) ; build system
64fddd74 142 (arguments package-arguments ; arguments for the build method
21c203a5 143 (default '()) (thunked))
062c6927 144
e3ce5d70 145 (inputs package-inputs ; input packages or derivations
dd6b9a37 146 (default '()) (thunked))
062c6927
LC
147 (propagated-inputs package-propagated-inputs ; same, but propagated
148 (default '()))
e3ce5d70
LC
149 (native-inputs package-native-inputs ; native input packages/derivations
150 (default '()))
c9d01150
LC
151 (self-native-input? package-self-native-input? ; whether to use itself as
152 ; a native input when cross-
153 (default #f)) ; compiling
062c6927 154
e3ce5d70
LC
155 (outputs package-outputs ; list of strings
156 (default '("out")))
a18eda27
LC
157
158 ; lists of
159 ; <search-path-specification>,
160 ; for native and cross
161 ; inputs
162 (native-search-paths package-native-search-paths (default '()))
163 (search-paths package-search-paths (default '()))
e3ce5d70 164
d45122f5
LC
165 (synopsis package-synopsis) ; one-line description
166 (description package-description) ; one or two paragraphs
1fb78cb2 167 (license package-license)
45753b65 168 (home-page package-home-page)
e3ce5d70 169 (platforms package-platforms (default '()))
35f3c5f5 170 (maintainers package-maintainers (default '()))
45753b65 171
062c6927
LC
172 (properties package-properties (default '())) ; alist for anything else
173
35f3c5f5
LC
174 (location package-location
175 (default (and=> (current-source-location)
176 source-properties->location))))
e3ce5d70 177
946b72c9
LC
178(set-record-type-printer! <package>
179 (lambda (package port)
180 (let ((loc (package-location package))
181 (format simple-format))
182 (format port "#<package ~a-~a ~a:~a ~a>"
183 (package-name package)
184 (package-version package)
185 (location-file loc)
186 (location-line loc)
187 (number->string (object-address
188 package)
189 16)))))
190
d66c7096 191(define (package-field-location package field)
f903dc05
LC
192 "Return the source code location of the definition of FIELD for PACKAGE, or
193#f if it could not be determined."
194 (define (goto port line column)
195 (unless (and (= (port-column port) (- column 1))
196 (= (port-line port) (- line 1)))
197 (unless (eof-object? (read-char port))
198 (goto port line column))))
d66c7096
LC
199
200 (match (package-location package)
201 (($ <location> file line column)
202 (catch 'system
203 (lambda ()
204 (call-with-input-file (search-path %load-path file)
205 (lambda (port)
f903dc05
LC
206 (goto port line column)
207 (match (read port)
208 (('package inits ...)
209 (let ((field (assoc field inits)))
210 (match field
211 ((_ value)
8e77f41e
LC
212 ;; Put the `or' here, and not in the first argument of
213 ;; `and=>', to work around a compiler bug in 2.0.5.
214 (or (and=> (source-properties value)
215 source-properties->location)
216 (and=> (source-properties field)
217 source-properties->location)))
f903dc05
LC
218 (_
219 #f))))
220 (_
221 #f)))))
d66c7096 222 (lambda _
f903dc05 223 #f)))
d66c7096
LC
224 (_ #f)))
225
d36622dc
LC
226
227;; Error conditions.
228
229(define-condition-type &package-error &error
230 package-error?
231 (package package-error-package))
232
233(define-condition-type &package-input-error &package-error
234 package-input-error?
235 (input package-error-invalid-input))
236
237
2847050a
LC
238(define (package-full-name package)
239 "Return the full name of PACKAGE--i.e., `NAME-VERSION'."
240 (string-append (package-name package) "-" (package-version package)))
241
b642e4b8
LC
242(define* (package-source-derivation store source
243 #:optional (system (%current-system)))
244 "Return the derivation path for SOURCE, a package source, for SYSTEM."
e3ce5d70 245 (match source
90c68be8 246 (($ <origin> uri method sha256 name)
b642e4b8
LC
247 (method store uri 'sha256 sha256 name
248 #:system system))))
e3ce5d70 249
113aef68
LC
250(define (transitive-inputs inputs)
251 (let loop ((inputs inputs)
a3d73f59
LC
252 (result '()))
253 (match inputs
254 (()
255 (delete-duplicates (reverse result))) ; XXX: efficiency
256 (((and i (name (? package? p) sub ...)) rest ...)
257 (let ((t (map (match-lambda
258 ((dep-name derivation ...)
259 (cons (string-append name "/" dep-name)
260 derivation)))
261 (package-propagated-inputs p))))
262 (loop (append t rest)
263 (append t (cons i result)))))
264 ((input rest ...)
265 (loop rest (cons input result))))))
266
113aef68
LC
267(define (package-transitive-inputs package)
268 "Return the transitive inputs of PACKAGE---i.e., its direct inputs along
269with their propagated inputs, recursively."
270 (transitive-inputs (append (package-native-inputs package)
271 (package-inputs package)
272 (package-propagated-inputs package))))
273
9c1edabd
LC
274(define (package-transitive-target-inputs package)
275 "Return the transitive target inputs of PACKAGE---i.e., its direct inputs
276along with their propagated inputs, recursively. This only includes inputs
277for the target system, and not native inputs."
278 (transitive-inputs (append (package-inputs package)
279 (package-propagated-inputs package))))
280
281(define (package-transitive-native-inputs package)
282 "Return the transitive native inputs of PACKAGE---i.e., its direct inputs
283along with their propagated inputs, recursively. This only includes inputs
284for the host system (\"native inputs\"), and not target inputs."
285 (transitive-inputs (package-native-inputs package)))
286
113aef68
LC
287(define (package-transitive-propagated-inputs package)
288 "Return the propagated inputs of PACKAGE, and their propagated inputs,
289recursively."
290 (transitive-inputs (package-propagated-inputs package)))
291
a2ebaddd
LC
292\f
293;;;
294;;; Package derivations.
295;;;
296
297(define %derivation-cache
298 ;; Package to derivation-path mapping.
e4588af9 299 (make-weak-key-hash-table 100))
a2ebaddd 300
e509d152
LC
301(define (cache package system thunk)
302 "Memoize the return values of THUNK as the derivation of PACKAGE on
303SYSTEM."
304 (let ((vals (call-with-values thunk list)))
305 ;; Use `hashq-set!' instead of `hash-set!' because `hash' returns the
306 ;; same value for all structs (as of Guile 2.0.6), and because pointer
307 ;; equality is sufficient in practice.
308 (hashq-set! %derivation-cache package `((,system ,@vals)))
309 (apply values vals)))
310
311(define-syntax-rule (cached package system body ...)
312 "Memoize the result of BODY for the arguments PACKAGE and SYSTEM.
313Return the cached result when available."
314 (let ((thunk (lambda () body ...)))
315 (match (hashq-ref %derivation-cache package)
316 ((alist (... ...))
317 (match (assoc-ref alist system)
318 ((vals (... ...))
319 (apply values vals))
320 (#f
321 (cache package system thunk))))
322 (#f
323 (cache package system thunk)))))
a2ebaddd 324
a63062b5
LC
325(define* (expand-input store package input system #:optional cross-system)
326 "Expand INPUT, an input tuple, such that it contains only references to
327derivation paths or store paths. PACKAGE is only used to provide contextual
328information in exceptions."
592ef6c8
LC
329 (define (intern file)
330 ;; Add FILE to the store. Set the `recursive?' bit to #t, so that
331 ;; file permissions are preserved.
a9ebd9ef 332 (add-to-store store (basename file) #t "sha256" file))
592ef6c8 333
a63062b5
LC
334 (define derivation
335 (if cross-system
336 (cut package-cross-derivation store <> cross-system system)
337 (cut package-derivation store <> system)))
338
339 (match input
340 (((? string? name) (? package? package))
341 (list name (derivation package)))
342 (((? string? name) (? package? package)
343 (? string? sub-drv))
344 (list name (derivation package)
345 sub-drv))
346 (((? string? name)
347 (and (? string?) (? derivation-path?) drv))
348 (list name drv))
349 (((? string? name)
350 (and (? string?) (? file-exists? file)))
351 ;; Add FILE to the store. When FILE is in the sub-directory of a
352 ;; store path, it needs to be added anyway, so it can be used as a
353 ;; source.
354 (list name (intern file)))
355 (((? string? name) (? origin? source))
356 (list name (package-source-derivation store source system)))
357 (x
358 (raise (condition (&package-input-error
359 (package package)
360 (input x)))))))
592ef6c8 361
a63062b5
LC
362(define* (package-derivation store package
363 #:optional (system (%current-system)))
364 "Return the derivation path and corresponding <derivation> object of
365PACKAGE for SYSTEM."
e509d152
LC
366 ;; Compute the derivation and cache the result. Caching is important
367 ;; because some derivations, such as the implicit inputs of the GNU build
368 ;; system, will be queried many, many times in a row.
369 (cached package system
21c203a5
LC
370
371 ;; Bind %CURRENT-SYSTEM so that thunked field values can refer
372 ;; to it.
9c1edabd
LC
373 (parameterize ((%current-system system)
374 (%current-target-system #f))
21c203a5
LC
375 (match package
376 (($ <package> name version source (= build-system-builder builder)
377 args inputs propagated-inputs native-inputs self-native-input?
378 outputs)
a18eda27 379 (let* ((inputs (package-transitive-inputs package))
a63062b5
LC
380 (input-drvs (map (cut expand-input
381 store package <> system)
382 inputs))
a18eda27
LC
383 (paths (delete-duplicates
384 (append-map (match-lambda
385 ((_ (? package? p) _ ...)
386 (package-native-search-paths
387 p))
388 (_ '()))
389 inputs))))
21c203a5
LC
390
391 (apply builder
392 store (package-full-name package)
393 (and source
394 (package-source-derivation store source system))
a18eda27
LC
395 input-drvs
396 #:search-paths paths
21c203a5
LC
397 #:outputs outputs #:system system
398 (args))))))))
e3ce5d70 399
9c1edabd 400(define* (package-cross-derivation store package target
a63062b5 401 #:optional (system (%current-system)))
9c1edabd
LC
402 "Cross-build PACKAGE for TARGET (a GNU triplet) from host SYSTEM (a Guix
403system identifying string)."
404 (cached package (cons system target)
405
406 ;; Bind %CURRENT-SYSTEM so that thunked field values can refer
407 ;; to it.
408 (parameterize ((%current-system system)
409 (%current-target-system target))
410 (match package
411 (($ <package> name version source
412 (= build-system-cross-builder builder)
413 args inputs propagated-inputs native-inputs self-native-input?
414 outputs)
415 (let* ((inputs (package-transitive-target-inputs package))
416 (input-drvs (map (cut expand-input
417 store package <>
418 system target)
419 inputs))
420 (host (append (if self-native-input?
421 `(("self" ,package))
422 '())
423 (package-transitive-native-inputs package)))
424 (host-drvs (map (cut expand-input
425 store package <> system)
426 host))
427 (all (append host inputs))
428 (paths (delete-duplicates
429 (append-map (match-lambda
430 ((_ (? package? p) _ ...)
431 (package-search-paths p))
432 (_ '()))
433 all)))
434 (npaths (delete-duplicates
435 (append-map (match-lambda
436 ((_ (? package? p) _ ...)
437 (package-native-search-paths
438 p))
439 (_ '()))
440 all))))
441
442 (apply builder
443 store (package-full-name package) target
444 (and source
445 (package-source-derivation store source system))
446 input-drvs host-drvs
447 #:search-paths paths
448 #:native-search-paths npaths
449 #:outputs outputs #:system system
450 (args))))))))
d510ab46
LC
451
452(define* (package-output store package output
453 #:optional (system (%current-system)))
454 "Return the output path of PACKAGE's OUTPUT for SYSTEM---where OUTPUT is the
455symbolic output name, such as \"out\". Note that this procedure calls
456`package-derivation', which is costly."
457 (let-values (((_ drv)
458 (package-derivation store package system)))
459 (derivation-output-path
460 (assoc-ref (derivation-outputs drv) output))))