self.scm 56 KB

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