;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2013-2024 Ludovic Courtès ;;; Copyright © 2016 Christine Lemmer-Webber ;;; Copyright © 2016, 2017 Leo Famulari ;;; Copyright © 2017 Mathieu Othacehe ;;; Copyright © 2017 Marius Bakke ;;; Copyright © 2018 Chris Marusich ;;; Copyright © 2024 Zheng Junjie <873216071@qq.com> ;;; ;;; This file is part of GNU Guix. ;;; ;;; GNU Guix is free software; you can redistribute it and/or modify it ;;; under the terms of the GNU General Public License as published by ;;; the Free Software Foundation; either version 3 of the License, or (at ;;; your option) any later version. ;;; ;;; GNU Guix is distributed in the hope that it will be useful, but ;;; WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have re
aboutsummaryrefslogtreecommitdiff
blob: b2f820bf26d2714f7901fc4a73a13d05889dc830 (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# GNU Guix --- Functional package management for GNU
# Copyright © 2021-2023 Ludovic Courtès <ludo@gnu.org>
#
# This file is part of GNU Guix.
#
# GNU Guix is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or (at
# your option) any later version.
#
# GNU Guix is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

#
# Test the 'guix shell' alias.
#

guix shell --version

configdir="t-guix-shell-config-$$"
tmpdir="t-guix-shell-$$"
trap 'rm -r "$tmpdir" "$configdir"' EXIT
mkdir "$tmpdir" "$configdir" "$configdir/guix"

XDG_CONFIG_HOME="$(realpath $configdir)"
export XDG_CONFIG_HOME

guix shell --bootstrap --pure guile-bootstrap -- guile --version

# '--symlink' can only be used with --container.
guix shell --bootstrap guile-bootstrap -S /dummy=bin/guile && false

# '--ad-hoc' is a thing of the past.
guix shell --ad-hoc guile-bootstrap && false

# Rejecting unsupported packages.
guix shell -s armhf-linux intelmetool -n && false

# Test approximately that the child process does not inherit extra file
# descriptors.  Ideally we'd check there's nothing more than 0, 1, and 2, but
# we cannot do that because (1) we might be inheriting additional FDs, for
# example due to <https://issues.guix.gnu.org/57567>, and (2) Bash itself
# opens a couple of extra FDs.
initial_fd_list="$(echo /proc/$$/fd/*)"
fd_list="$(guix shell --bootstrap guile-bootstrap -- \
		 bash -c 'echo /proc/$$/fd/*')"
test "$(echo $fd_list | wc -w)" -le "$(echo $initial_fd_list | wc -w)"

# Ignoring unauthorized files.
cat > "$tmpdir/guix.scm" <<EOF
This is a broken guix.scm file.
EOF
(cd "$tmpdir"; SHELL="$(type -P true)" guix shell --bootstrap 2> "stderr") && false
grep "not authorized" "$tmpdir/stderr"
rm "$tmpdir/stderr"

# Authorize the directory.
echo "$(realpath "$tmpdir")" > "$configdir/guix/shell-authorized-directories"

# Ignoring 'manifest.scm' and 'guix.scm' in non-interactive use.
(cd "$tmpdir"; guix shell --bootstrap -- true)
mv "$tmpdir/guix.scm" "$tmpdir/manifest.scm"
(cd "$tmpdir"; guix shell --bootstrap -- true)
rm "$tmpdir/manifest.scm"

# Honoring the local 'manifest.scm' file.
cat > "$tmpdir/manifest.scm" <<EOF
(specifications->manifest '("guile-bootstrap"))
EOF
cat > "$tmpdir/fake-shell.sh" <<EOF
#!$SHELL
# This fake shell allows us to test interactive use.
exec echo "\$GUIX_ENVIRONMENT"
EOF
chmod +x "$tmpdir/fake-shell.sh"
profile1="$(cd "$tmpdir"; SHELL="$(realpath fake-shell.sh)" guix shell --bootstrap)"
profile2="$(guix shell --bootstrap guile-bootstrap -- "$SHELL" -c 'echo $GUIX_ENVIRONMENT')"
test -n "$profile1"
test "$profile1" = "$profile2"
rm "$tmpdir/manifest.scm"

# Do not read manifest when passed '-q'.
echo "Broken manifest." > "$tmpdir/manifest.scm"
(cd "$tmpdir"; SHELL="$(realpath fake-shell.sh)" guix shell --bootstrap -q)
rm "$tmpdir/manifest.scm"

# Make sure '-D' affects only the immediately following '-f', and not packages
# that appear later: <https://issues.guix.gnu.org/52093>.
cat > "$tmpdir/empty-package.scm" <<EOF
(use-modules (guix) (guix tests)
             (guix build-system trivial))

(dummy-package "empty-package"
  (build-system trivial-build-system))   ;zero inputs
EOF

guix shell --bootstrap --pure -D -f "$tmpdir/empty-package.scm" \
     guile-bootstrap -- guile --version
rm "$tmpdir/empty-package.scm"

# Make sure '--development' honors '--system'.
this_system="$(guile -c '(use-modules (guix utils))
  (display (%current-system))')"
other_system="$(guile -c '(use-modules (guix utils))
  (display (if (string=? "riscv64-linux" (%current-system))
	       "x86_64-linux"
	       "riscv64-linux"))')"
cat > "$tmpdir/some-package.scm" <<EOF
(use-modules (guix utils)
             (guix packages)
             (gnu packages base))

(define unsupported-dependency
  (package
    (inherit grep)
    (name "unsupported-dependency")
    (supported-systems '())))

(package
  (inherit hello)
  (name "phony-package")
  (inputs
    (if (string=? (%current-system) "$this_system")
        (list unsupported-dependency)
        '())))
EOF

guix shell -D -f "$tmpdir/some-package.scm" -n && false
guix shell -D -f "$tmpdir/some-package.scm" -n -s "$other_system"


if guile -c '(getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV)' 2> /dev/null
then
    # Compute the build environment for the initial GNU Make.
    guix shell --bootstrap --no-substitutes --search-paths --pure \
         -D -e '(@ (guix tests) gnu-make-for-tests)' > "$tmpdir/a"

    # Make sure bootstrap binaries are in the profile.
    profile=`grep "^export PATH" "$tmpdir/a" | sed -r 's|^.*="(.*)/bin"|\1|'`

    # Make sure the bootstrap binaries are all listed where they belong.
    grep -E "^export PATH=\"$profile/bin\""               "$tmpdir/a"
    grep -E "^export C_INCLUDE_PATH=\"$profile/include\"" "$tmpdir/a"
    grep -E "^export LIBRARY_PATH=\"$profile/lib\""       "$tmpdir/a"
    for dep in bootstrap-binaries-0 gcc-bootstrap-0 glibc-bootstrap-0
    do
	guix gc --references "$profile" | grep "$dep"
    done

    # 'make-boot0' itself must not be listed.
    guix gc --references "$profile" | grep make-boot0 && false

    # Honoring the local 'guix.scm' file.
    echo '(@ (guix tests) gnu-make-for-tests)' > "$tmpdir/guix.scm"
    (cd "$tmpdir"; guix shell --bootstrap --search-paths --pure > "b")
    cmp "$tmpdir/a" "$tmpdir/b"
    rm "$tmpdir/guix.scm"
fi
#+(file-append bash "/bin/sh")) #$@(if volatile? #~() #~((format port "~a~%" #+copy-image))) (format port "exec ~a \"$@\"~%" (string-join #$qemu-exec " ")) (chmod port #o555)))) (gexp->derivation "run-vm.sh" builder))) (define* (linux-image-startup-command image #:key (system (%current-system)) (target #f) (qemu qemu-minimal) (graphic? #f) (cpu "max") (cpu-count 1) (memory-size 1024) (port-forwardings '()) (date #f)) "Return a list-valued gexp representing the command to start QEMU to run IMAGE, assuming it uses the Linux kernel, and not sharing the store with the host." (define os ;; Note: 'image-operating-system' would return the wrong OS, before ;; its root partition has been assigned a UUID. (operating-system-for-image image)) (define kernel-arguments #~(list #$@(if graphic? #~() #~("console=ttyS0")) #$@(operating-system-kernel-arguments os "/dev/vda1"))) #~`(#+(file-append qemu "/bin/" (qemu-command (or target system))) ,@(if (access? "/dev/kvm" (logior R_OK W_OK)) '("-enable-kvm") '()) "-cpu" #$cpu #$@(if (> cpu-count 1) #~("-smp" #$(string-append "cpus=" (number->string cpu-count))) #~()) "-m" #$(number->string memory-size) "-nic" #$(string-append "user,model=virtio-net-pci," (port-forwardings->qemu-options port-forwardings)) "-kernel" #$(operating-system-kernel-file os) "-initrd" #$(file-append os "/initrd") "-append" ,(string-join #$kernel-arguments) "-serial" "stdio" #$@(if date #~("-rtc" #$(string-append "base=" (date->string date "~5"))) #~()) "-object" "rng-random,filename=/dev/urandom,id=guix-vm-rng" "-device" "virtio-rng-pci,rng=guix-vm-rng" "-drive" ,(string-append "file=" #$(system-image image) ",format=qcow2,if=virtio," "cache=writeback,werror=report,readonly=off") "-snapshot" "-no-reboot")) ;;; ;;; High-level abstraction. ;;; (define-record-type* %virtual-machine make-virtual-machine virtual-machine? (operating-system virtual-machine-operating-system) ; (qemu virtual-machine-qemu ; (default qemu-minimal)) (cpu-count virtual-machine-cpu-count ;integer (default 1)) (volatile? virtual-machine-volatile? ;Boolean (default #t)) (graphic? virtual-machine-graphic? ;Boolean (default #f)) (memory-size virtual-machine-memory-size ;integer (MiB) (default 256)) (disk-image-size virtual-machine-disk-image-size ;integer (bytes) (default 'guess)) (port-forwardings virtual-machine-port-forwardings ;list of integer pairs (default '())) (date virtual-machine-date ;SRFI-19 date | #f (default #f))) (define-syntax virtual-machine (syntax-rules () "Declare a virtual machine running the specified OS, with the given options." ((_ os) ;shortcut (%virtual-machine (operating-system os))) ((_ fields ...) (%virtual-machine fields ...)))) (define (port-forwardings->qemu-options forwardings) "Return the QEMU option for the given port FORWARDINGS as a string, where FORWARDINGS is a list of host-port/guest-port pairs." (string-join (map (match-lambda ((host-port . guest-port) (string-append "hostfwd=tcp::" (number->string host-port) "-:" (number->string guest-port)))) forwardings) ",")) (define-gexp-compiler (virtual-machine-compiler (vm ) system target) (match vm (($ os qemu cpus volatile? graphic? memory-size disk-image-size forwardings date) (let ((options (append (if (null? forwardings) '() `("-nic" ,(string-append "user,model=virtio-net-pci," (port-forwardings->qemu-options forwardings)))) (if (> cpus 1) `("-smp" ,(string-append "cpus=" (number->string cpus))) '()) (if date `("-rtc" ,(string-append "base=" (date->string date "~5"))) '())))) (system-qemu-image/shared-store-script os #:system system #:target target #:qemu qemu #:graphic? graphic? #:volatile? volatile? #:memory-size memory-size #:disk-image-size disk-image-size #:options options))))) ;;; vm.scm ends here