;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2017, 2018 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
#:use-module (guix discovery)
#:use-module (guix packages)
#:use-module (guix sets)
- #:use-module (guix utils)
#:use-module (guix modules)
- #:use-module (guix build utils)
+ #:use-module ((guix build utils) #:select (find-files))
#:use-module ((guix build compile) #:select (%lightweight-optimizations))
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9)
+ #:use-module (srfi srfi-35)
#:use-module (ice-9 match)
#:export (make-config.scm
whole-package ;for internal use in 'guix pull'
compiled-guix
- guix-derivation
- reload-guix))
+ guix-derivation))
\f
;;;
;;; Dependency handling.
;;;
-(define* (false-if-wrong-guile package
- #:optional (guile-version (effective-version)))
- "Return #f if PACKAGE depends on the \"wrong\" major version of Guile (e.g.,
-2.0 instead of 2.2), otherwise return PACKAGE."
- (let ((guile (any (match-lambda
- ((label (? package? dep) _ ...)
- (and (string=? (package-name dep) "guile")
- dep)))
- (package-direct-inputs package))))
- (and (or (not guile)
- (string-prefix? guile-version
- (package-version guile)))
- package)))
-
-(define (package-for-guile guile-version . names)
- "Return the package with one of the given NAMES that depends on
-GUILE-VERSION (\"2.0\" or \"2.2\"), or #f if none of the packages matches."
- (let loop ((names names))
- (match names
- (()
- #f)
- ((name rest ...)
- (match (specification->package name)
- (#f
- (loop rest))
- ((? package? package)
- (or (false-if-wrong-guile package guile-version)
- (loop rest))))))))
-
(define specification->package
;; Use our own variant of that procedure because that of (gnu packages)
;; would traverse all the .scm files, which is wasteful.
("guile-ssh" (ref '(gnu packages ssh) 'guile-ssh))
("guile-git" (ref '(gnu packages guile) 'guile-git))
("guile-sqlite3" (ref '(gnu packages guile) 'guile-sqlite3))
- ("libgcrypt" (ref '(gnu packages gnupg) 'libgcrypt))
+ ("guile-gcrypt" (ref '(gnu packages gnupg) 'guile-gcrypt))
+ ("gnutls" (ref '(gnu packages tls) 'gnutls))
("zlib" (ref '(gnu packages compression) 'zlib))
("gzip" (ref '(gnu packages compression) 'gzip))
("bzip2" (ref '(gnu packages compression) 'bzip2))
("xz" (ref '(gnu packages compression) 'xz))
- ("guix" (ref '(gnu packages package-management)
- 'guix-register))
- ("guile2.0-json" (ref '(gnu packages guile) 'guile2.0-json))
- ("guile2.0-ssh" (ref '(gnu packages ssh) 'guile2.0-ssh))
- ("guile2.0-git" (ref '(gnu packages guile) 'guile2.0-git))
- ;; XXX: No "guile2.0-sqlite3".
- (_ #f)))) ;no such package
+ (_ #f)))) ;no such package
\f
;;;
(dependencies node-dependencies) ;list of nodes
(compiled node-compiled)) ;node -> lowerable object
+;; File mappings are essentially an alist as passed to 'imported-files'.
+(define-record-type <file-mapping>
+ (file-mapping name alist)
+ file-mapping?
+ (name file-mapping-name)
+ (alist file-mapping-alist))
+
+(define-gexp-compiler (file-mapping-compiler (mapping <file-mapping>)
+ system target)
+ ;; Here we use 'imported-files', which can arrange to directly import all
+ ;; the files instead of creating a derivation, when possible.
+ (imported-files (map (match-lambda
+ ((destination (? local-file? file))
+ (cons destination
+ (local-file-absolute-file-name file)))
+ ((destination source)
+ (cons destination source))) ;silliness
+ (file-mapping-alist mapping))
+ #:name (file-mapping-name mapping)
+ #:system system))
+
+(define (node-source+compiled node)
+ "Return a \"bundle\" containing both the source code and object files for
+NODE's modules, under their FHS directories: share/guile/site and lib/guile."
+ (define build
+ (with-imported-modules '((guix build utils))
+ #~(begin
+ (use-modules (guix build utils))
+
+ (define source
+ (string-append #$output "/share/guile/site/"
+ (effective-version)))
+
+ (define object
+ (string-append #$output "/lib/guile/" (effective-version)
+ "/site-ccache"))
+
+ (mkdir-p (dirname source))
+ (symlink #$(node-source node) source)
+ (mkdir-p (dirname object))
+ (symlink #$(node-compiled node) object))))
+
+ (computed-file (string-append (node-name node) "-modules")
+ build))
+
(define (node-fold proc init nodes)
(let loop ((nodes nodes)
(visited (setq))
(closure modules
(node-modules/recursive dependencies))))
(module-files (map module->import modules))
- (source (imported-files (string-append name "-source")
- (append module-files extra-files))))
+ (source (file-mapping (string-append name "-source")
+ (append module-files extra-files))))
(node name modules source dependencies
(compiled-modules name source
(map car module-files)
(local-file file #:recursive? #t)))
(find-files (string-append directory "/" sub-directory) pred)))
-(define (scheme-modules* directory sub-directory)
- "Return the list of module names found under SUB-DIRECTORY in DIRECTORY."
- (let ((prefix (string-length directory)))
- (map (lambda (file)
- (file-name->module-name (string-drop file prefix)))
- (scheme-files (string-append directory "/" sub-directory)))))
+(define* (file-append* item file #:key (recursive? #t))
+ "Return FILE within ITEM, which may be a file name or a file-like object.
+When ITEM is a plain file name (a string), simply return a 'local-file'
+record with the new file name."
+ (match item
+ ((? string?)
+ ;; This is the optimal case: we return a new "source". Thus, a
+ ;; derivation that depends on this sub-directory does not depend on ITEM
+ ;; itself.
+ (local-file (string-append item "/" file)
+ #:recursive? recursive?))
+ ;; TODO: Add 'local-file?' case.
+ (_
+ ;; In this case, anything that refers to the result also depends on ITEM,
+ ;; which isn't great.
+ (file-append item "/" file))))
+
+(define* (locale-data source domain
+ #:optional (directory domain))
+ "Return the locale data from 'po/DIRECTORY' in SOURCE, corresponding to
+DOMAIN, a gettext domain."
+ (define gettext
+ (module-ref (resolve-interface '(gnu packages gettext))
+ 'gettext-minimal))
+
+ (define build
+ (with-imported-modules '((guix build utils))
+ #~(begin
+ (use-modules (guix build utils)
+ (srfi srfi-26)
+ (ice-9 match) (ice-9 ftw))
+
+ (define po-directory
+ #+(file-append* source (string-append "po/" directory)))
+
+ (define (compile language)
+ (let ((gmo (string-append #$output "/" language "/LC_MESSAGES/"
+ #$domain ".mo")))
+ (mkdir-p (dirname gmo))
+ (invoke #+(file-append gettext "/bin/msgfmt")
+ "-c" "--statistics" "--verbose"
+ "-o" gmo
+ (string-append po-directory "/" language ".po"))))
+
+ (define (linguas)
+ ;; Return the list of languages. Note: don't read 'LINGUAS'
+ ;; because it contains things like 'en@boldquot' that do not have
+ ;; a corresponding .po file.
+ (map (cut basename <> ".po")
+ (scandir po-directory
+ (cut string-suffix? ".po" <>))))
+
+ (for-each compile (linguas)))))
+
+ (computed-file (string-append "guix-locale-" domain)
+ build))
+
+(define (info-manual source)
+ "Return the Info manual built from SOURCE."
+ (define texinfo
+ (module-ref (resolve-interface '(gnu packages texinfo))
+ 'texinfo))
+
+ (define graphviz
+ (module-ref (resolve-interface '(gnu packages graphviz))
+ 'graphviz))
+
+ (define glibc-utf8-locales
+ (module-ref (resolve-interface '(gnu packages base))
+ 'glibc-utf8-locales))
+
+ (define documentation
+ (file-append* source "doc"))
+
+ (define examples
+ (file-append* source "gnu/system/examples"))
+
+ (define build
+ (with-imported-modules '((guix build utils))
+ #~(begin
+ (use-modules (guix build utils))
+
+ (mkdir #$output)
+
+ ;; Create 'version.texi'.
+ ;; XXX: Can we use a more meaningful version string yet one that
+ ;; doesn't change at each commit?
+ (call-with-output-file "version.texi"
+ (lambda (port)
+ (let ((version "0.0-git"))
+ (format port "
+@set UPDATED 1 January 1970
+@set UPDATED-MONTH January 1970
+@set EDITION ~a
+@set VERSION ~a\n" version version))))
+
+ ;; Copy configuration templates that the manual includes.
+ (for-each (lambda (template)
+ (copy-file template
+ (string-append
+ "os-config-"
+ (basename template ".tmpl")
+ ".texi")))
+ (find-files #$examples "\\.tmpl$"))
+
+ ;; Build graphs.
+ (mkdir-p (string-append #$output "/images"))
+ (for-each (lambda (dot-file)
+ (invoke #+(file-append graphviz "/bin/dot")
+ "-Tpng" "-Gratio=.9" "-Gnodesep=.005"
+ "-Granksep=.00005" "-Nfontsize=9"
+ "-Nheight=.1" "-Nwidth=.1"
+ "-o" (string-append #$output "/images/"
+ (basename dot-file ".dot")
+ ".png")
+ dot-file))
+ (find-files (string-append #$documentation "/images")
+ "\\.dot$"))
+
+ ;; Copy other PNGs.
+ (for-each (lambda (png-file)
+ (install-file png-file
+ (string-append #$output "/images")))
+ (find-files (string-append #$documentation "/images")
+ "\\.png$"))
+
+ ;; Finally build the manual. Copy it the Texinfo files to $PWD and
+ ;; add a symlink to the 'images' directory so that 'makeinfo' can
+ ;; see those images and produce image references in the Info output.
+ (copy-recursively #$documentation "."
+ #:log (%make-void-port "w"))
+ (delete-file-recursively "images")
+ (symlink (string-append #$output "/images") "images")
+
+ ;; Provide UTF-8 locales needed by the 'xspara.c' code in makeinfo.
+ (setenv "GUIX_LOCPATH"
+ #+(file-append glibc-utf8-locales "/lib/locale"))
+
+ (for-each (lambda (texi)
+ (unless (string=? "guix.texi" texi)
+ ;; Create 'version-LL.texi'.
+ (let* ((base (basename texi ".texi"))
+ (dot (string-index base #\.))
+ (tag (string-drop base (+ 1 dot))))
+ (symlink "version.texi"
+ (string-append "version-" tag ".texi"))))
+
+ (invoke #+(file-append texinfo "/bin/makeinfo")
+ texi "-I" #$documentation
+ "-I" "."
+ "-o" (string-append #$output "/"
+ (basename texi ".texi")
+ ".info")))
+ (cons "guix.texi"
+ (find-files "." "^guix\\.[a-z]{2}\\.texi$")))
+
+ ;; Compress Info files.
+ (setenv "PATH"
+ #+(file-append (specification->package "gzip") "/bin"))
+ (for-each (lambda (file)
+ (invoke "gzip" "-9n" file))
+ (find-files #$output "\\.info(-[0-9]+)?$")))))
+
+ (computed-file "guix-manual" build))
+
+(define* (guile-module-union things #:key (name "guix-module-union"))
+ "Return the union of the subset of THINGS (packages, computed files, etc.)
+that provide Guile modules."
+ (define build
+ (with-imported-modules '((guix build union))
+ #~(begin
+ (use-modules (guix build union))
+
+ (define (modules directory)
+ (string-append directory "/share/guile/site"))
-(define* (guix-command modules #:key (dependencies '())
- (guile-version (effective-version)))
+ (define (objects directory)
+ (string-append directory "/lib/guile"))
+
+ (union-build #$output
+ (filter (lambda (directory)
+ (or (file-exists? (modules directory))
+ (file-exists? (objects directory))))
+ '#$things)
+
+ #:log-port (%make-void-port "w")))))
+
+ (computed-file name build))
+
+(define* (guix-command modules
+ #:key source (dependencies '())
+ guile (guile-version (effective-version)))
"Return the 'guix' command such that it adds MODULES and DEPENDENCIES in its
load path."
+ (define module-directory
+ ;; To minimize the number of 'stat' calls needed to locate a module,
+ ;; create the union of all the module directories.
+ (guile-module-union (cons modules dependencies)))
+
(program-file "guix-command"
#~(begin
(set! %load-path
- (append '#$(map (lambda (package)
- (file-append package
- "/share/guile/site/"
- guile-version))
- dependencies)
- %load-path))
+ (cons (string-append #$module-directory
+ "/share/guile/site/"
+ (effective-version))
+ %load-path))
(set! %load-compiled-path
- (append '#$(map (lambda (package)
- (file-append package "/lib/guile/"
- guile-version
- "/site-ccache"))
- dependencies)
- %load-compiled-path))
-
- (set! %load-path (cons #$modules %load-path))
- (set! %load-compiled-path
- (cons #$modules %load-compiled-path))
+ (cons (string-append #$module-directory
+ "/lib/guile/"
+ (effective-version)
+ "/site-ccache")
+ %load-compiled-path))
(let ((guix-main (module-ref (resolve-interface '(guix ui))
'guix-main)))
- ;; TODO: Compute locale data.
- ;; (bindtextdomain "guix" "@localedir@")
- ;; (bindtextdomain "guix-packages" "@localedir@")
+ #$(if source
+ #~(begin
+ (bindtextdomain "guix"
+ #$(locale-data source "guix"))
+ (bindtextdomain "guix-packages"
+ #$(locale-data source
+ "guix-packages"
+ "packages")))
+ #t)
;; XXX: It would be more convenient to change it to:
;; (exit (apply guix-main (command-line)))
- (apply guix-main (command-line))))))
+ (apply guix-main (command-line))))
+ #:guile guile))
+
+(define (miscellaneous-files source)
+ "Return data files taken from SOURCE."
+ (file-mapping "guix-misc"
+ `(("etc/bash_completion.d/guix"
+ ,(file-append* source "/etc/completion/bash/guix"))
+ ("etc/bash_completion.d/guix-daemon"
+ ,(file-append* source "/etc/completion/bash/guix-daemon"))
+ ("share/zsh/site-functions/_guix"
+ ,(file-append* source "/etc/completion/zsh/_guix"))
+ ("share/fish/vendor_completions.d/guix.fish"
+ ,(file-append* source "/etc/completion/fish/guix.fish"))
+ ("share/guix/hydra.gnu.org.pub"
+ ,(file-append* source
+ "/etc/substitutes/hydra.gnu.org.pub"))
+ ("share/guix/berlin.guixsd.org.pub"
+ ,(file-append* source
+ "/etc/substitutes/berlin.guixsd.org.pub"))
+ ("share/guix/ci.guix.info.pub" ;alias
+ ,(file-append* source "/etc/substitutes/berlin.guixsd.org.pub")))))
(define* (whole-package name modules dependencies
- #:key (guile-version (effective-version)))
+ #:key
+ (guile-version (effective-version))
+ info daemon miscellany
+ guile
+ (command (guix-command modules
+ #:dependencies dependencies
+ #:guile guile
+ #:guile-version guile-version)))
"Return the whole Guix package NAME that uses MODULES, a derivation of all
-the modules, and DEPENDENCIES, a list of packages depended on."
- (let ((command (guix-command modules
- #:dependencies dependencies
- #:guile-version guile-version)))
- ;; TODO: Move compiled modules to 'lib/guile' instead of 'share/guile'.
- (computed-file name
- (with-imported-modules '((guix build utils))
- #~(begin
- (use-modules (guix build utils))
- (mkdir-p (string-append #$output "/bin"))
- (symlink #$command
- (string-append #$output "/bin/guix"))
-
- (let ((modules (string-append #$output
- "/share/guile/site/"
- (effective-version))))
- (mkdir-p (dirname modules))
- (symlink #$modules modules)))))))
+the modules (under share/guile/site and lib/guile), and DEPENDENCIES, a list
+of packages depended on. COMMAND is the 'guix' program to use; INFO is the
+Info manual."
+ (computed-file name
+ (with-imported-modules '((guix build utils))
+ #~(begin
+ (use-modules (guix build utils))
+
+ (mkdir-p (string-append #$output "/bin"))
+ (symlink #$command
+ (string-append #$output "/bin/guix"))
+
+ (when #$daemon
+ (symlink (string-append #$daemon "/bin/guix-daemon")
+ (string-append #$output "/bin/guix-daemon")))
+
+ (let ((share (string-append #$output "/share"))
+ (lib (string-append #$output "/lib"))
+ (info #$info))
+ (mkdir-p share)
+ (symlink #$(file-append modules "/share/guile")
+ (string-append share "/guile"))
+ (when info
+ (symlink #$info (string-append share "/info")))
+
+ (mkdir-p lib)
+ (symlink #$(file-append modules "/lib/guile")
+ (string-append lib "/guile")))
+
+ (when #$miscellany
+ (copy-recursively #$miscellany #$output
+ #:log (%make-void-port "w")))))))
(define* (compiled-guix source #:key (version %guix-version)
(pull-version 1)
(name (string-append "guix-" version))
(guile-version (effective-version))
- (guile-for-build (guile-for-build guile-version))
- (libgcrypt (specification->package "libgcrypt"))
+ (guile-for-build (default-guile))
(zlib (specification->package "zlib"))
(gzip (specification->package "gzip"))
(bzip2 (specification->package "bzip2"))
(guix (specification->package "guix")))
"Return a file-like object that contains a compiled Guix."
(define guile-json
- (package-for-guile guile-version
- "guile-json"
- "guile2.0-json"))
+ (specification->package "guile-json"))
(define guile-ssh
- (package-for-guile guile-version
- "guile-ssh"
- "guile2.0-ssh"))
+ (specification->package "guile-ssh"))
(define guile-git
- (package-for-guile guile-version
- "guile-git"
- "guile2.0-git"))
+ (specification->package "guile-git"))
(define guile-sqlite3
- (package-for-guile guile-version
- "guile-sqlite3"
- "guile2.0-sqlite3"))
+ (specification->package "guile-sqlite3"))
+
+ (define guile-gcrypt
+ (specification->package "guile-gcrypt"))
+
+ (define gnutls
+ (specification->package "gnutls"))
(define dependencies
(match (append-map (lambda (package)
(cons (list "x" package)
(package-transitive-propagated-inputs package)))
- (list guile-git guile-json guile-ssh guile-sqlite3))
+ (list guile-gcrypt gnutls guile-git guile-json
+ guile-ssh guile-sqlite3))
(((labels packages _ ...) ...)
packages)))
;; rebuilt when the version changes, which in turn means we
;; can have substitutes for it.
#:extra-modules
- `(((guix config)
- => ,(make-config.scm #:libgcrypt
- (specification->package
- "libgcrypt"))))
+ `(((guix config) => ,(make-config.scm)))
;; (guix man-db) is needed at build-time by (guix profiles)
;; but we don't need to compile it; not compiling it allows
;; us to avoid an extra dependency on guile-gdbm-ffi.
#:extra-files
- `(("guix/man-db.scm" ,(local-file "../guix/man-db.scm")))
+ `(("guix/man-db.scm" ,(local-file "../guix/man-db.scm"))
+ ("guix/store/schema.sql"
+ ,(local-file "../guix/store/schema.sql")))
+ #:extensions (list guile-gcrypt)
#:guile-for-build guile-for-build))
(define *extra-modules*
(append (file-imports source "gnu/system/examples"
(const #t))
+ ;; All the installer code is on the build-side.
+ (file-imports source "gnu/installer/"
+ (const #t))
;; Build-side code that we don't build. Some of
;; these depend on guile-rsvg, the Shepherd, etc.
(file-imports source "gnu/build" (const #t)))
#:guile-for-build
guile-for-build))
+ (define *system-test-modules*
+ ;; Ship these modules mostly so (gnu ci) can refer to them.
+ (scheme-node "guix-system-tests"
+ `((gnu tests)
+ ,@(scheme-modules* source "gnu/tests"))
+ (list *core-package-modules* *package-modules*
+ *extra-modules* *system-modules* *core-modules*)
+ #:extensions dependencies
+ #:guile-for-build guile-for-build))
+
(define *cli-modules*
(scheme-node "guix-cli"
- (scheme-modules* source "/guix/scripts")
+ (append (scheme-modules* source "/guix/scripts")
+ `((gnu ci)))
(list *core-modules* *extra-modules*
*core-package-modules* *package-modules*
*system-modules*)
'()
#:extra-modules
`(((guix config)
- => ,(make-config.scm #:libgcrypt libgcrypt
- #:zlib zlib
+ => ,(make-config.scm #:zlib zlib
#:gzip gzip
#:bzip2 bzip2
#:xz xz
- #:guix guix
#:package-name
%guix-package-name
#:package-version
%guix-home-page-url)))
#:guile-for-build guile-for-build))
- (define built-modules
+ (define (built-modules node-subset)
(directory-union (string-append name "-modules")
- (append-map (lambda (node)
- (list (node-source node)
- (node-compiled node)))
+ (append-map node-subset
;; Note: *CONFIG* comes first so that it
;; overrides the (guix config) module that
;; comes with *CORE-MODULES*.
(list *config*
*cli-modules*
+ *system-test-modules*
*system-modules*
*package-modules*
*core-package-modules*
;; Version 1 is when we return the full package.
(cond ((= 1 pull-version)
;; The whole package, with a standard file hierarchy.
- (whole-package name built-modules dependencies
- #:guile-version guile-version))
+ (let* ((modules (built-modules (compose list node-source+compiled)))
+ (command (guix-command modules
+ #:source source
+ #:dependencies dependencies
+ #:guile guile-for-build
+ #:guile-version guile-version)))
+ (whole-package name modules dependencies
+ #:command command
+ #:guile guile-for-build
+
+ ;; Include 'guix-daemon'. XXX: Here we inject an
+ ;; older snapshot of guix-daemon, but that's a good
+ ;; enough approximation for now.
+ #:daemon (module-ref (resolve-interface
+ '(gnu packages
+ package-management))
+ 'guix-daemon)
+
+ #:info (info-manual source)
+ #:miscellany (miscellaneous-files source)
+ #:guile-version guile-version)))
((= 0 pull-version)
- ;; Legacy 'guix pull': just return the compiled modules.
- built-modules)
+ ;; Legacy 'guix pull': return the .scm and .go files as one
+ ;; directory.
+ (built-modules (lambda (node)
+ (list (node-source node)
+ (node-compiled node)))))
(else
;; Unsupported 'guix pull' version.
#f)))
(define %dependency-variables
;; (guix config) variables corresponding to dependencies.
- '(%libgcrypt %libz %xz %gzip %bzip2 %nix-instantiate
- %sbindir %guix-register-program))
+ '(%libz %xz %gzip %bzip2))
(define %persona-variables
;; (guix config) variables that define Guix's persona.
%guix-home-page-url))
(define %config-variables
- ;; (guix config) variables corresponding to Guix configuration (storedir,
- ;; localstatedir, etc.)
- (sort (filter pair?
- (module-map (lambda (name var)
- (and (not (memq name %dependency-variables))
- (not (memq name %persona-variables))
- (cons name (variable-ref var))))
- (resolve-interface '(guix config))))
- (lambda (name+value1 name+value2)
- (string<? (symbol->string (car name+value1))
- (symbol->string (car name+value2))))))
-
-(define* (make-config.scm #:key libgcrypt zlib gzip xz bzip2 guix
+ ;; (guix config) variables corresponding to Guix configuration.
+ (letrec-syntax ((variables (syntax-rules ()
+ ((_)
+ '())
+ ((_ variable rest ...)
+ (cons `(variable . ,variable)
+ (variables rest ...))))))
+ (variables %localstatedir %storedir %sysconfdir %system)))
+
+(define* (make-config.scm #:key zlib gzip xz bzip2
(package-name "GNU Guix")
(package-version "0")
(bug-report-address "bug-guix@gnu.org")
%guix-version
%guix-bug-report-address
%guix-home-page-url
- %sbindir
- %guix-register-program
- %libgcrypt
+ %store-directory
+ %state-directory
+ %store-database-directory
+ %config-directory
%libz
%gzip
%bzip2
- %xz
- %nix-instantiate))
+ %xz))
#$@(map (match-lambda
((name . value)
#~(define-public #$name #$value)))
%config-variables)
+ (define %store-directory
+ (or (and=> (getenv "NIX_STORE_DIR") canonicalize-path)
+ %storedir))
+
+ (define %state-directory
+ ;; This must match `NIX_STATE_DIR' as defined in
+ ;; `nix/local.mk'.
+ (or (getenv "NIX_STATE_DIR")
+ (string-append %localstatedir "/guix")))
+
+ (define %store-database-directory
+ (or (getenv "NIX_DB_DIR")
+ (string-append %state-directory "/db")))
+
+ (define %config-directory
+ ;; This must match `GUIX_CONFIGURATION_DIRECTORY' as
+ ;; defined in `nix/local.mk'.
+ (or (getenv "GUIX_CONFIGURATION_DIRECTORY")
+ (string-append %sysconfdir "/guix")))
+
(define %guix-package-name #$package-name)
(define %guix-version #$package-version)
(define %guix-bug-report-address #$bug-report-address)
(define %guix-home-page-url #$home-page-url)
- (define %sbindir
- ;; This is used to define '%guix-register-program'.
- ;; TODO: Use a derivation that builds nothing but the
- ;; C++ part.
- #+(and guix (file-append guix "/sbin")))
-
- (define %guix-register-program
- (or (getenv "GUIX_REGISTER")
- (and %sbindir
- (string-append %sbindir "/guix-register"))))
-
(define %gzip
#+(and gzip (file-append gzip "/bin/gzip")))
(define %bzip2
(define %xz
#+(and xz (file-append xz "/bin/xz")))
- (define %libgcrypt
- #+(and libgcrypt
- (file-append libgcrypt "/lib/libgcrypt")))
(define %libz
#+(and zlib
- (file-append zlib "/lib/libz")))
-
- (define %nix-instantiate ;for (guix import snix)
- "nix-instantiate"))
+ (file-append zlib "/lib/libz"))))
;; Guile 2.0 *requires* the 'define-module' to be at the
- ;; top-level or it 'toplevel-ref' in the resulting .go file are
+ ;; top-level or the 'toplevel-ref' in the resulting .go file are
;; made relative to a nonexistent anonymous module.
#:splice? #t))
-
\f
;;;
;;; Building.
;;;
-(define (imported-files name files)
- ;; This is a non-monadic, simplified version of 'imported-files' from (guix
- ;; gexp).
- (define same-target?
- (match-lambda*
- (((file1 . _) (file2 . _))
- (string=? file1 file2))))
-
- (define build
- (with-imported-modules (source-module-closure
- '((guix build utils)))
- #~(begin
- (use-modules (ice-9 match)
- (guix build utils))
-
- (mkdir (ungexp output)) (chdir (ungexp output))
- (for-each (match-lambda
- ((final-path store-path)
- (mkdir-p (dirname final-path))
-
- ;; Note: We need regular files to be regular files, not
- ;; symlinks, as this makes a difference for
- ;; 'add-to-store'.
- (copy-file store-path final-path)))
- '#$(delete-duplicates files same-target?)))))
-
- ;; We're just copying files around, no need to substitute or offload it.
- (computed-file name build
- #:options '(#:local-build? #t
- #:substitutable? #f
- #:env-vars (("COLUMNS" . "200")))))
-
(define* (compiled-modules name module-tree module-files
#:optional
(dependencies '())
#:report-load report-load
#:report-compilation report-compilation)))
- (setvbuf (current-output-port) _IONBF)
- (setvbuf (current-error-port) _IONBF)
+ (setvbuf (current-output-port) 'none)
+ (setvbuf (current-error-port) 'none)
(set! %load-path (cons #+module-tree %load-path))
(set! %load-path
;;; Building.
;;;
-(define (guile-for-build version)
- "Return a derivation for Guile 2.0 or 2.2, whichever matches the currently
-running Guile."
- (define canonical-package ;soft reference
- (module-ref (resolve-interface '(gnu packages base))
- 'canonical-package))
-
- (match version
- ("2.2.2"
- ;; Gross hack to avoid ABI incompatibilities (see
- ;; <https://bugs.gnu.org/29570>.)
- (module-ref (resolve-interface '(gnu packages guile))
- 'guile-2.2.2))
- ("2.2"
- (canonical-package (module-ref (resolve-interface '(gnu packages guile))
- 'guile-2.2/fixed)))
- ("2.0"
- (module-ref (resolve-interface '(gnu packages guile))
- 'guile-2.0))))
-
(define* (guix-derivation source version
#:optional (guile-version (effective-version))
#:key (pull-version 0))
version))
(define guile
- (guile-for-build guile-version))
+ ;; When PULL-VERSION >= 1, produce a self-contained Guix and use Guile 2.2
+ ;; unconditionally.
+ (default-guile))
+
+ (when (and (< pull-version 1)
+ (not (string=? (package-version guile) guile-version)))
+ ;; Guix < 0.15.0 has PULL-VERSION = 0, where the host Guile is reused and
+ ;; can be any version. When that happens and Guile is not current (e.g.,
+ ;; it's Guile 2.0), just bail out.
+ (raise (condition
+ (&message
+ (message "Guix is too old and cannot be upgraded")))))
(mbegin %store-monad
(set-guile-for-build guile)
#:name (string-append "guix-"
(shorten version))
#:pull-version pull-version
- #:guile-version (match guile-version
- ("2.2.2" "2.2")
- (version version))
+ #:guile-version (if (>= pull-version 1)
+ "2.2" guile-version)
#:guile-for-build guile)))
(if guix
(lower-object guix)