1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2016, 2017 Andy Patterson <ajpatter@uwaterloo.ca>
4 ;;; This file is part of GNU Guix.
6 ;;; GNU 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.
11 ;;; GNU 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.
16 ;;; You should have received a copy of the GNU General Public License
17 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
19 (define-module (guix build-system asdf)
20 #:use-module (guix store)
21 #:use-module (guix utils)
22 #:use-module (guix memoization)
23 #:use-module (guix packages)
24 #:use-module (guix derivations)
25 #:use-module (guix search-paths)
26 #:use-module ((guix build utils)
27 #:select ((package-name->name+version
28 . hyphen-separated-name->name+version)))
29 #:use-module (guix build-system)
30 #:use-module (guix build-system gnu)
31 #:use-module (ice-9 match)
32 #:use-module (ice-9 regex)
33 #:use-module (srfi srfi-1)
34 #:use-module (srfi srfi-26)
35 #:export (%asdf-build-system-modules
38 asdf-build-system/sbcl
40 asdf-build-system/source
41 sbcl-package->cl-source-package
42 sbcl-package->ecl-package))
46 ;; Standard build procedure for asdf packages. This is implemented as an
47 ;; extension of 'gnu-build-system'.
51 (define %asdf-build-system-modules
52 ;; Imported build-side modules
53 `((guix build asdf-build-system)
54 (guix build lisp-utils)
55 ,@%gnu-build-system-modules))
57 (define %asdf-build-modules
58 ;; Used (visible) build-side modules
59 '((guix build asdf-build-system)
61 (guix build lisp-utils)))
63 (define (default-lisp implementation)
64 "Return the default package for the lisp IMPLEMENTATION."
65 ;; Lazily resolve the binding to avoid a circular dependency.
66 (let ((lisp-module (resolve-interface '(gnu packages lisp))))
67 (module-ref lisp-module implementation)))
69 (define* (lower/source name
70 #:key source inputs outputs native-inputs system target
73 "Return a bag for NAME"
74 (define private-keywords
75 '(#:target #:inputs #:native-inputs))
81 (host-inputs `(,@(if source
85 ,@(standard-packages)))
86 (build-inputs native-inputs)
88 (build asdf-build/source)
89 (arguments (strip-keyword-arguments private-keywords arguments)))))
91 (define* (asdf-build/source store name inputs
93 (phases '(@ (guix build asdf-build-system)
94 %standard-phases/source))
96 (system (%current-system))
98 (imported-modules %asdf-build-system-modules)
99 (modules %asdf-build-modules))
102 (use-modules ,@modules)
103 (asdf-build/source #:name ,name
104 #:source ,(match (assoc-ref inputs "source")
105 (((? derivation? source))
106 (derivation->output-path source))
112 #:search-paths ',(map search-path-specification->sexp
114 #:inputs %build-inputs)))
116 (define guile-for-build
119 (package-derivation store guile system #:graft? #f))
121 (let* ((distro (resolve-interface '(gnu packages commencement)))
122 (guile (module-ref distro 'guile-final)))
123 (package-derivation store guile system #:graft? #f)))))
125 (build-expression->derivation store name builder
128 #:modules imported-modules
130 #:guile-for-build guile-for-build))
132 (define* (package-with-build-system from-build-system to-build-system
133 from-prefix to-prefix
134 #:key variant-property
136 "Return a precedure which takes a package PKG which uses FROM-BUILD-SYSTEM,
137 and returns one using TO-BUILD-SYSTEM. If PKG was prefixed by FROM-PREFIX,
138 the resulting package will be prefixed by TO-PREFIX. Inputs of PKG are
139 recursively transformed using the same rule. The result's #:phases argument
140 will be modified by PHASES-TRANSFORMER, an S-expression which evaluates on the
141 build side to a procedure of one argument.
143 VARIANT-PROPERTY can be added to a package's properties to indicate that the
144 corresponding package promise should be used as the result of this
145 transformation. This allows the result to differ from what the transformation
146 would otherwise produce.
148 If TO-BUILD-SYSTEM is asdf-build-system/source, the resulting package will be
149 set up using CL source package conventions."
150 (define target-is-source? (eq? asdf-build-system/source to-build-system))
152 (define (transform-package-name name)
153 (if (string-prefix? from-prefix name)
154 (let ((new-name (string-drop name (string-length from-prefix))))
155 (if (string-prefix? to-prefix new-name)
157 (string-append to-prefix new-name)))
160 (define (has-from-build-system? pkg)
161 (eq? from-build-system (package-build-system pkg)))
167 ((name content . rest)
168 (let* ((is-package? (package? content))
169 (new-content (if is-package? (transform content) content)))
170 `(,name ,new-content ,@rest)))))
172 ;; Special considerations for source packages: CL inputs become
173 ;; propagated, and un-handled arguments are removed.
175 (define (new-propagated-inputs)
176 (if target-is-source?
179 (filter (match-lambda
181 (has-from-build-system? input)))
182 (append (package-inputs pkg)
183 ;; The native inputs might be needed just
184 ;; to load the system.
185 (package-native-inputs pkg)))
186 (package-propagated-inputs pkg)))
188 (map rewrite (package-propagated-inputs pkg))))
190 (define (new-inputs inputs-getter)
191 (if target-is-source?
193 (filter (match-lambda
195 (not (has-from-build-system? input))))
196 (inputs-getter pkg)))
197 (map rewrite (inputs-getter pkg))))
199 (define base-arguments
200 (if target-is-source?
201 (strip-keyword-arguments
202 '(#:tests? #:asd-file #:lisp #:asd-system-name #:test-asd-file)
203 (package-arguments pkg))
204 (package-arguments pkg)))
207 ((and variant-property
208 (assoc-ref (package-properties pkg) variant-property))
211 ((has-from-build-system? pkg)
214 (location (package-location pkg))
215 (name (transform-package-name (package-name pkg)))
216 (build-system to-build-system)
218 (substitute-keyword-arguments base-arguments
219 ((#:phases phases) (list phases-transformer phases))))
220 (inputs (new-inputs package-inputs))
221 (propagated-inputs (new-propagated-inputs))
222 (native-inputs (new-inputs package-native-inputs))
223 (outputs (if target-is-source?
225 (package-outputs pkg)))))
230 (define (strip-variant-as-necessary variant pkg)
231 (define properties (package-properties pkg))
232 (if (assoc variant properties)
235 (properties (alist-delete variant properties)))
238 (define (lower lisp-type)
240 #:key source inputs outputs native-inputs system target
241 (lisp (default-lisp (string->symbol lisp-type)))
244 "Return a bag for NAME"
245 (define private-keywords
246 '(#:target #:inputs #:native-inputs #:lisp))
252 (host-inputs `(,@(if source
253 `(("source" ,source))
256 ,@(standard-packages)))
257 (build-inputs `((,lisp-type ,lisp)
260 (build (asdf-build lisp-type))
261 (arguments (strip-keyword-arguments private-keywords arguments))))))
263 (define (asdf-build lisp-type)
264 (lambda* (store name inputs
270 (phases '(@ (guix build asdf-build-system)
273 (system (%current-system))
275 (imported-modules %asdf-build-system-modules)
276 (modules %asdf-build-modules))
281 ;; NAME is the value returned from `package-full-name'.
282 (hyphen-separated-name->name+version name)
283 (1+ (string-length lisp-type))))) ; drop the "<lisp>-" prefix.
287 (use-modules ,@modules)
288 (parameterize ((%lisp (string-append
289 (assoc-ref %build-inputs ,lisp-type)
291 (%lisp-type ,lisp-type))
292 (asdf-build #:name ,name
293 #:source ,(match (assoc-ref inputs "source")
294 (((? derivation? source))
295 (derivation->output-path source))
298 #:asd-file ,(or asd-file (string-append system-name ".asd"))
299 #:asd-system-name ,system-name
300 #:test-asd-file ,test-asd-file
305 #:search-paths ',(map search-path-specification->sexp
307 #:inputs %build-inputs))))
309 (define guile-for-build
312 (package-derivation store guile system #:graft? #f))
314 (let* ((distro (resolve-interface '(gnu packages commencement)))
315 (guile (module-ref distro 'guile-final)))
316 (package-derivation store guile system #:graft? #f)))))
318 (build-expression->derivation store name builder
321 #:modules imported-modules
323 #:guile-for-build guile-for-build)))
325 (define asdf-build-system/sbcl
328 (description "The build system for ASDF binary packages using SBCL")
329 (lower (lower "sbcl"))))
331 (define asdf-build-system/ecl
334 (description "The build system for ASDF binary packages using ECL")
335 (lower (lower "ecl"))))
337 (define asdf-build-system/source
340 (description "The build system for ASDF source packages")
341 (lower lower/source)))
343 (define sbcl-package->cl-source-package
344 (let* ((property 'cl-source-variant)
346 (package-with-build-system asdf-build-system/sbcl
347 asdf-build-system/source
350 #:variant-property property
352 '(const %standard-phases/source))))
355 (strip-variant-as-necessary property pkg)))))
357 (define sbcl-package->ecl-package
358 (let* ((property 'ecl-variant)
360 (package-with-build-system asdf-build-system/sbcl
361 asdf-build-system/ecl
364 #:variant-property property
369 (strip-variant-as-necessary property pkg)))))
371 ;;; asdf.scm ends here