diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2018-03-23 15:36:12 +0100 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2018-04-08 17:41:08 +0200 |
| commit | eaae07ec2878707744fed76029a28ab9a494fc2e (patch) | |
| tree | 6c2cd2dfec1d1f2aa951dcc66907d0c1cbfac137 | |
| parent | 278c16579dfe59833155b1e7678a727e60fa6540 (diff) | |
Add (guix self).
* guix/self.scm: New file.
* Makefile.am (MODULES): Add it.
* gnu/packages.scm (%distro-root-directory): Rewrite to try different
directories.
* guix/discovery.scm (guix): Export 'scheme-files'.
| -rw-r--r-- | Makefile.am | 1 | ||||
| -rw-r--r-- | gnu/packages.scm | 21 | ||||
| -rw-r--r-- | guix/discovery.scm | 3 | ||||
| -rw-r--r-- | guix/self.scm | 599 |
4 files changed, 621 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am index 244069b5337..e4edd05d727 100644 --- a/Makefile.am +++ b/Makefile.am | |||
| @@ -81,6 +81,7 @@ MODULES = \ | |||
| 81 | guix/derivations.scm \ | 81 | guix/derivations.scm \ |
| 82 | guix/grafts.scm \ | 82 | guix/grafts.scm \ |
| 83 | guix/gnu-maintenance.scm \ | 83 | guix/gnu-maintenance.scm \ |
| 84 | guix/self.scm \ | ||
| 84 | guix/upstream.scm \ | 85 | guix/upstream.scm \ |
| 85 | guix/licenses.scm \ | 86 | guix/licenses.scm \ |
| 86 | guix/glob.scm \ | 87 | guix/glob.scm \ |
diff --git a/gnu/packages.scm b/gnu/packages.scm index 97e6cb347f2..44a56dfde07 100644 --- a/gnu/packages.scm +++ b/gnu/packages.scm | |||
| @@ -110,8 +110,25 @@ for system '~a'") | |||
| 110 | file-name system))))))) | 110 | file-name system))))))) |
| 111 | 111 | ||
| 112 | (define %distro-root-directory | 112 | (define %distro-root-directory |
| 113 | ;; Absolute file name of the module hierarchy. | 113 | ;; Absolute file name of the module hierarchy. Since (gnu packages …) might |
| 114 | (dirname (search-path %load-path "guix.scm"))) | 114 | ;; live in a directory different from (guix), try to get the best match. |
| 115 | (letrec-syntax ((dirname* (syntax-rules () | ||
| 116 | ((_ file) | ||
| 117 | (dirname file)) | ||
| 118 | ((_ file head tail ...) | ||
| 119 | (dirname (dirname* file tail ...))))) | ||
| 120 | (try (syntax-rules () | ||
| 121 | ((_ (file things ...) rest ...) | ||
| 122 | (match (search-path %load-path file) | ||
| 123 | (#f | ||
| 124 | (try rest ...)) | ||
| 125 | (absolute | ||
| 126 | (dirname* absolute things ...)))) | ||
| 127 | ((_) | ||
| 128 | #f)))) | ||
| 129 | (try ("gnu/packages/base.scm" gnu/ packages/) | ||
| 130 | ("gnu/packages.scm" gnu/) | ||
| 131 | ("guix.scm")))) | ||
| 115 | 132 | ||
| 116 | (define %package-module-path | 133 | (define %package-module-path |
| 117 | ;; Search path for package modules. Each item must be either a directory | 134 | ;; Search path for package modules. Each item must be either a directory |
diff --git a/guix/discovery.scm b/guix/discovery.scm index 7b575790237..8ffcf7cd9ab 100644 --- a/guix/discovery.scm +++ b/guix/discovery.scm | |||
| @@ -25,7 +25,8 @@ | |||
| 25 | #:use-module (ice-9 match) | 25 | #:use-module (ice-9 match) |
| 26 | #:use-module (ice-9 vlist) | 26 | #:use-module (ice-9 vlist) |
| 27 | #:use-module (ice-9 ftw) | 27 | #:use-module (ice-9 ftw) |
| 28 | #:export (scheme-modules | 28 | #:export (scheme-files |
| 29 | scheme-modules | ||
| 29 | fold-modules | 30 | fold-modules |
| 30 | all-modules | 31 | all-modules |
| 31 | fold-module-public-variables)) | 32 | fold-module-public-variables)) |
diff --git a/guix/self.scm b/guix/self.scm new file mode 100644 index 00000000000..c9e4a4250eb --- /dev/null +++ b/guix/self.scm | |||
| @@ -0,0 +1,599 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | ||
| 2 | ;;; Copyright © 2017, 2018 Ludovic Courtès <ludo@gnu.org> | ||
| 3 | ;;; | ||
| 4 | ;;; This file is part of GNU Guix. | ||
| 5 | ;;; | ||
| 6 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | ||
| 7 | ;;; under the terms of the GNU General Public License as published by | ||
| 8 | ;;; the Free Software Foundation; either version 3 of the License, or (at | ||
| 9 | ;;; your option) any later version. | ||
| 10 | ;;; | ||
| 11 | ;;; GNU Guix is distributed in the hope that it will be useful, but | ||
| 12 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;;; GNU General Public License for more details. | ||
| 15 | ;;; | ||
| 16 | ;;; You should have received a copy of the GNU General Public License | ||
| 17 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | (define-module (guix self) | ||
| 20 | #:use-module (guix config) | ||
| 21 | #:use-module (guix i18n) | ||
| 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 utils) | ||
| 30 | #:use-module (guix modules) | ||
| 31 | #:use-module (guix build utils) | ||
| 32 | #:use-module ((guix build compile) #:select (%lightweight-optimizations)) | ||
| 33 | #:use-module (srfi srfi-1) | ||
| 34 | #:use-module (srfi srfi-9) | ||
| 35 | #:use-module (ice-9 match) | ||
| 36 | #:export (make-config.scm | ||
| 37 | compiled-guix | ||
| 38 | guix-derivation | ||
| 39 | reload-guix)) | ||
| 40 | |||
| 41 | |||
| 42 | ;;; | ||
| 43 | ;;; Dependency handling. | ||
| 44 | ;;; | ||
| 45 | |||
| 46 | (define* (false-if-wrong-guile package | ||
| 47 | #:optional (guile-version (effective-version))) | ||
| 48 | "Return #f if PACKAGE depends on the \"wrong\" major version of Guile (e.g., | ||
| 49 | 2.0 instead of 2.2), otherwise return PACKAGE." | ||
| 50 | (let ((guile (any (match-lambda | ||
| 51 | ((label (? package? dep) _ ...) | ||
| 52 | (and (string=? (package-name dep) "guile") | ||
| 53 | dep))) | ||
| 54 | (package-direct-inputs package)))) | ||
| 55 | (and (or (not guile) | ||
| 56 | (string-prefix? guile-version | ||
| 57 | (package-version guile))) | ||
| 58 | package))) | ||
| 59 | |||
| 60 | (define (package-for-guile guile-version . names) | ||
| 61 | "Return the package with one of the given NAMES that depends on | ||
| 62 | GUILE-VERSION (\"2.0\" or \"2.2\"), or #f if none of the packages matches." | ||
| 63 | (let loop ((names names)) | ||
| 64 | (match names | ||
| 65 | (() | ||
| 66 | #f) | ||
| 67 | ((name rest ...) | ||
| 68 | (match (specification->package name) | ||
| 69 | (#f | ||
| 70 | (loop rest)) | ||
| 71 | ((? package? package) | ||
| 72 | (or (false-if-wrong-guile package) | ||
| 73 | (loop rest)))))))) | ||
| 74 | |||
| 75 | (define specification->package | ||
| 76 | ;; Use our own variant of that procedure because that of (gnu packages) | ||
| 77 | ;; would traverse all the .scm files, which is wasteful. | ||
| 78 | (let ((ref (lambda (module variable) | ||
| 79 | (module-ref (resolve-interface module) variable)))) | ||
| 80 | (match-lambda | ||
| 81 | ("guile" (ref '(gnu packages commencement) 'guile-final)) | ||
| 82 | ("guile-json" (ref '(gnu packages guile) 'guile-json)) | ||
| 83 | ("guile-ssh" (ref '(gnu packages ssh) 'guile-ssh)) | ||
| 84 | ("guile-git" (ref '(gnu packages guile) 'guile-git)) | ||
| 85 | ("libgcrypt" (ref '(gnu packages gnupg) 'libgcrypt)) | ||
| 86 | ("zlib" (ref '(gnu packages compression) 'zlib)) | ||
| 87 | ("gzip" (ref '(gnu packages compression) 'gzip)) | ||
| 88 | ("bzip2" (ref '(gnu packages compression) 'bzip2)) | ||
| 89 | ("xz" (ref '(gnu packages compression) 'xz)) | ||
| 90 | ("guix" (ref '(gnu packages package-management) | ||
| 91 | 'guix-register))))) | ||
| 92 | |||
| 93 | |||
| 94 | ;;; | ||
| 95 | ;;; Derivations. | ||
| 96 | ;;; | ||
| 97 | |||
| 98 | ;; Node in a DAG of build tasks. Each node maps to a derivation, but it's | ||
| 99 | ;; easier to express things this way. | ||
| 100 | (define-record-type <node> | ||
| 101 | (node name modules source dependencies compiled) | ||
| 102 | node? | ||
| 103 | (name node-name) ;string | ||
| 104 | (modules node-modules) ;list of module names | ||
| 105 | (source node-source) ;list of source files | ||
| 106 | (dependencies node-dependencies) ;list of nodes | ||
| 107 | (compiled node-compiled)) ;node -> lowerable object | ||
| 108 | |||
| 109 | (define (node-fold proc init nodes) | ||
| 110 | (let loop ((nodes nodes) | ||
| 111 | (visited (setq)) | ||
| 112 | (result init)) | ||
| 113 | (match nodes | ||
| 114 | (() result) | ||
| 115 | ((head tail ...) | ||
| 116 | (if (set-contains? visited head) | ||
| 117 | (loop tail visited result) | ||
| 118 | (loop tail (set-insert head visited) | ||
| 119 | (proc head result))))))) | ||
| 120 | |||
| 121 | (define (node-modules/recursive nodes) | ||
| 122 | (node-fold (lambda (node modules) | ||
| 123 | (append (node-modules node) modules)) | ||
| 124 | '() | ||
| 125 | nodes)) | ||
| 126 | |||
| 127 | (define* (closure modules #:optional (except '())) | ||
| 128 | (source-module-closure modules | ||
| 129 | #:select? | ||
| 130 | (match-lambda | ||
| 131 | (('guix 'config) | ||
| 132 | #f) | ||
| 133 | ((and module | ||
| 134 | (or ('guix _ ...) ('gnu _ ...))) | ||
| 135 | (not (member module except))) | ||
| 136 | (rest #f)))) | ||
| 137 | |||
| 138 | (define module->import | ||
| 139 | ;; Return a file-name/file-like object pair for the specified module and | ||
| 140 | ;; suitable for 'imported-files'. | ||
| 141 | (match-lambda | ||
| 142 | ((module '=> thing) | ||
| 143 | (let ((file (module-name->file-name module))) | ||
| 144 | (list file thing))) | ||
| 145 | (module | ||
| 146 | (let ((file (module-name->file-name module))) | ||
| 147 | (list file | ||
| 148 | (local-file (search-path %load-path file))))))) | ||
| 149 | |||
| 150 | (define* (scheme-node name modules #:optional (dependencies '()) | ||
| 151 | #:key (extra-modules '()) (extra-files '()) | ||
| 152 | (extensions '()) | ||
| 153 | parallel? guile-for-build) | ||
| 154 | "Return a node that builds the given Scheme MODULES, and depends on | ||
| 155 | DEPENDENCIES (a list of nodes). EXTRA-MODULES is a list of additional modules | ||
| 156 | added to the source, and EXTRA-FILES is a list of additional files. | ||
| 157 | EXTENSIONS is a set of full-blown Guile packages (e.g., 'guile-json') that | ||
| 158 | must be present in the search path." | ||
| 159 | (let* ((modules (append extra-modules | ||
| 160 | (closure modules | ||
| 161 | (node-modules/recursive dependencies)))) | ||
| 162 | (module-files (map module->import modules)) | ||
| 163 | (source (imported-files (string-append name "-source") | ||
| 164 | (append module-files extra-files)))) | ||
| 165 | (node name modules source dependencies | ||
| 166 | (compiled-modules name source modules | ||
| 167 | (map node-source dependencies) | ||
| 168 | (map node-compiled dependencies) | ||
| 169 | #:extensions extensions | ||
| 170 | #:parallel? parallel? | ||
| 171 | #:guile-for-build guile-for-build)))) | ||
| 172 | |||
| 173 | (define (file-imports directory sub-directory pred) | ||
| 174 | "List all the files matching PRED under DIRECTORY/SUB-DIRECTORY. Return a | ||
| 175 | list of file-name/file-like objects suitable as inputs to 'imported-files'." | ||
| 176 | (map (lambda (file) | ||
| 177 | (list (string-drop file (+ 1 (string-length directory))) | ||
| 178 | (local-file file #:recursive? #t))) | ||
| 179 | (find-files (string-append directory "/" sub-directory) pred))) | ||
| 180 | |||
| 181 | (define (scheme-modules* directory sub-directory) | ||
| 182 | "Return the list of module names found under SUB-DIRECTORY in DIRECTORY." | ||
| 183 | (let ((prefix (string-length directory))) | ||
| 184 | (map (lambda (file) | ||
| 185 | (file-name->module-name (string-drop file prefix))) | ||
| 186 | (scheme-files (string-append directory "/" sub-directory))))) | ||
| 187 | |||
| 188 | (define* (compiled-guix source #:key (version %guix-version) | ||
| 189 | (name (string-append "guix-" version)) | ||
| 190 | (guile-version (effective-version)) | ||
| 191 | (guile-for-build (guile-for-build guile-version)) | ||
| 192 | (libgcrypt (specification->package "libgcrypt")) | ||
| 193 | (zlib (specification->package "zlib")) | ||
| 194 | (gzip (specification->package "gzip")) | ||
| 195 | (bzip2 (specification->package "bzip2")) | ||
| 196 | (xz (specification->package "xz")) | ||
| 197 | (guix (specification->package "guix"))) | ||
| 198 | "Return a file-like object that contains a compiled Guix." | ||
| 199 | (define guile-json | ||
| 200 | (package-for-guile guile-version | ||
| 201 | "guile-json" | ||
| 202 | "guile2.2-json" | ||
| 203 | "guile2.0-json")) | ||
| 204 | |||
| 205 | (define guile-ssh | ||
| 206 | (package-for-guile guile-version | ||
| 207 | "guile-ssh" | ||
| 208 | "guile2.2-ssh" | ||
| 209 | "guile2.0-ssh")) | ||
| 210 | |||
| 211 | (define guile-git | ||
| 212 | (package-for-guile guile-version | ||
| 213 | "guile-git" | ||
| 214 | "guile2.0-git")) | ||
| 215 | |||
| 216 | |||
| 217 | (define dependencies | ||
| 218 | (match (append-map (lambda (package) | ||
| 219 | (cons (list "x" package) | ||
| 220 | (package-transitive-inputs package))) | ||
| 221 | (list guile-git guile-json guile-ssh)) | ||
| 222 | (((labels packages _ ...) ...) | ||
| 223 | packages))) | ||
| 224 | |||
| 225 | (define *core-modules* | ||
| 226 | (scheme-node "guix-core" | ||
| 227 | '((guix) | ||
| 228 | (guix monad-repl) | ||
| 229 | (guix packages) | ||
| 230 | (guix download) | ||
| 231 | (guix discovery) | ||
| 232 | (guix profiles) | ||
| 233 | (guix build-system gnu) | ||
| 234 | (guix build-system trivial) | ||
| 235 | (guix build profiles) | ||
| 236 | (guix build gnu-build-system)) | ||
| 237 | |||
| 238 | ;; Provide a dummy (guix config) with the default version | ||
| 239 | ;; number, storedir, etc. This is so that "guix-core" is the | ||
| 240 | ;; same across all installations and doesn't need to be | ||
| 241 | ;; rebuilt when the version changes, which in turn means we | ||
| 242 | ;; can have substitutes for it. | ||
| 243 | #:extra-modules | ||
| 244 | `(((guix config) | ||
| 245 | => ,(make-config.scm #:libgcrypt | ||
| 246 | (specification->package | ||
| 247 | "libgcrypt")))) | ||
| 248 | |||
| 249 | #:guile-for-build guile-for-build)) | ||
| 250 | |||
| 251 | (define *extra-modules* | ||
| 252 | (scheme-node "guix-extra" | ||
| 253 | (filter-map (match-lambda | ||
| 254 | (('guix 'scripts _ ..1) #f) | ||
| 255 | (name name)) | ||
| 256 | (scheme-modules* source "guix")) | ||
| 257 | (list *core-modules*) | ||
| 258 | #:extensions dependencies | ||
| 259 | #:guile-for-build guile-for-build)) | ||
| 260 | |||
| 261 | (define *package-modules* | ||
| 262 | (scheme-node "guix-packages" | ||
| 263 | `((gnu packages) | ||
| 264 | ,@(scheme-modules* source "gnu/packages")) | ||
| 265 | (list *core-modules* *extra-modules*) | ||
| 266 | #:extensions dependencies | ||
| 267 | #:extra-files ;all the non-Scheme files | ||
| 268 | (file-imports source "gnu/packages" | ||
| 269 | (lambda (file stat) | ||
| 270 | (and (eq? 'regular (stat:type stat)) | ||
| 271 | (not (string-suffix? ".scm" file)) | ||
| 272 | (not (string-suffix? ".go" file)) | ||
| 273 | (not (string-prefix? ".#" file)) | ||
| 274 | (not (string-suffix? "~" file))))) | ||
| 275 | #:guile-for-build guile-for-build)) | ||
| 276 | |||
| 277 | (define *system-modules* | ||
| 278 | (scheme-node "guix-system" | ||
| 279 | `((gnu system) | ||
| 280 | (gnu services) | ||
| 281 | ,@(scheme-modules* source "gnu/system") | ||
| 282 | ,@(scheme-modules* source "gnu/services")) | ||
| 283 | (list *package-modules* *extra-modules* *core-modules*) | ||
| 284 | #:extensions dependencies | ||
| 285 | #:extra-files | ||
| 286 | (file-imports source "gnu/system/examples" (const #t)) | ||
| 287 | #:guile-for-build | ||
| 288 | guile-for-build)) | ||
| 289 | |||
| 290 | (define *cli-modules* | ||
| 291 | (scheme-node "guix-cli" | ||
| 292 | (scheme-modules* source "/guix/scripts") | ||
| 293 | (list *core-modules* *extra-modules* *package-modules* | ||
| 294 | *system-modules*) | ||
| 295 | #:extensions dependencies | ||
| 296 | #:guile-for-build guile-for-build)) | ||
| 297 | |||
| 298 | (define *config* | ||
| 299 | (scheme-node "guix-config" | ||
| 300 | '() | ||
| 301 | #:extra-modules | ||
| 302 | `(((guix config) | ||
| 303 | => ,(make-config.scm #:libgcrypt libgcrypt | ||
| 304 | #:zlib zlib | ||
| 305 | #:gzip gzip | ||
| 306 | #:bzip2 bzip2 | ||
| 307 | #:xz xz | ||
| 308 | #:guix guix | ||
| 309 | #:package-name | ||
| 310 | %guix-package-name | ||
| 311 | #:package-version | ||
| 312 | version | ||
| 313 | #:bug-report-address | ||
| 314 | %guix-bug-report-address | ||
| 315 | #:home-page-url | ||
| 316 | %guix-home-page-url))) | ||
| 317 | #:guile-for-build guile-for-build)) | ||
| 318 | |||
| 319 | (directory-union name | ||
| 320 | (append-map (lambda (node) | ||
| 321 | (list (node-source node) | ||
| 322 | (node-compiled node))) | ||
| 323 | |||
| 324 | ;; Note: *CONFIG* comes first so that it | ||
| 325 | ;; overrides the (guix config) module that | ||
| 326 | ;; comes with *CORE-MODULES*. | ||
| 327 | (list *config* | ||
| 328 | *cli-modules* | ||
| 329 | *system-modules* | ||
| 330 | *package-modules* | ||
| 331 | *extra-modules* | ||
| 332 | *core-modules*)) | ||
| 333 | |||
| 334 | ;; Silently choose the first entry upon collision so that | ||
| 335 | ;; we choose *CONFIG*. | ||
| 336 | #:resolve-collision 'first | ||
| 337 | |||
| 338 | ;; When we do (add-to-store "utils.scm"), "utils.scm" must | ||
| 339 | ;; be a regular file, not a symlink. Thus, arrange so that | ||
| 340 | ;; regular files appear as regular files in the final | ||
| 341 | ;; output. | ||
| 342 | #:copy? #t | ||
| 343 | #:quiet? #t)) | ||
| 344 | |||
| 345 | |||
| 346 | ;;; | ||
| 347 | ;;; Generating (guix config). | ||
| 348 | ;;; | ||
| 349 | |||
| 350 | (define %dependency-variables | ||
| 351 | ;; (guix config) variables corresponding to dependencies. | ||
| 352 | '(%libgcrypt %libz %xz %gzip %bzip2 %nix-instantiate | ||
| 353 | %sbindir %guix-register-program)) | ||
| 354 | |||
| 355 | (define %persona-variables | ||
| 356 | ;; (guix config) variables that define Guix's persona. | ||
| 357 | '(%guix-package-name | ||
| 358 | %guix-version | ||
| 359 | %guix-bug-report-address | ||
| 360 | %guix-home-page-url)) | ||
| 361 | |||
| 362 | (define %config-variables | ||
| 363 | ;; (guix config) variables corresponding to Guix configuration (storedir, | ||
| 364 | ;; localstatedir, etc.) | ||
| 365 | (sort (filter pair? | ||
| 366 | (module-map (lambda (name var) | ||
| 367 | (and (not (memq name %dependency-variables)) | ||
| 368 | (not (memq name %persona-variables)) | ||
| 369 | (cons name (variable-ref var)))) | ||
| 370 | (resolve-interface '(guix config)))) | ||
| 371 | (lambda (name+value1 name+value2) | ||
| 372 | (string<? (symbol->string (car name+value1)) | ||
| 373 | (symbol->string (car name+value2)))))) | ||
| 374 | |||
| 375 | (define* (make-config.scm #:key libgcrypt zlib gzip xz bzip2 guix | ||
| 376 | (package-name "GNU Guix") | ||
| 377 | (package-version "0") | ||
| 378 | (bug-report-address "bug-guix@gnu.org") | ||
| 379 | (home-page-url "https://gnu.org/s/guix")) | ||
| 380 | |||
| 381 | ;; Hack so that Geiser is not confused. | ||
| 382 | (define defmod 'define-module) | ||
| 383 | |||
| 384 | (scheme-file "config.scm" | ||
| 385 | #~(begin | ||
| 386 | (#$defmod (guix config) | ||
| 387 | #:export (%guix-package-name | ||
| 388 | %guix-version | ||
| 389 | %guix-bug-report-address | ||
| 390 | %guix-home-page-url | ||
| 391 | %sbindir | ||
| 392 | %libgcrypt | ||
| 393 | %libz | ||
| 394 | %gzip | ||
| 395 | %bzip2 | ||
| 396 | %xz | ||
| 397 | %nix-instantiate)) | ||
| 398 | |||
| 399 | ;; XXX: Work around <http://bugs.gnu.org/15602>. | ||
| 400 | (eval-when (expand load eval) | ||
| 401 | #$@(map (match-lambda | ||
| 402 | ((name . value) | ||
| 403 | #~(define-public #$name #$value))) | ||
| 404 | %config-variables) | ||
| 405 | |||
| 406 | (define %guix-package-name #$package-name) | ||
| 407 | (define %guix-version #$package-version) | ||
| 408 | (define %guix-bug-report-address #$bug-report-address) | ||
| 409 | (define %guix-home-page-url #$home-page-url) | ||
| 410 | |||
| 411 | (define %sbindir | ||
| 412 | ;; This is used to define '%guix-register-program'. | ||
| 413 | ;; TODO: Use a derivation that builds nothing but the | ||
| 414 | ;; C++ part. | ||
| 415 | #+(and guix (file-append guix "/sbin"))) | ||
| 416 | |||
| 417 | (define %guix-register-program | ||
| 418 | (or (getenv "GUIX_REGISTER") | ||
| 419 | (and %sbindir | ||
| 420 | (string-append %sbindir "/guix-register")))) | ||
| 421 | |||
| 422 | (define %gzip | ||
| 423 | #+(and gzip (file-append gzip "/bin/gzip"))) | ||
| 424 | (define %bzip2 | ||
| 425 | #+(and bzip2 (file-append bzip2 "/bin/bzip2"))) | ||
| 426 | (define %xz | ||
| 427 | #+(and xz (file-append xz "/bin/xz"))) | ||
| 428 | |||
| 429 | (define %libgcrypt | ||
| 430 | #+(and libgcrypt | ||
| 431 | (file-append libgcrypt "/lib/libgcrypt"))) | ||
| 432 | (define %libz | ||
| 433 | #+(and zlib | ||
| 434 | (file-append zlib "/lib/libz"))) | ||
| 435 | |||
| 436 | (define %nix-instantiate ;for (guix import snix) | ||
| 437 | "nix-instantiate"))))) | ||
| 438 | |||
| 439 | |||
| 440 | |||
| 441 | ;;; | ||
| 442 | ;;; Building. | ||
| 443 | ;;; | ||
| 444 | |||
| 445 | (define (imported-files name files) | ||
| 446 | ;; This is a non-monadic, simplified version of 'imported-files' from (guix | ||
| 447 | ;; gexp). | ||
| 448 | (define build | ||
| 449 | (with-imported-modules (source-module-closure | ||
| 450 | '((guix build utils))) | ||
| 451 | #~(begin | ||
| 452 | (use-modules (ice-9 match) | ||
| 453 | (guix build utils)) | ||
| 454 | |||
| 455 | (mkdir (ungexp output)) (chdir (ungexp output)) | ||
| 456 | (for-each (match-lambda | ||
| 457 | ((final-path store-path) | ||
| 458 | (mkdir-p (dirname final-path)) | ||
| 459 | |||
| 460 | ;; Note: We need regular files to be regular files, not | ||
| 461 | ;; symlinks, as this makes a difference for | ||
| 462 | ;; 'add-to-store'. | ||
| 463 | (copy-file store-path final-path))) | ||
| 464 | '#$files)))) | ||
| 465 | |||
| 466 | (computed-file name build)) | ||
| 467 | |||
| 468 | (define* (compiled-modules name module-tree modules | ||
| 469 | #:optional | ||
| 470 | (dependencies '()) | ||
| 471 | (dependencies-compiled '()) | ||
| 472 | #:key | ||
| 473 | (extensions '()) ;full-blown Guile packages | ||
| 474 | parallel? | ||
| 475 | guile-for-build) | ||
| 476 | ;; This is a non-monadic, enhanced version of 'compiled-file' from (guix | ||
| 477 | ;; gexp). | ||
| 478 | (define build | ||
| 479 | (with-imported-modules (source-module-closure | ||
| 480 | '((guix build compile) | ||
| 481 | (guix build utils))) | ||
| 482 | #~(begin | ||
| 483 | (use-modules (srfi srfi-26) | ||
| 484 | (ice-9 match) | ||
| 485 | (ice-9 format) | ||
| 486 | (ice-9 threads) | ||
| 487 | (guix build compile) | ||
| 488 | (guix build utils)) | ||
| 489 | |||
| 490 | (define (regular? file) | ||
| 491 | (not (member file '("." "..")))) | ||
| 492 | |||
| 493 | (define (report-load file total completed) | ||
| 494 | (display #\cr) | ||
| 495 | (format #t | ||
| 496 | "loading...\t~5,1f% of ~d files" ;FIXME: i18n | ||
| 497 | (* 100. (/ completed total)) total) | ||
| 498 | (force-output)) | ||
| 499 | |||
| 500 | (define (report-compilation file total completed) | ||
| 501 | (display #\cr) | ||
| 502 | (format #t "compiling...\t~5,1f% of ~d files" ;FIXME: i18n | ||
| 503 | (* 100. (/ completed total)) total) | ||
| 504 | (force-output)) | ||
| 505 | |||
| 506 | (define (process-directory directory output) | ||
| 507 | (let ((files (find-files directory "\\.scm$")) | ||
| 508 | (prefix (+ 1 (string-length directory)))) | ||
| 509 | ;; Hide compilation warnings. | ||
| 510 | (parameterize ((current-warning-port (%make-void-port "w"))) | ||
| 511 | (compile-files directory #$output | ||
| 512 | (map (cut string-drop <> prefix) files) | ||
| 513 | #:workers (parallel-job-count) | ||
| 514 | #:report-load report-load | ||
| 515 | #:report-compilation report-compilation)))) | ||
| 516 | |||
| 517 | (setvbuf (current-output-port) _IONBF) | ||
| 518 | (setvbuf (current-error-port) _IONBF) | ||
| 519 | |||
| 520 | (set! %load-path (cons #+module-tree %load-path)) | ||
| 521 | (set! %load-path | ||
| 522 | (append '#+dependencies | ||
| 523 | (map (lambda (extension) | ||
| 524 | (string-append extension "/share/guile/site/" | ||
| 525 | (effective-version))) | ||
| 526 | '#+extensions) | ||
| 527 | %load-path)) | ||
| 528 | |||
| 529 | (set! %load-compiled-path | ||
| 530 | (append '#+dependencies-compiled | ||
| 531 | (map (lambda (extension) | ||
| 532 | (string-append extension "/lib/guile/" | ||
| 533 | (effective-version) | ||
| 534 | "/site-ccache")) | ||
| 535 | '#+extensions) | ||
| 536 | %load-compiled-path)) | ||
| 537 | |||
| 538 | ;; Load the compiler modules upfront. | ||
| 539 | (compile #f) | ||
| 540 | |||
| 541 | (mkdir #$output) | ||
| 542 | (chdir #+module-tree) | ||
| 543 | (process-directory "." #$output)))) | ||
| 544 | |||
| 545 | (computed-file name build | ||
| 546 | #:guile guile-for-build | ||
| 547 | #:options | ||
| 548 | `(#:local-build? #f ;allow substitutes | ||
| 549 | |||
| 550 | ;; Don't annoy people about _IONBF deprecation. | ||
| 551 | #:env-vars (("GUILE_WARN_DEPRECATED" . "no"))))) | ||
| 552 | |||
| 553 | |||
| 554 | ;;; | ||
| 555 | ;;; Building. | ||
| 556 | ;;; | ||
| 557 | |||
| 558 | (define (guile-for-build version) | ||
| 559 | "Return a derivation for Guile 2.0 or 2.2, whichever matches the currently | ||
| 560 | running Guile." | ||
| 561 | (define canonical-package ;soft reference | ||
| 562 | (module-ref (resolve-interface '(gnu packages base)) | ||
| 563 | 'canonical-package)) | ||
| 564 | |||
| 565 | (match version | ||
| 566 | ("2.2.2" | ||
| 567 | ;; Gross hack to avoid ABI incompatibilities (see | ||
| 568 | ;; <https://bugs.gnu.org/29570>.) | ||
| 569 | (module-ref (resolve-interface '(gnu packages guile)) | ||
| 570 | 'guile-2.2.2)) | ||
| 571 | ("2.2" | ||
| 572 | (canonical-package (module-ref (resolve-interface '(gnu packages guile)) | ||
| 573 | 'guile-2.2/fixed))) | ||
| 574 | ("2.0" | ||
| 575 | (canonical-package (specification->package "guile@2.0"))))) | ||
| 576 | |||
| 577 | (define* (guix-derivation source version | ||
| 578 | #:optional (guile-version (effective-version))) | ||
| 579 | "Return, as a monadic value, the derivation to build the Guix from SOURCE | ||
| 580 | for GUILE-VERSION. Use VERSION as the version string." | ||
| 581 | (define (shorten version) | ||
| 582 | (if (and (string-every char-set:hex-digit version) | ||
| 583 | (> (string-length version) 9)) | ||
| 584 | (string-take version 9) ;Git commit | ||
| 585 | version)) | ||
| 586 | |||
| 587 | (define guile | ||
| 588 | (guile-for-build guile-version)) | ||
| 589 | |||
| 590 | (mbegin %store-monad | ||
| 591 | (set-guile-for-build guile) | ||
| 592 | (lower-object (compiled-guix source | ||
| 593 | #:version version | ||
| 594 | #:name (string-append "guix-" | ||
| 595 | (shorten version)) | ||
| 596 | #:guile-version (match guile-version | ||
| 597 | ("2.2.2" "2.2") | ||
| 598 | (version version)) | ||
| 599 | #:guile-for-build guile)))) | ||
