self.scm 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2017-2023 Ludovic Courtès <ludo@gnu.org>
  3. ;;; Copyright © 2020 Martin Becze <mjbecze@riseup.net>
  4. ;;; Copyright © 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
  5. ;;;
  6. ;;; This file is part of GNU Guix.
  7. ;;;
  8. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  9. ;;; under the terms of the GNU General Public License as published by
  10. ;;; the Free Software Foundation; either version 3 of the License, or (at
  11. ;;; your option) any later version.
  12. ;;;
  13. ;;; GNU Guix is distributed in the hope that it will be useful, but
  14. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ;;; GNU General Public License for more details.
  17. ;;;
  18. ;;; You should have received a copy of the GNU General Public License
  19. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  20. (define-module (guix self)
  21. #:use-module (guix config)
  22. #:use-module (guix modules)
  23. #:use-module (guix gexp)
  24. #:use-module (guix store)
  25. #:use-module (guix monads)
  26. #:use-module (guix discovery)
  27. #:use-module (guix packages)
  28. #:use-module (guix sets)
  29. #:use-module (guix modules)
  30. #:use-module ((guix utils) #:select (version-major+minor))
  31. #:use-module ((guix build utils) #:select (find-files))
  32. #:use-module (srfi srfi-1)
  33. #:use-module (srfi srfi-9)
  34. #:use-module (srfi srfi-35)
  35. #:use-module (ice-9 match)
  36. #:export (make-config.scm
  37. whole-package ;for internal use in 'guix pull'
  38. compiled-guix
  39. guix-derivation))
  40. ;;;
  41. ;;; Dependency handling.
  42. ;;;
  43. (define %packages
  44. (let ((ref (lambda (module variable)
  45. (delay
  46. (module-ref (resolve-interface
  47. `(gnu packages ,module))
  48. variable)))))
  49. `(("guile" . ,(ref 'guile 'guile-3.0-latest))
  50. ("guile-avahi" . ,(ref 'guile-xyz 'guile-avahi))
  51. ("guile-json" . ,(ref 'guile 'guile-json-4))
  52. ("guile-ssh" . ,(ref 'ssh 'guile-ssh))
  53. ("guile-git" . ,(ref 'guile 'guile-git))
  54. ("guile-semver" . ,(ref 'guile-xyz 'guile-semver))
  55. ("guile-lib" . ,(ref 'guile-xyz 'guile-lib))
  56. ("guile-sqlite3" . ,(ref 'guile 'guile-sqlite3))
  57. ("guile-zlib" . ,(ref 'guile 'guile-zlib))
  58. ("guile-lzlib" . ,(ref 'guile 'guile-lzlib))
  59. ("guile-zstd" . ,(ref 'guile 'guile-zstd))
  60. ("guile-gcrypt" . ,(ref 'gnupg 'guile-gcrypt))
  61. ("guile-gnutls" . ,(ref 'tls 'guile-gnutls))
  62. ("guix-daemon" . ,(ref 'package-management 'guix-daemon))
  63. ("disarchive" . ,(ref 'backup 'disarchive))
  64. ("guile-lzma" . ,(ref 'guile 'guile-lzma))
  65. ("gzip" . ,(ref 'compression 'gzip))
  66. ("bzip2" . ,(ref 'compression 'bzip2))
  67. ("xz" . ,(ref 'compression 'xz))
  68. ("po4a" . ,(ref 'gettext 'po4a))
  69. ("gettext-minimal" . ,(ref 'gettext 'gettext-minimal))
  70. ("gcc-toolchain" . ,(ref 'commencement 'gcc-toolchain))
  71. ("glibc-utf8-locales" . ,(ref 'base 'glibc-utf8-locales))
  72. ("graphviz" . ,(ref 'graphviz 'graphviz-minimal))
  73. ("font-ghostscript" . ,(ref 'ghostscript 'font-ghostscript))
  74. ("texinfo" . ,(ref 'texinfo 'texinfo)))))
  75. (define (specification->package name)
  76. ;; Use our own variant of that procedure because that of (gnu packages)
  77. ;; would traverse all the .scm files, which is wasteful.
  78. (and=> (assoc-ref %packages name) force))
  79. ;;;
  80. ;;; Derivations.
  81. ;;;
  82. ;; Node in a DAG of build tasks. Each node maps to a derivation, but it's
  83. ;; easier to express things this way.
  84. (define-record-type <node>
  85. (node name modules source dependencies compiled)
  86. node?
  87. (name node-name) ;string
  88. (modules node-modules) ;list of module names
  89. (source node-source) ;list of source files
  90. (dependencies node-dependencies) ;list of nodes
  91. (compiled node-compiled)) ;node -> lowerable object
  92. ;; File mappings are essentially an alist as passed to 'imported-files'.
  93. (define-record-type <file-mapping>
  94. (file-mapping name alist)
  95. file-mapping?
  96. (name file-mapping-name)
  97. (alist file-mapping-alist))
  98. (define-gexp-compiler (file-mapping-compiler (mapping <file-mapping>)
  99. system target)
  100. ;; Here we use 'imported-files', which can arrange to directly import all
  101. ;; the files instead of creating a derivation, when possible.
  102. (imported-files (map (match-lambda
  103. ((destination (? local-file? file))
  104. (cons destination
  105. (local-file-absolute-file-name file)))
  106. ((destination source)
  107. (cons destination source))) ;silliness
  108. (file-mapping-alist mapping))
  109. #:name (file-mapping-name mapping)
  110. #:system system))
  111. (define (node-source+compiled node)
  112. "Return a \"bundle\" containing both the source code and object files for
  113. NODE's modules, under their FHS directories: share/guile/site and lib/guile."
  114. (define build
  115. (with-imported-modules '((guix build utils))
  116. #~(begin
  117. (use-modules (guix build utils))
  118. (define source
  119. (string-append #$output "/share/guile/site/"
  120. (effective-version)))
  121. (define object
  122. (string-append #$output "/lib/guile/" (effective-version)
  123. "/site-ccache"))
  124. (mkdir-p (dirname source))
  125. (symlink #$(node-source node) source)
  126. (mkdir-p (dirname object))
  127. (symlink #$(node-compiled node) object))))
  128. (computed-file (string-append (node-name node) "-modules")
  129. build
  130. #:options '(#:local-build? #t
  131. ;; "Building" it locally is faster.
  132. #:substitutable? #f)))
  133. (define (node-fold proc init nodes)
  134. (let loop ((nodes nodes)
  135. (visited (setq))
  136. (result init))
  137. (match nodes
  138. (() result)
  139. ((head tail ...)
  140. (if (set-contains? visited head)
  141. (loop tail visited result)
  142. (loop tail (set-insert head visited)
  143. (proc head result)))))))
  144. (define (node-modules/recursive nodes)
  145. (node-fold (lambda (node modules)
  146. (append (node-modules node) modules))
  147. '()
  148. nodes))
  149. (define* (closure modules #:optional (except '()))
  150. (source-module-closure modules
  151. #:select?
  152. (match-lambda
  153. (('guix 'config)
  154. #f)
  155. ((and module
  156. (or ('guix _ ...) ('gnu _ ...)))
  157. (not (member module except)))
  158. (rest #f))))
  159. (define module->import
  160. ;; Return a file-name/file-like object pair for the specified module and
  161. ;; suitable for 'imported-files'.
  162. (match-lambda
  163. ((module '=> thing)
  164. (let ((file (module-name->file-name module)))
  165. (list file thing)))
  166. (module
  167. (let ((file (module-name->file-name module)))
  168. (list file
  169. (local-file (search-path %load-path file)))))))
  170. (define* (scheme-node name modules #:optional (dependencies '())
  171. #:key (extra-modules '()) (extra-files '())
  172. (extensions '())
  173. parallel? guile-for-build)
  174. "Return a node that builds the given Scheme MODULES, and depends on
  175. DEPENDENCIES (a list of nodes). EXTRA-MODULES is a list of additional modules
  176. added to the source, and EXTRA-FILES is a list of additional files.
  177. EXTENSIONS is a set of full-blown Guile packages (e.g., 'guile-json') that
  178. must be present in the search path."
  179. (let* ((modules (append extra-modules
  180. (closure modules
  181. (node-modules/recursive dependencies))))
  182. (module-files (map module->import modules))
  183. (source (file-mapping (string-append name "-source")
  184. (append module-files extra-files))))
  185. (node name modules source dependencies
  186. (compiled-modules name source
  187. (map car module-files)
  188. (map node-source dependencies)
  189. (map node-compiled dependencies)
  190. #:extensions extensions
  191. #:parallel? parallel?
  192. #:guile-for-build guile-for-build))))
  193. (define (file-imports directory sub-directory pred)
  194. "List all the files matching PRED under DIRECTORY/SUB-DIRECTORY. Return a
  195. list of file-name/file-like objects suitable as inputs to 'imported-files'."
  196. (map (lambda (file)
  197. (list (string-drop file (+ 1 (string-length directory)))
  198. (local-file file #:recursive? #t)))
  199. (find-files (string-append directory "/" sub-directory) pred)))
  200. (define* (file-append* item file #:key (recursive? #t))
  201. "Return FILE within ITEM, which may be a file name or a file-like object.
  202. When ITEM is a plain file name (a string), simply return a 'local-file'
  203. record with the new file name."
  204. (match item
  205. ((? string?)
  206. ;; This is the optimal case: we return a new "source". Thus, a
  207. ;; derivation that depends on this sub-directory does not depend on ITEM
  208. ;; itself.
  209. (local-file (string-append item "/" file)
  210. #:recursive? recursive?))
  211. ((? local-file? base)
  212. ;; Likewise, but with a <local-file>.
  213. (if (local-file-recursive? base)
  214. (local-file (string-append (local-file-absolute-file-name base)
  215. "/" file)
  216. (basename file)
  217. #:recursive? recursive?
  218. #:select? (local-file-select? base))
  219. (file-append base file)))
  220. (_
  221. ;; In this case, anything that refers to the result also depends on ITEM,
  222. ;; which isn't great.
  223. (file-append item "/" file))))
  224. (define* (locale-data source domain
  225. #:optional (directory domain))
  226. "Return the locale data from 'po/DIRECTORY' in SOURCE, corresponding to
  227. DOMAIN, a gettext domain."
  228. (define gettext-minimal
  229. (specification->package "gettext-minimal"))
  230. (define build
  231. (with-imported-modules '((guix build utils))
  232. #~(begin
  233. (use-modules (guix build utils)
  234. (srfi srfi-26)
  235. (ice-9 match) (ice-9 ftw))
  236. (define po-directory
  237. #+(file-append* source (string-append "po/" directory)))
  238. (define (compile language)
  239. (let ((gmo (string-append #$output "/" language "/LC_MESSAGES/"
  240. #$domain ".mo")))
  241. (mkdir-p (dirname gmo))
  242. (invoke #+(file-append gettext-minimal "/bin/msgfmt")
  243. "-c" "--statistics" "--verbose"
  244. "-o" gmo
  245. (string-append po-directory "/" language ".po"))))
  246. (define (linguas)
  247. ;; Return the list of languages. Note: don't read 'LINGUAS'
  248. ;; because it contains things like 'en@boldquot' that do not have
  249. ;; a corresponding .po file.
  250. (map (cut basename <> ".po")
  251. (scandir po-directory
  252. (cut string-suffix? ".po" <>))))
  253. (for-each compile (linguas)))))
  254. (computed-file (string-append "guix-locale-" domain)
  255. build))
  256. (define (translate-texi-manuals source)
  257. "Return the translated texinfo manuals built from SOURCE."
  258. (define po4a
  259. (specification->package "po4a"))
  260. (define gettext-minimal
  261. (specification->package "gettext-minimal"))
  262. (define glibc-utf8-locales
  263. (specification->package "glibc-utf8-locales"))
  264. (define documentation
  265. (file-append* source "doc"))
  266. (define documentation-po
  267. (file-append* source "po/doc"))
  268. (define build
  269. (with-imported-modules '((guix build utils) (guix build po))
  270. #~(begin
  271. (use-modules (guix build utils) (guix build po)
  272. (ice-9 match) (ice-9 regex) (ice-9 textual-ports)
  273. (ice-9 vlist) (ice-9 threads)
  274. (srfi srfi-1))
  275. (define (translate-tmp-texi po source output)
  276. "Translate Texinfo file SOURCE using messages from PO, and write
  277. the result to OUTPUT."
  278. (invoke #+(file-append po4a "/bin/po4a-translate")
  279. "-M" "UTF-8" "-L" "UTF-8" "-k" "0" "-f" "texinfo"
  280. "-m" source "-p" po "-l" output))
  281. (define (canonicalize-whitespace str)
  282. ;; Change whitespace (newlines, etc.) in STR to #\space.
  283. (string-map (lambda (chr)
  284. (if (char-set-contains? char-set:whitespace chr)
  285. #\space
  286. chr))
  287. str))
  288. (define* (translate-texi prefix po lang
  289. #:key (extras '()))
  290. "Translate the manual for one language LANG using the PO file.
  291. PREFIX must be the prefix of the manual, 'guix' or 'guix-cookbook'. EXTRAS is
  292. a list of extra files, such as '(\"contributing\")."
  293. (for-each (lambda (file)
  294. (translate-tmp-texi po (string-append file ".texi")
  295. (string-append file "." lang
  296. ".texi.tmp")))
  297. (cons prefix extras))
  298. (for-each (lambda (file)
  299. (let* ((texi (string-append file "." lang ".texi"))
  300. (tmp (string-append texi ".tmp")))
  301. (copy-file tmp texi)
  302. (translate-cross-references texi po)))
  303. (cons prefix extras)))
  304. (define (available-translations directory domain)
  305. ;; Return the list of available translations under DIRECTORY for
  306. ;; DOMAIN, a gettext domain such as "guix-manual". The result is
  307. ;; a list of language/PO file pairs.
  308. (filter-map (lambda (po)
  309. (let ((base (basename po)))
  310. (and (string-prefix? (string-append domain ".")
  311. base)
  312. (match (string-split base #\.)
  313. ((_ ... lang "po")
  314. (cons lang po))))))
  315. (find-files directory
  316. "\\.[a-z]{2}(_[A-Z]{2})?\\.po$")))
  317. (define parallel-jobs
  318. ;; Limit thread creation by 'n-par-for-each', mostly to put an
  319. ;; upper bound on memory usage.
  320. (min (parallel-job-count) 4))
  321. (mkdir #$output)
  322. (copy-recursively #$documentation "."
  323. #:log (%make-void-port "w"))
  324. (for-each
  325. (lambda (file)
  326. (copy-file file (basename file)))
  327. (find-files #$documentation-po ".*.po$"))
  328. (setenv "GUIX_LOCPATH"
  329. #+(file-append glibc-utf8-locales "/lib/locale"))
  330. (setenv "PATH" #+(file-append gettext-minimal "/bin"))
  331. (setenv "LC_ALL" "en_US.UTF-8")
  332. (setlocale LC_ALL "en_US.UTF-8")
  333. (n-par-for-each parallel-jobs
  334. (match-lambda
  335. ((language . po)
  336. (translate-texi "guix" po language
  337. #:extras '("contributing"))))
  338. (available-translations "." "guix-manual"))
  339. (n-par-for-each parallel-jobs
  340. (match-lambda
  341. ((language . po)
  342. (translate-texi "guix-cookbook" po language)))
  343. (available-translations "." "guix-cookbook"))
  344. (for-each (lambda (file)
  345. (install-file file #$output))
  346. (append
  347. (find-files "." "contributing\\..*\\.texi$")
  348. (find-files "." "guix\\..*\\.texi$")
  349. (find-files "." "guix-cookbook\\..*\\.texi$"))))))
  350. (computed-file "guix-translated-texinfo" build))
  351. (define (info-manual source)
  352. "Return the Info manual built from SOURCE."
  353. (define texinfo
  354. (specification->package "texinfo"))
  355. (define graphviz
  356. (specification->package "graphviz"))
  357. (define font-ghostscript
  358. (specification->package "font-ghostscript"))
  359. (define glibc-utf8-locales
  360. (specification->package "glibc-utf8-locales"))
  361. (define documentation
  362. (file-append* source "doc"))
  363. (define examples
  364. (file-append* source "gnu/system/examples"))
  365. (define build
  366. (with-imported-modules '((guix build utils))
  367. #~(begin
  368. (use-modules (guix build utils)
  369. (ice-9 match))
  370. (mkdir #$output)
  371. ;; Create 'version.texi'.
  372. ;; XXX: Can we use a more meaningful version string yet one that
  373. ;; doesn't change at each commit?
  374. (call-with-output-file "version.texi"
  375. (lambda (port)
  376. (let ((version "0.0-git"))
  377. (format port "
  378. @set UPDATED 1 January 1970
  379. @set UPDATED-MONTH January 1970
  380. @set EDITION ~a
  381. @set VERSION ~a\n" version version))))
  382. ;; Copy configuration templates that the manual includes.
  383. (for-each (lambda (template)
  384. (copy-file template
  385. (string-append
  386. "os-config-"
  387. (basename template ".tmpl")
  388. ".texi")))
  389. (find-files #$examples "\\.tmpl$"))
  390. ;; Build graphs.
  391. (mkdir-p (string-append #$output "/images"))
  392. (setenv "XDG_DATA_DIRS" ;fonts needed by 'dot'
  393. #+(file-append font-ghostscript "/share"))
  394. (for-each (lambda (dot-file)
  395. (invoke #+(file-append graphviz "/bin/dot")
  396. "-Tpng" "-Gratio=.9" "-Gnodesep=.005"
  397. "-Granksep=.00005" "-Nfontsize=9"
  398. "-Nheight=.1" "-Nwidth=.1"
  399. "-o" (string-append #$output "/images/"
  400. (basename dot-file ".dot")
  401. ".png")
  402. dot-file))
  403. (find-files (string-append #$documentation "/images")
  404. "\\.dot$"))
  405. ;; Copy other PNGs.
  406. (for-each (lambda (png-file)
  407. (install-file png-file
  408. (string-append #$output "/images")))
  409. (find-files (string-append #$documentation "/images")
  410. "\\.png$"))
  411. ;; Finally build the manual. Copy it the Texinfo files to $PWD and
  412. ;; add a symlink to the 'images' directory so that 'makeinfo' can
  413. ;; see those images and produce image references in the Info output.
  414. (copy-recursively #$documentation "."
  415. #:log (%make-void-port "w"))
  416. (copy-recursively #+(translate-texi-manuals source) "."
  417. #:log (%make-void-port "w"))
  418. (delete-file-recursively "images")
  419. (symlink (string-append #$output "/images") "images")
  420. ;; Provide UTF-8 locales needed by the 'xspara.c' code in makeinfo.
  421. (setenv "GUIX_LOCPATH"
  422. #+(file-append glibc-utf8-locales "/lib/locale"))
  423. (for-each (lambda (texi)
  424. (match (string-split (basename texi) #\.)
  425. (("guix" language "texi")
  426. ;; Create 'version-LL.texi'.
  427. (symlink "version.texi"
  428. (string-append "version-" language
  429. ".texi")))
  430. (_ #f))
  431. (invoke #+(file-append texinfo "/bin/makeinfo")
  432. texi "-I" #$documentation
  433. "-I" "."
  434. "-o" (string-append #$output "/"
  435. (basename texi ".texi")
  436. ".info")))
  437. (cons "guix.texi"
  438. (append (find-files "."
  439. "^guix\\.[a-z]{2}(_[A-Z]{2})?\\.texi$")
  440. (find-files "."
  441. "^guix-cookbook.*\\.texi$"))))
  442. ;; Compress Info files.
  443. (setenv "PATH"
  444. #+(file-append (specification->package "gzip") "/bin"))
  445. (for-each (lambda (file)
  446. (invoke "gzip" "-9n" file))
  447. (find-files #$output "\\.info(-[0-9]+)?$")))))
  448. (computed-file "guix-manual" build))
  449. (define-syntax-rule (prevent-inlining! identifier ...)
  450. (begin (set! identifier identifier) ...))
  451. ;; XXX: These procedures are actually used by 'doc/build.scm'. Protect them
  452. ;; from inlining on Guile 3.
  453. (prevent-inlining! file-append* translate-texi-manuals info-manual)
  454. (define* (guile-module-union things #:key (name "guix-module-union"))
  455. "Return the union of the subset of THINGS (packages, computed files, etc.)
  456. that provide Guile modules."
  457. (define build
  458. (with-imported-modules '((guix build union))
  459. #~(begin
  460. (use-modules (guix build union))
  461. (define (modules directory)
  462. (string-append directory "/share/guile/site"))
  463. (define (objects directory)
  464. (string-append directory "/lib/guile"))
  465. (union-build #$output
  466. (filter (lambda (directory)
  467. (or (file-exists? (modules directory))
  468. (file-exists? (objects directory))))
  469. '#$things)
  470. #:log-port (%make-void-port "w")))))
  471. (computed-file name build))
  472. (define (quiet-guile guile)
  473. "Return a wrapper that does the same as the 'guile' executable of GUILE,
  474. except that it does not complain about locales and falls back to 'en_US.utf8'
  475. instead of 'C'."
  476. (define gcc
  477. (specification->package "gcc-toolchain"))
  478. (define source
  479. (search-path %load-path
  480. "gnu/packages/aux-files/guile-launcher.c"))
  481. (define effective
  482. (version-major+minor (package-version guile)))
  483. (define build
  484. ;; XXX: Reuse <c-compiler> from (guix scripts pack) instead?
  485. (with-imported-modules '((guix build utils))
  486. #~(begin
  487. (use-modules (guix build utils)
  488. (srfi srfi-26))
  489. (mkdir-p (string-append #$output "/bin"))
  490. (setenv "PATH" #$(file-append gcc "/bin"))
  491. (setenv "C_INCLUDE_PATH"
  492. (string-join
  493. (map (cut string-append <> "/include")
  494. '#$(match (bag-transitive-build-inputs
  495. (package->bag guile))
  496. (((labels packages . _) ...)
  497. (filter package? packages))))
  498. ":"))
  499. (setenv "LIBRARY_PATH" #$(file-append gcc "/lib"))
  500. (setenv "GUIX_LD_WRAPPER_DISABLE_RPATH" "1")
  501. (invoke "gcc" #$(local-file source) "-Wall" "-g0" "-O2"
  502. "-I" #$(file-append guile "/include/guile/" effective)
  503. "-L" #$(file-append guile "/lib")
  504. "-Wl,-rpath" #$(file-append guile "/lib")
  505. #$(string-append "-lguile-" effective)
  506. "-o" (string-append #$output "/bin/guile")))))
  507. (computed-file "guile-wrapper" build))
  508. (define* (guix-command modules
  509. #:key source (dependencies '())
  510. guile (guile-version (effective-version)))
  511. "Return the 'guix' command such that it adds MODULES and DEPENDENCIES in its
  512. load path."
  513. (define glibc-utf8-locales
  514. (specification->package "glibc-utf8-locales"))
  515. (define module-directory
  516. ;; To minimize the number of 'stat' calls needed to locate a module,
  517. ;; create the union of all the module directories.
  518. (guile-module-union (cons modules dependencies)))
  519. (program-file "guix-command"
  520. #~(begin
  521. ;; Remove the empty extension from the search path.
  522. (set! %load-extensions '(".scm"))
  523. (set! %load-path
  524. (append (list (string-append #$module-directory
  525. "/share/guile/site/"
  526. (effective-version))
  527. (string-append #$guile "/share/guile/"
  528. (effective-version)))
  529. %load-path))
  530. (set! %load-compiled-path
  531. (append (list (string-append #$module-directory
  532. "/lib/guile/"
  533. (effective-version)
  534. "/site-ccache")
  535. (string-append #$guile "/lib/guile/"
  536. (effective-version)
  537. "/ccache"))
  538. %load-compiled-path))
  539. ;; To maximize the chances that locales are set up right
  540. ;; out-of-the-box, bundle "common" UTF-8 locales.
  541. (let ((locpath (getenv "GUIX_LOCPATH")))
  542. (setenv "GUIX_LOCPATH"
  543. (string-append (if locpath
  544. (string-append locpath ":")
  545. "")
  546. #$(file-append glibc-utf8-locales
  547. "/lib/locale"))))
  548. (let ((guix-main (module-ref (resolve-interface '(guix ui))
  549. 'guix-main)))
  550. #$(if source
  551. #~(begin
  552. (bindtextdomain "guix"
  553. #$(locale-data source "guix"))
  554. (bindtextdomain "guix-packages"
  555. #$(locale-data source
  556. "guix-packages"
  557. "packages")))
  558. #t)
  559. ;; XXX: It would be more convenient to change it to:
  560. ;; (exit (apply guix-main (command-line)))
  561. (apply guix-main (command-line))))
  562. ;; Use a 'guile' variant that doesn't complain about locales.
  563. #:guile (quiet-guile guile)))
  564. (define (selinux-policy source daemon)
  565. "Return the SELinux policy file taken from SOURCE and adjusted to refer to
  566. DAEMON and to the current configuration variables."
  567. (define build
  568. (with-imported-modules '((guix build utils))
  569. #~(begin
  570. (use-modules (guix build utils))
  571. (copy-file #+(file-append* source "/etc/guix-daemon.cil.in")
  572. "guix-daemon.cil")
  573. (substitute* "guix-daemon.cil"
  574. (("@guix_sysconfdir@") #$%sysconfdir)
  575. (("@guix_localstatedir@") #$%localstatedir)
  576. (("@storedir@") #$%storedir)
  577. (("@prefix@") #$daemon))
  578. (copy-file "guix-daemon.cil" #$output))))
  579. (computed-file "guix-daemon.cil" build))
  580. (define (miscellaneous-files source daemon)
  581. "Return data files taken from SOURCE."
  582. (file-mapping "guix-misc"
  583. `(("etc/bash_completion.d/guix"
  584. ,(file-append* source "/etc/completion/bash/guix"))
  585. ("etc/bash_completion.d/guix-daemon"
  586. ,(file-append* source "/etc/completion/bash/guix-daemon"))
  587. ("share/zsh/site-functions/_guix"
  588. ,(file-append* source "/etc/completion/zsh/_guix"))
  589. ("share/fish/vendor_completions.d/guix.fish"
  590. ,(file-append* source "/etc/completion/fish/guix.fish"))
  591. ("share/selinux/guix-daemon.cil"
  592. ,(selinux-policy source daemon))
  593. ("share/guix/berlin.guix.gnu.org.pub"
  594. ,(file-append* source
  595. "/etc/substitutes/berlin.guix.gnu.org.pub"))
  596. ("share/guix/ci.guix.gnu.org.pub" ;alias
  597. ,(file-append* source "/etc/substitutes/berlin.guix.gnu.org.pub"))
  598. ("share/guix/ci.guix.info.pub" ;alias
  599. ,(file-append* source "/etc/substitutes/berlin.guix.gnu.org.pub"))
  600. ("share/guix/bordeaux.guix.gnu.org.pub"
  601. ,(file-append* source "/etc/substitutes/bordeaux.guix.gnu.org.pub")))))
  602. (define* (whole-package name modules dependencies
  603. #:key
  604. (guile-version (effective-version))
  605. info daemon miscellany
  606. guile
  607. (command (guix-command modules
  608. #:dependencies dependencies
  609. #:guile guile
  610. #:guile-version guile-version)))
  611. "Return the whole Guix package NAME that uses MODULES, a derivation of all
  612. the modules (under share/guile/site and lib/guile), and DEPENDENCIES, a list
  613. of packages depended on. COMMAND is the 'guix' program to use; INFO is the
  614. Info manual."
  615. (define (wrap daemon)
  616. (program-file "guix-daemon"
  617. #~(begin
  618. ;; Refer to the right 'guix' command for 'guix
  619. ;; substitute' & co.
  620. (setenv "GUIX" #$command)
  621. ;; Honor the user's settings rather than those hardcoded
  622. ;; in the 'guix-daemon' package.
  623. (unless (getenv "GUIX_STATE_DIRECTORY")
  624. (setenv "GUIX_STATE_DIRECTORY"
  625. #$(string-append %localstatedir "/guix")))
  626. (unless (getenv "GUIX_CONFIGURATION_DIRECTORY")
  627. (setenv "GUIX_CONFIGURATION_DIRECTORY"
  628. #$(string-append %sysconfdir "/guix")))
  629. (unless (getenv "NIX_STORE_DIR")
  630. (setenv "NIX_STORE_DIR" #$%storedir))
  631. (apply execl #$(file-append daemon "/bin/guix-daemon")
  632. "guix-daemon" (cdr (command-line))))
  633. #:guile guile))
  634. (computed-file name
  635. (with-imported-modules '((guix build utils))
  636. #~(begin
  637. (use-modules (guix build utils))
  638. (define daemon
  639. #$(and daemon (wrap daemon)))
  640. (mkdir-p (string-append #$output "/bin"))
  641. (symlink #$command
  642. (string-append #$output "/bin/guix"))
  643. (when daemon
  644. (symlink daemon
  645. (string-append #$output "/bin/guix-daemon")))
  646. (let ((share (string-append #$output "/share"))
  647. (lib (string-append #$output "/lib"))
  648. (info #$info))
  649. (mkdir-p share)
  650. (symlink #$(file-append modules "/share/guile")
  651. (string-append share "/guile"))
  652. (when info
  653. (symlink #$info (string-append share "/info")))
  654. (mkdir-p lib)
  655. (symlink #$(file-append modules "/lib/guile")
  656. (string-append lib "/guile")))
  657. (when #$miscellany
  658. (copy-recursively #$miscellany #$output
  659. #:log (%make-void-port "w")))))))
  660. (define (transitive-package-dependencies package)
  661. "Return the list of packages propagated by PACKAGE, including PACKAGE
  662. itself."
  663. (match (package-transitive-propagated-inputs package)
  664. (((labels packages _ ...) ...)
  665. (cons package packages))))
  666. (define* (compiled-guix source #:key
  667. (version %guix-version)
  668. (channel-metadata #f)
  669. (pull-version 1)
  670. (name (string-append "guix-" version))
  671. (guile-version (effective-version))
  672. (guile-for-build (default-guile))
  673. (gzip (specification->package "gzip"))
  674. (bzip2 (specification->package "bzip2"))
  675. (xz (specification->package "xz"))
  676. (guix (specification->package "guix")))
  677. "Return a file-like object that contains a compiled Guix."
  678. (define guile-avahi
  679. (specification->package "guile-avahi"))
  680. (define guile-json
  681. (specification->package "guile-json"))
  682. (define guile-ssh
  683. (specification->package "guile-ssh"))
  684. (define guile-lib
  685. (specification->package "guile-lib"))
  686. (define guile-git
  687. (specification->package "guile-git"))
  688. (define guile-sqlite3
  689. (specification->package "guile-sqlite3"))
  690. (define guile-zlib
  691. (specification->package "guile-zlib"))
  692. (define guile-lzlib
  693. (specification->package "guile-lzlib"))
  694. (define guile-zstd
  695. (specification->package "guile-zstd"))
  696. (define guile-gcrypt
  697. (specification->package "guile-gcrypt"))
  698. (define guile-semver
  699. (specification->package "guile-semver"))
  700. (define guile-gnutls
  701. (specification->package "guile-gnutls"))
  702. (define disarchive
  703. (specification->package "disarchive"))
  704. (define guile-lzma
  705. (specification->package "guile-lzma"))
  706. (define dependencies
  707. (append-map transitive-package-dependencies
  708. (list guile-gcrypt guile-gnutls guile-git guile-avahi
  709. guile-json guile-semver guile-ssh guile-sqlite3
  710. guile-lib guile-zlib guile-lzlib guile-zstd)))
  711. (define *core-modules*
  712. (scheme-node "guix-core"
  713. '((guix)
  714. (guix monad-repl)
  715. (guix packages)
  716. (guix download)
  717. (guix discovery)
  718. (guix profiles)
  719. (guix build-system gnu)
  720. (guix build-system trivial)
  721. (guix build profiles)
  722. (guix build gnu-build-system))
  723. ;; Provide a dummy (guix config) with the default version
  724. ;; number, storedir, etc. This is so that "guix-core" is the
  725. ;; same across all installations and doesn't need to be
  726. ;; rebuilt when the version changes, which in turn means we
  727. ;; can have substitutes for it.
  728. #:extra-modules
  729. `(((guix config)
  730. => ,(make-config.scm
  731. #:config-variables %default-config-variables)))
  732. ;; (guix man-db) is needed at build-time by (guix profiles)
  733. ;; but we don't need to compile it; not compiling it allows
  734. ;; us to avoid an extra dependency on guile-gdbm-ffi.
  735. #:extra-files
  736. `(("guix/man-db.scm" ,(local-file "../guix/man-db.scm"))
  737. ("guix/build/po.scm" ,(local-file "../guix/build/po.scm"))
  738. ("guix/store/schema.sql"
  739. ,(local-file "../guix/store/schema.sql")))
  740. #:extensions (list guile-gcrypt
  741. guile-json) ;for (guix swh)
  742. #:guile-for-build guile-for-build))
  743. (define *extra-modules*
  744. (scheme-node "guix-extra"
  745. (filter-map (match-lambda
  746. (('guix 'scripts _ ..1) #f)
  747. (('guix 'man-db) #f)
  748. (('guix 'tests _ ...) #f)
  749. (name name))
  750. (scheme-modules* source "guix"))
  751. (list *core-modules*)
  752. #:extra-files
  753. `(("guix/graph.js" ,(local-file "../guix/graph.js"))
  754. ("guix/d3.v3.js" ,(local-file "../guix/d3.v3.js")))
  755. #:extensions dependencies
  756. #:guile-for-build guile-for-build))
  757. (define *core-package-modules*
  758. (scheme-node "guix-packages-base"
  759. `((gnu packages)
  760. (gnu packages base))
  761. (list *core-modules* *extra-modules*)
  762. #:extensions dependencies
  763. ;; Add all the non-Scheme files here. We must do it here so
  764. ;; that 'search-patches' & co. can find them. Ideally we'd
  765. ;; keep them next to the .scm files that use them but it's
  766. ;; difficult to do (XXX).
  767. #:extra-files
  768. (file-imports source "gnu/packages"
  769. (lambda (file stat)
  770. (and (eq? 'regular (stat:type stat))
  771. (not (string-suffix? ".scm" file))
  772. (not (string-suffix? ".go" file))
  773. (not (string-prefix? ".#" file))
  774. (not (string-suffix? "~" file)))))
  775. #:guile-for-build guile-for-build))
  776. (define *package-modules*
  777. (scheme-node "guix-packages"
  778. (scheme-modules* source "gnu/packages")
  779. (list *core-modules* *extra-modules* *core-package-modules*)
  780. #:extensions dependencies
  781. #:guile-for-build guile-for-build))
  782. (define *system-modules*
  783. (scheme-node "guix-system"
  784. `((gnu system)
  785. (gnu services)
  786. ,@(scheme-modules* source "gnu/bootloader")
  787. ,@(scheme-modules* source "gnu/system")
  788. ,@(scheme-modules* source "gnu/services")
  789. ,@(scheme-modules* source "gnu/machine")
  790. ,@(scheme-modules* source "guix/platforms/"))
  791. (list *core-package-modules* *package-modules*
  792. *extra-modules* *core-modules*)
  793. #:extensions dependencies
  794. #:extra-files
  795. (append (file-imports source "gnu/system/examples"
  796. (const #t))
  797. ;; All the installer code is on the build-side.
  798. (file-imports source "gnu/installer/"
  799. (const #t))
  800. ;; Build-side code that we don't build. Some of
  801. ;; these depend on guile-rsvg, the Shepherd, etc.
  802. (file-imports source "gnu/build" (const #t)))
  803. #:guile-for-build
  804. guile-for-build))
  805. (define *home-modules*
  806. (scheme-node "guix-home"
  807. `((gnu home)
  808. (gnu home services)
  809. ,@(scheme-modules* source "gnu/home/services"))
  810. (list *core-package-modules* *package-modules*
  811. *extra-modules* *core-modules* *system-modules*)
  812. #:extensions dependencies
  813. #:guile-for-build guile-for-build))
  814. (define *core-cli-modules*
  815. ;; Core command-line interface modules that do not depend on (gnu system
  816. ;; …) or (gnu home …), and not even on *PACKAGE-MODULES*.
  817. (scheme-node "guix-cli-core"
  818. (remove (match-lambda
  819. (('guix 'scripts 'system . _) #t)
  820. (('guix 'scripts 'environment) #t)
  821. (('guix 'scripts 'container . _) #t)
  822. (('guix 'scripts 'deploy) #t)
  823. (('guix 'scripts 'home . _) #t)
  824. (('guix 'scripts 'import . _) #t)
  825. (('guix 'scripts 'gc) #t) ;autoloads (gnu home)
  826. (('guix 'pack) #t)
  827. (_ #f))
  828. (scheme-modules* source "guix/scripts"))
  829. (list *core-modules* *extra-modules*
  830. *core-package-modules*)
  831. #:extensions dependencies
  832. #:guile-for-build guile-for-build))
  833. (define *cli-modules*
  834. (scheme-node "guix-cli"
  835. (append (scheme-modules* source "/guix/scripts")
  836. `((gnu ci)))
  837. (list *core-modules* *extra-modules*
  838. *core-package-modules* *package-modules*
  839. *core-cli-modules* *system-modules* *home-modules*)
  840. #:extensions dependencies
  841. #:guile-for-build guile-for-build))
  842. (define *system-test-modules*
  843. ;; Ship these modules mostly so (gnu ci) can discover them.
  844. (scheme-node "guix-system-tests"
  845. `((gnu tests)
  846. ,@(scheme-modules* source "gnu/tests"))
  847. (list *core-package-modules* *package-modules*
  848. *extra-modules* *system-modules* *core-modules*
  849. *cli-modules*) ;for (guix scripts pack), etc.
  850. #:extra-files (file-imports source "gnu/tests/data"
  851. (const #t))
  852. #:extensions dependencies
  853. #:guile-for-build guile-for-build))
  854. (define *config*
  855. (scheme-node "guix-config"
  856. '()
  857. #:extra-modules
  858. `(((guix config)
  859. => ,(make-config.scm #:gzip gzip
  860. #:bzip2 bzip2
  861. #:xz xz
  862. #:package-name
  863. %guix-package-name
  864. #:package-version
  865. version
  866. #:channel-metadata
  867. channel-metadata
  868. #:bug-report-address
  869. %guix-bug-report-address
  870. #:home-page-url
  871. %guix-home-page-url)))
  872. #:guile-for-build guile-for-build))
  873. (define (built-modules node-subset)
  874. (directory-union (string-append name "-modules")
  875. (append-map node-subset
  876. ;; Note: *CONFIG* comes first so that it
  877. ;; overrides the (guix config) module that
  878. ;; comes with *CORE-MODULES*.
  879. (list *config*
  880. *cli-modules*
  881. *core-cli-modules*
  882. *system-test-modules*
  883. *system-modules*
  884. *home-modules*
  885. *package-modules*
  886. *core-package-modules*
  887. *extra-modules*
  888. *core-modules*))
  889. ;; Silently choose the first entry upon collision so that
  890. ;; we choose *CONFIG*.
  891. #:resolve-collision 'first
  892. ;; When we do (add-to-store "utils.scm"), "utils.scm" must
  893. ;; be a regular file, not a symlink. Thus, arrange so that
  894. ;; regular files appear as regular files in the final
  895. ;; output.
  896. #:copy? #t
  897. #:quiet? #t))
  898. ;; Version 0 of 'guix pull' meant we'd just return Scheme modules.
  899. ;; Version 1 is when we return the full package.
  900. (cond ((= 1 pull-version)
  901. ;; The whole package, with a standard file hierarchy.
  902. (let* ((modules (built-modules (compose list node-source+compiled)))
  903. (daemon (specification->package "guix-daemon"))
  904. (command (guix-command modules
  905. #:source source
  906. #:dependencies
  907. (cons* disarchive
  908. guile-lzma
  909. dependencies)
  910. #:guile guile-for-build
  911. #:guile-version guile-version)))
  912. (whole-package name modules dependencies
  913. #:command command
  914. #:guile guile-for-build
  915. ;; Include 'guix-daemon'. XXX: Here we inject an
  916. ;; older snapshot of guix-daemon, but that's a good
  917. ;; enough approximation for now.
  918. #:daemon daemon
  919. #:info (info-manual source)
  920. #:miscellany (miscellaneous-files source daemon)
  921. #:guile-version guile-version)))
  922. ((= 0 pull-version)
  923. ;; Legacy 'guix pull': return the .scm and .go files as one
  924. ;; directory.
  925. (built-modules (lambda (node)
  926. (list (node-source node)
  927. (node-compiled node)))))
  928. (else
  929. ;; Unsupported 'guix pull' version.
  930. #f)))
  931. ;;;
  932. ;;; Generating (guix config).
  933. ;;;
  934. (define %persona-variables
  935. ;; (guix config) variables that define Guix's persona.
  936. '(%guix-package-name
  937. %guix-version
  938. %guix-bug-report-address
  939. %guix-home-page-url))
  940. (define %config-variables
  941. ;; (guix config) variables corresponding to Guix configuration.
  942. (letrec-syntax ((variables (syntax-rules ()
  943. ((_)
  944. '())
  945. ((_ variable rest ...)
  946. (cons `(variable . ,variable)
  947. (variables rest ...))))))
  948. (variables %localstatedir %storedir %sysconfdir)))
  949. (define %default-config-variables
  950. ;; Default values of the configuration variables above.
  951. `((%localstatedir . "/var")
  952. (%storedir . "/gnu/store")
  953. (%sysconfdir . "/etc")))
  954. (define* (make-config.scm #:key gzip xz bzip2
  955. (package-name "GNU Guix")
  956. (package-version "0")
  957. (channel-metadata #f)
  958. (config-variables %config-variables)
  959. (bug-report-address "bug-guix@gnu.org")
  960. (home-page-url "https://guix.gnu.org"))
  961. ;; Hack so that Geiser is not confused.
  962. (define defmod 'define-module)
  963. (scheme-file "config.scm"
  964. #~(;; The following expressions get spliced.
  965. (#$defmod (guix config)
  966. ;; Mark it as non-declarative to prevent cross-module
  967. ;; inlining that could lead to inlining %GUIX-VERSION in
  968. ;; (guix ui).
  969. #:declarative? #f
  970. #:export (%guix-package-name
  971. %guix-version
  972. %guix-bug-report-address
  973. %guix-home-page-url
  974. %channel-metadata
  975. %system
  976. %store-directory
  977. %state-directory
  978. %store-database-directory
  979. %config-directory
  980. %gzip
  981. %bzip2
  982. %xz))
  983. (define %system
  984. #$(%current-system))
  985. #$@(map (match-lambda
  986. ((name . value)
  987. #~(define-public #$name #$value)))
  988. config-variables)
  989. (define %store-directory
  990. (or (and=> (getenv "NIX_STORE_DIR") canonicalize-path)
  991. %storedir))
  992. (define %state-directory
  993. ;; This must match `NIX_STATE_DIR' as defined in
  994. ;; `nix/local.mk'.
  995. (or (getenv "GUIX_STATE_DIRECTORY")
  996. (string-append %localstatedir "/guix")))
  997. (define %store-database-directory
  998. (or (getenv "GUIX_DATABASE_DIRECTORY")
  999. (string-append %state-directory "/db")))
  1000. (define %config-directory
  1001. ;; This must match `GUIX_CONFIGURATION_DIRECTORY' as
  1002. ;; defined in `nix/local.mk'.
  1003. (or (getenv "GUIX_CONFIGURATION_DIRECTORY")
  1004. (string-append %sysconfdir "/guix")))
  1005. (define %guix-package-name #$package-name)
  1006. (define %guix-version #$package-version)
  1007. (define %guix-bug-report-address #$bug-report-address)
  1008. (define %guix-home-page-url #$home-page-url)
  1009. (define %channel-metadata
  1010. ;; Metadata for the 'guix' channel in use. This
  1011. ;; information is used by (guix describe).
  1012. '#$channel-metadata)
  1013. (define %gzip
  1014. #+(and gzip (file-append gzip "/bin/gzip")))
  1015. (define %bzip2
  1016. #+(and bzip2 (file-append bzip2 "/bin/bzip2")))
  1017. (define %xz
  1018. #+(and xz (file-append xz "/bin/xz"))))
  1019. ;; Guile 2.0 *requires* the 'define-module' to be at the
  1020. ;; top-level or the 'toplevel-ref' in the resulting .go file are
  1021. ;; made relative to a nonexistent anonymous module.
  1022. #:splice? #t))
  1023. ;;;
  1024. ;;; Building.
  1025. ;;;
  1026. (define* (compiled-modules name module-tree module-files
  1027. #:optional
  1028. (dependencies '())
  1029. (dependencies-compiled '())
  1030. #:key
  1031. (extensions '()) ;full-blown Guile packages
  1032. parallel?
  1033. guile-for-build)
  1034. "Build all the MODULE-FILES from MODULE-TREE. MODULE-FILES must be a list
  1035. like '(\"guix/foo.scm\" \"gnu/bar.scm\") and MODULE-TREE is the directory
  1036. containing MODULE-FILES and possibly other files as well."
  1037. ;; This is a non-monadic, enhanced version of 'compiled-file' from (guix
  1038. ;; gexp).
  1039. (define build
  1040. (with-imported-modules (source-module-closure
  1041. '((guix build compile)
  1042. (guix build utils)))
  1043. #~(begin
  1044. (use-modules (srfi srfi-1)
  1045. (srfi srfi-26)
  1046. (ice-9 match)
  1047. (ice-9 format)
  1048. (ice-9 threads)
  1049. (guix build compile)
  1050. (guix build utils))
  1051. (define (regular? file)
  1052. (not (member file '("." ".."))))
  1053. (define (report-load file total completed)
  1054. (display #\cr)
  1055. (format #t
  1056. "[~3@a/~3@a] loading...\t~5,1f% of ~d files"
  1057. ;; Note: Multiply TOTAL by two to account for the
  1058. ;; compilation phase that follows.
  1059. completed (* total 2)
  1060. (* 100. (/ completed total)) total)
  1061. (force-output))
  1062. (define (report-compilation file total completed)
  1063. (display #\cr)
  1064. (format #t "[~3@a/~3@a] compiling...\t~5,1f% of ~d files"
  1065. ;; Add TOTAL to account for the load phase that came
  1066. ;; before.
  1067. (+ total completed) (* total 2)
  1068. (* 100. (/ completed total)) total)
  1069. (force-output))
  1070. (define* (process-directory directory files output #:key (size 25))
  1071. (let ((chunks (unfold
  1072. (lambda (seed) (< (length seed) size)) ;p
  1073. (cute take <> size) ;f
  1074. (cute drop <> size) ;g
  1075. files ;seed
  1076. list))) ;tail
  1077. (for-each
  1078. (lambda (chunk)
  1079. ;; Hide compilation warnings.
  1080. (parameterize ((current-warning-port (%make-void-port "w")))
  1081. (compile-files directory output chunk
  1082. #:workers (parallel-job-count)
  1083. #:report-load report-load
  1084. #:report-compilation report-compilation)
  1085. (gc)))
  1086. chunks)))
  1087. (setvbuf (current-output-port) 'line)
  1088. (setvbuf (current-error-port) 'line)
  1089. (set! %load-path (cons #+module-tree %load-path))
  1090. (set! %load-path
  1091. (append '#+dependencies
  1092. (map (lambda (extension)
  1093. (string-append extension "/share/guile/site/"
  1094. (effective-version)))
  1095. '#+extensions)
  1096. %load-path))
  1097. (set! %load-compiled-path
  1098. (append '#+dependencies-compiled
  1099. (map (lambda (extension)
  1100. (string-append extension "/lib/guile/"
  1101. (effective-version)
  1102. "/site-ccache"))
  1103. '#+extensions)
  1104. %load-compiled-path))
  1105. ;; Load the compiler modules upfront.
  1106. (compile #f)
  1107. (mkdir #$output)
  1108. (chdir #+module-tree)
  1109. (let ((size (if (equal? #$name "guix-packages-base") 10 25)))
  1110. (process-directory "." '#+module-files #$output #:size size))
  1111. (newline))))
  1112. (computed-file name build
  1113. #:guile guile-for-build
  1114. #:options
  1115. `(#:local-build? #f ;allow substitutes
  1116. ;; Don't annoy people about _IONBF deprecation.
  1117. ;; Initialize 'terminal-width' in (system repl debug)
  1118. ;; to a large-enough value to make backtrace more
  1119. ;; verbose.
  1120. #:env-vars (("GUILE_WARN_DEPRECATED" . "no")
  1121. ("COLUMNS" . "200")))))
  1122. ;;;
  1123. ;;; Building.
  1124. ;;;
  1125. (define* (guix-derivation source version
  1126. #:optional (guile-version (effective-version))
  1127. #:key (pull-version 0)
  1128. channel-metadata)
  1129. "Return, as a monadic value, the derivation to build the Guix from SOURCE
  1130. for GUILE-VERSION. Use VERSION as the version string. Use CHANNEL-METADATA
  1131. as the channel metadata sexp to include in (guix config).
  1132. PULL-VERSION specifies the version of the 'guix pull' protocol. Return #f if
  1133. this PULL-VERSION value is not supported."
  1134. (define (shorten version)
  1135. (if (and (string-every char-set:hex-digit version)
  1136. (> (string-length version) 9))
  1137. (string-take version 9) ;Git commit
  1138. version))
  1139. (define guile
  1140. ;; When PULL-VERSION >= 1, produce a self-contained Guix and use the
  1141. ;; current Guile unconditionally.
  1142. (specification->package "guile"))
  1143. (when (and (< pull-version 1)
  1144. (not (string=? (package-version guile) guile-version)))
  1145. ;; Guix < 0.15.0 has PULL-VERSION = 0, where the host Guile is reused and
  1146. ;; can be any version. When that happens and Guile is not current (e.g.,
  1147. ;; it's Guile 2.0), just bail out.
  1148. (raise (condition
  1149. (&message
  1150. (message "Guix is too old and cannot be upgraded")))))
  1151. (mbegin %store-monad
  1152. (set-guile-for-build guile)
  1153. (let ((guix (compiled-guix source
  1154. #:version version
  1155. #:channel-metadata channel-metadata
  1156. #:name (string-append "guix-"
  1157. (shorten version))
  1158. #:pull-version pull-version
  1159. #:guile-version (if (>= pull-version 1)
  1160. "3.0" guile-version)
  1161. #:guile-for-build guile)))
  1162. (if guix
  1163. (lower-object guix)
  1164. (return #f)))))