[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
03/07: build-self: Use (guix self).
From: |
Ludovic Courtès |
Subject: |
03/07: build-self: Use (guix self). |
Date: |
Tue, 27 Mar 2018 04:25:18 -0400 (EDT) |
civodul pushed a commit to branch wip-pull-multiple-derivations
in repository guix.
commit be323c875c1ac1f5fc15291d34b2c1b96293f711
Author: Ludovic Courtès <address@hidden>
Date: Fri Mar 23 17:18:15 2018 +0100
build-self: Use (guix self).
This mitigates <https://bugs.gnu.org/27284>.
* build-aux/build-self.scm (libgcrypt, zlib, gzip, bzip2, xz)
(false-if-wrong-guile, package-for-current-guile, guile-json)
(guile-ssh, guile-git, guile-bytestructures, matching-guile-2.2): Remove.
(%dependency-variables, %persona-variables, %config-variables): New
variables.
(make-config.scm, load-path-expression, gexp->script)
(build-program): New procedures.
(build): Rewrite to simply delegate to 'guix-derivation'.
---
build-aux/build-self.scm | 419 +++++++++++++++++++++++------------------------
1 file changed, 201 insertions(+), 218 deletions(-)
diff --git a/build-aux/build-self.scm b/build-aux/build-self.scm
index 4c85c09..f46991e 100644
--- a/build-aux/build-self.scm
+++ b/build-aux/build-self.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2014, 2016, 2017 Ludovic Courtès <address@hidden>
+;;; Copyright © 2014, 2016, 2017, 2018 Ludovic Courtès <address@hidden>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -19,10 +19,14 @@
(define-module (build-self)
#:use-module (gnu)
#:use-module (guix)
+ #:use-module (guix ui)
#:use-module (guix config)
+ #:use-module (guix modules)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-19)
+ #:use-module (rnrs io ports)
#:use-module (ice-9 match)
+ #:use-module (ice-9 popen)
#:export (build))
;;; Commentary:
@@ -40,116 +44,195 @@
;;; Code:
-;; The dependencies. Don't refer explicitly to the variables because they
-;; could be renamed or shuffled around in modules over time. Conversely,
-;; 'find-best-packages-by-name' is expected to always have the same semantics.
-
-(define guix
- (first (find-best-packages-by-name "guix" #f)))
-
-(define libgcrypt
- (first (find-best-packages-by-name "libgcrypt" #f)))
-
-(define zlib
- (first (find-best-packages-by-name "zlib" #f)))
-
-(define gzip
- (first (find-best-packages-by-name "gzip" #f)))
-
-(define bzip2
- (first (find-best-packages-by-name "bzip2" #f)))
-
-(define xz
- (first (find-best-packages-by-name "xz" #f)))
-
-(define (false-if-wrong-guile package)
- "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? (effective-version)
- (package-version guile)))
- package)))
-
-(define (package-for-current-guile . names)
- "Return the package with one of the given NAMES that depends on the current
-Guile major version (2.0 or 2.2), or #f if none of the packages matches."
- (let loop ((names names))
- (match names
- (()
- #f)
- ((name rest ...)
- (match (find-best-packages-by-name name #f)
- (()
- (loop rest))
- ((first _ ...)
- (or (false-if-wrong-guile first)
- (loop rest))))))))
-
-(define guile-json
- (package-for-current-guile "guile-json"
- "guile2.2-json"
- "guile2.0-json"))
-
-(define guile-ssh
- (package-for-current-guile "guile-ssh"
- "guile2.2-ssh"
- "guile2.0-ssh"))
+;;;
+;;; Generating (guix config).
+;;;
+;;; This is copied from (guix self) because we cannot assume (guix self) is
+;;; available at this point.
+;;;
-(define guile-git
- (package-for-current-guile "guile-git"
- "guile2.0-git"))
+(define %dependency-variables
+ ;; (guix config) variables corresponding to dependencies.
+ '(%libgcrypt %libz %xz %gzip %bzip2 %nix-instantiate))
+
+(define %persona-variables
+ ;; (guix config) variables that define Guix's persona.
+ '(%guix-package-name
+ %guix-version
+ %guix-bug-report-address
+ %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
+ (package-name "GNU Guix")
+ (package-version "0")
+ (bug-report-address "address@hidden")
+ (home-page-url "https://gnu.org/s/guix"))
+
+ ;; Hack so that Geiser is not confused.
+ (define defmod 'define-module)
+
+ (scheme-file "config.scm"
+ #~(begin
+ (#$defmod (guix config)
+ #:export (%guix-package-name
+ %guix-version
+ %guix-bug-report-address
+ %guix-home-page-url
+ %libgcrypt
+ %libz
+ %gzip
+ %bzip2
+ %xz
+ %nix-instantiate))
+
+ ;; XXX: Work around <http://bugs.gnu.org/15602>.
+ (eval-when (expand load eval)
+ #$@(map (match-lambda
+ ((name . value)
+ #~(define-public #$name #$value)))
+ %config-variables)
+
+ (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 %gzip
+ #+(and gzip (file-append gzip "/bin/gzip")))
+ (define %bzip2
+ #+(and bzip2 (file-append bzip2 "/bin/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")))))
-(define guile-bytestructures
- (package-for-current-guile "guile-bytestructures"
- "guile2.0-bytestructures"))
-;; The actual build procedure.
-
-(define (top-source-directory)
- "Return the name of the top-level directory of this source tree."
- (and=> (assoc-ref (current-source-location) 'filename)
- (lambda (file)
- (string-append (dirname file) "/.."))))
+;;;
+;;; 'gexp->script'.
+;;;
+;;; This is our own variant of 'gexp->script' with an extra #:module-path
+;;; parameter, which was unavailable in (guix gexp) until commit
+;;; 1ae16033f34cebe802023922436883867010850f (March 2018.)
+;;;
+(define (load-path-expression modules path)
+ "Return as a monadic value a gexp that sets '%load-path' and
+'%load-compiled-path' to point to MODULES, a list of module names. MODULES
+are searched for in PATH."
+ (mlet %store-monad ((modules (imported-modules modules
+ #:module-path path))
+ (compiled (compiled-modules modules
+ #:module-path path)))
+ (return (gexp (eval-when (expand load eval)
+ (set! %load-path
+ (cons (ungexp modules) %load-path))
+ (set! %load-compiled-path
+ (cons (ungexp compiled)
+ %load-compiled-path)))))))
+
+(define* (gexp->script name exp
+ #:key (guile (default-guile))
+ (module-path %load-path))
+ "Return an executable script NAME that runs EXP using GUILE, with EXP's
+imported modules in its search path."
+ (mlet %store-monad ((set-load-path
+ (load-path-expression (gexp-modules exp)
+ module-path)))
+ (gexp->derivation name
+ (gexp
+ (call-with-output-file (ungexp output)
+ (lambda (port)
+ ;; Note: that makes a long shebang. When the store
+ ;; is /gnu/store, that fits within the 128-byte
+ ;; limit imposed by Linux, but that may go beyond
+ ;; when running tests.
+ (format port
+ "#!~a/bin/guile --no-auto-compile~%!#~%"
+ (ungexp guile))
+
+ (write '(ungexp set-load-path) port)
+ (write '(ungexp exp) port)
+ (chmod port #o555))))
+ #:module-path module-path)))
+
(define (date-version-string)
"Return the current date and hour in UTC timezone, for use as a poor
person's version identifier."
;; XXX: Replace with a Git commit id.
(date->string (current-date 0) "~Y~m~d.~H"))
-(define (matching-guile-2.2)
- "Return a Guile 2.2 with the same version as the current one or immediately
-older than then current one. This is so that we do not build ABI-incompatible
-objects. See <https://bugs.gnu.org/29570>."
- (let loop ((packages (find-packages-by-name "guile" "2.2"))
- (best #f))
- (match packages
- (()
- best)
- ((head tail ...)
- (if (string=? (package-version head) (version))
- head
- (if best
- (if (version>? (package-version head) (version))
- (loop tail best)
- (loop tail head))
- (loop tail head)))))))
-
-(define (guile-for-build)
- "Return a derivation for Guile 2.0 or 2.2, whichever matches the currently
-running Guile."
- (package->derivation (cond-expand
- (guile-2.2
- (canonical-package (matching-guile-2.2)))
- (else
- (canonical-package
- (specification->package "address@hidden"))))))
+(define* (build-program source version
+ #:optional (guile-version (effective-version)))
+ "Return a program that computes the derivation to build Guix from SOURCE."
+ (with-imported-modules `(((guix config)
+ => ,(make-config.scm
+ #:libgcrypt
+ (specification->package "libgcrypt")))
+ ,@(delete '(guix config)
+ (source-module-closure `((guix store)
+ (guix self)
+ (guix
derivations)
+ (gnu packages
bootstrap))
+ (cons source
%load-path))))
+ (gexp->script "compute-guix-derivation"
+ #~(begin
+ (use-modules (ice-9 match))
+
+ (eval-when (expand load eval)
+ ;; XXX: This hack allows us to ignore
+ ;; $GUILE_LOAD_COMPILED_PATH, thereby making sure we
+ ;; only load our own modules or those of Guile.
+ (unsetenv "GUIX_PACKAGE_PATH")
+ (match %load-compiled-path
+ ((front _ ... sys1 sys2)
+ (set! %load-compiled-path
+ (list front sys1 sys2)))
+ (_ #t)))
+
+ (define-syntax source
+ (identifier-syntax
+ (match (command-line)
+ ((program source) source))))
+
+ ;; (gnu packages …) modules are going to be looked up
+ ;; under SOURCE.
+ (add-to-load-path source)
+
+ (use-modules (guix store)
+ (guix self)
+ (guix derivations))
+
+ (with-store store
+ (display "Computing Guix derivation...\n"
+ (current-error-port))
+ (display
+ (derivation-file-name
+ (run-with-store store
+ (guix-derivation source #$version
+ #$guile-version))))))
+ #:module-path (list source))))
;; The procedure below is our return value.
(define* (build source
@@ -158,124 +241,24 @@ running Guile."
#:rest rest)
"Return a derivation that unpacks SOURCE into STORE and compiles Scheme
files."
- ;; The '%xxxdir' variables were added to (guix config) in July 2016 so we
- ;; cannot assume that they are defined. Try to guess their value when
- ;; they're undefined (XXX: we get an incorrect guess when environment
- ;; variables such as 'NIX_STATE_DIR' are defined!).
- (define storedir
- (if (defined? '%storedir) %storedir %store-directory))
- (define localstatedir
- (if (defined? '%localstatedir) %localstatedir (dirname %state-directory)))
- (define sysconfdir
- (if (defined? '%sysconfdir) %sysconfdir (dirname %config-directory)))
-
- (define builder
- #~(begin
- (use-modules (guix build pull))
-
- (letrec-syntax ((maybe-load-path
- (syntax-rules ()
- ((_ item rest ...)
- (let ((tail (maybe-load-path rest ...)))
- (if (string? item)
- (cons (string-append item
- "/share/guile/site/"
- #$(effective-version))
- tail)
- tail)))
- ((_)
- '()))))
- (set! %load-path
- (append
- (maybe-load-path #$guile-json #$guile-ssh
- #$guile-git #$guile-bytestructures)
- %load-path)))
-
- (letrec-syntax ((maybe-load-compiled-path
- (syntax-rules ()
- ((_ item rest ...)
- (let ((tail (maybe-load-compiled-path rest ...)))
- (if (string? item)
- (cons (string-append item
- "/lib/guile/"
- #$(effective-version)
- "/site-ccache")
- tail)
- tail)))
- ((_)
- '()))))
- (set! %load-compiled-path
- (append
- (maybe-load-compiled-path #$guile-json #$guile-ssh
- #$guile-git #$guile-bytestructures)
- %load-compiled-path)))
-
- ;; XXX: The 'guile-ssh' package prior to Guix commit 92b7258 was
- ;; broken: libguile-ssh could not be found. Work around that.
- ;; FIXME: We want Guile-SSH 0.10.2 or later anyway.
- #$(if (string-prefix? "0.9." (package-version guile-ssh))
- #~(setenv "LTDL_LIBRARY_PATH" (string-append #$guile-ssh "/lib"))
- #t)
-
- (build-guix #$output #$source
-
- #:system #$%system
- #:storedir #$storedir
- #:localstatedir #$localstatedir
- #:sysconfdir #$sysconfdir
- #:sbindir (string-append #$guix "/sbin")
-
- #:package-name #$%guix-package-name
- #:package-version #$version
- #:bug-report-address #$%guix-bug-report-address
- #:home-page-url #$%guix-home-page-url
-
- #:libgcrypt #$libgcrypt
- #:zlib #$zlib
- #:gzip #$gzip
- #:bzip2 #$bzip2
- #:xz #$xz
-
- ;; XXX: This is not perfect, enabling VERBOSE? means
- ;; building a different derivation.
- #:debug-port (if #$verbose?
- (current-error-port)
- (%make-void-port "w")))))
-
- (unless guile-git
- ;; XXX: Guix before February 2017 lacks a 'guile-git' package altogether.
- ;; If we try to upgrade anyway, the logic in (guix scripts pull) will not
- ;; build (guix git), which will leave us with an unusable 'guix pull'. To
- ;; avoid that, fail early.
- (format (current-error-port)
- "\
-Your installation is too old and lacks a '~a' package.
-Please upgrade to an intermediate version first, for instance with:
-
- guix pull
--url=https://git.savannah.gnu.org/cgit/guix.git/snapshot/v0.13.0.tar.gz
-\n"
- (match (effective-version)
- ("2.0" "guile2.0-git")
- (_ "guile-git")))
- (exit 1))
-
- (mlet %store-monad ((guile (guile-for-build)))
- (gexp->derivation "guix-latest" builder
- #:modules '((guix build pull)
- (guix build utils)
- (guix build compile)
-
- ;; Closure of (guix modules).
- (guix modules)
- (guix memoization)
- (guix profiling)
- (guix sets))
-
- ;; Arrange so that our own (guix build …) modules are
- ;; used.
- #:module-path (list (top-source-directory))
-
- #:guile-for-build guile)))
+ ;; Build the build program and then use it as a trampoline to build from
+ ;; SOURCE.
+ (mlet %store-monad ((build (build-program source version)))
+ (mbegin %store-monad
+ (show-what-to-build* (list build))
+ (built-derivations (list build))
+ (let ((pipe (open-pipe* OPEN_READ
+ (derivation->output-path build)
+ source)))
+ (match (get-string-all pipe)
+ ((? eof-object?)
+ (error "build program failed" build))
+ ((? derivation-path? drv)
+ (mbegin %store-monad
+ ((store-lift add-temp-root) drv)
+ (return (read-derivation-from-file drv))))
+ ((? string? str)
+ (error "invalid build result" (list build str))))))))
;; This file is loaded by 'guix pull'; return it the build procedure.
build
- branch wip-pull-multiple-derivations created (now 45c9414), Ludovic Courtès, 2018/03/27
- 01/07: gnu: bootstrap: Remove unneeded import., Ludovic Courtès, 2018/03/27
- 04/07: build: Add 'as-derivation' target., Ludovic Courtès, 2018/03/27
- 07/07: cuirass: Add job specs for the modular Guix., Ludovic Courtès, 2018/03/27
- 06/07: cuirass: Factorize hydra-to-cuirass CI job translation., Ludovic Courtès, 2018/03/27
- 05/07: discovery: Remove dependency on (guix ui)., Ludovic Courtès, 2018/03/27
- 03/07: build-self: Use (guix self).,
Ludovic Courtès <=
- 02/07: Add (guix self)., Ludovic Courtès, 2018/03/27