projects/guix·blob master · refs

449 lines · 13.8 KiB

1# GNU Guix --- Functional package management for GNU
2# Copyright © 2012-2014, 2016-2025 Ludovic Courtès <[email protected]>
3# Copyright © 2020 Marius Bakke <[email protected]>
4# Copyright © 2021 Chris Marusich <[email protected]>
5# Copyright © 2025 Maxim Cournoyer <[email protected]>
6#
7# This file is part of GNU Guix.
8#
9# GNU Guix is free software; you can redistribute it and/or modify it
10# under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 3 of the License, or (at
12# your option) any later version.
13#
14# GNU Guix is distributed in the hope that it will be useful, but
15# WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
21
22#
23# Test the `guix build' command-line utility.
24#
25
26guix build --version
27
28# Should fail.
29guix build -e + && false
30
31# Source-less packages are accepted; they just return nothing.
32guix build -e '(@ (gnu packages bootstrap) %bootstrap-glibc)' -S
33test "`guix build -e '(@ (gnu packages bootstrap) %bootstrap-glibc)' -S`" = ""
34
35# Warn when attempting to build an unsupported package.
36case "$(guix build intelmetool -s armhf-linux -v0 -n 2>&1)" in
37 *warning:*intelmetool*support*armhf*)
38 true
39 break;;
40 *)
41 false;
42 break;;
43esac
44
45# Should pass.
46guix build -e '(@@ (gnu packages bootstrap) %bootstrap-guile)' | \
47 grep -e '-guile-'
48guix build hello -d | \
49 grep -e '-hello-[0-9\.]\+\.drv$'
50
51# Passing a .drv.
52drv="`guix build -e '(@@ (gnu packages bootstrap) %bootstrap-guile)' -d`"
53out="`guix build "$drv"`"
54out2="`guix build -e '(@@ (gnu packages bootstrap) %bootstrap-guile)'`"
55test "$out" = "$out2"
56
57# Passing the name of a .drv that doesn't exist. The daemon should try to
58# substitute the .drv. Here we just look for the "cannot build missing
59# derivation" error that indicates that the daemon did try to substitute the
60# .drv.
61guix build "$NIX_STORE_DIR/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-foo.drv" 2>&1 \
62 | grep "missing derivation"
63
64# Passing a URI.
65GUIX_DAEMON_SOCKET="file://$GUIX_STATE_DIRECTORY/daemon-socket/socket" \
66guix build -e '(@@ (gnu packages bootstrap) %bootstrap-guile)'
67
68( if GUIX_DAEMON_SOCKET="weird://uri" \
69 guix build -e '(@@ (gnu packages bootstrap) %bootstrap-guile)'; \
70 then exit 1; fi )
71
72# Passing one '-s' flag.
73test `guix build sed -s x86_64-linux -d | wc -l` = 1
74
75# Passing multiple '-s' flags.
76all_systems="-s x86_64-linux -s i686-linux -s armhf-linux -s aarch64-linux \
77-s powerpc64le-linux"
78test `guix build sed $all_systems -d | sort -u | wc -l` = 5
79
80# Check there's no weird memoization effect leading to erroneous results.
81# See <https://bugs.gnu.org/40482>.
82drv1="`guix build sed -s x86_64-linux -s armhf-linux -d | sort`"
83drv2="`guix build sed -s armhf-linux -s x86_64-linux -d | sort`"
84test "$drv1" = "$drv2"
85
86# Check --sources option with its arguments
87module_dir="t-guix-build-$$"
88mkdir "$module_dir"
89trap "rm -rf $module_dir" EXIT
90
91# Check error reporting for '-f'.
92cat > "$module_dir/foo.scm" <<EOF
93(use-modules (guix))
94) ;extra closing paren
95EOF
96guix build -f "$module_dir/foo.scm" 2> "$module_dir/stderr" && false
97grep "read error" "$module_dir/stderr"
98rm "$module_dir/stderr" "$module_dir/foo.scm"
99
100# Check 'GUIX_PACKAGE_PATH' & co.
101cat > "$module_dir/foo.scm"<<EOF
102(define-module (foo)
103 #:use-module (guix tests)
104 #:use-module (guix packages)
105 #:use-module (guix download)
106 #:use-module (guix build-system trivial))
107
108(define-public foo
109 (package
110 (name "foo")
111 (version "42")
112 (source (origin
113 (method url-fetch)
114 (uri "http://www.example.com/foo.tar.gz")
115 (sha256
116 (base32
117 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"))))
118 (build-system trivial-build-system)
119 (inputs
120 (quasiquote (("bar" ,bar))))
121 (home-page "www.example.com")
122 (synopsis "Dummy package")
123 (description "foo is a dummy package for testing.")
124 (license #f)))
125
126(define-public bar
127 (package
128 (name "bar")
129 (version "9001")
130 (source (origin
131 (method url-fetch)
132 (uri "http://www.example.com/bar.tar.gz")
133 (sha256
134 (base32
135 "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"))))
136 (build-system trivial-build-system)
137 (inputs
138 (quasiquote
139 (("data" ,(origin
140 (method url-fetch)
141 (uri "http://www.example.com/bar.dat")
142 (sha256
143 (base32
144 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz")))))))
145 (home-page "www.example.com")
146 (synopsis "Dummy package")
147 (description "bar is a dummy package for testing.")
148 (license #f)))
149
150(define-public baz
151 (dummy-package "baz" (replacement foo)))
152
153(define-public superseded
154 (deprecated-package "superseded" bar))
155
156EOF
157
158GUIX_PACKAGE_PATH="$module_dir"
159export GUIX_PACKAGE_PATH
160
161# foo.tar.gz
162guix build -d -S foo
163guix build -d -S foo | grep -e 'foo\.tar\.gz'
164
165# Make sure '-s' has an effect together with '-S'.
166test "$(guix build -Sd coreutils -s x86_64-linux)" \
167 != "$(guix build -Sd coreutils -s aarch64-linux)"
168
169# 'baz' has a replacement so we should be getting the replacement's source.
170(unset GUIX_BUILD_OPTIONS;
171 test "`guix build -d -S baz`" = "`guix build -d -S foo`")
172
173guix build -d --sources=package foo
174guix build -d --sources=package foo | grep -e 'foo\.tar\.gz'
175
176# bar.tar.gz and bar.dat
177guix build -d --sources bar
178test `guix build -d --sources bar \
179 | grep -e 'bar\.tar\.gz' -e 'bar\.dat' \
180 | wc -l` -eq 2
181
182# bar.tar.gz and bar.dat
183guix build -d --sources=all bar
184test `guix build -d --sources bar \
185 | grep -e 'bar\.tar\.gz' -e 'bar\.dat' \
186 | wc -l` -eq 2
187
188# Should include foo.tar.gz, bar.tar.gz, and bar.dat
189guix build -d --sources=transitive foo
190test `guix build -d --sources=transitive foo \
191 | grep -e 'foo\.tar\.gz' -e 'bar\.tar\.gz' -e 'bar\.dat' \
192 | wc -l` -eq 3
193
194# Building the inputs.
195guix build -D hello -n
196test `guix build -D hello -d \
197 | grep -e 'glibc.*\.drv$' -e 'gcc.*\.drv$' -e 'binutils.*\.drv$' \
198 | wc -l` -ge 3
199
200# Building the dependents.
201test `guix build -P1 libgcrypt -P1 libssh -d \
202 | grep -e 'guile-gcrypt.*\.drv$' -e 'guile-ssh.*\.drv$' \
203 -e 'libgcrypt-[0-9].*\.drv$' -e 'libssh-[0-9].*\.drv$' \
204 | sort -u \
205 | wc -l` -eq 4
206
207# Unbound variable in thunked field.
208cat > "$module_dir/foo.scm" <<EOF
209(define-module (foo)
210 #:use-module (guix tests)
211 #:use-module (guix build-system trivial))
212
213(define-public foo
214 (dummy-package "package-with-something-wrong"
215 (build-system trivial-build-system)
216 (inputs (quasiquote (("sed" ,sed)))))) ;unbound variable
217EOF
218
219guix build package-with-something-wrong -n && false
220guix build package-with-something-wrong -n 2> "$module_dir/err" || true
221grep "unbound" "$module_dir/err" # actual error
222grep "forget.*(gnu packages base)" "$module_dir/err" # hint
223
224# Unbound variable at the top level.
225cat > "$module_dir/foo.scm" <<EOF
226(define-module (foo)
227 #:use-module (guix tests))
228
229(define-public foo
230 (dummy-package "package-with-something-wrong"
231 (build-system gnu-build-system))) ;unbound variable
232EOF
233
234guix build sed -n 2> "$module_dir/err"
235grep "unbound" "$module_dir/err" # actual error
236grep "forget.*(guix build-system gnu)" "$module_dir/err" # hint
237
238rm -f "$module_dir"/*
239
240# Unbound variable: don't suggest modules that do not export the variable.
241cat > "$module_dir/aa-private.scm" <<EOF
242(define-module (aa-private))
243(define make-thing #f)
244(set! make-thing make-thing) ;don't inline
245EOF
246
247cat > "$module_dir/bb-public.scm" <<EOF
248(define-module (bb-public) #:export (make-thing))
249(define make-thing identity)
250EOF
251
252cat > "$module_dir/cc-user.scm" <<EOF
253;; Make those module available in the global name space.
254(load-from-path "aa-private.scm")
255(load-from-path "bb-public.scm")
256
257(define-module (cc-user))
258(make-thing 42)
259EOF
260guix build -f "$module_dir/cc-user.scm" -n 2> "$module_dir/err" && false
261cat "$module_dir/err"
262grep "make-thing.*unbound" "$module_dir/err" # actual error
263grep "forget.*(bb-public)" "$module_dir/err" # hint
264
265rm -f "$module_dir"/*
266
267# Wrong 'define-module' clause reported by 'warn-about-load-error'.
268cat > "$module_dir/foo.scm" <<EOF
269(define-module (something foo)
270 #:use-module (guix)
271 #:use-module (gnu))
272EOF
273guix build guile-bootstrap -n 2> "$module_dir/err"
274grep "does not match file name" "$module_dir/err"
275
276rm "$module_dir"/*
277
278# Should all return valid log files.
279drv="`guix build -d -e '(@@ (gnu packages bootstrap) %bootstrap-guile)'`"
280out="`guix build -e '(@@ (gnu packages bootstrap) %bootstrap-guile)'`"
281log="`guix build --log-file $drv`"
282echo "$log" | grep log/.*guile.*drv
283test -f "$log"
284test "`guix build -e '(@@ (gnu packages bootstrap) %bootstrap-guile)' --log-file`" \
285 = "$log"
286test "`guix build --log-file guile-bootstrap`" = "$log"
287test "`guix build --log-file $out`" = "$log"
288
289# Should fail because the name/version combination could not be found.
290guix build hello-0.0.1 -n && false
291
292# Keep a symlink to the result, registered as a root.
293result="t-result-$$"
294guix build -r "$result" \
295 -e '(@@ (gnu packages bootstrap) %bootstrap-guile)'
296test -x "$result/bin/guile"
297
298# Should fail, because $result already exists.
299guix build -r "$result" -e '(@@ (gnu packages bootstrap) %bootstrap-guile)' && false
300
301rm -f "$result"
302
303# Check relative file name canonicalization: <https://bugs.gnu.org/35271>.
304mkdir "$result"
305guix build -r "$result/x" -e '(@@ (gnu packages bootstrap) %bootstrap-guile)'
306test -x "$result/x/bin/guile"
307rm "$result/x"
308rmdir "$result"
309
310# Cross building.
311guix build coreutils --target=mips64el-linux-gnu --dry-run --no-substitutes
312
313# Likewise, but with '-e' (see <https://bugs.gnu.org/38093>).
314guix build --target=arm-linux-gnueabihf --dry-run \
315 -e '(@ (gnu packages base) coreutils)'
316
317# Replacements.
318drv1=`guix build guix --with-input=guile-zstd=idutils -d`
319drv2=`guix build guix -d`
320test "$drv1" != "$drv2"
321
322drv1=`guix build guile -d`
323drv2=`guix build guile --with-input=gimp=ruby -d`
324test "$drv1" = "$drv2"
325
326# See <https://bugs.gnu.org/42156>.
327drv1=`guix build glib -d`
328drv2=`guix build glib -d --with-input=libreoffice=inkscape`
329test "$drv1" = "$drv2"
330
331# '--with-graft' should have no effect when using '--no-grafts'.
332# See <https://bugs.gnu.org/43890>.
333drv1=`guix build inkscape -d --no-grafts`
334drv2=`guix build inkscape -d --no-grafts --with-graft=glib=glib-networking`
335test "$drv1" = "$drv2"
336
337# Rewriting implicit inputs.
338drv1=`guix build grep -d`
339drv2=`guix build grep -d --with-input=coreutils=hello`
340test "$drv1" != "$drv2"
341guix gc -R "$drv2" | grep `guix build -d hello`
342
343guix build guile --with-input=libunistring=something-really-silly && false
344
345# Deprecated/superseded packages.
346test "`guix build superseded -d`" = "`guix build bar -d`"
347
348# Parsing package names and versions.
349guix build -n time # PASS
350guix build -n [email protected] # PASS, version found
351guix build -n [email protected] && false # FAIL, version not found
352guix build -n something-that-will-never-exist && false # FAIL
353
354# Invoking a monadic procedure.
355guix build -e "(begin
356 (use-modules (guix gexp))
357 (lambda ()
358 (gexp->derivation \"test\"
359 (gexp (mkdir (ungexp output))))))" \
360 --dry-run
361
362# Running a gexp.
363guix build -e '#~(mkdir #$output)' -d
364guix build -e '#~(mkdir #$output)' -d | grep 'gexp\.drv'
365
366# Same with a file-like object.
367guix build -e '(computed-file "foo" #~(mkdir #$output))' -d
368guix build -e '(computed-file "foo" #~(mkdir #$output))' -d | grep 'foo\.drv'
369
370# Building from a package file.
371cat > "$module_dir/package.scm"<<EOF
372(use-modules (gnu))
373(use-package-modules bootstrap)
374
375%bootstrap-guile
376EOF
377guix build --file="$module_dir/package.scm"
378
379# Building from a monadic procedure file.
380cat > "$module_dir/proc.scm"<<EOF
381(use-modules (guix gexp))
382(lambda ()
383 (gexp->derivation "test"
384 (gexp (mkdir (ungexp output)))))
385EOF
386guix build --file="$module_dir/proc.scm" --dry-run
387
388# Building from a gexp file.
389cat > "$module_dir/gexp.scm"<<EOF
390(use-modules (guix gexp))
391
392(gexp (mkdir (ungexp output)))
393EOF
394guix build --file="$module_dir/gexp.scm" -d
395guix build --file="$module_dir/gexp.scm" -d | grep 'gexp\.drv'
396
397# Building from a manifest file.
398cat > "$module_dir/manifest.scm"<<EOF
399(specifications->manifest '("hello" "guix"))
400EOF
401test `guix build -d --manifest="$module_dir/manifest.scm" \
402 | grep -e '-hello-' -e '-guix-' \
403 | wc -l` -eq 2
404
405# Building from a manifest that contains a non-package object.
406cat > "$module_dir/manifest.scm"<<EOF
407(manifest
408 (list (manifest-entry (name "foo") (version "0")
409 (item (computed-file "computed-thingie"
410 #~(mkdir (ungexp output)))))))
411EOF
412guix build -d -m "$module_dir/manifest.scm" \
413 | grep 'computed-thingie\.drv$'
414
415rm "$module_dir"/*.scm
416
417if [ -n "$BASH_VERSION" ]
418then
419 # Check whether we can load from a /dev/fd/N denoting a pipe, using this
420 # handy Bash-specific construct.
421 guix build -m <(echo '(specifications->manifest (list "guile"))') -n
422fi
423
424# Build a scheme-file object via multiple expressions, and validate it
425# produces the correct result when evaluated.
426scheme_file=$(guix build -e \
427 "(use-modules (guix gexp)) \
428 (scheme-file \"mathematics\" \
429 '(begin \
430 (define add +) \
431 (define multiply *) \
432 (add 5 (multiply 2 10)))
433 #:guile (@@ (gnu packages bootstrap) %bootstrap-guile))")
434guile -c \
435 "(begin \
436 (use-modules (guix ui) (rnrs base) (srfi srfi-26)) \
437 (assert (= 25 (call-with-input-file \"$scheme_file\" \
438 (cut read/eval <>)))))"
439
440# Using 'GUIX_BUILD_OPTIONS'.
441GUIX_BUILD_OPTIONS="--dry-run --no-grafts"
442export GUIX_BUILD_OPTIONS
443
444guix build emacs
445
446GUIX_BUILD_OPTIONS="--something-completely-crazy"
447guix build emacs && false
448
449exit 0