summaryrefslogtreecommitdiff
path: root/guix
diff options
context:
space:
mode:
Diffstat (limited to 'guix')
-rw-r--r--guix/build-system/asdf.scm109
-rw-r--r--guix/build/asdf-build-system.scm182
-rw-r--r--guix/build/lisp-utils.scm384
-rw-r--r--guix/download.scm3
-rw-r--r--guix/import/cran.scm101
-rw-r--r--guix/scripts/lint.scm3
-rw-r--r--guix/scripts/system.scm236
7 files changed, 585 insertions, 433 deletions
diff --git a/guix/build-system/asdf.scm b/guix/build-system/asdf.scm
index f28c098ea2..ec8b64497f 100644
--- a/guix/build-system/asdf.scm
+++ b/guix/build-system/asdf.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2016 Andy Patterson <ajpatter@uwaterloo.ca>
+;;; Copyright © 2016, 2017 Andy Patterson <ajpatter@uwaterloo.ca>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -22,6 +22,9 @@
#:use-module (guix packages)
#:use-module (guix derivations)
#:use-module (guix search-paths)
+ #:use-module ((guix build utils)
+ #:select ((package-name->name+version
+ . hyphen-separated-name->name+version)))
#:use-module (guix build-system)
#:use-module (guix build-system gnu)
#:use-module (ice-9 match)
@@ -163,39 +166,40 @@ set up using CL source package conventions."
(match-lambda
((name content . rest)
(let* ((is-package? (package? content))
- (new-content (if is-package? (transform content) content))
- (new-name (if (and is-package?
- (string-prefix? from-prefix name))
- (package-name new-content)
- name)))
- `(,new-name ,new-content ,@rest)))))
+ (new-content (if is-package? (transform content) content)))
+ `(,name ,new-content ,@rest)))))
;; Special considerations for source packages: CL inputs become
- ;; propagated, and un-handled arguments are removed. Native inputs are
- ;; removed as are extraneous outputs.
+ ;; propagated, and un-handled arguments are removed.
+
(define new-propagated-inputs
(if target-is-source?
(map rewrite
- (filter (match-lambda
- ((_ input . _)
- (has-from-build-system? input)))
- (package-inputs pkg)))
- '()))
-
- (define new-inputs
+ (append
+ (filter (match-lambda
+ ((_ input . _)
+ (has-from-build-system? input)))
+ (append (package-inputs pkg)
+ ;; The native inputs might be needed just
+ ;; to load the system.
+ (package-native-inputs pkg)))
+ (package-propagated-inputs pkg)))
+
+ (map rewrite (package-propagated-inputs pkg))))
+
+ (define (new-inputs inputs-getter)
(if target-is-source?
(map rewrite
(filter (match-lambda
((_ input . _)
(not (has-from-build-system? input))))
- (package-inputs pkg)))
- (map rewrite (package-inputs pkg))))
+ (inputs-getter pkg)))
+ (map rewrite (inputs-getter pkg))))
(define base-arguments
(if target-is-source?
(strip-keyword-arguments
- '(#:tests? #:special-dependencies #:asd-file
- #:test-only-systems #:lisp)
+ '(#:tests? #:asd-file #:lisp #:asd-system-name #:test-asd-file)
(package-arguments pkg))
(package-arguments pkg)))
@@ -213,11 +217,9 @@ set up using CL source package conventions."
(arguments
(substitute-keyword-arguments base-arguments
((#:phases phases) (list phases-transformer phases))))
- (inputs new-inputs)
+ (inputs (new-inputs package-inputs))
(propagated-inputs new-propagated-inputs)
- (native-inputs (if target-is-source?
- '()
- (map rewrite (package-native-inputs pkg))))
+ (native-inputs (new-inputs package-native-inputs))
(outputs (if target-is-source?
'("out")
(package-outputs pkg)))))
@@ -233,10 +235,10 @@ set up using CL source package conventions."
(properties (alist-delete variant properties)))
pkg))
-(define (lower lisp-implementation)
+(define (lower lisp-type)
(lambda* (name
#:key source inputs outputs native-inputs system target
- (lisp (default-lisp (string->symbol lisp-implementation)))
+ (lisp (default-lisp (string->symbol lisp-type)))
#:allow-other-keys
#:rest arguments)
"Return a bag for NAME"
@@ -252,20 +254,19 @@ set up using CL source package conventions."
'())
,@inputs
,@(standard-packages)))
- (build-inputs `((,lisp-implementation ,lisp)
+ (build-inputs `((,lisp-type ,lisp)
,@native-inputs))
(outputs outputs)
- (build (asdf-build lisp-implementation))
+ (build (asdf-build lisp-type))
(arguments (strip-keyword-arguments private-keywords arguments))))))
-(define (asdf-build lisp-implementation)
+(define (asdf-build lisp-type)
(lambda* (store name inputs
#:key source outputs
(tests? #t)
- (special-dependencies ''())
(asd-file #f)
- (test-only-systems ''())
- (lisp lisp-implementation)
+ (asd-system-name #f)
+ (test-asd-file #f)
(phases '(@ (guix build asdf-build-system)
%standard-phases))
(search-paths '())
@@ -274,26 +275,36 @@ set up using CL source package conventions."
(imported-modules %asdf-build-system-modules)
(modules %asdf-build-modules))
+ (define system-name
+ (or asd-system-name
+ (string-drop
+ ;; NAME is the value returned from `package-full-name'.
+ (hyphen-separated-name->name+version name)
+ (1+ (string-length lisp-type))))) ; drop the "<lisp>-" prefix.
+
(define builder
`(begin
(use-modules ,@modules)
- (asdf-build #:name ,name
- #:source ,(match (assoc-ref inputs "source")
- (((? derivation? source))
- (derivation->output-path source))
- ((source) source)
- (source source))
- #:lisp ,lisp
- #:special-dependencies ,special-dependencies
- #:asd-file ,asd-file
- #:test-only-systems ,test-only-systems
- #:system ,system
- #:tests? ,tests?
- #:phases ,phases
- #:outputs %outputs
- #:search-paths ',(map search-path-specification->sexp
- search-paths)
- #:inputs %build-inputs)))
+ (parameterize ((%lisp (string-append
+ (assoc-ref %build-inputs ,lisp-type)
+ "/bin/" ,lisp-type))
+ (%lisp-type ,lisp-type))
+ (asdf-build #:name ,name
+ #:source ,(match (assoc-ref inputs "source")
+ (((? derivation? source))
+ (derivation->output-path source))
+ ((source) source)
+ (source source))
+ #:asd-file ,(or asd-file (string-append system-name ".asd"))
+ #:asd-system-name ,system-name
+ #:test-asd-file ,test-asd-file
+ #:system ,system
+ #:tests? ,tests?
+ #:phases ,phases
+ #:outputs %outputs
+ #:search-paths ',(map search-path-specification->sexp
+ search-paths)
+ #:inputs %build-inputs))))
(define guile-for-build
(match guile
diff --git a/guix/build/asdf-build-system.scm b/guix/build/asdf-build-system.scm
index 085d073dea..c5e820a00a 100644
--- a/guix/build/asdf-build-system.scm
+++ b/guix/build/asdf-build-system.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2016 Andy Patterson <ajpatter@uwaterloo.ca>
+;;; Copyright © 2016, 2017 Andy Patterson <ajpatter@uwaterloo.ca>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -21,6 +21,7 @@
#:use-module (guix build utils)
#:use-module (guix build lisp-utils)
#:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-11)
#:use-module (srfi srfi-26)
#:use-module (ice-9 rdelim)
#:use-module (ice-9 receive)
@@ -42,50 +43,42 @@
(define %object-prefix "/lib")
-(define (source-install-prefix lisp)
- (string-append %install-prefix "/" lisp "-source"))
+(define (%lisp-source-install-prefix)
+ (string-append %source-install-prefix "/" (%lisp-type) "-source"))
(define %system-install-prefix
- (string-append %install-prefix "/systems"))
+ (string-append %source-install-prefix "/systems"))
-(define (output-path->package-name path)
- (package-name->name+version (strip-store-file-name path)))
-
-(define (outputs->name outputs)
- (output-path->package-name
- (assoc-ref outputs "out")))
-
-(define (lisp-source-directory output lisp name)
- (string-append output (source-install-prefix lisp) "/" name))
+(define (lisp-source-directory output name)
+ (string-append output (%lisp-source-install-prefix) "/" name))
(define (source-directory output name)
- (string-append output %install-prefix "/source/" name))
+ (string-append output %source-install-prefix "/source/" name))
-(define (library-directory output lisp)
+(define (library-directory output)
(string-append output %object-prefix
- "/" lisp))
+ "/" (%lisp-type)))
(define (output-translation source-path
- object-output
- lisp)
+ object-output)
"Return a translation for the system's source path
to it's binary output."
`((,source-path
:**/ :*.*.*)
- (,(library-directory object-output lisp)
+ (,(library-directory object-output)
:**/ :*.*.*)))
-(define (source-asd-file output lisp name asd-file)
- (string-append (lisp-source-directory output lisp name) "/" asd-file))
-
-(define (copy-files-to-output outputs output name)
- "Copy all files from OUTPUT to \"out\". Create an extra link to any
-system-defining files in the source to a convenient location. This is done
-before any compiling so that the compiled source locations will be valid."
- (let* ((out (assoc-ref outputs output))
- (source (getcwd))
- (target (source-directory out name))
- (system-path (string-append out %system-install-prefix)))
+(define (source-asd-file output name asd-file)
+ (string-append (lisp-source-directory output name) "/" asd-file))
+
+(define (copy-files-to-output out name)
+ "Copy all files from the current directory to OUT. Create an extra link to
+any system-defining files in the source to a convenient location. This is
+done before any compiling so that the compiled source locations will be
+valid."
+ (let ((source (getcwd))
+ (target (source-directory out name))
+ (system-path (string-append out %system-install-prefix)))
(copy-recursively source target)
(mkdir-p system-path)
(for-each
@@ -97,45 +90,38 @@ before any compiling so that the compiled source locations will be valid."
(define* (install #:key outputs #:allow-other-keys)
"Copy and symlink all the source files."
- (copy-files-to-output outputs "out" (outputs->name outputs)))
-
-(define* (copy-source #:key outputs lisp #:allow-other-keys)
- "Copy the source to \"out\"."
- (let* ((out (assoc-ref outputs "out"))
- (name (remove-lisp-from-name (output-path->package-name out) lisp))
- (install-path (string-append out %install-prefix)))
- (copy-files-to-output outputs "out" name)
+ (define output (assoc-ref outputs "out"))
+ (copy-files-to-output output
+ (package-name->name+version
+ (strip-store-file-name output))))
+
+(define* (copy-source #:key outputs asd-system-name #:allow-other-keys)
+ "Copy the source to the library output."
+ (let* ((out (library-output outputs))
+ (install-path (string-append out %source-install-prefix)))
+ (copy-files-to-output out asd-system-name)
;; Hide the files from asdf
(with-directory-excursion install-path
- (rename-file "source" (string-append lisp "-source"))
+ (rename-file "source" (string-append (%lisp-type) "-source"))
(delete-file-recursively "systems")))
#t)
-(define* (build #:key outputs inputs lisp asd-file
+(define* (build #:key outputs inputs asd-file asd-system-name
#:allow-other-keys)
"Compile the system."
- (let* ((out (assoc-ref outputs "out"))
- (name (remove-lisp-from-name (output-path->package-name out) lisp))
- (source-path (lisp-source-directory out lisp name))
+ (let* ((out (library-output outputs))
+ (source-path (lisp-source-directory out asd-system-name))
(translations (wrap-output-translations
`(,(output-translation source-path
- out
- lisp))))
- (asd-file (and=> asd-file (cut source-asd-file out lisp name <>))))
+ out))))
+ (asd-file (source-asd-file out asd-system-name asd-file)))
(setenv "ASDF_OUTPUT_TRANSLATIONS"
(replace-escaped-macros (format #f "~S" translations)))
- ;; We don't need this if we have the asd file, and it can mess with the
- ;; load ordering we're trying to enforce
- (unless asd-file
- (prepend-to-source-registry (string-append source-path "//")))
-
(setenv "HOME" out) ; ecl's asdf sometimes wants to create $HOME/.cache
- (parameterize ((%lisp (string-append
- (assoc-ref inputs lisp) "/bin/" lisp)))
- (compile-system name lisp asd-file))
+ (compile-system asd-system-name asd-file)
;; As above, ecl will sometimes create this even though it doesn't use it
@@ -144,56 +130,48 @@ before any compiling so that the compiled source locations will be valid."
(delete-file-recursively cache-directory))))
#t)
-(define* (check #:key lisp tests? outputs inputs asd-file
+(define* (check #:key tests? outputs inputs asd-file asd-system-name
+ test-asd-file
#:allow-other-keys)
"Test the system."
- (let* ((name (remove-lisp-from-name (outputs->name outputs) lisp))
- (out (assoc-ref outputs "out"))
- (asd-file (and=> asd-file (cut source-asd-file out lisp name <>))))
+ (let* ((out (library-output outputs))
+ (asd-file (source-asd-file out asd-system-name asd-file))
+ (test-asd-file
+ (and=> test-asd-file
+ (cut source-asd-file out asd-system-name <>))))
(if tests?
- (parameterize ((%lisp (string-append
- (assoc-ref inputs lisp) "/bin/" lisp)))
- (test-system name lisp asd-file))
+ (test-system asd-system-name asd-file test-asd-file)
(format #t "test suite not run~%")))
#t)
-(define* (patch-asd-files #:key outputs
+(define* (create-asd-file #:key outputs
inputs
- lisp
- special-dependencies
- test-only-systems
+ asd-file
+ asd-system-name
#:allow-other-keys)
- "Patch any asd files created by the compilation process so that they can
-find their dependencies. Exclude any TEST-ONLY-SYSTEMS which were only
-included to run tests. Add any SPECIAL-DEPENDENCIES which the LISP
-implementation itself provides."
- (let* ((out (assoc-ref outputs "out"))
- (name (remove-lisp-from-name (output-path->package-name out) lisp))
- (registry (lset-difference
- (lambda (input system)
- (match input
- ((name . path) (string=? name system))))
- (lisp-dependencies lisp inputs)
- test-only-systems))
- (lisp-systems (map first registry)))
-
- (for-each
- (lambda (asd-file)
- (patch-asd-file asd-file registry lisp
- (append lisp-systems special-dependencies)))
- (find-files out "\\.asd$")))
+ "Create a system definition file for the built system."
+ (let*-values (((out) (library-output outputs))
+ ((_ version) (package-name->name+version
+ (strip-store-file-name out)))
+ ((new-asd-file) (string-append
+ (library-directory out)
+ "/" (normalize-string asd-system-name)
+ ".asd")))
+
+ (make-asd-file new-asd-file
+ #:system asd-system-name
+ #:version version
+ #:inputs inputs
+ #:system-asd-file asd-file))
#t)
-(define* (symlink-asd-files #:key outputs lisp #:allow-other-keys)
+(define* (symlink-asd-files #:key outputs #:allow-other-keys)
"Create an extra reference to the system in a convenient location."
- (let* ((out (assoc-ref outputs "out")))
+ (let* ((out (library-output outputs)))
(for-each
(lambda (asd-file)
- (substitute* asd-file
- ((";;; Built for.*") "") ; remove potential non-determinism
- (("^\\(DEFSYSTEM(.*)$" all end) (string-append "(asdf:defsystem" end)))
(receive (new-asd-file asd-file-directory)
- (bundle-asd-file out asd-file lisp)
+ (bundle-asd-file out asd-file)
(mkdir-p asd-file-directory)
(symlink asd-file new-asd-file)
;; Update the source registry for future phases which might want to
@@ -201,15 +179,14 @@ implementation itself provides."
(prepend-to-source-registry
(string-append asd-file-directory "/"))))
- (find-files (string-append out %object-prefix) "\\.asd$"))
-)
+ (find-files (string-append out %object-prefix) "\\.asd$")))
#t)
-(define* (cleanup-files #:key outputs lisp
- #:allow-other-keys)
+(define* (cleanup-files #:key outputs
+ #:allow-other-keys)
"Remove any compiled files which are not a part of the final bundle."
- (let ((out (assoc-ref outputs "out")))
- (match lisp
+ (let ((out (library-output outputs)))
+ (match (%lisp-type)
("sbcl"
(for-each
(lambda (file)
@@ -219,10 +196,9 @@ implementation itself provides."
("ecl"
(for-each delete-file
(append (find-files out "\\.fas$")
- (find-files out "\\.o$")
- (find-files out "\\.a$")))))
+ (find-files out "\\.o$")))))
- (with-directory-excursion (library-directory out lisp)
+ (with-directory-excursion (library-directory out)
(for-each
(lambda (file)
(rename-file file
@@ -237,9 +213,9 @@ implementation itself provides."
(string<> ".." file)))))))
#t)
-(define* (strip #:key lisp #:allow-other-keys #:rest args)
+(define* (strip #:rest args)
;; stripping sbcl binaries removes their entry program and extra systems
- (or (string=? lisp "sbcl")
+ (or (string=? (%lisp-type) "sbcl")
(apply (assoc-ref gnu:%standard-phases 'strip) args)))
(define %standard-phases/source
@@ -257,8 +233,8 @@ implementation itself provides."
(add-before 'build 'copy-source copy-source)
(replace 'check check)
(replace 'strip strip)
- (add-after 'check 'link-dependencies patch-asd-files)
- (add-after 'link-dependencies 'cleanup cleanup-files)
+ (add-after 'check 'create-asd-file create-asd-file)
+ (add-after 'create-asd-file 'cleanup cleanup-files)
(add-after 'cleanup 'create-symlinks symlink-asd-files)))
(define* (asdf-build #:key inputs
diff --git a/guix/build/lisp-utils.scm b/guix/build/lisp-utils.scm
index 55a07c7207..21cb620d59 100644
--- a/guix/build/lisp-utils.scm
+++ b/guix/build/lisp-utils.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2016 Andy Patterson <ajpatter@uwaterloo.ca>
+;;; Copyright © 2016, 2017 Andy Patterson <ajpatter@uwaterloo.ca>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -18,13 +18,15 @@
(define-module (guix build lisp-utils)
#:use-module (ice-9 format)
+ #:use-module (ice-9 hash-table)
#:use-module (ice-9 match)
#:use-module (ice-9 regex)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:use-module (guix build utils)
#:export (%lisp
- %install-prefix
+ %lisp-type
+ %source-install-prefix
lisp-eval-program
compile-system
test-system
@@ -32,15 +34,16 @@
generate-executable-wrapper-system
generate-executable-entry-point
generate-executable-for-system
- patch-asd-file
- bundle-install-prefix
- lisp-dependencies
+ %bundle-install-prefix
bundle-asd-file
- remove-lisp-from-name
wrap-output-translations
prepend-to-source-registry
build-program
- build-image))
+ build-image
+ make-asd-file
+ valid-char-set
+ normalize-string
+ library-output))
;;; Commentary:
;;;
@@ -54,102 +57,164 @@
;; File name of the Lisp compiler.
(make-parameter "lisp"))
-(define %install-prefix "/share/common-lisp")
-
-(define (bundle-install-prefix lisp)
- (string-append %install-prefix "/" lisp "-bundle-systems"))
+(define %lisp-type
+ ;; String representing the class of implementation being used.
+ (make-parameter "lisp"))
-(define (remove-lisp-from-name name lisp)
- (string-drop name (1+ (string-length lisp))))
+;; The common parent for Lisp source files, as will as the symbolic
+;; link farm for system definition (.asd) files.
+(define %source-install-prefix "/share/common-lisp")
+
+(define (%bundle-install-prefix)
+ (string-append %source-install-prefix "/" (%lisp-type) "-bundle-systems"))
+
+(define (library-output outputs)
+ "If a `lib' output exists, build things there. Otherwise use `out'."
+ (or (assoc-ref outputs "lib") (assoc-ref outputs "out")))
+
+;; See nix/libstore/store-api.cc#checkStoreName.
+(define valid-char-set
+ (string->char-set
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-._?="))
+
+(define (normalize-string str)
+ "Replace invalid characters in STR with a hyphen."
+ (string-join (string-tokenize str valid-char-set) "-"))
+
+(define (inputs->asd-file-map inputs)
+ "Produce a hash table of the form (system . asd-file), where system is the
+name of an ASD system, and asd-file is the full path to its definition."
+ (alist->hash-table
+ (filter-map
+ (match-lambda
+ ((_ . path)
+ (let ((prefix (string-append path (%bundle-install-prefix))))
+ (and (directory-exists? prefix)
+ (match (find-files prefix "\\.asd$")
+ ((asd-file)
+ (cons
+ (string-drop-right (basename asd-file) 4) ; drop ".asd"
+ asd-file))
+ (_ #f))))))
+ inputs)))
(define (wrap-output-translations translations)
`(:output-translations
,@translations
:inherit-configuration))
-(define (lisp-eval-program lisp program)
+(define (lisp-eval-program program)
"Evaluate PROGRAM with a given LISP implementation."
(unless (zero? (apply system*
- (lisp-invoke lisp (format #f "~S" program))))
- (error "lisp-eval-program failed!" lisp program)))
-
-(define (lisp-invoke lisp program)
+ (lisp-invocation program)))
+ (error "lisp-eval-program failed!" (%lisp) program)))
+
+(define (spread-statements program argument-name)
+ "Return a list with the statements from PROGRAM spread between
+ARGUMENT-NAME, a string representing the argument a lisp implementation uses
+to accept statements to be evaluated before starting."
+ (append-map (lambda (statement)
+ (list argument-name (format #f "~S" statement)))
+ program))
+
+(define (lisp-invocation program)
"Return a list of arguments for system* determining how to invoke LISP
with PROGRAM."
- (match lisp
- ("sbcl" `(,(%lisp) "--non-interactive" "--eval" ,program))
- ("ecl" `(,(%lisp) "-eval" ,program "-eval" "(quit)"))))
+ (match (%lisp-type)
+ ("sbcl" `(,(%lisp) "--non-interactive"
+ ,@(spread-statements program "--eval")))
+ ("ecl" `(,(%lisp)
+ ,@(spread-statements program "--eval")
+ "--eval" "(quit)"))
+ (_ (error "The LISP provided is not supported at this time."))))
(define (asdf-load-all systems)
(map (lambda (system)
- `(funcall
- (find-symbol
- (symbol-name :load-system)
- (symbol-name :asdf))
- ,system))
+ `(asdf:load-system ,system))
systems))
-(define (compile-system system lisp asd-file)
+(define (compile-system system asd-file)
"Use a lisp implementation to compile SYSTEM using asdf. Load ASD-FILE
-first if SYSTEM is defined there."
- (lisp-eval-program lisp
- `(progn
- (require :asdf)
- (in-package :asdf)
- ,@(if asd-file
- `((load ,asd-file))
- '())
- (in-package :cl-user)
- (funcall (find-symbol
- (symbol-name :operate)
- (symbol-name :asdf))
- (find-symbol
- (symbol-name :compile-bundle-op)
- (symbol-name :asdf))
- ,system)
- (funcall (find-symbol
- (symbol-name :operate)
- (symbol-name :asdf))
- (find-symbol
- (symbol-name :deliver-asd-op)
- (symbol-name :asdf))
- ,system))))
-
-(define (test-system system lisp asd-file)
- "Use a lisp implementation to test SYSTEM using asdf. Load ASD-FILE first
-if SYSTEM is defined there."
- (lisp-eval-program lisp
- `(progn
- (require :asdf)
- (in-package :asdf)
- ,@(if asd-file
- `((load ,asd-file))
- '())
- (in-package :cl-user)
- (funcall (find-symbol
- (symbol-name :test-system)
- (symbol-name :asdf))
- ,system))))
+first."
+ (lisp-eval-program
+ `((require :asdf)
+ (let ((*package* (find-package :asdf)))
+ (load ,asd-file))
+ (asdf:operate 'asdf:compile-bundle-op ,system))))
+
+(define (system-dependencies system asd-file)
+ "Return the dependencies of SYSTEM, as reported by
+asdf:system-depends-on. First load the system's ASD-FILE."
+ (define deps-file ".deps.sexp")
+ (define program
+ `((require :asdf)
+ (let ((*package* (find-package :asdf)))
+ (load ,asd-file))
+ (with-open-file
+ (stream ,deps-file :direction :output)
+ (format stream
+ "~s~%"
+ (asdf:system-depends-on
+ (asdf:find-system ,system))))))
+
+ (dynamic-wind
+ (lambda _
+ (lisp-eval-program program))
+ (lambda _
+ (call-with-input-file deps-file read))
+ (lambda _
+ (when (file-exists? deps-file)
+ (delete-file deps-file)))))
+
+(define (compiled-system system)
+ (let ((system (basename system))) ; this is how asdf handles slashes
+ (match (%lisp-type)
+ ("sbcl" (string-append system "--system"))
+ (_ system))))
+
+(define* (generate-system-definition system
+ #:key version dependencies)
+ `(asdf:defsystem
+ ,(normalize-string system)
+ :class asdf/bundle:prebuilt-system
+ :version ,version
+ :depends-on ,dependencies
+ :components ((:compiled-file ,(compiled-system system)))
+ ,@(if (string=? "ecl" (%lisp-type))
+ `(:lib ,(string-append system ".a"))
+ '())))
+
+(define (test-system system asd-file test-asd-file)
+ "Use a lisp implementation to test SYSTEM using asdf. Load ASD-FILE first.
+Also load TEST-ASD-FILE if necessary."
+ (lisp-eval-program
+ `((require :asdf)
+ (let ((*package* (find-package :asdf)))
+ (load ,asd-file)
+ ,@(if test-asd-file
+ `((load ,test-asd-file))
+ ;; Try some likely files.
+ (map (lambda (file)
+ `(when (uiop:file-exists-p ,file)
+ (load ,file)))
+ (list
+ (string-append system "-tests.asd")
+ (string-append system "-test.asd")
+ "tests.asd"
+ "test.asd"))))
+ (asdf:test-system ,system))))
(define (string->lisp-keyword . strings)
"Return a lisp keyword for the concatenation of STRINGS."
(string->symbol (apply string-append ":" strings)))
-(define (generate-executable-for-system type system lisp)
- "Use LISP to generate an executable, whose TYPE can be \"image\" or
-\"program\". The latter will always be standalone. Depends on having created
-a \"SYSTEM-exec\" system which contains the entry program."
+(define (generate-executable-for-system type system)
+ "Use LISP to generate an executable, whose TYPE can be 'asdf:image-op or
+'asdf:program-op. The latter will always be standalone. Depends on having
+created a \"SYSTEM-exec\" system which contains the entry program."
(lisp-eval-program
- lisp
- `(progn
- (require :asdf)
- (funcall (find-symbol
- (symbol-name :operate)
- (symbol-name :asdf))
- (find-symbol
- (symbol-name ,(string->lisp-keyword type "-op"))
- (symbol-name :asdf))
- ,(string-append system "-exec")))))
+ `((require :asdf)
+ (asdf:operate ',type ,(string-append system "-exec")))))
(define (generate-executable-wrapper-system system dependencies)
"Generates a system which can be used by asdf to produce an image or program
@@ -183,65 +248,59 @@ ENTRY-PROGRAM for SYSTEM within the current directory."
(declare (ignorable arguments))
,@entry-program))))))))
-(define (wrap-perform-method lisp registry dependencies file-name)
- "Creates a wrapper method which allows the system to locate its dependent
-systems from REGISTRY, an alist of the same form as %outputs, which contains
-lisp systems which the systems is dependent on. All DEPENDENCIES which the
-system depends on will the be loaded before this system."
- (let* ((system (string-drop-right (basename file-name) 4))
- (system-symbol (string->lisp-keyword system)))
-
- `(defmethod asdf:perform :before
- (op (c (eql (asdf:find-system ,system-symbol))))
- (asdf/source-registry:ensure-source-registry)
- ,@(map (match-lambda
- ((name . path)
- (let ((asd-file (string-append path
- (bundle-install-prefix lisp)
- "/" name ".asd")))
- `(setf
- (gethash ,name
- asdf/source-registry:*source-registry*)
- ,(string->symbol "#p")
- ,(bundle-asd-file path asd-file lisp)))))
- registry)
- ,@(map (lambda (system)
- `(asdf:load-system ,(string->lisp-keyword system)))
- dependencies))))
-
-(define (patch-asd-file asd-file registry lisp dependencies)
- "Patches ASD-FILE with a perform method as described in WRAP-PERFORM-METHOD."
- (chmod asd-file #o644)
- (let ((port (open-file asd-file "a")))
- (dynamic-wind
- (lambda _ #t)
- (lambda _
- (display
- (replace-escaped-macros
- (format #f "~%~y~%"
- (wrap-perform-method lisp registry
- dependencies asd-file)))
- port))
- (lambda _ (close-port port))))
- (chmod asd-file #o444))
-
-(define (lisp-dependencies lisp inputs)
- "Determine which inputs are lisp system dependencies, by using the convention
-that a lisp system dependency will resemble \"system-LISP\"."
- (filter-map (match-lambda
- ((name . value)
- (and (string-prefix? lisp name)
- (string<> lisp name)
- `(,(remove-lisp-from-name name lisp)
- . ,value))))
- inputs))
-
-(define (bundle-asd-file output-path original-asd-file lisp)
+(define (generate-dependency-links registry system)
+ "Creates a program which populates asdf's source registry from REGISTRY, an
+alist of dependency names to corresponding asd files. This allows the system
+to locate its dependent systems."
+ `(progn
+ (asdf/source-registry:ensure-source-registry)
+ ,@(map (match-lambda
+ ((name . asd-file)
+ `(setf
+ (gethash ,name
+ asdf/source-registry:*source-registry*)
+ ,(string->symbol "#p")
+ ,asd-file)))
+ registry)))
+
+(define* (make-asd-file asd-file
+ #:key system version inputs
+ (system-asd-file #f))
+ "Create an ASD-FILE for SYSTEM@VERSION, appending a program to allow the
+system to find its dependencies, as described by GENERATE-DEPENDENCY-LINKS."
+ (define dependencies
+ (let ((deps
+ (system-dependencies system system-asd-file)))
+ (if (eq? 'NIL deps)
+ '()
+ (map normalize-string deps))))
+
+ (define lisp-input-map
+ (inputs->asd-file-map inputs))
+
+ (define registry
+ (filter-map hash-get-handle
+ (make-list (length dependencies)
+ lisp-input-map)
+ dependencies))
+
+ (call-with-output-file asd-file
+ (lambda (port)
+ (display
+ (replace-escaped-macros
+ (format #f "~y~%~y~%"
+ (generate-system-definition system
+ #:version version
+ #:dependencies dependencies)
+ (generate-dependency-links registry system)))
+ port))))
+
+(define (bundle-asd-file output-path original-asd-file)
"Find the symlinked bundle file for ORIGINAL-ASD-FILE by looking in
OUTPUT-PATH/share/common-lisp/LISP-bundle-systems/<system>.asd. Returns two
values: the asd file itself and the directory in which it resides."
(let ((bundle-asd-path (string-append output-path
- (bundle-install-prefix lisp))))
+ (%bundle-install-prefix))))
(values (string-append bundle-asd-path "/" (basename original-asd-file))
bundle-asd-path)))
@@ -256,19 +315,22 @@ which are not nested."
(setenv "CL_SOURCE_REGISTRY"
(string-append path ":" (or (getenv "CL_SOURCE_REGISTRY") ""))))
-(define* (build-program lisp program #:key inputs
+(define* (build-program program outputs #:key
+ (dependency-prefixes (list (library-output outputs)))
(dependencies (list (basename program)))
entry-program
#:allow-other-keys)
"Generate an executable program containing all DEPENDENCIES, and which will
execute ENTRY-PROGRAM. The result is placed in PROGRAM. When executed, it
will run ENTRY-PROGRAM, a list of Common Lisp expressions in which `arguments'
-has been bound to the command-line arguments which were passed."
- (generate-executable lisp program
- #:inputs inputs
+has been bound to the command-line arguments which were passed. Link in any
+asd files from DEPENDENCY-PREFIXES to ensure references to those libraries are
+retained."
+ (generate-executable program
#:dependencies dependencies
+ #:dependency-prefixes dependency-prefixes
#:entry-program entry-program
- #:type "program")
+ #:type 'asdf:program-op)
(let* ((name (basename program))
(bin-directory (dirname program)))
(with-directory-excursion bin-directory
@@ -276,16 +338,18 @@ has been bound to the command-line arguments which were passed."
name)))
#t)
-(define* (build-image lisp image #:key inputs
+(define* (build-image image outputs #:key
+ (dependency-prefixes (list (library-output outputs)))
(dependencies (list (basename image)))
#:allow-other-keys)
"Generate an image, possibly standalone, which contains all DEPENDENCIES,
-placing the result in IMAGE.image."
- (generate-executable lisp image
- #:inputs inputs
+placing the result in IMAGE.image. Link in any asd files from
+DEPENDENCY-PREFIXES to ensure references to those libraries are retained."
+ (generate-executable image
#:dependencies dependencies
+ #:dependency-prefixes dependency-prefixes
#:entry-program '(nil)
- #:type "image")
+ #:type 'asdf:image-op)
(let* ((name (basename image))
(bin-directory (dirname image)))
(with-directory-excursion bin-directory
@@ -293,14 +357,16 @@ placing the result in IMAGE.image."
(string-append name ".image"))))
#t)
-(define* (generate-executable lisp out-file #:key inputs
+(define* (generate-executable out-file #:key
dependencies
+ dependency-prefixes
entry-program
type
#:allow-other-keys)
- "Generate an executable by using asdf's TYPE-op, containing whithin the
+ "Generate an executable by using asdf operation TYPE, containing whithin the
image all DEPENDENCIES, and running ENTRY-PROGRAM in the case of an
-executable."
+executable. Link in any asd files from DEPENDENCY-PREFIXES to ensure
+references to those libraries are retained."
(let* ((bin-directory (dirname out-file))
(name (basename out-file)))
(mkdir-p bin-directory)
@@ -319,9 +385,25 @@ executable."
`(((,bin-directory :**/ :*.*.*)
(,bin-directory :**/ :*.*.*)))))))
- (parameterize ((%lisp (string-append
- (assoc-ref inputs lisp) "/bin/" lisp)))
- (generate-executable-for-system type name lisp))
+ (generate-executable-for-system type name)
+
+ (let* ((after-store-prefix-index
+ (string-index out-file #\/
+ (1+ (string-length (%store-directory)))))
+ (output (string-take out-file after-store-prefix-index))
+ (hidden-asd-links (string-append output "/.asd-files")))
+
+ (mkdir-p hidden-asd-links)
+ (for-each
+ (lambda (path)
+ (for-each
+ (lambda (asd-file)
+ (symlink asd-file
+ (string-append hidden-asd-links
+ "/" (basename asd-file))))
+ (find-files (string-append path (%bundle-install-prefix))
+ "\\.asd$")))
+ dependency-prefixes))
(delete-file (string-append bin-directory "/" name "-exec.asd"))
(delete-file (string-append bin-directory "/" name "-exec.lisp"))))
diff --git a/guix/download.scm b/guix/download.scm
index 5a25725b49..bed1f502cf 100644
--- a/guix/download.scm
+++ b/guix/download.scm
@@ -213,7 +213,6 @@
;; mirrors keeping old versions at the top level
"ftp://sunsite.icm.edu.pl/packages/ImageMagick/"
;; mirrors moving old versions to "legacy"
- "http://mirrors-au.go-parts.com/mirrors/ImageMagick/"
"ftp://mirror.aarnet.edu.au/pub/imagemagick/"
"http://mirror.checkdomain.de/imagemagick/"
"ftp://ftp.kddlabs.co.jp/graphics/ImageMagick/"
@@ -222,9 +221,7 @@
"http://ftp.surfnet.nl/pub/ImageMagick/"
"http://mirror.searchdaimon.com/ImageMagick"
"ftp://ftp.tpnet.pl/pub/graphics/ImageMagick/"
- "http://mirrors-ru.go-parts.com/mirrors/ImageMagick/"
"http://mirror.is.co.za/pub/imagemagick/"
- "http://mirrors-uk.go-parts.com/mirrors/ImageMagick/"
"http://mirrors-usa.go-parts.com/mirrors/ImageMagick/"
"ftp://ftp.fifi.org/pub/ImageMagick/"
"http://www.imagemagick.org/download/"
diff --git a/guix/import/cran.scm b/guix/import/cran.scm
index a94051655c..8d963a7475 100644
--- a/guix/import/cran.scm
+++ b/guix/import/cran.scm
@@ -45,7 +45,12 @@
bioconductor->guix-package
recursive-import
%cran-updater
- %bioconductor-updater))
+ %bioconductor-updater
+
+ cran-package?
+ bioconductor-package?
+ bioconductor-data-package?
+ bioconductor-experiment-package?))
;;; Commentary:
;;;
@@ -125,17 +130,19 @@ package definition."
;; The latest Bioconductor release is 3.5. Bioconductor packages should be
;; updated together.
-(define %bioconductor-svn-url
- (string-append "https://readonly:readonly@"
- "hedgehog.fhcrc.org/bioconductor/branches/RELEASE_3_5/"
- "madman/Rpacks/"))
-
+(define (bioconductor-mirror-url name)
+ (string-append "https://raw.githubusercontent.com/Bioconductor-mirror/"
+ name "/release-3.5"))
-(define (fetch-description base-url name)
+(define (fetch-description repository name)
"Return an alist of the contents of the DESCRIPTION file for the R package
-NAME, or #f in case of failure. NAME is case-sensitive."
+NAME in the given REPOSITORY, or #f in case of failure. NAME is
+case-sensitive."
;; This API always returns the latest release of the module.
- (let ((url (string-append base-url name "/DESCRIPTION")))
+ (let ((url (string-append (case repository
+ ((cran) (string-append %cran-url name))
+ ((bioconductor) (bioconductor-mirror-url name)))
+ "/DESCRIPTION")))
(guard (c ((http-get-error? c)
(format (current-error-port)
"error: failed to retrieve package information \
@@ -200,17 +207,16 @@ empty list when the FIELD cannot be found."
(check "*.f95")
(check "*.f")))
-(define (needs-zlib? tarball)
- "Return #T if any of the Makevars files in the src directory of the TARBALL
-contain a zlib linker flag."
+(define (tarball-files-match-pattern? tarball regexp . file-patterns)
+ "Return #T if any of the files represented by FILE-PATTERNS in the TARBALL
+match the given REGEXP."
(call-with-temporary-directory
(lambda (dir)
- (let ((pattern (make-regexp "-lz")))
+ (let ((pattern (make-regexp regexp)))
(parameterize ((current-error-port (%make-void-port "rw+")))
- (system* "tar"
- "xf" tarball "-C" dir
- "--wildcards"
- "*/src/Makevars*" "*/src/configure*" "*/configure*"))
+ (apply system* "tar"
+ "xf" tarball "-C" dir
+ `("--wildcards" ,@file-patterns)))
(any (lambda (file)
(call-with-input-file file
(lambda (port)
@@ -219,10 +225,23 @@ contain a zlib linker flag."
(cond
((eof-object? line) #f)
((regexp-exec pattern line) #t)
- (else (loop)))))))
- #t)
+ (else (loop))))))))
(find-files dir))))))
+(define (needs-zlib? tarball)
+ "Return #T if any of the Makevars files in the src directory of the TARBALL
+contain a zlib linker flag."
+ (tarball-files-match-pattern?
+ tarball "-lz"
+ "*/src/Makevars*" "*/src/configure*" "*/configure*"))
+
+(define (needs-pkg-config? tarball)
+ "Return #T if any of the Makevars files in the src directory of the TARBALL
+reference the pkg-config tool."
+ (tarball-files-match-pattern?
+ tarball "pkg-config"
+ "*/src/Makevars*" "*/src/configure*" "*/configure*"))
+
(define (description->package repository meta)
"Return the `package' s-expression for an R package published on REPOSITORY
from the alist META, which was derived from the R package's DESCRIPTION file."
@@ -272,11 +291,12 @@ from the alist META, which was derived from the R package's DESCRIPTION file."
(build-system r-build-system)
,@(maybe-inputs sysdepends)
,@(maybe-inputs (map guix-name propagate) 'propagated-inputs)
- ,@(if (needs-fortran? tarball)
- `((native-inputs (,'quasiquote
- ,(list "gfortran"
- (list 'unquote 'gfortran)))))
- '())
+ ,@(maybe-inputs
+ `(,@(if (needs-fortran? tarball)
+ '("gfortran") '())
+ ,@(if (needs-pkg-config? tarball)
+ '("pkg-config") '()))
+ 'native-inputs)
(home-page ,(if (string-null? home-page)
(string-append base-url name)
home-page))
@@ -291,11 +311,8 @@ from the alist META, which was derived from the R package's DESCRIPTION file."
(lambda* (package-name #:optional (repo 'cran))
"Fetch the metadata for PACKAGE-NAME from REPO and return the `package'
s-expression corresponding to that package, or #f on failure."
- (let* ((url (case repo
- ((cran) %cran-url)
- ((bioconductor) %bioconductor-svn-url)))
- (module-meta (fetch-description url package-name)))
- (and=> module-meta (cut description->package repo <>))))))
+ (and=> (fetch-description repo package-name)
+ (cut description->package repo <>)))))
(define* (recursive-import package-name #:optional (repo 'cran))
"Generate a stream of package expressions for PACKAGE-NAME and all its
@@ -386,7 +403,7 @@ dependencies."
(package->upstream-name package))
(define meta
- (fetch-description %cran-url upstream-name))
+ (fetch-description 'cran upstream-name))
(and meta
(let ((version (assoc-ref meta "Version")))
@@ -403,7 +420,7 @@ dependencies."
(package->upstream-name package))
(define meta
- (fetch-description %bioconductor-svn-url upstream-name))
+ (fetch-description 'bioconductor upstream-name))
(and meta
(let ((version (assoc-ref meta "Version")))
@@ -430,8 +447,13 @@ dependencies."
"Return true if PACKAGE is an R package from Bioconductor."
(let ((predicate (lambda (uri)
(and (string-prefix? "http://bioconductor.org" uri)
- ;; Data packages are not listed in SVN
- (not (string-contains uri "/data/annotation/"))))))
+ ;; Data packages are neither listed in SVN nor on
+ ;; the Github mirror, so we have to exclude them
+ ;; from the set of bioconductor packages that can be
+ ;; updated automatically.
+ (not (string-contains uri "/data/annotation/"))
+ ;; Experiment packages are in a separate repository.
+ (not (string-contains uri "/data/experiment/"))))))
(and (string-prefix? "r-" (package-name package))
(match (and=> (package-source package) origin-uri)
((? string? uri)
@@ -453,6 +475,19 @@ dependencies."
(any predicate uris))
(_ #f)))))
+(define (bioconductor-experiment-package? package)
+ "Return true if PACKAGE is an R experiment package from Bioconductor."
+ (let ((predicate (lambda (uri)
+ (and (string-prefix? "http://bioconductor.org" uri)
+ (string-contains uri "/data/experiment/")))))
+ (and (string-prefix? "r-" (package-name package))
+ (match (and=> (package-source package) origin-uri)
+ ((? string? uri)
+ (predicate uri))
+ ((? list? uris)
+ (any predicate uris))
+ (_ #f)))))
+
(define %cran-updater
(upstream-updater
(name 'cran)
diff --git a/guix/scripts/lint.scm b/guix/scripts/lint.scm
index f2720f669e..6f30d371a2 100644
--- a/guix/scripts/lint.scm
+++ b/guix/scripts/lint.scm
@@ -255,7 +255,8 @@ of a package, and INPUT-NAMES, a list of package specifications such as
;; native inputs.
(let ((inputs (package-inputs package))
(input-names
- '("pkg-config"
+ '("pkg-config"
+ "cmake"
"extra-cmake-modules"
"glib:bin"
"intltool"
diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm
index ede158c17c..f71b1d71b8 100644
--- a/guix/scripts/system.scm
+++ b/guix/scripts/system.scm
@@ -38,10 +38,10 @@
#:use-module (guix build utils)
#:use-module (gnu build install)
#:use-module (gnu system)
+ #:use-module (gnu bootloader)
#:use-module (gnu system file-systems)
#:use-module (gnu system linux-container)
#:use-module (gnu system vm)
- #:use-module (gnu system grub)
#:use-module (gnu services)
#:use-module (gnu services shepherd)
#:use-module (gnu services herd)
@@ -147,36 +147,45 @@ TARGET, and register them."
(map (cut copy-item <> target #:log-port log-port)
to-copy))))
-(define (install-grub* grub.cfg device target)
- "This is a variant of 'install-grub' with error handling, lifted in
-%STORE-MONAD"
- (let* ((gc-root (string-append target %gc-roots-directory
- "/grub.cfg"))
- (temp-gc-root (string-append gc-root ".new"))
- (delete-file (lift1 delete-file %store-monad))
- (make-symlink (lift2 switch-symlinks %store-monad))
- (rename (lift2 rename-file %store-monad)))
- (mbegin %store-monad
- ;; Prepare the symlink to GRUB.CFG to make sure that it's a GC root when
- ;; 'install-grub' completes (being a bit paranoid.)
- (make-symlink temp-gc-root grub.cfg)
-
- (munless (false-if-exception (install-grub grub.cfg device target))
+(define* (install-bootloader installer-drv
+ #:key
+ bootcfg bootcfg-file
+ device target)
+ "Call INSTALLER-DRV with error handling, in %STORE-MONAD."
+ (with-monad %store-monad
+ (let* ((gc-root (string-append target %gc-roots-directory
+ "/bootcfg"))
+ (temp-gc-root (string-append gc-root ".new"))
+ (install (and installer-drv
+ (derivation->output-path installer-drv)))
+ (bootcfg (derivation->output-path bootcfg)))
+ ;; Prepare the symlink to bootloader config file to make sure that it's
+ ;; a GC root when 'installer-drv' completes (being a bit paranoid.)
+ (switch-symlinks temp-gc-root bootcfg)
+
+ (unless (false-if-exception
+ (begin
+ (install-boot-config bootcfg bootcfg-file target)
+ (when install
+ (save-load-path-excursion (primitive-load install)))))
(delete-file temp-gc-root)
- (leave (G_ "failed to install GRUB on device '~a'~%") device))
+ (leave (G_ "failed to install bootloader on device ~a '~a'~%") install device))
- ;; Register GRUB.CFG as a GC root so that its dependencies (background
- ;; image, font, etc.) are not reclaimed.
- (rename temp-gc-root gc-root))))
+ ;; Register bootloader config file as a GC root so that its dependencies
+ ;; (background image, font, etc.) are not reclaimed.
+ (rename-file temp-gc-root gc-root)
+ (return #t))))
(define* (install os-drv target
#:key (log-port (current-output-port))
- grub? grub.cfg device)
- "Copy the closure of GRUB.CFG, which includes the output of OS-DRV, to
+ bootloader-installer install-bootloader?
+ bootcfg bootcfg-file
+ device)
+ "Copy the closure of BOOTCFG, which includes the output of OS-DRV, to
directory TARGET. TARGET must be an absolute directory name since that's what
'guix-register' expects.
-When GRUB? is true, install GRUB on DEVICE, using GRUB.CFG."
+When INSTALL-BOOTLOADER? is true, install bootloader on DEVICE, using BOOTCFG."
(define (maybe-copy to-copy)
(with-monad %store-monad
(if (string=? target "/")
@@ -205,16 +214,21 @@ the ownership of '~a' may be incorrect!~%")
(populate (lift2 populate-root-file-system %store-monad)))
(mbegin %store-monad
- ;; Copy the closure of GRUB.CFG, which includes OS-DIR, GRUB's
- ;; background image and so on.
- (maybe-copy grub.cfg)
+ ;; Copy the closure of BOOTCFG, which includes OS-DIR,
+ ;; eventual background image and so on.
+ (maybe-copy
+ (derivation->output-path bootcfg))
;; Create a bunch of additional files.
(format log-port "populating '~a'...~%" target)
(populate os-dir target)
- (mwhen grub?
- (install-grub* grub.cfg device target)))))
+ (mwhen install-bootloader?
+ (install-bootloader bootloader-installer
+ #:bootcfg bootcfg
+ #:bootcfg-file bootcfg-file
+ #:device device
+ #:target target)))))
;;;
@@ -398,49 +412,58 @@ connection to the store."
;;;
(define (switch-to-system-generation store spec)
"Switch the system profile to the generation specified by SPEC, and
-re-install grub with a grub configuration file that uses the specified system
+re-install bootloader with a configuration file that uses the specified system
generation as its default entry. STORE is an open connection to the store."
(let ((number (relative-generation-spec->number %system-profile spec)))
(if number
(begin
- (reinstall-grub store number)
+ (reinstall-bootloader store number)
(switch-to-generation* %system-profile number))
(leave (G_ "cannot switch to system generation '~a'~%") spec))))
-(define (reinstall-grub store number)
- "Re-install grub for existing system profile generation NUMBER. STORE is an
-open connection to the store."
+(define* (system-bootloader-name #:optional (system %system-profile))
+ "Return the bootloader name stored in SYSTEM's \"parameters\" file."
+ (let ((params (unless-file-not-found
+ (read-boot-parameters-file system))))
+ (boot-parameters-boot-name params)))
+
+(define (reinstall-bootloader store number)
+ "Re-install bootloader for existing system profile generation NUMBER.
+STORE is an open connection to the store."
(let* ((generation (generation-file-name %system-profile number))
(params (unless-file-not-found
(read-boot-parameters-file generation)))
- (root-device (boot-parameters-root-device params))
- ;; We don't currently keep track of past menu entries' details. The
- ;; default values will allow the system to boot, even if they differ
- ;; from the actual past values for this generation's entry.
- (grub-config (grub-configuration (device root-device)))
+ ;; Detect the bootloader used in %system-profile.
+ (bootloader (lookup-bootloader-by-name (system-bootloader-name)))
+
+ ;; Use the detected bootloader with default configuration.
+ ;; It will be enough to allow the system to boot.
+ (bootloader-config (bootloader-configuration
+ (bootloader bootloader)))
+
;; Make the specified system generation the default entry.
(entries (profile-boot-parameters %system-profile (list number)))
(old-generations (delv number (generation-numbers %system-profile)))
- (old-entries (profile-boot-parameters %system-profile old-generations))
- (grub.cfg (run-with-store store
- (grub-configuration-file grub-config
- entries
- #:old-entries old-entries))))
- (show-what-to-build store (list grub.cfg))
- (build-derivations store (list grub.cfg))
- ;; This is basically the same as install-grub*, but for now we avoid
- ;; re-installing the GRUB boot loader itself onto a device, mainly because
- ;; we don't in general have access to the same version of the GRUB package
- ;; which was used when installing this other system generation.
- (let* ((grub.cfg-path (derivation->output-path grub.cfg))
- (gc-root (string-append %gc-roots-directory "/grub.cfg"))
- (temp-gc-root (string-append gc-root ".new")))
- (switch-symlinks temp-gc-root grub.cfg-path)
- (unless (false-if-exception (install-grub-config grub.cfg-path "/"))
- (delete-file temp-gc-root)
- (leave (G_ "failed to re-install GRUB configuration file: '~a'~%")
- grub.cfg-path))
- (rename-file temp-gc-root gc-root))))
+ (old-entries (profile-boot-parameters
+ %system-profile old-generations)))
+ (run-with-store store
+ (mlet* %store-monad
+ ((bootcfg ((bootloader-configuration-file-generator bootloader)
+ bootloader-config entries
+ #:old-entries old-entries))
+ (bootcfg-file -> (bootloader-configuration-file bootloader))
+ (target -> "/")
+ (drvs -> (list bootcfg)))
+ (mbegin %store-monad
+ (show-what-to-build* drvs)
+ (built-derivations drvs)
+ ;; Only install bootloader configuration file. Thus, no installer
+ ;; nor device is provided here.
+ (install-bootloader #f
+ #:bootcfg bootcfg
+ #:bootcfg-file bootcfg-file
+ #:device #f
+ #:target target))))))
;;;
@@ -498,6 +521,7 @@ list of services."
(let* ((generation (generation-file-name profile number))
(params (read-boot-parameters-file generation))
(label (boot-parameters-label params))
+ (boot-name (boot-parameters-boot-name params))
(root (boot-parameters-root-device params))
(root-device (if (bytevector? root)
(uuid->string root)
@@ -508,6 +532,7 @@ list of services."
(format #t (G_ " canonical file name: ~a~%") (readlink* generation))
;; TRANSLATORS: Please preserve the two-space indentation.
(format #t (G_ " label: ~a~%") label)
+ (format #t (G_ " bootloader: ~a~%") boot-name)
(format #t (G_ " root device: ~a~%") root-device)
(format #t (G_ " kernel: ~a~%") kernel))))
@@ -570,17 +595,29 @@ PATTERN, a string. When PATTERN is #f, display all the system generations."
(warning (G_ "Consider running 'guix pull' before 'reconfigure'.~%"))
(warning (G_ "Failing to do that may downgrade your system!~%"))))
+(define (bootloader-installer-derivation installer
+ bootloader device target)
+ "Return a file calling INSTALLER gexp with given BOOTLOADER, DEVICE
+and TARGET arguments."
+ (with-monad %store-monad
+ (gexp->file "bootloader-installer"
+ (with-imported-modules '((guix build utils))
+ #~(begin
+ (use-modules (guix build utils))
+ (#$installer #$bootloader #$device #$target))))))
+
(define* (perform-action action os
- #:key bootloader? dry-run? derivations-only?
+ #:key install-bootloader?
+ dry-run? derivations-only?
use-substitutes? device target
image-size full-boot?
(mappings '())
(gc-root #f))
- "Perform ACTION for OS. GRUB? specifies whether to install GRUB; DEVICE is
-the target devices for GRUB; TARGET is the target root directory; IMAGE-SIZE
-is the size of the image to be built, for the 'vm-image' and 'disk-image'
-actions. FULL-BOOT? is used for the 'vm' action; it determines whether to
-boot directly to the kernel or to the bootloader.
+ "Perform ACTION for OS. INSTALL-BOOTLOADER? specifies whether to install
+bootloader; DEVICE is the target devices for bootloader; TARGET is the target
+root directory; IMAGE-SIZE is the size of the image to be built, for the
+'vm-image' and 'disk-image' actions. FULL-BOOT? is used for the 'vm' action;
+it determines whether to boot directly to the kernel or to the bootloader.
When DERIVATIONS-ONLY? is true, print the derivation file name(s) without
building anything.
@@ -598,22 +635,37 @@ output when building a system derivation, such as a disk image."
#:image-size image-size
#:full-boot? full-boot?
#:mappings mappings))
- (grub (package->derivation (grub-configuration-grub
- (operating-system-bootloader os))))
- (grub.cfg (if (eq? 'container action)
- (return #f)
- (operating-system-bootcfg os
- (if (eq? 'init action)
- '()
- (profile-boot-parameters)))))
-
- ;; For 'init' and 'reconfigure', always build GRUB.CFG, even if
- ;; --no-grub is passed, because GRUB.CFG because we then use it as a GC
- ;; root. See <http://bugs.gnu.org/21068>.
+ (bootloader -> (bootloader-configuration-bootloader
+ (operating-system-bootloader os)))
+ (bootloader-package
+ (let ((package (bootloader-package bootloader)))
+ (if package
+ (package->derivation package)
+ (return #f))))
+ (bootcfg (if (eq? 'container action)
+ (return #f)
+ (operating-system-bootcfg
+ os
+ (if (eq? 'init action)
+ '()
+ (profile-boot-parameters)))))
+ (bootcfg-file -> (bootloader-configuration-file bootloader))
+ (bootloader-installer
+ (let ((installer (bootloader-installer bootloader))
+ (target (or target "/")))
+ (bootloader-installer-derivation installer
+ bootloader-package
+ device target)))
+
+ ;; For 'init' and 'reconfigure', always build BOOTCFG, even if
+ ;; --no-bootloader is passed, because we then use it as a GC root.
+ ;; See <http://bugs.gnu.org/21068>.
(drvs -> (if (memq action '(init reconfigure))
- (if bootloader?
- (list sys grub.cfg grub)
- (list sys grub.cfg))
+ (if (and install-bootloader? bootloader-package)
+ (list sys bootcfg
+ bootloader-package
+ bootloader-installer)
+ (list sys bootcfg))
(list sys)))
(% (if derivations-only?
(return (for-each (compose println derivation-file-name)
@@ -627,27 +679,25 @@ output when building a system derivation, such as a disk image."
(for-each (compose println derivation->output-path)
drvs)
- ;; Make sure GRUB is accessible.
- (when bootloader?
- (let ((prefix (derivation->output-path grub)))
- (setenv "PATH"
- (string-append prefix "/bin:" prefix "/sbin:"
- (getenv "PATH")))))
-
(case action
((reconfigure)
(mbegin %store-monad
(switch-to-system os)
- (mwhen bootloader?
- (install-grub* (derivation->output-path grub.cfg)
- device "/"))))
+ (mwhen install-bootloader?
+ (install-bootloader bootloader-installer
+ #:bootcfg bootcfg
+ #:bootcfg-file bootcfg-file
+ #:device device
+ #:target "/"))))
((init)
(newline)
(format #t (G_ "initializing operating system under '~a'...~%")
target)
(install sys (canonicalize-path target)
- #:grub? bootloader?
- #:grub.cfg (derivation->output-path grub.cfg)
+ #:install-bootloader? install-bootloader?
+ #:bootcfg bootcfg
+ #:bootcfg-file bootcfg-file
+ #:bootloader-installer bootloader-installer
#:device device))
(else
;; All we had to do was to build SYS and maybe register an
@@ -832,7 +882,7 @@ resulting from command-line parsing."
((first second) second)
(_ #f)))
(device (and bootloader?
- (grub-configuration-device
+ (bootloader-configuration-device
(operating-system-bootloader os)))))
(with-store store
@@ -863,7 +913,7 @@ resulting from command-line parsing."
m)
(_ #f))
opts)
- #:bootloader? bootloader?
+ #:install-bootloader? bootloader?
#:target target #:device device
#:gc-root (assoc-ref opts 'gc-root)))))
#:system system))))