gnu-system.scm 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
  3. ;;; Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
  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. ;;;
  20. ;;; This file defines build jobs for the Hydra continuation integration
  21. ;;; tool.
  22. ;;;
  23. ;; Attempt to use our very own Guix modules.
  24. (eval-when (compile load eval)
  25. ;; Ignore any available .go, and force recompilation. This is because our
  26. ;; checkout in the store has mtime set to the epoch, and thus .go files look
  27. ;; newer, even though they may not correspond.
  28. (set! %fresh-auto-compile #t)
  29. (and=> (assoc-ref (current-source-location) 'filename)
  30. (lambda (file)
  31. (let ((dir (string-append (dirname file) "/../..")))
  32. (format (current-error-port) "prepending ~s to the load path~%"
  33. dir)
  34. (set! %load-path (cons dir %load-path))))))
  35. (use-modules (guix config)
  36. (guix store)
  37. (guix grafts)
  38. (guix profiles)
  39. (guix packages)
  40. (guix derivations)
  41. (guix monads)
  42. ((guix licenses) #:select (gpl3+))
  43. ((guix utils) #:select (%current-system))
  44. ((guix scripts system) #:select (read-operating-system))
  45. ((guix scripts pack)
  46. #:select (lookup-compressor self-contained-tarball))
  47. (gnu packages)
  48. (gnu packages gcc)
  49. (gnu packages base)
  50. (gnu packages gawk)
  51. (gnu packages guile)
  52. (gnu packages gettext)
  53. (gnu packages compression)
  54. (gnu packages multiprecision)
  55. (gnu packages make-bootstrap)
  56. (gnu packages package-management)
  57. (gnu system)
  58. (gnu system vm)
  59. (gnu system install)
  60. (gnu tests)
  61. (srfi srfi-1)
  62. (srfi srfi-26)
  63. (ice-9 match))
  64. ;; XXX: Debugging hack: since `hydra-eval-guile-jobs' redirects the output
  65. ;; port to the bit bucket, let us write to the error port instead.
  66. (setvbuf (current-error-port) _IOLBF)
  67. (set-current-output-port (current-error-port))
  68. (define* (package->alist store package system
  69. #:optional (package-derivation package-derivation))
  70. "Convert PACKAGE to an alist suitable for Hydra."
  71. (parameterize ((%graft? #f))
  72. `((derivation . ,(derivation-file-name
  73. (package-derivation store package system
  74. #:graft? #f)))
  75. (description . ,(package-synopsis package))
  76. (long-description . ,(package-description package))
  77. (license . ,(package-license package))
  78. (home-page . ,(package-home-page package))
  79. (maintainers . ("bug-guix@gnu.org"))
  80. (max-silent-time . ,(or (assoc-ref (package-properties package)
  81. 'max-silent-time)
  82. 3600)) ;1 hour by default
  83. (timeout . ,(or (assoc-ref (package-properties package) 'timeout)
  84. 72000))))) ;20 hours by default
  85. (define (package-job store job-name package system)
  86. "Return a job called JOB-NAME that builds PACKAGE on SYSTEM."
  87. (let ((job-name (symbol-append job-name (string->symbol ".")
  88. (string->symbol system))))
  89. `(,job-name . ,(cut package->alist store package system))))
  90. (define (package-cross-job store job-name package target system)
  91. "Return a job called TARGET.JOB-NAME that cross-builds PACKAGE for TARGET on
  92. SYSTEM."
  93. `(,(symbol-append (string->symbol target) (string->symbol ".") job-name
  94. (string->symbol ".") (string->symbol system)) .
  95. ,(cute package->alist store package system
  96. (lambda* (store package system #:key graft?)
  97. (package-cross-derivation store package target system
  98. #:graft? graft?)))))
  99. (define %core-packages
  100. ;; Note: Don't put the '-final' package variants because (1) that's
  101. ;; implicit, and (2) they cannot be cross-built (due to the explicit input
  102. ;; chain.)
  103. (list gcc-4.8 gcc-4.9 gcc-5 glibc binutils
  104. gmp mpfr mpc coreutils findutils diffutils patch sed grep
  105. gawk gnu-gettext hello guile-2.0 guile-2.2 zlib gzip xz
  106. %bootstrap-binaries-tarball
  107. %binutils-bootstrap-tarball
  108. (%glibc-bootstrap-tarball)
  109. %gcc-bootstrap-tarball
  110. %guile-bootstrap-tarball
  111. %bootstrap-tarballs))
  112. (define %packages-to-cross-build
  113. %core-packages)
  114. (define %cross-targets
  115. '("mips64el-linux-gnu"
  116. "mips64el-linux-gnuabi64"
  117. "arm-linux-gnueabihf"
  118. "aarch64-linux-gnu"
  119. "powerpc-linux-gnu"
  120. "i586-pc-gnu" ;aka. GNU/Hurd
  121. "i686-w64-mingw32"))
  122. (define %guixsd-supported-systems
  123. '("x86_64-linux" "i686-linux"))
  124. (define (qemu-jobs store system)
  125. "Return a list of jobs that build QEMU images for SYSTEM."
  126. (define (->alist drv)
  127. `((derivation . ,(derivation-file-name drv))
  128. (description . "Stand-alone QEMU image of the GNU system")
  129. (long-description . "This is a demo stand-alone QEMU image of the GNU
  130. system.")
  131. (license . ,gpl3+)
  132. (home-page . ,%guix-home-page-url)
  133. (maintainers . ("bug-guix@gnu.org"))))
  134. (define (->job name drv)
  135. (let ((name (symbol-append name (string->symbol ".")
  136. (string->symbol system))))
  137. `(,name . ,(lambda ()
  138. (parameterize ((%graft? #f))
  139. (->alist drv))))))
  140. (define MiB
  141. (expt 2 20))
  142. (if (member system %guixsd-supported-systems)
  143. (list (->job 'usb-image
  144. (run-with-store store
  145. (mbegin %store-monad
  146. (set-guile-for-build (default-guile))
  147. (system-disk-image installation-os
  148. #:disk-image-size
  149. (* 1024 MiB)))))
  150. (->job 'iso9660-image
  151. (run-with-store store
  152. (mbegin %store-monad
  153. (set-guile-for-build (default-guile))
  154. (system-disk-image installation-os
  155. #:file-system-type
  156. "iso9660")))))
  157. '()))
  158. (define (system-test-jobs store system)
  159. "Return a list of jobs for the system tests."
  160. (define (test->thunk test)
  161. (lambda ()
  162. (define drv
  163. (run-with-store store
  164. (mbegin %store-monad
  165. (set-current-system system)
  166. (set-grafting #f)
  167. (set-guile-for-build (default-guile))
  168. (system-test-value test))))
  169. `((derivation . ,(derivation-file-name drv))
  170. (description . ,(format #f "GuixSD '~a' system test"
  171. (system-test-name test)))
  172. (long-description . ,(system-test-description test))
  173. (license . ,gpl3+)
  174. (home-page . ,%guix-home-page-url)
  175. (maintainers . ("bug-guix@gnu.org")))))
  176. (define (->job test)
  177. (let ((name (string->symbol
  178. (string-append "test." (system-test-name test)
  179. "." system))))
  180. (cons name (test->thunk test))))
  181. (if (member system %guixsd-supported-systems)
  182. (map ->job (all-system-tests))
  183. '()))
  184. (define (tarball-jobs store system)
  185. "Return Hydra jobs to build the self-contained Guix binary tarball."
  186. (define (->alist drv)
  187. `((derivation . ,(derivation-file-name drv))
  188. (description . "Stand-alone binary Guix tarball")
  189. (long-description . "This is a tarball containing binaries of Guix and
  190. all its dependencies, and ready to be installed on non-GuixSD distributions.")
  191. (license . ,gpl3+)
  192. (home-page . ,%guix-home-page-url)
  193. (maintainers . ("bug-guix@gnu.org"))))
  194. (define (->job name drv)
  195. (let ((name (symbol-append name (string->symbol ".")
  196. (string->symbol system))))
  197. `(,name . ,(lambda ()
  198. (parameterize ((%graft? #f))
  199. (->alist drv))))))
  200. ;; XXX: Add a job for the stable Guix?
  201. (list (->job 'binary-tarball
  202. (run-with-store store
  203. (mbegin %store-monad
  204. (set-guile-for-build (default-guile))
  205. (>>= (profile-derivation (packages->manifest (list guix)))
  206. (lambda (profile)
  207. (self-contained-tarball "guix-binary" profile
  208. #:localstatedir? #t
  209. #:compressor
  210. (lookup-compressor "xz")))))
  211. #:system system))))
  212. (define job-name
  213. ;; Return the name of a package's job.
  214. (compose string->symbol package-full-name))
  215. (define package->job
  216. (let ((base-packages
  217. (delete-duplicates
  218. (append-map (match-lambda
  219. ((_ package _ ...)
  220. (match (package-transitive-inputs package)
  221. (((_ inputs _ ...) ...)
  222. inputs))))
  223. (%final-inputs)))))
  224. (lambda (store package system)
  225. "Return a job for PACKAGE on SYSTEM, or #f if this combination is not
  226. valid."
  227. (cond ((member package base-packages)
  228. #f)
  229. ((supported-package? package system)
  230. (let ((drv (package-derivation store package system
  231. #:graft? #f)))
  232. (and (substitutable-derivation? drv)
  233. (package-job store (job-name package)
  234. package system))))
  235. (else
  236. #f)))))
  237. ;;;
  238. ;;; Hydra entry point.
  239. ;;;
  240. (define (hydra-jobs store arguments)
  241. "Return Hydra jobs."
  242. (define subset
  243. (match (assoc-ref arguments 'subset)
  244. ("core" 'core) ; only build core packages
  245. ("hello" 'hello) ; only build hello
  246. (((? string?) (? string?) ...) 'list) ; only build selected list of packages
  247. (_ 'all))) ; build everything
  248. (define (cross-jobs system)
  249. (define (from-32-to-64? target)
  250. ;; Return true if SYSTEM is 32-bit and TARGET is 64-bit. This hack
  251. ;; prevents known-to-fail cross-builds from i686-linux or armhf-linux to
  252. ;; mips64el-linux-gnuabi64.
  253. (and (or (string-prefix? "i686-" system)
  254. (string-prefix? "i586-" system)
  255. (string-prefix? "armhf-" system))
  256. (string-contains target "64"))) ;x86_64, mips64el, aarch64, etc.
  257. (define (same? target)
  258. ;; Return true if SYSTEM and TARGET are the same thing. This is so we
  259. ;; don't try to cross-compile to 'mips64el-linux-gnu' from
  260. ;; 'mips64el-linux'.
  261. (or (string-contains target system)
  262. (and (string-prefix? "armhf" system) ;armhf-linux
  263. (string-prefix? "arm" target)))) ;arm-linux-gnueabihf
  264. (define (pointless? target)
  265. ;; Return #t if it makes no sense to cross-build to TARGET from SYSTEM.
  266. (and (string-contains target "mingw")
  267. (not (string=? "x86_64-linux" system))))
  268. (define (either proc1 proc2 proc3)
  269. (lambda (x)
  270. (or (proc1 x) (proc2 x) (proc3 x))))
  271. (append-map (lambda (target)
  272. (map (lambda (package)
  273. (package-cross-job store (job-name package)
  274. package target system))
  275. %packages-to-cross-build))
  276. (remove (either from-32-to-64? same? pointless?)
  277. %cross-targets)))
  278. ;; Turn off grafts. Grafting is meant to happen on the user's machines.
  279. (parameterize ((%graft? #f))
  280. ;; Return one job for each package, except bootstrap packages.
  281. (append-map (lambda (system)
  282. (case subset
  283. ((all)
  284. ;; Build everything, including replacements.
  285. (let ((all (fold-packages
  286. (lambda (package result)
  287. (cond ((package-replacement package)
  288. (cons* package
  289. (package-replacement package)
  290. result))
  291. ((package-superseded package)
  292. result) ;don't build it
  293. (else
  294. (cons package result))))
  295. '()))
  296. (job (lambda (package)
  297. (package->job store package
  298. system))))
  299. (append (filter-map job all)
  300. (qemu-jobs store system)
  301. (system-test-jobs store system)
  302. (tarball-jobs store system)
  303. (cross-jobs system))))
  304. ((core)
  305. ;; Build core packages only.
  306. (append (map (lambda (package)
  307. (package-job store (job-name package)
  308. package system))
  309. %core-packages)
  310. (cross-jobs system)))
  311. ((hello)
  312. ;; Build hello package only.
  313. (if (string=? system (%current-system))
  314. (let ((hello (specification->package "hello")))
  315. (list (package-job store (job-name hello) hello system)))
  316. '()))
  317. ((list)
  318. ;; Build selected list of packages only.
  319. (if (string=? system (%current-system))
  320. (let* ((names (assoc-ref arguments 'subset))
  321. (packages (map specification->package names)))
  322. (map (lambda (package)
  323. (package-job store (job-name package)
  324. package system))
  325. packages))
  326. '()))
  327. (else
  328. (error "unknown subset" subset))))
  329. %hydra-supported-systems)))