Move base32 code to (guix base32).
[jackhill/guix/guix.git] / guix / packages.scm
CommitLineData
e3ce5d70
LC
1;;; Guix --- Nix package management from Guile. -*- coding: utf-8 -*-
2;;; Copyright (C) 2012 Ludovic Courtès <ludo@gnu.org>
3;;;
4;;; This file is part of Guix.
5;;;
6;;; Guix is free software; you can redistribute it and/or modify it
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;;;
11;;; Guix is distributed in the hope that it will be useful, but
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
17;;; along with Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(define-module (guix packages)
20 #:use-module (guix utils)
21 #:use-module (guix store)
ddc29a78 22 #:use-module (guix base32)
e3ce5d70
LC
23 #:use-module (guix build-system)
24 #:use-module (ice-9 match)
062c6927 25 #:use-module (srfi srfi-1)
946b72c9 26 #:use-module (srfi srfi-9 gnu)
d36622dc
LC
27 #:use-module (srfi srfi-34)
28 #:use-module (srfi srfi-35)
ff352cfb 29 #:export (origin
90c68be8
LC
30 origin?
31 origin-uri
32 origin-method
33 origin-sha256
34 origin-file-name
e4c245f8 35 base32
e3ce5d70
LC
36
37 package
38 package?
39 package-name
40 package-version
2847050a 41 package-full-name
e3ce5d70
LC
42 package-source
43 package-build-system
44 package-arguments
45 package-inputs
46 package-native-inputs
062c6927 47 package-propagated-inputs
e3ce5d70
LC
48 package-outputs
49 package-search-paths
d45122f5 50 package-synopsis
e3ce5d70 51 package-description
e3ce5d70
LC
52 package-license
53 package-platforms
54 package-maintainers
062c6927 55 package-properties
35f3c5f5 56 package-location
e3ce5d70 57
a3d73f59 58 package-transitive-inputs
113aef68 59 package-transitive-propagated-inputs
e3ce5d70
LC
60 package-source-derivation
61 package-derivation
d36622dc
LC
62 package-cross-derivation
63
64 &package-error
07783858 65 package-error?
d36622dc
LC
66 package-error-package
67 &package-input-error
07783858 68 package-input-error?
d36622dc 69 package-error-invalid-input))
e3ce5d70
LC
70
71;;; Commentary:
72;;;
73;;; This module provides a high-level mechanism to define packages in a
74;;; Guix-based distribution.
75;;;
76;;; Code:
77
90c68be8
LC
78;; The source of a package, such as a tarball URL and fetcher---called
79;; "origin" to avoid name clash with `package-source', `source', etc.
80(define-record-type* <origin>
81 origin make-origin
82 origin?
83 (uri origin-uri) ; string
84 (method origin-method) ; symbol
85 (sha256 origin-sha256) ; bytevector
86 (file-name origin-file-name (default #f))) ; optional file name
e3ce5d70 87
e4c245f8
LC
88(define-syntax base32
89 (lambda (s)
90 "Return the bytevector corresponding to the given Nix-base32
91representation."
92 (syntax-case s ()
93 ((_ str)
94 (string? (syntax->datum #'str))
95 (with-syntax ((bv (nix-base32-string->bytevector
96 (syntax->datum #'str))))
97 #''bv)))))
98
35f3c5f5 99;; A package.
d36622dc 100
e3ce5d70
LC
101(define-record-type* <package>
102 package make-package
103 package?
104 (name package-name) ; string
105 (version package-version) ; string
90c68be8 106 (source package-source) ; <origin> instance
e3ce5d70 107 (build-system package-build-system) ; build system
64fddd74
LC
108 (arguments package-arguments ; arguments for the build method
109 (default '()))
062c6927 110
e3ce5d70
LC
111 (inputs package-inputs ; input packages or derivations
112 (default '()))
062c6927
LC
113 (propagated-inputs package-propagated-inputs ; same, but propagated
114 (default '()))
e3ce5d70
LC
115 (native-inputs package-native-inputs ; native input packages/derivations
116 (default '()))
c9d01150
LC
117 (self-native-input? package-self-native-input? ; whether to use itself as
118 ; a native input when cross-
119 (default #f)) ; compiling
062c6927 120
e3ce5d70
LC
121 (outputs package-outputs ; list of strings
122 (default '("out")))
123 (search-paths package-search-paths ; list of (ENV-VAR (DIRS ...))
124 (default '())) ; tuples; see
125 ; `set-path-environment-variable'
126 ; (aka. "setup-hook")
127
d45122f5
LC
128 (synopsis package-synopsis) ; one-line description
129 (description package-description) ; one or two paragraphs
e3ce5d70 130 (license package-license (default '()))
45753b65 131 (home-page package-home-page)
e3ce5d70 132 (platforms package-platforms (default '()))
35f3c5f5 133 (maintainers package-maintainers (default '()))
45753b65 134
062c6927
LC
135 (properties package-properties (default '())) ; alist for anything else
136
35f3c5f5
LC
137 (location package-location
138 (default (and=> (current-source-location)
139 source-properties->location))))
e3ce5d70 140
946b72c9
LC
141(set-record-type-printer! <package>
142 (lambda (package port)
143 (let ((loc (package-location package))
144 (format simple-format))
145 (format port "#<package ~a-~a ~a:~a ~a>"
146 (package-name package)
147 (package-version package)
148 (location-file loc)
149 (location-line loc)
150 (number->string (object-address
151 package)
152 16)))))
153
d36622dc
LC
154
155;; Error conditions.
156
157(define-condition-type &package-error &error
158 package-error?
159 (package package-error-package))
160
161(define-condition-type &package-input-error &package-error
162 package-input-error?
163 (input package-error-invalid-input))
164
165
2847050a
LC
166(define (package-full-name package)
167 "Return the full name of PACKAGE--i.e., `NAME-VERSION'."
168 (string-append (package-name package) "-" (package-version package)))
169
b642e4b8
LC
170(define* (package-source-derivation store source
171 #:optional (system (%current-system)))
172 "Return the derivation path for SOURCE, a package source, for SYSTEM."
e3ce5d70 173 (match source
90c68be8 174 (($ <origin> uri method sha256 name)
b642e4b8
LC
175 (method store uri 'sha256 sha256 name
176 #:system system))))
e3ce5d70 177
113aef68
LC
178(define (transitive-inputs inputs)
179 (let loop ((inputs inputs)
a3d73f59
LC
180 (result '()))
181 (match inputs
182 (()
183 (delete-duplicates (reverse result))) ; XXX: efficiency
184 (((and i (name (? package? p) sub ...)) rest ...)
185 (let ((t (map (match-lambda
186 ((dep-name derivation ...)
187 (cons (string-append name "/" dep-name)
188 derivation)))
189 (package-propagated-inputs p))))
190 (loop (append t rest)
191 (append t (cons i result)))))
192 ((input rest ...)
193 (loop rest (cons input result))))))
194
113aef68
LC
195(define (package-transitive-inputs package)
196 "Return the transitive inputs of PACKAGE---i.e., its direct inputs along
197with their propagated inputs, recursively."
198 (transitive-inputs (append (package-native-inputs package)
199 (package-inputs package)
200 (package-propagated-inputs package))))
201
202(define (package-transitive-propagated-inputs package)
203 "Return the propagated inputs of PACKAGE, and their propagated inputs,
204recursively."
205 (transitive-inputs (package-propagated-inputs package)))
206
a2ebaddd
LC
207\f
208;;;
209;;; Package derivations.
210;;;
211
212(define %derivation-cache
213 ;; Package to derivation-path mapping.
e4588af9 214 (make-weak-key-hash-table 100))
a2ebaddd
LC
215
216(define (cache package system drv)
217 "Memoize DRV as the derivation of PACKAGE on SYSTEM."
e4588af9
LC
218
219 ;; Use `hashq-set!' instead of `hash-set!' because `hash' returns the
220 ;; same value for all structs (as of Guile 2.0.6), and because pointer
221 ;; equality is sufficient in practice.
222 (hashq-set! %derivation-cache package `((,system . ,drv)))
a2ebaddd
LC
223 drv)
224
225(define (cached-derivation package system)
226 "Return the cached derivation path of PACKAGE for SYSTEM, or #f."
e4588af9
LC
227 (match (hashq-ref %derivation-cache package)
228 ((alist ...)
229 (assoc-ref alist system))
230 (#f #f)))
a2ebaddd 231
e3ce5d70
LC
232(define* (package-derivation store package
233 #:optional (system (%current-system)))
234 "Return the derivation of PACKAGE for SYSTEM."
592ef6c8
LC
235 (define (intern file)
236 ;; Add FILE to the store. Set the `recursive?' bit to #t, so that
237 ;; file permissions are preserved.
238 (add-to-store store (basename file)
239 #t #t "sha256" file))
240
241 (define expand-input
242 ;; Expand the given input tuple such that it contains only
243 ;; references to derivation paths or store paths.
244 (match-lambda
245 (((? string? name) (? package? package))
b642e4b8 246 (list name (package-derivation store package system)))
592ef6c8
LC
247 (((? string? name) (? package? package)
248 (? string? sub-drv))
b642e4b8 249 (list name (package-derivation store package system)
592ef6c8
LC
250 sub-drv))
251 (((? string? name)
252 (and (? string?) (? derivation-path?) drv))
253 (list name drv))
254 (((? string? name)
255 (and (? string?) (? file-exists? file)))
256 ;; Add FILE to the store. When FILE is in the sub-directory of a
257 ;; store path, it needs to be added anyway, so it can be used as a
258 ;; source.
259 (list name (intern file)))
260 (((? string? name) (? origin? source))
b642e4b8 261 (list name (package-source-derivation store source system)))
592ef6c8
LC
262 ((and i ((? string? name) (? procedure? proc) sub-drv ...))
263 ;; This form allows PROC to make a SYSTEM-dependent choice.
264
265 ;; XXX: Currently PROC must return a .drv, a store path, a local
266 ;; file name, or an <origin>. If it were allowed to return a
267 ;; package, then `transitive-inputs' and co. would need to be
268 ;; adjusted.
269 (let ((input (proc system)))
270 (if (or (string? input) (origin? input))
271 (expand-input (cons* name input sub-drv))
272 (raise (condition (&package-input-error
273 (package package)
274 (input i)))))))
275 (x
276 (raise (condition (&package-input-error
277 (package package)
278 (input x)))))))
279
a2ebaddd 280 (or (cached-derivation package system)
ead1f108
LC
281
282 ;; Compute the derivation and cache the result. Caching is
283 ;; important because some derivations, such as the implicit inputs
284 ;; of the GNU build system, will be queried many, many times in a
285 ;; row.
286 (cache
287 package system
288 (match package
289 (($ <package> name version source (= build-system-builder builder)
290 args inputs propagated-inputs native-inputs self-native-input?
291 outputs)
292 ;; TODO: For `search-paths', add a builder prologue that calls
293 ;; `set-path-environment-variable'.
592ef6c8 294 (let ((inputs (map expand-input
ead1f108
LC
295 (package-transitive-inputs package))))
296
297 (apply builder
298 store (package-full-name package)
b642e4b8
LC
299 (and source
300 (package-source-derivation store source system))
ead1f108
LC
301 inputs
302 #:outputs outputs #:system system
303 (if (procedure? args)
304 (args system)
305 args))))))))
e3ce5d70
LC
306
307(define* (package-cross-derivation store package)
308 ;; TODO
309 #f)