asdf.scm 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  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>
  4. ;;;
  5. ;;; This file is part of GNU Guix.
  6. ;;;
  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.
  11. ;;;
  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.
  16. ;;;
  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/>.
  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. #:use-module (gnu packages)
  36. #:export (%asdf-build-system-modules
  37. %asdf-build-modules
  38. asdf-build
  39. asdf-build-system/sbcl
  40. asdf-build-system/ecl
  41. asdf-build-system/source
  42. sbcl-package->cl-source-package
  43. sbcl-package->ecl-package))
  44. ;; Commentary:
  45. ;;
  46. ;; Standard build procedure for asdf packages. This is implemented as an
  47. ;; extension of 'gnu-build-system'.
  48. ;;
  49. ;; Code:
  50. (define %asdf-build-system-modules
  51. ;; Imported build-side modules
  52. `((guix build asdf-build-system)
  53. (guix build lisp-utils)
  54. ,@%gnu-build-system-modules))
  55. (define %asdf-build-modules
  56. ;; Used (visible) build-side modules
  57. '((guix build asdf-build-system)
  58. (guix build utils)
  59. (guix build lisp-utils)))
  60. (define (default-lisp implementation)
  61. "Return the default package for the lisp IMPLEMENTATION."
  62. ;; Lazily resolve the binding to avoid a circular dependency.
  63. (let ((lisp-module (resolve-interface '(gnu packages lisp))))
  64. (module-ref lisp-module implementation)))
  65. (define* (lower/source name
  66. #:key source inputs outputs native-inputs system target
  67. #:allow-other-keys
  68. #:rest arguments)
  69. "Return a bag for NAME"
  70. (define private-keywords
  71. '(#:target #:inputs #:native-inputs))
  72. (and (not target)
  73. (bag
  74. (name name)
  75. (system system)
  76. (host-inputs `(,@(if source
  77. `(("source" ,source))
  78. '())
  79. ,@inputs
  80. ,@(standard-packages)))
  81. (build-inputs native-inputs)
  82. (outputs outputs)
  83. (build asdf-build/source)
  84. (arguments (strip-keyword-arguments private-keywords arguments)))))
  85. (define* (asdf-build/source store name inputs
  86. #:key source outputs
  87. (phases '(@ (guix build asdf-build-system)
  88. %standard-phases/source))
  89. (search-paths '())
  90. (system (%current-system))
  91. (guile #f)
  92. (imported-modules %asdf-build-system-modules)
  93. (modules %asdf-build-modules))
  94. (define builder
  95. `(begin
  96. (use-modules ,@modules)
  97. (asdf-build/source #:name ,name
  98. #:source ,(match (assoc-ref inputs "source")
  99. (((? derivation? source))
  100. (derivation->output-path source))
  101. ((source) source)
  102. (source source))
  103. #:system ,system
  104. #:phases ,phases
  105. #:outputs %outputs
  106. #:search-paths ',(map search-path-specification->sexp
  107. search-paths)
  108. #:inputs %build-inputs)))
  109. (define guile-for-build
  110. (match guile
  111. ((? package?)
  112. (package-derivation store guile system #:graft? #f))
  113. (#f
  114. (let* ((distro (resolve-interface '(gnu packages commencement)))
  115. (guile (module-ref distro 'guile-final)))
  116. (package-derivation store guile system #:graft? #f)))))
  117. (build-expression->derivation store name builder
  118. #:inputs inputs
  119. #:system system
  120. #:modules imported-modules
  121. #:outputs outputs
  122. #:guile-for-build guile-for-build))
  123. (define* (package-with-build-system from-build-system to-build-system
  124. from-prefix to-prefix
  125. #:key variant-property
  126. phases-transformer)
  127. "Return a precedure which takes a package PKG which uses FROM-BUILD-SYSTEM,
  128. and returns one using TO-BUILD-SYSTEM. If PKG was prefixed by FROM-PREFIX,
  129. the resulting package will be prefixed by TO-PREFIX. Inputs of PKG are
  130. recursively transformed using the same rule. The result's #:phases argument
  131. will be modified by PHASES-TRANSFORMER, an S-expression which evaluates on the
  132. build side to a procedure of one argument.
  133. VARIANT-PROPERTY can be added to a package's properties to indicate that the
  134. corresponding package promise should be used as the result of this
  135. transformation. This allows the result to differ from what the transformation
  136. would otherwise produce.
  137. If TO-BUILD-SYSTEM is asdf-build-system/source, the resulting package will be
  138. set up using CL source package conventions."
  139. (define target-is-source? (eq? asdf-build-system/source to-build-system))
  140. (define (transform-package-name name)
  141. (if (string-prefix? from-prefix name)
  142. (let ((new-name (string-drop name (string-length from-prefix))))
  143. (if (string-prefix? to-prefix new-name)
  144. new-name
  145. (string-append to-prefix new-name)))
  146. name))
  147. (define (has-from-build-system? pkg)
  148. (eq? from-build-system (package-build-system pkg)))
  149. (define (find-input-package pkg)
  150. (let* ((name (package-name pkg))
  151. (new-name (transform-package-name name))
  152. (pkgs (find-packages-by-name new-name)))
  153. (if (null? pkgs) #f (list-ref pkgs 0))))
  154. (define transform
  155. (mlambda (pkg)
  156. (define rewrite
  157. (match-lambda
  158. ((name content . rest)
  159. (let* ((is-package? (package? content))
  160. (new-content (if is-package?
  161. (or (find-input-package content)
  162. (transform content))
  163. content)))
  164. `(,name ,new-content ,@rest)))))
  165. ;; Special considerations for source packages: CL inputs become
  166. ;; propagated, and un-handled arguments are removed.
  167. (define (new-propagated-inputs)
  168. (if target-is-source?
  169. (map rewrite
  170. (append
  171. (filter (match-lambda
  172. ((_ input . _)
  173. (has-from-build-system? input)))
  174. (append (package-inputs pkg)
  175. ;; The native inputs might be needed just
  176. ;; to load the system.
  177. (package-native-inputs pkg)))
  178. (package-propagated-inputs pkg)))
  179. (map rewrite (package-propagated-inputs pkg))))
  180. (define (new-inputs inputs-getter)
  181. (if target-is-source?
  182. (map rewrite
  183. (filter (match-lambda
  184. ((_ input . _)
  185. (not (has-from-build-system? input))))
  186. (inputs-getter pkg)))
  187. (map rewrite (inputs-getter pkg))))
  188. (define base-arguments
  189. (if target-is-source?
  190. (strip-keyword-arguments
  191. '(#:tests? #:asd-file #:lisp #:asd-system-name #:test-asd-file)
  192. (package-arguments pkg))
  193. (package-arguments pkg)))
  194. (cond
  195. ((and variant-property
  196. (assoc-ref (package-properties pkg) variant-property))
  197. => force)
  198. ((has-from-build-system? pkg)
  199. (package
  200. (inherit pkg)
  201. (location (package-location pkg))
  202. (name (transform-package-name (package-name pkg)))
  203. (build-system to-build-system)
  204. (arguments
  205. (substitute-keyword-arguments base-arguments
  206. ((#:phases phases) (list phases-transformer phases))))
  207. (inputs (new-inputs package-inputs))
  208. (propagated-inputs (new-propagated-inputs))
  209. (native-inputs (append (if target-is-source?
  210. (list (list (package-name pkg) pkg))
  211. '())
  212. (new-inputs package-native-inputs)))
  213. (outputs (if target-is-source?
  214. '("out")
  215. (package-outputs pkg)))))
  216. (else pkg))))
  217. transform)
  218. (define (strip-variant-as-necessary variant pkg)
  219. (define properties (package-properties pkg))
  220. (if (assoc variant properties)
  221. (package
  222. (inherit pkg)
  223. (properties (alist-delete variant properties)))
  224. pkg))
  225. (define (lower lisp-type)
  226. (lambda* (name
  227. #:key source inputs outputs native-inputs system target
  228. (lisp (default-lisp (string->symbol lisp-type)))
  229. #:allow-other-keys
  230. #:rest arguments)
  231. "Return a bag for NAME"
  232. (define private-keywords
  233. '(#:target #:inputs #:native-inputs #:lisp))
  234. (and (not target)
  235. (bag
  236. (name name)
  237. (system system)
  238. (host-inputs `(,@(if source
  239. `(("source" ,source))
  240. '())
  241. ,@inputs
  242. ,@(standard-packages)))
  243. (build-inputs `((,lisp-type ,lisp)
  244. ,@native-inputs))
  245. (outputs outputs)
  246. (build (asdf-build lisp-type))
  247. (arguments (strip-keyword-arguments private-keywords arguments))))))
  248. (define (asdf-build lisp-type)
  249. (lambda* (store name inputs
  250. #:key source outputs
  251. (tests? #t)
  252. (asd-file #f)
  253. (asd-system-name #f)
  254. (test-asd-file #f)
  255. (phases '(@ (guix build asdf-build-system)
  256. %standard-phases))
  257. (search-paths '())
  258. (system (%current-system))
  259. (guile #f)
  260. (imported-modules %asdf-build-system-modules)
  261. (modules %asdf-build-modules))
  262. (define system-name
  263. (or asd-system-name
  264. (string-drop
  265. ;; NAME is the value returned from `package-full-name'.
  266. (hyphen-separated-name->name+version name)
  267. (1+ (string-length lisp-type))))) ; drop the "<lisp>-" prefix.
  268. (define builder
  269. `(begin
  270. (use-modules ,@modules)
  271. (parameterize ((%lisp (string-append
  272. (assoc-ref %build-inputs ,lisp-type)
  273. "/bin/" ,lisp-type))
  274. (%lisp-type ,lisp-type))
  275. (asdf-build #:name ,name
  276. #:source ,(match (assoc-ref inputs "source")
  277. (((? derivation? source))
  278. (derivation->output-path source))
  279. ((source) source)
  280. (source source))
  281. #:asd-file ,(or asd-file (string-append system-name ".asd"))
  282. #:asd-system-name ,system-name
  283. #:test-asd-file ,test-asd-file
  284. #:system ,system
  285. #:tests? ,tests?
  286. #:phases ,phases
  287. #:outputs %outputs
  288. #:search-paths ',(map search-path-specification->sexp
  289. search-paths)
  290. #:inputs %build-inputs))))
  291. (define guile-for-build
  292. (match guile
  293. ((? package?)
  294. (package-derivation store guile system #:graft? #f))
  295. (#f
  296. (let* ((distro (resolve-interface '(gnu packages commencement)))
  297. (guile (module-ref distro 'guile-final)))
  298. (package-derivation store guile system #:graft? #f)))))
  299. (build-expression->derivation store name builder
  300. #:inputs inputs
  301. #:system system
  302. #:modules imported-modules
  303. #:outputs outputs
  304. #:guile-for-build guile-for-build)))
  305. (define asdf-build-system/sbcl
  306. (build-system
  307. (name 'asdf/sbcl)
  308. (description "The build system for ASDF binary packages using SBCL")
  309. (lower (lower "sbcl"))))
  310. (define asdf-build-system/ecl
  311. (build-system
  312. (name 'asdf/ecl)
  313. (description "The build system for ASDF binary packages using ECL")
  314. (lower (lower "ecl"))))
  315. (define asdf-build-system/source
  316. (build-system
  317. (name 'asdf/source)
  318. (description "The build system for ASDF source packages")
  319. (lower lower/source)))
  320. (define sbcl-package->cl-source-package
  321. (let* ((property 'cl-source-variant)
  322. (transformer
  323. (package-with-build-system asdf-build-system/sbcl
  324. asdf-build-system/source
  325. "sbcl-"
  326. "cl-"
  327. #:variant-property property
  328. #:phases-transformer
  329. '(const %standard-phases/source))))
  330. (lambda (pkg)
  331. (transformer
  332. (strip-variant-as-necessary property pkg)))))
  333. (define sbcl-package->ecl-package
  334. (let* ((property 'ecl-variant)
  335. (transformer
  336. (package-with-build-system asdf-build-system/sbcl
  337. asdf-build-system/ecl
  338. "sbcl-"
  339. "ecl-"
  340. #:variant-property property
  341. #:phases-transformer
  342. 'identity)))
  343. (lambda (pkg)
  344. (transformer
  345. (strip-variant-as-necessary property pkg)))))
  346. ;;; asdf.scm ends here