diff options
-rw-r--r-- | Makefile.am | 7 | ||||
-rw-r--r-- | doc/guix.texi | 102 | ||||
-rw-r--r-- | gnu/packages/base.scm | 15 | ||||
-rw-r--r-- | gnu/packages/maths.scm | 21 | ||||
-rw-r--r-- | gnu/packages/video.scm | 3 | ||||
-rw-r--r-- | gnu/services/networking.scm | 49 | ||||
-rw-r--r-- | gnu/system.scm | 6 | ||||
-rw-r--r-- | gnu/system/linux-container.scm | 21 | ||||
-rw-r--r-- | gnu/system/locale.scm | 62 | ||||
-rw-r--r-- | guix/scripts/environment.scm | 24 | ||||
-rw-r--r-- | guix/scripts/system.scm | 19 | ||||
-rw-r--r-- | tests/guix-environment.sh | 11 |
12 files changed, 279 insertions, 61 deletions
diff --git a/Makefile.am b/Makefile.am index 4f90b1d15b..b2ee3245b3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -337,6 +337,10 @@ AM_V_GUILEC = $(AM_V_GUILEC_$(V)) AM_V_GUILEC_ = $(AM_V_GUILEC_$(AM_DEFAULT_VERBOSITY)) AM_V_GUILEC_0 = @echo " GUILEC" $@; +# Flags passed to 'guild compile'. +GUILD_COMPILE_FLAGS = \ + -Wformat -Wunbound-variable -Warity-mismatch + # Unset 'GUILE_LOAD_COMPILED_PATH' altogether while compiling. Otherwise, if # $GUILE_LOAD_COMPILED_PATH contains $(moduledir), we may find .go files in # there that are newer than the local .scm files (for instance because the @@ -352,8 +356,7 @@ AM_V_GUILEC_0 = @echo " GUILEC" $@; LC_ALL=C \ $(top_builddir)/pre-inst-env \ $(GUILD) compile -L "$(top_builddir)" -L "$(top_srcdir)" \ - -Wformat -Wunbound-variable -Warity-mismatch \ - --target="$(host)" \ + $(GUILD_COMPILE_FLAGS) --target="$(host)" \ -o "$@" "$<" SUFFIXES = .go diff --git a/doc/guix.texi b/doc/guix.texi index 236c5973cd..483d6e2608 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -4730,7 +4730,8 @@ The available options are summarized below. @table @code @item --expression=@var{expr} @itemx -e @var{expr} -Create an environment for the package that @var{expr} evaluates to. +Create an environment for the package or list of packages that +@var{expr} evaluates to. For example, running: @@ -4741,10 +4742,18 @@ guix environment -e '(@@ (gnu packages maths) petsc-openmpi)' starts a shell with the environment for this specific variant of the PETSc package. +Running: + +@example +guix environment --ad-hoc -e '(@ (gnu) %base-packages)' +@end example + +starts a shell with all the GuixSD base packages available. + @item --load=@var{file} @itemx -l @var{file} -Create an environment for the package that the code within @var{file} -evaluates to. +Create an environment for the package or list of packages that the code +within @var{file} evaluates to. As an example, @var{file} might contain a definition like this (@pxref{Defining Packages}): @@ -5562,6 +5571,11 @@ Library Reference Manual}). @xref{Locales}, for more information. The list of locale definitions to be compiled and that may be used at run time. @xref{Locales}. +@item @code{locale-libcs} (default: @code{(list @var{glibc})}) +The list of GNU@tie{}libc packages whose locale data and tools are used +to build the locale definitions. @xref{Locales}, for compatibility +considerations that justify this option. + @item @code{name-service-switch} (default: @var{%default-nss}) Configuration of libc's name service switch (NSS)---a @code{<name-service-switch>} object. @xref{Name Service Switch}, for @@ -6020,6 +6034,57 @@ instance it has @code{uk_UA.utf8} but @emph{not}, say, @code{uk_UA.UTF-8}. @end defvr +@subsubsection Locale Data Compatibility Considerations + +@cindex incompatibility, of locale data +@code{operating-system} declarations provide a @code{locale-libcs} field +to specify the GNU@tie{}libc packages that are used to compile locale +declarations (@pxref{operating-system Reference}). ``Why would I +care?'', you may ask. Well, it turns out that the binary format of +locale data is occasionally incompatible from one libc version to +another. + +@c See <https://sourceware.org/ml/libc-alpha/2015-09/msg00575.html> +@c and <https://lists.gnu.org/archive/html/guix-devel/2015-08/msg00737.html>. +For instance, a program linked against libc version 2.21 is unable to +read locale data produced with libc 2.22; worse, that program +@emph{aborts} instead of simply ignoring the incompatible locale +data@footnote{Versions 2.23 and later of GNU@tie{}libc will simply skip +the incompatible locale data, which is already an improvement.}. +Similarly, a program linked against libc 2.22 can read most, but not +all, the locale data from libc 2.21 (specifically, @code{LC_COLLATE} +data is incompatible); thus calls to @code{setlocale} may fail, but +programs will not abort. + +The ``problem'' in GuixSD is that users have a lot of freedom: They can +choose whether and when to upgrade software in their profiles, and might +be using a libc version different from the one the system administrator +used to build the system-wide locale data. + +Fortunately, unprivileged users can also install their own locale data +and define @var{GUIX_LOCPATH} accordingly (@pxref{locales-and-locpath, +@code{GUIX_LOCPATH} and locale packages}). + +Still, it is best if the system-wide locale data at +@file{/run/current-system/locale} is built for all the libc versions +actually in use on the system, so that all the programs can access +it---this is especially crucial on a multi-user system. To do that, the +administrator can specify several libc packages in the +@code{locale-libcs} field of @code{operating-system}: + +@example +(use-package-modules base) + +(operating-system + ;; @dots{} + (locale-libcs (list glibc-2.21 (canonical-package glibc)))) +@end example + +This example would lead to a system containing locale definitions for +both libc 2.21 and the current version of libc in +@file{/run/current-system/locale}. + + @node Services @subsection Services @@ -6328,11 +6393,13 @@ keep the system clock synchronized with that of @var{servers}. List of host names used as the default NTP servers. @end defvr -@deffn {Scheme Procedure} tor-service [#:tor tor] -Return a service to run the @uref{https://torproject.org,Tor} daemon. +@deffn {Scheme Procedure} tor-service [@var{config-file}] [#:tor @var{tor}] +Return a service to run the @uref{https://torproject.org, Tor} anonymous +networking daemon. -The daemon runs with the default settings (in particular the default exit -policy) as the @code{tor} unprivileged user. +The daemon runs as the @code{tor} unprivileged user. It is passed +@var{config-file}, a file-like object, with an additional @code{User tor} +line. Run @command{man tor} for information about the configuration file. @end deffn @deffn {Scheme Procedure} bitlbee-service [#:bitlbee bitlbee] @ @@ -7264,6 +7331,27 @@ using the following command: # dd if=$(guix system disk-image my-os.scm) of=/dev/sdc @end example +@item container +Return a script to run the operating system declared in @var{file} +within a container. Containers are a set of lightweight isolation +mechanisms provided by the kernel Linux-libre. Containers are +substantially less resource-demanding than full virtual machines since +the kernel, shared objects, and other resources can be shared with the +host system; this also means they provide thinner isolation. + +Currently, the script must be run as root in order to support more than +a single user and group. The container shares its store with the host +system. + +As with the @code{vm} action (@pxref{guix system vm}), additional file +systems to be shared between the host and container can be specified +using the @option{--share} and @option{--expose} options: + +@example +guix system container my-config.scm \ + --expose=$HOME --share=$HOME/tmp=/exchange +@end example + @end table @var{options} can contain any of the common build options provided by diff --git a/gnu/packages/base.scm b/gnu/packages/base.scm index f951e28b3b..61eeba3cee 100644 --- a/gnu/packages/base.scm +++ b/gnu/packages/base.scm @@ -633,6 +633,21 @@ with the Linux kernel.") (license lgpl2.0+) (home-page "http://www.gnu.org/software/libc/"))) +(define-public glibc-2.21 + ;; The old libc, which we use mostly to build locale data in the old format + ;; (which the new libc can cope with.) + (package + (inherit glibc) + (version "2.21") + (source (origin + (inherit (package-source glibc)) + (uri (string-append "mirror://gnu/glibc/glibc-" + version ".tar.xz")) + (sha256 + (base32 + "1f135546j34s9bfkydmx2nhh9vwxlx60jldi80zmsnln6wj3dsxf")) + (patches (list (search-patch "glibc-ldd-x86_64.patch"))))))) + (define-public glibc-locales (package (inherit glibc) diff --git a/gnu/packages/maths.scm b/gnu/packages/maths.scm index 4935f8019f..b4b930de47 100644 --- a/gnu/packages/maths.scm +++ b/gnu/packages/maths.scm @@ -1474,13 +1474,14 @@ constant parts of it.") (build-system gnu-build-system) (arguments `(#:tests? #f ;no "check" target - ;; DYNAMIC_ARCH is only supported on x86. When it is disabled, - ;; OpenBLAS will tune itself to the build host, so we need to disable - ;; substitutions. + ;; DYNAMIC_ARCH is only supported on x86. When it is disabled and no + ;; TARGET is specified, OpenBLAS will tune itself to the build host, so + ;; we need to disable substitutions. #:substitutable? ,(let ((system (or (%current-target-system) (%current-system)))) (or (string-prefix? "x86_64" system) - (string-prefix? "i686" system))) + (string-prefix? "i686" system) + (string-prefix? "mips" system))) #:make-flags (list (string-append "PREFIX=" (assoc-ref %outputs "out")) "SHELL=bash" @@ -1491,10 +1492,16 @@ constant parts of it.") ;; Unfortunately, this is not supported on non-x86 architectures, ;; where it leads to failed builds. ,@(let ((system (or (%current-target-system) (%current-system)))) - (if (or (string-prefix? "x86_64" system) + (cond + ((or (string-prefix? "x86_64" system) (string-prefix? "i686" system)) - '("DYNAMIC_ARCH=1") - '()))) + '("DYNAMIC_ARCH=1")) + ;; On MIPS we force the "SICORTEX" TARGET, as for the other + ;; two available MIPS targets special extended instructions + ;; for Loongson cores are used. + ((string-prefix? "mips" system) + '("TARGET=SICORTEX")) + (else '())))) ;; no configure script #:phases (alist-delete 'configure %standard-phases))) (inputs diff --git a/gnu/packages/video.scm b/gnu/packages/video.scm index 773b2ebf99..f4b242df87 100644 --- a/gnu/packages/video.scm +++ b/gnu/packages/video.scm @@ -384,6 +384,7 @@ standards (MPEG-2, MPEG-4 ASP/H.263, MPEG-4 AVC/H.264, and VC-1/VMW3).") (inputs `(("fontconfig" ,fontconfig) ("freetype" ,freetype) + ("gnutls" ,gnutls) ("opus" ,opus) ("ladspa" ,ladspa) ("lame" ,lame) @@ -467,7 +468,7 @@ standards (MPEG-2, MPEG-4 ASP/H.263, MPEG-4 AVC/H.264, and VC-1/VMW3).") "--enable-gpl" ; enable optional gpl licensed parts "--enable-shared" "--enable-fontconfig" - ;; "--enable-gnutls" ; causes test failures + "--enable-gnutls" "--enable-ladspa" "--enable-libass" "--enable-libbluray" diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm index 003d5a5010..d33ff4fc4a 100644 --- a/gnu/services/networking.scm +++ b/gnu/services/networking.scm @@ -316,20 +316,33 @@ keep the system clock synchronized with that of @var{servers}." (home-directory "/var/empty") (shell #~(string-append #$shadow "/sbin/nologin"))))) -(define (tor-dmd-service tor) +(define (tor-dmd-service config) "Return a <dmd-service> running TOR." - (let ((torrc (plain-file "torrc" "User tor\n"))) - (list (dmd-service - (provision '(tor)) + (match config + ((tor config-file) + (let ((torrc (computed-file "torrc" + #~(begin + (use-modules (guix build utils)) + (call-with-output-file #$output + (lambda (port) + (display "\ +User tor # automatically added\n" port) + (call-with-input-file #$config-file + (lambda (input) + (dump-port input port))) + #t))) + #:modules '((guix build utils))))) + (list (dmd-service + (provision '(tor)) - ;; Tor needs at least one network interface to be up, hence the - ;; dependency on 'loopback'. - (requirement '(user-processes loopback)) + ;; Tor needs at least one network interface to be up, hence the + ;; dependency on 'loopback'. + (requirement '(user-processes loopback)) - (start #~(make-forkexec-constructor - (list (string-append #$tor "/bin/tor") "-f" #$torrc))) - (stop #~(make-kill-destructor)) - (documentation "Run the Tor anonymous network overlay."))))) + (start #~(make-forkexec-constructor + (list (string-append #$tor "/bin/tor") "-f" #$torrc))) + (stop #~(make-kill-destructor)) + (documentation "Run the Tor anonymous network overlay."))))))) (define tor-service-type (service-type (name 'tor) @@ -339,12 +352,16 @@ keep the system clock synchronized with that of @var{servers}." (service-extension account-service-type (const %tor-accounts)))))) -(define* (tor-service #:key (tor tor)) - "Return a service to run the @uref{https://torproject.org,Tor} daemon. +(define* (tor-service #:optional + (config-file (plain-file "empty" "")) + #:key (tor tor)) + "Return a service to run the @uref{https://torproject.org, Tor} anonymous +networking daemon. -The daemon runs with the default settings (in particular the default exit -policy) as the @code{tor} unprivileged user." - (service tor-service-type tor)) +The daemon runs as the @code{tor} unprivileged user. It is passed +@var{config-file}, a file-like object, with an additional @code{User tor} +line. Run @command{man tor} for information about the configuration file." + (service tor-service-type (list tor config-file))) ;;; diff --git a/gnu/system.scm b/gnu/system.scm index 3d570c0d1f..8fed857b39 100644 --- a/gnu/system.scm +++ b/gnu/system.scm @@ -76,6 +76,7 @@ operating-system-timezone operating-system-locale operating-system-locale-definitions + operating-system-locale-libcs operating-system-mapped-devices operating-system-file-systems operating-system-activation-script @@ -144,6 +145,8 @@ (default "en_US.utf8")) (locale-definitions operating-system-locale-definitions ; list of <locale-definition> (default %default-locale-definitions)) + (locale-libcs operating-system-locale-libcs ; list of <packages> + (default %default-locale-libcs)) (name-service-switch operating-system-name-service-switch ; <name-service-switch> (default %default-nss)) @@ -643,7 +646,8 @@ listed in OS. The C library expects to find it under (raise (condition (&message (message "system locale lacks a definition"))))) - (locale-directory (operating-system-locale-definitions os))) + (locale-directory (operating-system-locale-definitions os) + #:libcs (operating-system-locale-libcs os))) (define (kernel->grub-label kernel) "Return a label for the GRUB menu entry that boots KERNEL." diff --git a/gnu/system/linux-container.scm b/gnu/system/linux-container.scm index fdf7460872..c2eb773931 100644 --- a/gnu/system/linux-container.scm +++ b/gnu/system/linux-container.scm @@ -25,6 +25,7 @@ #:use-module (guix derivations) #:use-module (guix monads) #:use-module (gnu build linux-container) + #:use-module (gnu services) #:use-module (gnu system) #:use-module (gnu system file-systems) #:export (mapping->file-system @@ -50,14 +51,15 @@ "Return a derivation that builds OS as a Linux container." (mlet* %store-monad ((profile (operating-system-profile os)) - (etc (operating-system-etc-directory os)) + (etc -> (operating-system-etc-directory os)) (boot (operating-system-boot-script os #:container? #t)) (locale (operating-system-locale-directory os))) - (file-union "system-container" - `(("boot" ,#~#$boot) - ("profile" ,#~#$profile) - ("locale" ,#~#$locale) - ("etc" ,#~#$etc))))) + (lower-object + (file-union "system-container" + `(("boot" ,#~#$boot) + ("profile" ,#~#$profile) + ("locale" ,#~#$locale) + ("etc" ,#~#$etc)))))) (define (containerized-operating-system os mappings) "Return an operating system based on OS for use in a Linux container @@ -106,7 +108,12 @@ that will be shared with the host system." (setenv "TMPDIR" "/tmp") (setenv "GUIX_NEW_SYSTEM" #$os-drv) (for-each mkdir-p '("/run" "/bin" "/etc" "/home" "/var")) - (primitive-load (string-append #$os-drv "/boot")))))) + (primitive-load (string-append #$os-drv "/boot"))) + ;; A range of 65536 uid/gids is used to cover 16 bits worth of + ;; users and groups, which is sufficient for most cases. + ;; + ;; See: http://www.freedesktop.org/software/systemd/man/systemd-nspawn.html#--private-users= + #:host-uids 65536))) (gexp->script "run-container" script #:modules '((ice-9 match) diff --git a/gnu/system/locale.scm b/gnu/system/locale.scm index 010fb45272..e798827a01 100644 --- a/gnu/system/locale.scm +++ b/gnu/system/locale.scm @@ -18,11 +18,15 @@ (define-module (gnu system locale) #:use-module (guix gexp) + #:use-module (guix store) + #:use-module (guix monads) #:use-module (guix records) #:use-module (guix packages) + #:use-module (guix utils) #:use-module (gnu packages base) #:use-module (gnu packages compression) #:use-module (srfi srfi-26) + #:use-module (ice-9 match) #:export (locale-definition locale-definition? locale-definition-name @@ -31,6 +35,7 @@ locale-directory + %default-locale-libcs %default-locale-definitions)) ;;; Commentary: @@ -50,6 +55,15 @@ (define* (localedef-command locale #:key (libc (canonical-package glibc))) "Return a gexp that runs 'localedef' from LIBC to build LOCALE." + (define (maybe-version-directory) + ;; XXX: For libc prior to 2.22, GuixSD did not store locale data in a + ;; version-specific sub-directory. Check whether this is the case. + ;; TODO: Remove this hack once libc 2.21 is buried. + (let ((version (package-version libc))) + (if (version>=? version "2.22") + (list version "/") + '()))) + #~(begin (format #t "building locale '~a'...~%" #$(locale-definition-name locale)) @@ -58,20 +72,29 @@ "-i" #$(locale-definition-source locale) "-f" #$(locale-definition-charset locale) (string-append #$output "/" - #$(package-version libc) "/" + #$@(maybe-version-directory) #$(locale-definition-name locale)))))) -(define* (locale-directory locales - #:key (libc (canonical-package glibc))) +(define* (single-locale-directory locales + #:key (libc (canonical-package glibc))) "Return a directory containing all of LOCALES for LIBC compiled. Because locale data formats are incompatible when switching from one libc to another, locale data is put in a sub-directory named after the 'version' field of LIBC." + (define version + (package-version libc)) + (define build #~(begin (mkdir #$output) - (mkdir (string-append #$output "/" #$(package-version libc))) + + ;; XXX: For libcs < 2.22, locale data is stored in the top-level + ;; directory. + ;; TODO: Remove this hack once libc 2.21 is buried. + #$(if (version>=? version "2.22") + #~(mkdir (string-append #$output "/" #$version)) + #~(symlink "." (string-append #$output "/" #$version))) ;; 'localedef' executes 'gzip' to access compressed locale sources. (setenv "PATH" (string-append #$gzip "/bin")) @@ -80,9 +103,38 @@ of LIBC." (and #$@(map (cut localedef-command <> #:libc libc) locales))))) - (gexp->derivation "locale" build + (gexp->derivation (string-append "locale-" version) build #:local-build? #t)) +(define* (locale-directory locales + #:key (libcs %default-locale-libcs)) + "Return a locale directory containing all of LOCALES for each libc package +listed in LIBCS. + +It is useful to list more than one libc when willing to support +already-installed packages built against a different libc since the locale +data format changes between libc versions." + (match libcs + ((libc) + (single-locale-directory locales #:libc libc)) + ((libcs ..1) + (mlet %store-monad ((dirs (mapm %store-monad + (lambda (libc) + (single-locale-directory locales + #:libc libc)) + libcs))) + (gexp->derivation "locale-multiple-versions" + #~(begin + (use-modules (guix build union)) + (union-build #$output (list #$@dirs))) + #:modules '((guix build union)) + #:local-build? #t + #:substitutable? #f))))) + +(define %default-locale-libcs + ;; The libcs for which we build locales by default. + (list (canonical-package glibc))) + (define %default-locale-definitions ;; Arbitrary set of locales that are built by default. They are here mostly ;; to facilitate first-time use to some people, while others may have to add diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm index 188838574f..f9ab9a483f 100644 --- a/guix/scripts/environment.scm +++ b/guix/scripts/environment.scm @@ -253,6 +253,18 @@ COMMAND or an interactive shell in that environment.\n")) (define (options/resolve-packages opts) "Return OPTS with package specification strings replaced by actual packages." + (define (package->outputs package mode) + (map (lambda (output) + (list mode package output)) + (package-outputs package))) + + (define (packages->outputs packages mode) + (match packages + ((? package? package) + (package->outputs package mode)) + (((? package? packages) ...) + (append-map (cut package->outputs <> mode) packages)))) + (compact (append-map (match-lambda (('package mode (? string? spec)) @@ -261,17 +273,11 @@ packages." (list (list mode package output)))) (('expression mode str) ;; Add all the outputs of the package STR evaluates to. - (match (read/eval str) - ((? package? package) - (map (lambda (output) - (list mode package output)) - (package-outputs package))))) + (packages->outputs (read/eval str) mode)) (('load mode file) ;; Add all the outputs of the package defined in FILE. - (let ((package (load* file (make-user-module '())))) - (map (lambda (output) - (list mode package output)) - (package-outputs package)))) + (let ((module (make-user-module '()))) + (packages->outputs (load* file module) mode))) (_ '(#f))) opts))) diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm index d847c75444..499038ffa1 100644 --- a/guix/scripts/system.scm +++ b/guix/scripts/system.scm @@ -34,6 +34,7 @@ #:use-module (gnu build install) #:use-module (gnu system) #: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) @@ -406,6 +407,8 @@ PATTERN, a string. When PATTERN is #f, display all the system generations." (case action ((build init reconfigure) (operating-system-derivation os)) + ((container) + (container-script os #:mappings mappings)) ((vm-image) (system-qemu-image os #:disk-image-size image-size)) ((vm) @@ -438,10 +441,12 @@ building anything." #:full-boot? full-boot? #:mappings mappings)) (grub (package->derivation grub)) - (grub.cfg (operating-system-grub.cfg os - (if (eq? 'init action) - '() - (previous-grub-entries)))) + (grub.cfg (if (eq? 'container action) + (return #f) + (operating-system-grub.cfg os + (if (eq? 'init action) + '() + (previous-grub-entries))))) (drvs -> (if (and grub? (memq action '(init reconfigure))) (list sys grub grub.cfg) (list sys))) @@ -524,6 +529,8 @@ Build the operating system declared in FILE according to ACTION.\n")) (display (_ "\ build build the operating system without installing anything\n")) (display (_ "\ + container build a container that shares the host's store\n")) + (display (_ "\ vm build a virtual machine image that shares the host's store\n")) (display (_ "\ vm-image build a freestanding virtual machine image\n")) @@ -694,7 +701,7 @@ argument list and OPTS is the option alist." (alist-cons 'argument arg result) (let ((action (string->symbol arg))) (case action - ((build vm vm-image disk-image reconfigure init + ((build container vm vm-image disk-image reconfigure init extension-graph dmd-graph list-generations) (alist-cons 'action action result)) (else (leave (_ "~a: unknown action~%") action)))))) @@ -723,7 +730,7 @@ argument list and OPTS is the option alist." (exit 1)) (case action - ((build vm vm-image disk-image reconfigure) + ((build container vm vm-image disk-image reconfigure) (unless (= count 1) (fail))) ((init) diff --git a/tests/guix-environment.sh b/tests/guix-environment.sh index 49b3b1ccc3..f7b0259e1b 100644 --- a/tests/guix-environment.sh +++ b/tests/guix-environment.sh @@ -111,4 +111,15 @@ then grep -E '^export CPATH=.*-gcc-bootstrap-0/include' "$tmpdir/a" grep -E '^export CPATH=.*-glibc-bootstrap-0/include' "$tmpdir/a" grep -E '^export LIBRARY_PATH=.*-glibc-bootstrap-0/lib' "$tmpdir/a" + + # Make sure a package list can be used with -e. + expr_list_test_code=" +(list (@@ (gnu packages commencement) gnu-make-boot0) + (@ (gnu packages bootstrap) %bootstrap-guile))" + + guix environment --ad-hoc --no-substitutes --search-paths --pure \ + -e "$expr_list_test_code" > "$tmpdir/a" + + grep -E '^export PATH=.*-make-boot0-4.1/bin' "$tmpdir/a" + grep -E '^export PATH=.*-guile-bootstrap-2.0/bin' "$tmpdir/a" fi |