1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2016, 2017 Andy Patterson <ajpatter@uwaterloo.ca>
3 ;;; Copyright © 2019 Guillaume Le Vaillant <glv@posteo.net>
5 ;;; This file is part of GNU Guix.
7 ;;; GNU Guix is free software; you can redistribute it and/or modify it
8 ;;; under the terms of the GNU General Public License as published by
9 ;;; the Free Software Foundation; either version 3 of the License, or (at
10 ;;; your option) any later version.
12 ;;; GNU Guix is distributed in the hope that it will be useful, but
13 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;;; GNU General Public License for more details.
17 ;;; You should have received a copy of the GNU General Public License
18 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
20 (define-module (guix build-system asdf)
21 #:use-module (guix store)
22 #:use-module (guix utils)
23 #:use-module (guix memoization)
24 #:use-module (guix packages)
25 #:use-module (guix derivations)
26 #:use-module (guix search-paths)
27 #:use-module ((guix build utils)
28 #:select ((package-name->name+version
29 . hyphen-separated-name->name+version)))
30 #:use-module (guix build-system)
31 #:use-module (guix build-system gnu)
32 #:use-module (ice-9 match)
33 #:use-module (ice-9 regex)
34 #:use-module (srfi srfi-1)
35 #:use-module (srfi srfi-26)
36 #:use-module (gnu packages)
37 #:export (%asdf-build-system-modules
40 asdf-build-system/sbcl
42 asdf-build-system/source
43 sbcl-package->cl-source-package
44 sbcl-package->ecl-package))
48 ;; Standard build procedure for asdf packages. This is implemented as an
49 ;; extension of 'gnu-build-system'.
53 (define %asdf-build-system-modules
54 ;; Imported build-side modules
55 `((guix build asdf-build-system)
56 (guix build lisp-utils)
57 ,@%gnu-build-system-modules))
59 (define %asdf-build-modules
60 ;; Used (visible) build-side modules
61 '((guix build asdf-build-system)
63 (guix build lisp-utils)))
65 (define (default-lisp implementation)
66 "Return the default package for the lisp IMPLEMENTATION."
67 ;; Lazily resolve the binding to avoid a circular dependency.
68 (let ((lisp-module (resolve-interface '(gnu packages lisp))))
69 (module-ref lisp-module implementation)))
71 (define* (lower/source name
72 #:key source inputs outputs native-inputs system target
75 "Return a bag for NAME"
76 (define private-keywords
77 '(#:target #:inputs #:native-inputs))
83 (host-inputs `(,@(if source
87 ,@(standard-packages)))
88 (build-inputs native-inputs)
90 (build asdf-build/source)
91 (arguments (strip-keyword-arguments private-keywords arguments)))))
93 (define* (asdf-build/source store name inputs
95 (phases '(@ (guix build asdf-build-system)
96 %standard-phases/source))
98 (system (%current-system))
100 (imported-modules %asdf-build-system-modules)
101 (modules %asdf-build-modules))
104 (use-modules ,@modules)
105 (asdf-build/source #:name ,name
106 #:source ,(match (assoc-ref inputs "source")
107 (((? derivation? source))
108 (derivation->output-path source))
114 #:search-paths ',(map search-path-specification->sexp
116 #:inputs %build-inputs)))
118 (define guile-for-build
121 (package-derivation store guile system #:graft? #f))
123 (let* ((distro (resolve-interface '(gnu packages commencement)))
124 (guile (module-ref distro 'guile-final)))
125 (package-derivation store guile system #:graft? #f)))))
127 (build-expression->derivation store name builder
130 #:modules imported-modules
132 #:guile-for-build guile-for-build))
134 (define* (package-with-build-system from-build-system to-build-system
135 from-prefix to-prefix
136 #:key variant-property
138 "Return a precedure which takes a package PKG which uses FROM-BUILD-SYSTEM,
139 and returns one using TO-BUILD-SYSTEM. If PKG was prefixed by FROM-PREFIX,
140 the resulting package will be prefixed by TO-PREFIX. Inputs of PKG are
141 recursively transformed using the same rule. The result's #:phases argument
142 will be modified by PHASES-TRANSFORMER, an S-expression which evaluates on the
143 build side to a procedure of one argument.
145 VARIANT-PROPERTY can be added to a package's properties to indicate that the
146 corresponding package promise should be used as the result of this
147 transformation. This allows the result to differ from what the transformation
148 would otherwise produce.
150 If TO-BUILD-SYSTEM is asdf-build-system/source, the resulting package will be
151 set up using CL source package conventions."
152 (define target-is-source? (eq? asdf-build-system/source to-build-system))
154 (define (transform-package-name name)
155 (if (string-prefix? from-prefix name)
156 (let ((new-name (string-drop name (string-length from-prefix))))
157 (if (string-prefix? to-prefix new-name)
159 (string-append to-prefix new-name)))
162 (define (has-from-build-system? pkg)
163 (eq? from-build-system (package-build-system pkg)))
165 (define (find-input-package pkg)
166 (let* ((name (package-name pkg))
167 (new-name (transform-package-name name))
168 (pkgs (find-packages-by-name new-name)))
169 (if (null? pkgs) #f (list-ref pkgs 0))))
175 ((name content . rest)
176 (let* ((is-package? (package? content))
177 (new-content (if is-package?
178 (or (find-input-package content)
181 `(,name ,new-content ,@rest)))))
183 ;; Special considerations for source packages: CL inputs become
184 ;; propagated, and un-handled arguments are removed.
186 (define (new-propagated-inputs)
187 (if target-is-source?
190 (filter (match-lambda
192 (has-from-build-system? input)))
193 (append (package-inputs pkg)
194 ;; The native inputs might be needed just
195 ;; to load the system.
196 (package-native-inputs pkg)))
197 (package-propagated-inputs pkg)))
199 (map rewrite (package-propagated-inputs pkg))))
201 (define (new-inputs inputs-getter)
202 (if target-is-source?
204 (filter (match-lambda
206 (not (has-from-build-system? input))))
207 (inputs-getter pkg)))
208 (map rewrite (inputs-getter pkg))))
210 (define base-arguments
211 (if target-is-source?
212 (strip-keyword-arguments
213 '(#:tests? #:asd-file #:lisp #:asd-system-name #:test-asd-file)
214 (package-arguments pkg))
215 (package-arguments pkg)))
218 ((and variant-property
219 (assoc-ref (package-properties pkg) variant-property))
222 ((has-from-build-system? pkg)
225 (location (package-location pkg))
226 (name (transform-package-name (package-name pkg)))
227 (build-system to-build-system)
229 (substitute-keyword-arguments base-arguments
230 ((#:phases phases) (list phases-transformer phases))))
231 (inputs (new-inputs package-inputs))
232 (propagated-inputs (new-propagated-inputs))
233 (native-inputs (append (if target-is-source?
234 (list (list (package-name pkg) pkg))
236 (new-inputs package-native-inputs)))
237 (outputs (if target-is-source?
239 (package-outputs pkg)))))
244 (define (strip-variant-as-necessary variant pkg)
245 (define properties (package-properties pkg))
246 (if (assoc variant properties)
249 (properties (alist-delete variant properties)))
252 (define (lower lisp-type)
254 #:key source inputs outputs native-inputs system target
255 (lisp (default-lisp (string->symbol lisp-type)))
258 "Return a bag for NAME"
259 (define private-keywords
260 '(#:target #:inputs #:native-inputs #:lisp))
266 (host-inputs `(,@(if source
267 `(("source" ,source))
270 ,@(standard-packages)))
271 (build-inputs `((,lisp-type ,lisp)
274 (build (asdf-build lisp-type))
275 (arguments (strip-keyword-arguments private-keywords arguments))))))
277 (define (asdf-build lisp-type)
278 (lambda* (store name inputs
284 (phases '(@ (guix build asdf-build-system)
287 (system (%current-system))
289 (imported-modules %asdf-build-system-modules)
290 (modules %asdf-build-modules))
295 ;; NAME is the value returned from `package-full-name'.
296 (hyphen-separated-name->name+version name)
297 (1+ (string-length lisp-type))))) ; drop the "<lisp>-" prefix.
301 (use-modules ,@modules)
302 (parameterize ((%lisp (string-append
303 (assoc-ref %build-inputs ,lisp-type)
305 (%lisp-type ,lisp-type))
306 (asdf-build #:name ,name
307 #:source ,(match (assoc-ref inputs "source")
308 (((? derivation? source))
309 (derivation->output-path source))
312 #:asd-file ,(or asd-file (string-append system-name ".asd"))
313 #:asd-system-name ,system-name
314 #:test-asd-file ,test-asd-file
319 #:search-paths ',(map search-path-specification->sexp
321 #:inputs %build-inputs))))
323 (define guile-for-build
326 (package-derivation store guile system #:graft? #f))
328 (let* ((distro (resolve-interface '(gnu packages commencement)))
329 (guile (module-ref distro 'guile-final)))
330 (package-derivation store guile system #:graft? #f)))))
332 (build-expression->derivation store name builder
335 #:modules imported-modules
337 #:guile-for-build guile-for-build)))
339 (define asdf-build-system/sbcl
342 (description "The build system for ASDF binary packages using SBCL")
343 (lower (lower "sbcl"))))
345 (define asdf-build-system/ecl
348 (description "The build system for ASDF binary packages using ECL")
349 (lower (lower "ecl"))))
351 (define asdf-build-system/source
354 (description "The build system for ASDF source packages")
355 (lower lower/source)))
357 (define sbcl-package->cl-source-package
358 (let* ((property 'cl-source-variant)
360 (package-with-build-system asdf-build-system/sbcl
361 asdf-build-system/source
364 #:variant-property property
366 '(const %standard-phases/source))))
369 (strip-variant-as-necessary property pkg)))))
371 (define sbcl-package->ecl-package
372 (let* ((property 'ecl-variant)
374 (package-with-build-system asdf-build-system/sbcl
375 asdf-build-system/ecl
378 #:variant-property property
383 (strip-variant-as-necessary property pkg)))))
385 ;;; asdf.scm ends here