summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.dir-locals.el1
-rw-r--r--NEWS7
-rw-r--r--doc/guix.texi5
-rw-r--r--guix/scripts/pack.scm180
-rw-r--r--tests/pack.scm75
5 files changed, 265 insertions, 3 deletions
diff --git a/.dir-locals.el b/.dir-locals.el
index 8f07a08eb5b..a4fcbfe7ca9 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -75,6 +75,7 @@
75 (eval . (put 'origin 'scheme-indent-function 0)) 75 (eval . (put 'origin 'scheme-indent-function 0))
76 (eval . (put 'build-system 'scheme-indent-function 0)) 76 (eval . (put 'build-system 'scheme-indent-function 0))
77 (eval . (put 'bag 'scheme-indent-function 0)) 77 (eval . (put 'bag 'scheme-indent-function 0))
78 (eval . (put 'gexp->derivation 'scheme-indent-function 1))
78 (eval . (put 'graft 'scheme-indent-function 0)) 79 (eval . (put 'graft 'scheme-indent-function 0))
79 (eval . (put 'operating-system 'scheme-indent-function 0)) 80 (eval . (put 'operating-system 'scheme-indent-function 0))
80 (eval . (put 'file-system 'scheme-indent-function 0)) 81 (eval . (put 'file-system 'scheme-indent-function 0))
diff --git a/NEWS b/NEWS
index 1d3f5aaffdf..b0647b3700a 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@
4 4
5Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org> 5Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
6Copyright © 2016, 2017, 2018 Ricardo Wurmus <rekado@elephly.net> 6Copyright © 2016, 2017, 2018 Ricardo Wurmus <rekado@elephly.net>
7Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
7 8
8 Copying and distribution of this file, with or without modification, 9 Copying and distribution of this file, with or without modification,
9 are permitted in any medium without royalty provided the copyright 10 are permitted in any medium without royalty provided the copyright
@@ -11,10 +12,12 @@ Copyright © 2016, 2017, 2018 Ricardo Wurmus <rekado@elephly.net>
11 12
12Please send Guix bug reports to bug-guix@gnu.org. 13Please send Guix bug reports to bug-guix@gnu.org.
13 14
14* Changes in 1.3.0 (since 1.2.0) 15* Changes in 1.4.0 (since 1.3.0)
15
16** Package management 16** Package management
17 * New 'deb' format for the 'guix pack' command
17 18
19* Changes in 1.3.0 (since 1.2.0)
20** Package management
18*** POWER9 (powerpc64le-linux) is now supported as a technology preview 21*** POWER9 (powerpc64le-linux) is now supported as a technology preview
19*** New ‘--export-manifest’ and ‘--export-channels’ options of ‘guix package’ 22*** New ‘--export-manifest’ and ‘--export-channels’ options of ‘guix package’
20*** New ‘--profile’ option for ‘guix environment’ 23*** New ‘--profile’ option for ‘guix environment’
diff --git a/doc/guix.texi b/doc/guix.texi
index 37936bb0f3d..e0668b1f5f4 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -6028,6 +6028,11 @@ This produces a SquashFS image containing all the specified binaries and
6028symlinks, as well as empty mount points for virtual file systems like 6028symlinks, as well as empty mount points for virtual file systems like
6029procfs. 6029procfs.
6030 6030
6031@item deb
6032This produces a Debian archive (a package with the @samp{.deb} file
6033extension) containing all the specified binaries and symbolic links,
6034that can be installed on top of any dpkg-based GNU/Linux distribution.
6035
6031@quotation Note 6036@quotation Note
6032Singularity @emph{requires} you to provide @file{/bin/sh} in the image. 6037Singularity @emph{requires} you to provide @file{/bin/sh} in the image.
6033For that reason, @command{guix pack -f squashfs} always implies @code{-S 6038For that reason, @command{guix pack -f squashfs} always implies @code{-S
diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm
index cee14441103..6d8b70d1c70 100644
--- a/guix/scripts/pack.scm
+++ b/guix/scripts/pack.scm
@@ -6,6 +6,7 @@
6;;; Copyright © 2018 Efraim Flashner <efraim@flashner.co.il> 6;;; Copyright © 2018 Efraim Flashner <efraim@flashner.co.il>
7;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr> 7;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr>
8;;; Copyright © 2020 Eric Bavier <bavier@posteo.net> 8;;; Copyright © 2020 Eric Bavier <bavier@posteo.net>
9;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
9;;; 10;;;
10;;; This file is part of GNU Guix. 11;;; This file is part of GNU Guix.
11;;; 12;;;
@@ -65,6 +66,7 @@
65 %compressors 66 %compressors
66 lookup-compressor 67 lookup-compressor
67 self-contained-tarball 68 self-contained-tarball
69 debian-archive
68 docker-image 70 docker-image
69 squashfs-image 71 squashfs-image
70 72
@@ -346,6 +348,10 @@ added to the pack."
346 #:target target 348 #:target target
347 #:references-graphs `(("profile" ,profile)))) 349 #:references-graphs `(("profile" ,profile))))
348 350
351
352;;;
353;;; Singularity.
354;;;
349(define (singularity-environment-file profile) 355(define (singularity-environment-file profile)
350 "Return a shell script that defines the environment variables corresponding 356 "Return a shell script that defines the environment variables corresponding
351to the search paths of PROFILE." 357to the search paths of PROFILE."
@@ -372,6 +378,10 @@ to the search paths of PROFILE."
372 378
373 (computed-file "singularity-environment.sh" build)) 379 (computed-file "singularity-environment.sh" build))
374 380
381
382;;;
383;;; SquashFS image format.
384;;;
375(define* (squashfs-image name profile 385(define* (squashfs-image name profile
376 #:key target 386 #:key target
377 (profile-name "guix-profile") 387 (profile-name "guix-profile")
@@ -546,6 +556,10 @@ added to the pack."
546 #:target target 556 #:target target
547 #:references-graphs `(("profile" ,profile)))) 557 #:references-graphs `(("profile" ,profile))))
548 558
559
560;;;
561;;; Docker image format.
562;;;
549(define* (docker-image name profile 563(define* (docker-image name profile
550 #:key target 564 #:key target
551 (profile-name "guix-profile") 565 (profile-name "guix-profile")
@@ -635,6 +649,167 @@ the image."
635 649
636 650
637;;; 651;;;
652;;; Debian archive format.
653;;;
654;;; TODO: When relocatable option is selected, install to a unique prefix.
655;;; This would enable installation of multiple deb packs with conflicting
656;;; files at the same time.
657;;; TODO: Allow passing a custom control file from the CLI.
658;;; TODO: Allow providing a postinst script.
659(define* (debian-archive name profile
660 #:key target
661 (profile-name "guix-profile")
662 deduplicate?
663 entry-point
664 (compressor (first %compressors))
665 localstatedir?
666 (symlinks '())
667 (archiver tar))
668 "Return a Debian archive (.deb) containing a store initialized with the
669closure of PROFILE, a derivation. The archive contains /gnu/store; if
670LOCALSTATEDIR? is true, it also contains /var/guix, including /var/guix/db
671with a properly initialized store database. The supported compressors are
672\"none\", \"gz\" or \"xz\".
673
674SYMLINKS must be a list of (SOURCE -> TARGET) tuples denoting symlinks to be
675added to the pack."
676 ;; For simplicity, limit the supported compressors to the superset of
677 ;; compressors able to compress both the control file (gz or xz) and the
678 ;; data tarball (gz, bz2 or xz).
679 (define %valid-compressors '("gzip" "xz" "none"))
680
681 (let ((compressor-name (compressor-name compressor)))
682 (unless (member compressor-name %valid-compressors)
683 (leave (G_ "~a is not a valid Debian archive compressor. \
684Valid compressors are: ~a~%") compressor-name %valid-compressors)))
685
686 (when entry-point
687 (warning (G_ "entry point not supported in the '~a' format~%")
688 'deb))
689
690 (define data-tarball
691 (computed-file (string-append "data.tar"
692 (compressor-extension compressor))
693 (self-contained-tarball/builder
694 profile
695 #:profile-name profile-name
696 #:compressor compressor
697 #:localstatedir? localstatedir?
698 #:symlinks symlinks
699 #:archiver archiver)
700 #:local-build? #f ;allow offloading
701 #:options (list #:references-graphs `(("profile" ,profile))
702 #:target target)))
703
704 (define build
705 (with-extensions (list guile-gcrypt)
706 (with-imported-modules `(((guix config) => ,(make-config.scm))
707 ,@(source-module-closure
708 `((guix build pack)
709 (guix build utils)
710 (guix profiles))
711 #:select? not-config?))
712 #~(begin
713 (use-modules (guix build pack)
714 (guix build utils)
715 (guix profiles)
716 (ice-9 match)
717 (srfi srfi-1))
718
719 (define machine-type
720 ;; Extract the machine type from the specified target, else from the
721 ;; current system.
722 (and=> (or #$target %host-type) (lambda (triplet)
723 (first (string-split triplet #\-)))))
724
725 (define (gnu-machine-type->debian-machine-type type)
726 "Translate machine TYPE from the GNU to Debian terminology."
727 ;; Debian has its own jargon, different from the one used in GNU, for
728 ;; machine types (see data/cputable in the sources of dpkg).
729 (match type
730 ("i586" "i386")
731 ("i486" "i386")
732 ("i686" "i386")
733 ("x86_64" "amd64")
734 ("aarch64" "arm64")
735 ("mipsisa32r6" "mipsr6")
736 ("mipsisa32r6el" "mipsr6el")
737 ("mipsisa64r6" "mips64r6")
738 ("mipsisa64r6el" "mips64r6el")
739 ("powerpcle" "powerpcel")
740 ("powerpc64" "ppc64")
741 ("powerpc64le" "ppc64el")
742 (machine machine)))
743
744 (define architecture
745 (gnu-machine-type->debian-machine-type machine-type))
746
747 #$(procedure-source manifest->friendly-name)
748
749 (define manifest (profile-manifest #$profile))
750
751 (define single-entry ;manifest entry
752 (match (manifest-entries manifest)
753 ((entry)
754 entry)
755 (() #f)))
756
757 (define package-name (or (and=> single-entry manifest-entry-name)
758 (manifest->friendly-name manifest)))
759
760 (define package-version
761 (or (and=> single-entry manifest-entry-version)
762 "0.0.0"))
763
764 (define debian-format-version "2.0")
765
766 ;; Generate the debian-binary file.
767 (call-with-output-file "debian-binary"
768 (lambda (port)
769 (format port "~a~%" debian-format-version)))
770
771 (define data-tarball-file-name (strip-store-file-name
772 #+data-tarball))
773
774 (copy-file #+data-tarball data-tarball-file-name)
775
776 (define control-tarball-file-name
777 (string-append "control.tar"
778 #$(compressor-extension compressor)))
779
780 ;; Write the compressed control tarball. Only the control file is
781 ;; mandatory (see: 'man deb' and 'man deb-control').
782 (call-with-output-file "control"
783 (lambda (port)
784 (format port "\
785Package: ~a
786Version: ~a
787Description: Debian archive generated by GNU Guix.
788Maintainer: GNU Guix
789Architecture: ~a
790~%" package-name package-version architecture)))
791
792 (define tar (string-append #+archiver "/bin/tar"))
793
794 (apply invoke tar
795 `(,@(tar-base-options
796 #:tar tar
797 #:compressor '#+(and=> compressor compressor-command))
798 "-cvf" ,control-tarball-file-name
799 "control"))
800
801 ;; Create the .deb archive using GNU ar.
802 (invoke (string-append #+binutils "/bin/ar") "-rv" #$output
803 "debian-binary"
804 control-tarball-file-name data-tarball-file-name)))))
805
806 (gexp->derivation (string-append name ".deb")
807 build
808 #:target target
809 #:references-graphs `(("profile" ,profile))))
810
811
812;;;
638;;; Compiling C programs. 813;;; Compiling C programs.
639;;; 814;;;
640 815
@@ -965,7 +1140,8 @@ last resort for relocation."
965 ;; Supported pack formats. 1140 ;; Supported pack formats.
966 `((tarball . ,self-contained-tarball) 1141 `((tarball . ,self-contained-tarball)
967 (squashfs . ,squashfs-image) 1142 (squashfs . ,squashfs-image)
968 (docker . ,docker-image))) 1143 (docker . ,docker-image)
1144 (deb . ,debian-archive)))
969 1145
970(define (show-formats) 1146(define (show-formats)
971 ;; Print the supported pack formats. 1147 ;; Print the supported pack formats.
@@ -977,6 +1153,8 @@ last resort for relocation."
977 squashfs Squashfs image suitable for Singularity")) 1153 squashfs Squashfs image suitable for Singularity"))
978 (display (G_ " 1154 (display (G_ "
979 docker Tarball ready for 'docker load'")) 1155 docker Tarball ready for 'docker load'"))
1156 (display (G_ "
1157 deb Debian archive installable via dpkg/apt"))
980 (newline)) 1158 (newline))
981 1159
982(define %options 1160(define %options
diff --git a/tests/pack.scm b/tests/pack.scm
index ae6247a1d51..9473d4f384d 100644
--- a/tests/pack.scm
+++ b/tests/pack.scm
@@ -1,6 +1,7 @@
1;;; GNU Guix --- Functional package management for GNU 1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org> 2;;; Copyright © 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
3;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net> 3;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
4;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
4;;; 5;;;
5;;; This file is part of GNU Guix. 6;;; This file is part of GNU Guix.
6;;; 7;;;
@@ -32,6 +33,7 @@
32 #:use-module ((gnu packages base) #:select (glibc-utf8-locales)) 33 #:use-module ((gnu packages base) #:select (glibc-utf8-locales))
33 #:use-module (gnu packages bootstrap) 34 #:use-module (gnu packages bootstrap)
34 #:use-module ((gnu packages compression) #:select (squashfs-tools)) 35 #:use-module ((gnu packages compression) #:select (squashfs-tools))
36 #:use-module ((gnu packages debian) #:select (dpkg))
35 #:use-module ((gnu packages guile) #:select (guile-sqlite3)) 37 #:use-module ((gnu packages guile) #:select (guile-sqlite3))
36 #:use-module ((gnu packages gnupg) #:select (guile-gcrypt)) 38 #:use-module ((gnu packages gnupg) #:select (guile-gcrypt))
37 #:use-module (srfi srfi-64)) 39 #:use-module (srfi srfi-64))
@@ -56,6 +58,8 @@
56 58
57(define %tar-bootstrap %bootstrap-coreutils&co) 59(define %tar-bootstrap %bootstrap-coreutils&co)
58 60
61(define %ar-bootstrap %bootstrap-binutils)
62
59 63
60(test-begin "pack") 64(test-begin "pack")
61 65
@@ -270,6 +274,77 @@
270 1) 274 1)
271 (pk 'guilelink (readlink "bin")))) 275 (pk 'guilelink (readlink "bin"))))
272 (mkdir #$output)))))))) 276 (mkdir #$output))))))))
277 (built-derivations (list check))))
278
279 (unless store (test-skip 1))
280 (test-assertm "deb archive with symlinks" store
281 (mlet* %store-monad
282 ((guile (set-guile-for-build (default-guile)))
283 (profile (profile-derivation (packages->manifest
284 (list %bootstrap-guile))
285 #:hooks '()
286 #:locales? #f))
287 (deb (debian-archive "deb-pack" profile
288 #:compressor %gzip-compressor
289 #:symlinks '(("/opt/gnu/bin" -> "bin"))
290 #:archiver %tar-bootstrap))
291 (check
292 (gexp->derivation "check-deb-pack"
293 (with-imported-modules '((guix build utils))
294 #~(begin
295 (use-modules (guix build utils)
296 (ice-9 match)
297 (ice-9 popen)
298 (ice-9 rdelim)
299 (ice-9 textual-ports)
300 (rnrs base))
301
302 (setenv "PATH" (string-join
303 (list (string-append #+%tar-bootstrap "/bin")
304 (string-append #+dpkg "/bin")
305 (string-append #+%ar-bootstrap "/bin"))
306 ":"))
307
308 ;; Validate the output of 'dpkg --info'.
309 (let* ((port (open-pipe* OPEN_READ "dpkg" "--info" #$deb))
310 (info (get-string-all port))
311 (exit-val (status:exit-val (close-pipe port))))
312 (assert (zero? exit-val))
313
314 (assert (string-contains
315 info
316 (string-append "Package: "
317 #+(package-name %bootstrap-guile))))
318
319 (assert (string-contains
320 info
321 (string-append "Version: "
322 #+(package-version %bootstrap-guile)))))
323
324 ;; Sanity check .deb contents.
325 (invoke "ar" "-xv" #$deb)
326 (assert (file-exists? "debian-binary"))
327 (assert (file-exists? "data.tar.gz"))
328 (assert (file-exists? "control.tar.gz"))
329
330 ;; Verify there are no hard links in data.tar.gz, as hard
331 ;; links would cause dpkg to fail unpacking the archive.
332 (define hard-links
333 (let ((port (open-pipe* OPEN_READ "tar" "-tvf" "data.tar.gz")))
334 (let loop ((hard-links '()))
335 (match (read-line port)
336 ((? eof-object?)
337 (assert (zero? (status:exit-val (close-pipe port))))
338 hard-links)
339 (line
340 (if (string-prefix? "u" line)
341 (loop (cons line hard-links))
342 (loop hard-links)))))))
343
344 (unless (null? hard-links)
345 (error "hard links found in data.tar.gz" hard-links))
346
347 (mkdir #$output))))))
273 (built-derivations (list check))))) 348 (built-derivations (list check)))))
274 349
275(test-end) 350(test-end)