* [bug#73842] [PATCH] pack: Add support for AppImage pack format.
@ 2024-10-16 21:51 Noé Lopez
2024-10-18 12:20 ` Ludovic Courtès
` (5 more replies)
0 siblings, 6 replies; 24+ messages in thread
From: Noé Lopez @ 2024-10-16 21:51 UTC (permalink / raw)
To: 73842
Cc: Noé Lopez, Sebastian Dümcke, Christopher Baines,
Josselin Poiret, Ludovic Courtès, Mathieu Othacehe,
Maxim Cournoyer, Simon Tournier, Tobias Geerinckx-Rice
From: Sebastian Dümcke <code@sam-d.com>
* guix/scripts/pack.scm: Add Appimage format.
* gnu/packages/appimage.scm
(gnu packages appimage): New module.
(fuse-for-appimage, squashfuse-for-appimage)
(appimage-type2-runtime): New variables.
* doc/guix.texi: Document AppImage pack.
Co-authored-by: Noé Lopez <noelopez@free.fr>
Change-Id: I09f1241dfb9b267f94dce59914dea527d35ac60e
---
Hi,
This patch adds a new AppImage export format to « guix pack ». This
enables guix users to easily share packets or environments with their
peers that don’t have guix via a statically linked, runs-everywhere
executable.
Sebastian and I co-authored this patch, I did the runtime packaging
and Sebastian did the actual command. I’ve personally tested the
generated AppImages with my friend’s various distros, they work great!
Here are some cool examples to try (in ./pre-inst-env):
guix pack -f appimage -R --entry-point=bin/hello hello
guix pack -f appimage -R --entry-point=bin/openttd openttd
guix pack -f appimage -R --entry-point=bin/torbrowser torbrowser
Keep in mind the generated AppImage files don’t have execution
permission, so you need to copy them and chmod it :)
Have a great day,
Noé Lopez
doc/guix.texi | 56 +++++++++++-
gnu/packages/appimage.scm | 179 ++++++++++++++++++++++++++++++++++++++
guix/scripts/pack.scm | 100 ++++++++++++++++++++-
3 files changed, 333 insertions(+), 2 deletions(-)
create mode 100644 gnu/packages/appimage.scm
diff --git a/doc/guix.texi b/doc/guix.texi
index b91d229d7c..327876c92f 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -6949,6 +6949,18 @@ Invoking guix pack
environment}, using commands like @command{singularity shell} or
@command{singularity exec}.
+@cindex AppImage, create an AppImage file with guix pack
+Another format internally based on SquashFS is
+@uref{https://appimage.org/, AppImage}. An AppImage file can be made
+executable and run without any special privileges:
+
+@example
+guix pack -f appimage --entry-point=bin/guile guile
+cp @var{file} . && chmod u+x $(basename @var{file})
+./$(basename @var{file}) --help
+@end example
+where @var{file} is the image returned by @command{guix pack}.
+
Several command-line options allow you to customize your pack:
@table @code
@@ -7065,6 +7077,48 @@ Invoking guix pack
installation or other, non-rpm packs.
@end quotation
+@item appimage
+@cindex AppImage, create an AppImage file with guix pack
+This produces an AppImage file with the @samp{.AppImage} extension.
+AppImage is a SquashFS volume prefixed with a runtime that mounts the
+SquashFS file system and executes the binary provided with
+@option{--entry-point}. This results in a self-contained archive that
+bundles the software and all its requirements into a single file. When
+the file is made executable it runs the packaged software.
+
+@example
+guix pack -f appimage --entry-point=bin/vlc vlc
+@end example
+
+The runtime used by AppImages makes use of libfuse to mount the image
+quickly. If libfuse is not available, the AppImage can still be started
+using the @option{--appimage-extract-and-run} flag.
+
+@quotation Warning
+Unless @option{--relocatable} is used, the software will contain
+references to items inside the guix store, which are not present on
+systems without Guix. It is recommended to use @option{--relocatable}
+when distributing software to 3rd parties. A warning is printed when
+this option is not used.
+@end quotation
+
+@example
+guix pack -f appimage --entry-point=bin/hello --relocatable hello
+@end example
+
+@quotation Note
+The resulting AppImage does not conform to the complete standard as it
+currently does not contain a @code{.DirIcon} file. This does not impact
+functionality of the AppImage itself, but possibly that of software used
+to manage AppImages.
+@end quotation
+
+@quotation Note
+As the generated AppImage packages the complete dependency graph, it
+will be larger than comparable AppImage files found online, which depend
+on host system libraries.
+@end quotation
+
@end table
@cindex relocatable binaries
@@ -7155,7 +7209,7 @@ Invoking guix pack
@cindex entry point, for Docker and Singularity images
@item --entry-point=@var{command}
Use @var{command} as the @dfn{entry point} of the resulting pack, if the pack
-format supports it---currently @code{docker} and @code{squashfs} (Singularity)
+format supports it---currently @code{docker}, @code{appimage} and @code{squashfs} (Singularity)
support it. @var{command} must be relative to the profile contained in the
pack.
diff --git a/gnu/packages/appimage.scm b/gnu/packages/appimage.scm
new file mode 100644
index 0000000000..3bf9d84181
--- /dev/null
+++ b/gnu/packages/appimage.scm
@@ -0,0 +1,179 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2024 Noé Lopez <noelopez@free.fr>
+;;;
+;;; 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/>.
+
+(define-module (gnu packages appimage)
+ #:use-module ((guix licenses) #:prefix license:)
+ #:use-module (gnu packages)
+ #:use-module (gnu packages base)
+ #:use-module (gnu packages compression)
+ #:use-module (gnu packages file-systems)
+ #:use-module (gnu packages linux)
+ #:use-module (guix build-system gnu)
+ #:use-module (guix download)
+ #:use-module (guix gexp)
+ #:use-module (guix git-download)
+ #:use-module (guix packages))
+
+(define fuse-for-appimage
+ (package
+ (inherit fuse)
+ (name "fuse")
+ (version "3.15.0")
+ (source
+ (origin
+ (method url-fetch)
+ (uri (string-append "https://github.com/libfuse/libfuse/releases/"
+ "download/fuse-"
+ version
+ "/fuse-"
+ version
+ ".tar.xz"))
+ (sha256
+ (base32 "181cx8g40ki8m85j0pjw50kv4h733g08c769db6przqwbvyrqn3h"))))
+ (arguments
+ `(#:configure-flags ,#~(list (string-append "-Dudevrulesdir="
+ #$output "/udev/rules.d")
+ "-Duseroot=false" "--default-library=static")
+ #:tests? #f
+ #:phases ,#~(modify-phases %standard-phases
+ (add-after 'unpack 'set-file-names
+ (lambda* (#:key inputs #:allow-other-keys)
+ ;; libfuse calls out to mount(8) and umount(8). Make sure
+ ;; it refers to the right ones.
+ (substitute* '("lib/mount_util.c")
+ (("/bin/(u?)mount" _ maybe-u)
+ (search-input-file inputs
+ (string-append "bin/" maybe-u
+ "mount"))))
+ (substitute* '("util/mount.fuse.c")
+ (("/bin/sh")
+ (search-input-file inputs "/bin/sh")))
+
+ ;; This hack leads libfuse to search for 'fusermount' in
+ ;; $PATH, where it may find a setuid-root binary, instead of
+ ;; trying solely $out/sbin/fusermount and failing because
+ ;; it's not setuid.
+ (substitute* "lib/meson.build"
+ (("-DFUSERMOUNT_DIR=[[:graph:]]+")
+ "-DFUSERMOUNT_DIR=\"/var/empty\"'"))))
+ (add-after 'unpack 'fix-install
+ (lambda* (#:key inputs #:allow-other-keys)
+ (substitute* '("util/meson.build")
+ (("install_helper.sh")
+ "true"))
+ (substitute* '("util/meson.build")
+ (("fuseconf_path = .*")
+ "fuseconf_path = '/etc/fuse.conf'"))))
+ (add-before 'configure 'set-paths
+ (lambda* (#:key inputs outputs #:allow-other-keys)
+ (let ((dummy-init.d (string-append (getcwd)
+ "/etc/init.d")))
+ (setenv "MOUNT_FUSE_PATH"
+ (string-append #$output "/sbin"))
+ (setenv "UDEV_RULES_PATH"
+ (string-append #$output "/lib/udev/rules.d"))))))))))
+
+(define squashfuse-for-appimage
+ (let ((revision "0")
+ (commit "e51978cd6bb5c4d16fae9eee43d0b258f570bb0f"))
+ (package
+ (inherit squashfuse)
+ (name "squashfuse")
+ (version (git-version "0.1.104" revision commit))
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/vasi/squashfuse")
+ (commit commit)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32 "02421zsgcvbip5ff999ci4c748zxsc34yycjfp7rq8afrlnlvl29"))))
+ (arguments
+ (list
+ #:configure-flags #~'("CFLAGS=-ffunction-sections -fdata-sections -Os -no-pie"
+ "LDFLAGS=-static")
+ #:phases #~(modify-phases %standard-phases
+ (add-after 'install 'install-private-headers
+ (lambda _
+ (install-file "fuseprivate.h"
+ (string-append #$output
+ "/include/squashfuse/")))))))
+ (inputs (list fuse-for-appimage
+ `(,zstd "lib")
+ `(,zstd "static")
+ `(,zlib "out")
+ `(,zlib "static"))))))
+
+(define-public appimage-type2-runtime
+ (let ((revision "0")
+ (commit "47b665594856b4e8928f8932adcf6d13061d8c30"))
+ (package
+ (name "appimage-type2-runtime")
+ (version (git-version "continuous" revision commit))
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/AppImage/type2-runtime")
+ (commit commit)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32 "0954crhlbapxis96g1s0vfpf78ybr64zvjalak387ksxj560g44x"))))
+ (arguments
+ (list
+ #:make-flags #~(list "-Csrc/runtime" "runtime-fuse3"
+ (string-append "CFLAGS="
+ "-I"
+ #$fuse-2
+ "/include/fuse/"
+ " -DGIT_COMMIT='\""
+ "guix-"
+ #$version
+ "\"'"
+ " -D_FILE_OFFSET_BITS=64"
+ " -static"))
+ #:phases #~(modify-phases %standard-phases
+ (delete 'configure)
+ (delete 'check)
+ (replace 'install
+ (lambda _
+ (install-file "src/runtime/runtime-fuse3"
+ (string-append #$output "/bin"))))
+ ;; must be after all elf reliant phases
+ (add-after 'make-dynamic-linker-cache 'set-magic-bytes
+ (lambda _
+ (use-modules (ice-9 binary-ports))
+ (let ((port (open (string-append #$output
+ "/bin/runtime-fuse3")
+ (logior O_WRONLY))))
+ (seek port 8 SEEK_SET)
+ (put-bytevector port #vu8(#x41 #x49 #x02))
+ (close-port port)))))
+ #:disallowed-references (list squashfuse-for-appimage
+ fuse-for-appimage zstd zlib)))
+ ;; only needed at build time
+ (inputs (list squashfuse-for-appimage fuse-for-appimage
+ `(,zstd "static")
+ `(,zlib "static")))
+ (build-system gnu-build-system)
+ (home-page "https://github.com/AppImage/type2-runtime")
+ (synopsis "Runtime for AppImages")
+ (description "The runtime is the executable part of every AppImage. It
+mounts the payload via FUSE and executes the entrypoint.")
+ (license license:expat))))
diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm
index 7c5fe76fe0..f517100fcf 100644
--- a/guix/scripts/pack.scm
+++ b/guix/scripts/pack.scm
@@ -10,6 +10,8 @@
;;; Copyright © 2022 Alex Griffin <a@ajgrf.com>
;;; Copyright © 2023 Graham James Addis <graham@addis.org.uk>
;;; Copyright © 2023 Oleg Pykhalov <go.wigust@gmail.com>
+;;; Copyright © 2024 Sebastian Dümcke <code@sam-d.com>
+;;; Copyright © 2024 Noé Lopez <noelopez@free.fr>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -56,6 +58,7 @@ (define-module (guix scripts pack)
#:use-module ((gnu packages compression) #:hide (zip))
#:use-module (gnu packages guile)
#:use-module (gnu packages base)
+ #:autoload (gnu packages appimage) (appimage-type2-runtime)
#:autoload (gnu packages gnupg) (guile-gcrypt)
#:autoload (gnu packages guile) (guile2.0-json guile-json)
#:use-module (srfi srfi-1)
@@ -64,6 +67,7 @@ (define-module (guix scripts pack)
#:use-module (srfi srfi-35)
#:use-module (srfi srfi-37)
#:use-module (ice-9 match)
+ #:use-module (ice-9 optargs)
#:export (symlink-spec-option-parser
self-contained-tarball
@@ -71,6 +75,7 @@ (define-module (guix scripts pack)
rpm-archive
docker-image
squashfs-image
+ self-contained-appimage
%formats
guix-pack))
@@ -974,8 +979,96 @@ (define* (rpm-archive name profile
(gexp->derivation (string-append name ".rpm") build
#:target target
#:references-graphs `(("profile" ,profile))))
+\f
+;;;
+;;; AppImage format
+;;;
+(define* (self-contained-appimage name profile
+ #:key target
+ (profile-name "guix-profile")
+ entry-point
+ (compressor "zstd")
+ localstatedir?
+ (symlinks '())
+ (archiver tar)
+ (extra-options '()))
+ "Return a self-contained AppImage containing a store initialized with the
+closure of PROFILE, a derivation. The AppImage contains /gnu/store unless
+RELOCATABLE option is used; if LOCALSTATEDIR? is true, it also contains
+/var/guix, including /var/guix/db with a properly initialized store database.
+
+SYMLINKS must be a list of (SOURCE -> TARGET) tuples denoting symlinks to be
+added to the pack."
+ (unless entry-point
+ (leave (G_ "entry-point must be provided in the '~a' format~%")
+ 'appimage))
+ (let-keywords extra-options #f ((relocatable? #f))
+ (unless relocatable?
+ (warning (G_ "AppImages should be built with the --relocatable flag~%"))))
+
+ (define runtime-package appimage-type2-runtime)
+ (define runtime-path "bin/runtime-fuse3")
+ (define %valid-compressors '("gzip" "zstd"))
+
+ (let ((compressor-name (compressor-name compressor)))
+ (unless (member compressor-name %valid-compressors)
+ (leave (G_ "~a is not a valid squashfs archive compressor used in
+generating the AppImage. Valid compressors are: ~a~%")
+ compressor-name
+ %valid-compressors)))
- \f
+ (define builder
+ (with-extensions (list guile-gcrypt)
+ (with-imported-modules (source-module-closure
+ '((guix build store-copy)
+ (guix build utils))
+ #:select? not-config?)
+ #~(begin
+ (use-modules (guix build utils)
+ (guix build store-copy)
+ (rnrs io ports)
+ (srfi srfi-1)
+ (srfi srfi-26))
+
+ (define (concatenate result file1 file2)
+ (let ((p (open-file-output-port result))
+ (f1 (open-file-input-port file1))
+ (f2 (open-file-input-port file2)))
+ (put-bytevector p (get-bytevector-all f1))
+ (close-port f1)
+ (put-bytevector p (get-bytevector-all f2))
+ (close-port f2)
+ (close-port p)))
+
+ (let* ((appdir "AppDir")
+ (squashfs "squashfs")
+ (profile-items (map store-info-item
+ (call-with-input-file "profile" read-reference-graph)))
+ (profile-path (find (cut (file-name-predicate "profile$") <> #f) profile-items)))
+ (mkdir-p appdir)
+ ;; copy all store items from the profile to the AppDir
+ (for-each (lambda (f)
+ (copy-store-item f appdir)) profile-items)
+ ;; symlink the provided entry-point to AppDir/AppRun
+ (symlink (string-append "." profile-path "/" #$entry-point)
+ (string-append appdir "/AppRun"))
+ ;; create .desktop file as required by the spec
+ (make-desktop-entry-file
+ (string-append appdir "/" #$name ".desktop")
+ #:name #$name
+ #:exec #$entry-point)
+ ;; compress the AppDir
+ (invoke #+(file-append squashfs-tools "/bin/mksquashfs") appdir
+ squashfs "-root-owned" "-noappend"
+ "-comp" #+(compressor-name compressor))
+ ;; append runtime and squashFS into file AppImage
+ (concatenate #$output
+ #$(file-append runtime-package "/" runtime-path)
+ squashfs))))))
+ (gexp->derivation (string-append name ".AppImage") builder
+ #:target target
+ #:references-graphs `(("profile" ,profile))))
+\f
;;;
;;; Compiling C programs.
;;;
@@ -1311,6 +1404,7 @@ (define %formats
(squashfs . ,squashfs-image)
(docker . ,docker-image)
(deb . ,debian-archive)
+ (appimage . ,self-contained-appimage)
(rpm . ,rpm-archive)))
(define (show-formats)
@@ -1327,6 +1421,8 @@ (define (show-formats)
deb Debian archive installable via dpkg/apt"))
(display (G_ "
rpm RPM archive installable via rpm/yum"))
+ (display (G_ "
+ appimage AppImage self-contained and executable format"))
(newline))
(define (required-option symbol)
@@ -1694,6 +1790,8 @@ (define-command (guix-pack . args)
(process-file-arg opts 'preun-file)
#:postun-file
(process-file-arg opts 'postun-file)))
+ ('appimage
+ (list #:relocatable? relocatable?))
(_ '())))
(target (assoc-ref opts 'target))
(bootstrap? (assoc-ref opts 'bootstrap?))
base-commit: d95588242c605fbb72e25fe36a0903a1538e9018
--
2.46.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH] pack: Add support for AppImage pack format.
2024-10-16 21:51 [bug#73842] [PATCH] pack: Add support for AppImage pack format Noé Lopez
@ 2024-10-18 12:20 ` Ludovic Courtès
2024-10-18 12:22 ` Ludovic Courtès
` (4 subsequent siblings)
5 siblings, 0 replies; 24+ messages in thread
From: Ludovic Courtès @ 2024-10-18 12:20 UTC (permalink / raw)
To: Noé Lopez
Cc: Josselin Poiret, 73842, Maxim Cournoyer, Simon Tournier,
Mathieu Othacehe, Tobias Geerinckx-Rice, Sebastian Dümcke,
Christopher Baines
Hi Noé & Sebastian,
Noé Lopez <noelopez@free.fr> skribis:
> From: Sebastian Dümcke <code@sam-d.com>
>
> * guix/scripts/pack.scm: Add Appimage format.
> * gnu/packages/appimage.scm
> (gnu packages appimage): New module.
> (fuse-for-appimage, squashfuse-for-appimage)
> (appimage-type2-runtime): New variables.
> * doc/guix.texi: Document AppImage pack.
>
> Co-authored-by: Noé Lopez <noelopez@free.fr>
> Change-Id: I09f1241dfb9b267f94dce59914dea527d35ac60e
[...]
> This patch adds a new AppImage export format to « guix pack ». This
> enables guix users to easily share packets or environments with their
> peers that don’t have guix via a statically linked, runs-everywhere
> executable.
>
> Sebastian and I co-authored this patch, I did the runtime packaging
> and Sebastian did the actual command. I’ve personally tested the
> generated AppImages with my friend’s various distros, they work great!
Nice work! Overall looks great to me. What follows are pretty minor
suggestions.
> +@cindex AppImage, create an AppImage file with guix pack
s/guix pack/@command{guix pack}/
> +Another format internally based on SquashFS is
> +@uref{https://appimage.org/, AppImage}. An AppImage file can be made
^
Nitpick: please leave two spaces after end-of-sentence periods
throughout this patch.
> +The resulting AppImage does not conform to the complete standard as it
> +currently does not contain a @code{.DirIcon} file. This does not impact
s/@code/@file/
> +@quotation Warning
> +Unless @option{--relocatable} is used, the software will contain
> +references to items inside the guix store, which are not present on
> +systems without Guix. It is recommended to use @option{--relocatable}
> +when distributing software to 3rd parties. A warning is printed when
> +this option is not used.
I would it perhaps more upfront, like:
When building an AppImage, always @emph{pass} the
@option{--relocatable} option (or @option{-R}, or @option{-RR}) to
make sure the image can be used on systems where Guix is not
installed.
In practice, if Guix is installed but the image’s dependencies are not
in the store, it won’t work either. So I think the “always” bit is not
exaggerated.
WDYT?
> +++ b/gnu/packages/appimage.scm
Could you add this file as a separate commit, before the one adding
AppImage support to ‘guix pack’?
> + (arguments
> + `(#:configure-flags ,#~(list (string-append "-Dudevrulesdir="
> + #$output "/udev/rules.d")
> + "-Duseroot=false" "--default-library=static")
> + #:tests? #f
Please add a short comment explaining why tests are skipped.
> + #:phases ,#~(modify-phases %standard-phases
The recommended style is to avoid quasiquote/unquote and instead write:
(arguments
(list #:configure-flags …
#:phases #~(…)))
> + (add-before 'configure 'set-paths
> + (lambda* (#:key inputs outputs #:allow-other-keys)
> + (let ((dummy-init.d (string-append (getcwd)
> + "/etc/init.d")))
> + (setenv "MOUNT_FUSE_PATH"
> + (string-append #$output "/sbin"))
> + (setenv "UDEV_RULES_PATH"
> + (string-append #$output "/lib/udev/rules.d"))))))))))
Maybe call this phase ‘set-fuse+udev+paths’, to avoid confusion with the
standard ‘set-paths’ phase.
> +(define squashfuse-for-appimage
> + (let ((revision "0")
> + (commit "e51978cd6bb5c4d16fae9eee43d0b258f570bb0f"))
> + (package
> + (inherit squashfuse)
> + (name "squashfuse")
> + (version (git-version "0.1.104" revision commit))
Can you add a comment explaining why this specific commit is needed?
That way, our future selves will know when ‘squashfuse-for-appimage’ can
be removed.
> +(define-public appimage-type2-runtime
> + (let ((revision "0")
> + (commit "47b665594856b4e8928f8932adcf6d13061d8c30"))
> + (package
> + (name "appimage-type2-runtime")
Likewise.
> + #:phases #~(modify-phases %standard-phases
> + (delete 'configure)
> + (delete 'check)
> + (replace 'install
> + (lambda _
> + (install-file "src/runtime/runtime-fuse3"
> + (string-append #$output "/bin"))))
> + ;; must be after all elf reliant phases
> + (add-after 'make-dynamic-linker-cache 'set-magic-bytes
> + (lambda _
> + (use-modules (ice-9 binary-ports))
Please do not use ‘use-modules’ in a non-top-level context; it’s not
guaranteed to work in that context.
Instead use #:modules (check the repo for examples).
> + (home-page "https://github.com/AppImage/type2-runtime")
> + (synopsis "Runtime for AppImages")
> + (description "The runtime is the executable part of every AppImage. It
Please make it a full sentence, as per
<https://guix.gnu.org/manual/devel/en/html_node/Synopses-and-Descriptions.html>.
> + (define (concatenate result file1 file2)
Please add a short comment below ‘define’ explaining what it does,
similar to docstrings.
> + (let ((p (open-file-output-port result))
Rather:
(call-with-output-file result
(lambda (output)
…))
> + (f1 (open-file-input-port file1))
> + (f2 (open-file-input-port file2)))
> + (put-bytevector p (get-bytevector-all f1))
> + (close-port f1)
> + (put-bytevector p (get-bytevector-all f2))
To avoid loading it all in memory, rather use:
(call-with-input-file file1
(lambda (input)
(dump-port input output)))
Same with FILE2.
> + (let* ((appdir "AppDir")
> + (squashfs "squashfs")
> + (profile-items (map store-info-item
> + (call-with-input-file "profile" read-reference-graph)))
> + (profile-path (find (cut (file-name-predicate "profile$") <> #f) profile-items)))
s/-path//
Also, rather: (find (lambda (item)
(string-suffix? "-profile" item))
items)
> + (mkdir-p appdir)
> + ;; copy all store items from the profile to the AppDir
> + (for-each (lambda (f)
> + (copy-store-item f appdir)) profile-items)
I believe you could write:
(populate-store '("profile") appdir)
> + ;; symlink the provided entry-point to AppDir/AppRun
> + (symlink (string-append "." profile-path "/" #$entry-point)
> + (string-append appdir "/AppRun"))
> + ;; create .desktop file as required by the spec
> + (make-desktop-entry-file
> + (string-append appdir "/" #$name ".desktop")
> + #:name #$name
> + #:exec #$entry-point)
> + ;; compress the AppDir
> + (invoke #+(file-append squashfs-tools "/bin/mksquashfs") appdir
> + squashfs "-root-owned" "-noappend"
> + "-comp" #+(compressor-name compressor))
> + ;; append runtime and squashFS into file AppImage
> + (concatenate #$output
> + #$(file-append runtime-package "/" runtime-path)
> + squashfs))))))
And you can finish with: (chmod #$output #o555).
(Then you can remove the doc that says to “chmod +x” the result.)
It looks like this procedure ignores its #:symlinks argument. Could you
add support for it?
Could you send an updated patch?
At any rate, kudos for this new backend! This had been suggested many
times, so I’m sure it’ll find some good use.
Thank you!
Ludo’.
^ permalink raw reply [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH] pack: Add support for AppImage pack format.
2024-10-16 21:51 [bug#73842] [PATCH] pack: Add support for AppImage pack format Noé Lopez
2024-10-18 12:20 ` Ludovic Courtès
@ 2024-10-18 12:22 ` Ludovic Courtès
2024-10-18 20:34 ` Ludovic Courtès
` (3 subsequent siblings)
5 siblings, 0 replies; 24+ messages in thread
From: Ludovic Courtès @ 2024-10-18 12:22 UTC (permalink / raw)
To: Noé Lopez
Cc: Josselin Poiret, 73842, Maxim Cournoyer, Simon Tournier,
Mathieu Othacehe, Tobias Geerinckx-Rice, Sebastian Dümcke,
Christopher Baines
Oh, I forgot one thing: could you add a followup commit adding a news
entry in ‘etc/news.scm’?
Make sure the synopsis is intelligible to the Guix user base at large
and that the target audience is clear.
Thanks,
Ludo’.
^ permalink raw reply [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH] pack: Add support for AppImage pack format.
2024-10-16 21:51 [bug#73842] [PATCH] pack: Add support for AppImage pack format Noé Lopez
2024-10-18 12:20 ` Ludovic Courtès
2024-10-18 12:22 ` Ludovic Courtès
@ 2024-10-18 20:34 ` Ludovic Courtès
2024-10-26 17:28 ` [bug#73842] [PATCH v2 0/3] " Noé Lopez
` (2 subsequent siblings)
5 siblings, 0 replies; 24+ messages in thread
From: Ludovic Courtès @ 2024-10-18 20:34 UTC (permalink / raw)
To: Noé Lopez
Cc: Josselin Poiret, 73842, Maxim Cournoyer, Simon Tournier,
Mathieu Othacehe, Tobias Geerinckx-Rice, Sebastian Dümcke,
Christopher Baines
Noé Lopez <noelopez@free.fr> skribis:
> From: Sebastian Dümcke <code@sam-d.com>
>
> * guix/scripts/pack.scm: Add Appimage format.
> * gnu/packages/appimage.scm
> (gnu packages appimage): New module.
> (fuse-for-appimage, squashfuse-for-appimage)
> (appimage-type2-runtime): New variables.
> * doc/guix.texi: Document AppImage pack.
>
> Co-authored-by: Noé Lopez <noelopez@free.fr>
> Change-Id: I09f1241dfb9b267f94dce59914dea527d35ac60e
One last thing: could you add a test?
Since such a test needs to build a whole bunch of things, it would only
be executed when a connection to a “real” store is available. See the
examples in ‘tests/pack.scm’ and ‘tests/guix-pack-relocatable.sh’. I
guess a test could go in either of these two files, or in a third one
similar to ‘guix-pack-relocatable.sh’.
Let me know what you think!
Ludo’.
^ permalink raw reply [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v2 0/3] pack: Add support for AppImage pack format.
2024-10-16 21:51 [bug#73842] [PATCH] pack: Add support for AppImage pack format Noé Lopez
` (2 preceding siblings ...)
2024-10-18 20:34 ` Ludovic Courtès
@ 2024-10-26 17:28 ` Noé Lopez
2024-10-26 17:28 ` [bug#73842] [PATCH v2 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez
` (2 more replies)
2024-11-03 22:37 ` [bug#73842] [PATCH v4 0/3] pack: Add support for AppImage pack format Noé Lopez via Guix-patches via
2024-11-07 16:50 ` [bug#73842] [PATCH v5 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez via Guix-patches via
5 siblings, 3 replies; 24+ messages in thread
From: Noé Lopez @ 2024-10-26 17:28 UTC (permalink / raw)
To: 73842; +Cc: Noé Lopez, Florian Pelz, Julien Lepiller
Hi Ludovic,
Thank you for the complete review, here is a new version of the patch
containing the changes you asked for. Sebastian did the news entry in
three languages (!!!) while I made the tests and git magic.
Can you explain why you want support for symlinks? I can’t think of a
use for it since AppImages are only meant to be ran through their
entrypoint, not unpacked.
A summary of changes since previous patch:
– Improved package definition for [squash]fuse-for-appimage and
bumped versions;
– Added news entry;
– Added tests;
– Applied code suggestions from review:
– Don’t use (use-modules) on non-toplevel;
– Change -R warning in documentation, and ensure two spaces
after dots;
– Change appimage-type2-runtime synopsis and description;
– Document and improve (concatenate-files)
– Use better lambdas for `profile' and populating the store.
– chmod 555 the resulting AppImage
Have a wonderful week-end,
Noé Lopez
Noé Lopez (1):
gnu: appimage: New packages for the appimage runtime.
Sebastian Dümcke (2):
pack: Add support for AppImage pack format.
news: Add entry for guix pack’s AppImage format
doc/guix.texi | 55 +++++++++++++++-
etc/news.scm | 38 +++++++++++
gnu/packages/appimage.scm | 133 ++++++++++++++++++++++++++++++++++++++
guix/scripts/pack.scm | 104 ++++++++++++++++++++++++++++-
tests/pack.scm | 41 +++++++++++-
5 files changed, 368 insertions(+), 3 deletions(-)
create mode 100644 gnu/packages/appimage.scm
base-commit: df666602c7936f7d87354374b148ef6269844c01
--
2.46.0
^ permalink raw reply [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v2 1/3] gnu: appimage: New packages for the appimage runtime.
2024-10-26 17:28 ` [bug#73842] [PATCH v2 0/3] " Noé Lopez
@ 2024-10-26 17:28 ` Noé Lopez
2024-11-01 13:24 ` Maxim Cournoyer
2024-10-26 17:28 ` [bug#73842] [PATCH v2 2/3] pack: Add support for AppImage pack format Noé Lopez
2024-10-26 17:28 ` [bug#73842] [PATCH v2 3/3] news: Add entry for guix pack’s AppImage format Noé Lopez
2 siblings, 1 reply; 24+ messages in thread
From: Noé Lopez @ 2024-10-26 17:28 UTC (permalink / raw)
To: 73842; +Cc: Noé Lopez
* gnu/packages/appimage.scm
(gnu packages appimage): New module.
(fuse-for-appimage, squashfuse-for-appimage)
(appimage-type2-runtime): New variables.
Change-Id: I857a8eb5399a6a493e52db70b6c8cf0c71360930
---
gnu/packages/appimage.scm | 133 ++++++++++++++++++++++++++++++++++++++
1 file changed, 133 insertions(+)
create mode 100644 gnu/packages/appimage.scm
diff --git a/gnu/packages/appimage.scm b/gnu/packages/appimage.scm
new file mode 100644
index 0000000000..028b59ab30
--- /dev/null
+++ b/gnu/packages/appimage.scm
@@ -0,0 +1,133 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2024 Noé Lopez <noelopez@free.fr>
+;;;
+;;; 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/>.
+
+(define-module (gnu packages appimage)
+ #:use-module ((guix licenses) #:prefix license:)
+ #:use-module (gnu packages base)
+ #:use-module (gnu packages compression)
+ #:use-module (gnu packages file-systems)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages)
+ #:use-module (guix build-system gnu)
+ #:use-module (guix download)
+ #:use-module (guix gexp)
+ #:use-module (guix git-download)
+ #:use-module (guix packages)
+ #:use-module (guix utils))
+
+(define fuse-for-appimage
+ (package
+ (inherit fuse)
+ (name "fuse")
+ (version "3.16.2")
+ (source
+ (origin
+ (method url-fetch)
+ (uri (string-append "https://github.com/libfuse/libfuse/releases/"
+ "download/fuse-"
+ version
+ "/fuse-"
+ version
+ ".tar.gz"))
+ (sha256
+ (base32 "11yfl2w2a445hllyzlakq97n32g06972vxpmh7lpbclnj9fhb5zp"))))
+ (arguments
+ (substitute-keyword-arguments (package-arguments fuse)
+ ((#:configure-flags original-flags #~(list))
+ #~(append #$original-flags '("--default-library=static")))))))
+
+(define squashfuse-for-appimage
+ (package
+ (inherit squashfuse)
+ (arguments
+ (list
+ #:configure-flags #~'("CFLAGS=-ffunction-sections -fdata-sections -Os -no-pie"
+ "LDFLAGS=-static")
+ #:phases #~(modify-phases %standard-phases
+ (add-after 'install 'install-private-headers
+ (lambda _
+ (install-file "fuseprivate.h"
+ (string-append #$output
+ "/include/squashfuse/")))))))
+ (inputs (list fuse-for-appimage
+ `(,zstd "lib")
+ `(,zstd "static")
+ `(,zlib "out")
+ `(,zlib "static")))))
+
+(define-public appimage-type2-runtime
+ (let ((revision "0")
+ ;; No releases, just the latest commit.
+ (commit "47b665594856b4e8928f8932adcf6d13061d8c30"))
+ (package
+ (name "appimage-type2-runtime")
+ (version (git-version "continuous" revision commit))
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/AppImage/type2-runtime")
+ (commit commit)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32 "0954crhlbapxis96g1s0vfpf78ybr64zvjalak387ksxj560g44x"))))
+ (arguments
+ (list
+ #:make-flags #~(list "-Csrc/runtime" "runtime-fuse3"
+ (string-append "CFLAGS="
+ "-I"
+ #$fuse-2
+ "/include/fuse/"
+ " -DGIT_COMMIT='\""
+ "guix-"
+ #$version
+ "\"'"
+ " -D_FILE_OFFSET_BITS=64"
+ " -static"))
+ #:modules
+ `((guix build gnu-build-system)
+ (guix build utils)
+ (ice-9 binary-ports))
+ #:phases #~(modify-phases %standard-phases
+ (delete 'configure)
+ (delete 'check) ; No tests.
+ (replace 'install
+ (lambda _
+ (install-file "src/runtime/runtime-fuse3"
+ (string-append #$output "/bin"))))
+ ;; must be after all elf reliant phases
+ (add-after 'make-dynamic-linker-cache 'set-magic-bytes
+ (lambda _
+ (let ((port (open (string-append #$output
+ "/bin/runtime-fuse3")
+ (logior O_WRONLY))))
+ (seek port 8 SEEK_SET)
+ (put-bytevector port #vu8(#x41 #x49 #x02))
+ (close-port port)))))
+ #:disallowed-references (list squashfuse-for-appimage
+ fuse-for-appimage zstd zlib)))
+ ;; only needed at build time
+ (inputs (list squashfuse-for-appimage fuse-for-appimage
+ `(,zstd "static")
+ `(,zlib "static")))
+ (build-system gnu-build-system)
+ (home-page "https://github.com/AppImage/type2-runtime")
+ (synopsis "Runtime for executing AppImages")
+ (description "The runtime is the executable part of every AppImage, it mounts
+the payload via FUSE and executes the entrypoint.")
+ (license license:expat))))
--
2.46.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v2 2/3] pack: Add support for AppImage pack format.
2024-10-26 17:28 ` [bug#73842] [PATCH v2 0/3] " Noé Lopez
2024-10-26 17:28 ` [bug#73842] [PATCH v2 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez
@ 2024-10-26 17:28 ` Noé Lopez
2024-11-01 13:19 ` Maxim Cournoyer
2024-10-26 17:28 ` [bug#73842] [PATCH v2 3/3] news: Add entry for guix pack’s AppImage format Noé Lopez
2 siblings, 1 reply; 24+ messages in thread
From: Noé Lopez @ 2024-10-26 17:28 UTC (permalink / raw)
To: 73842
Cc: Noé Lopez, Sebastian Dümcke, Christopher Baines,
Josselin Poiret, Ludovic Courtès, Mathieu Othacehe,
Maxim Cournoyer, Simon Tournier, Tobias Geerinckx-Rice
From: Sebastian Dümcke <code@sam-d.com>
* guix/scripts/pack.scm: Add Appimage format.
* doc/guix.texi: Document AppImage pack.
Co-authored-by: Noé Lopez <noelopez@free.fr>
Change-Id: I33ebfec623cff1cfcd6f029d2d3054c23ab1949a
---
doc/guix.texi | 55 +++++++++++++++++++++-
guix/scripts/pack.scm | 104 +++++++++++++++++++++++++++++++++++++++++-
tests/pack.scm | 41 ++++++++++++++++-
3 files changed, 197 insertions(+), 3 deletions(-)
diff --git a/doc/guix.texi b/doc/guix.texi
index ac3a7adef0..18edf8e550 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -6949,6 +6949,18 @@ Invoking guix pack
environment}, using commands like @command{singularity shell} or
@command{singularity exec}.
+@cindex AppImage, create an AppImage file with @command{guix pack}
+Another format internally based on SquashFS is
+@uref{https://appimage.org/, AppImage}. An AppImage file can be made
+executable and run without any special privileges:
+
+@example
+guix pack -f appimage --entry-point=bin/guile guile
+cp @var{file} . && chmod u+x $(basename @var{file})
+./$(basename @var{file}) --help
+@end example
+where @var{file} is the image returned by @command{guix pack}.
+
Several command-line options allow you to customize your pack:
@table @code
@@ -7065,6 +7077,47 @@ Invoking guix pack
installation or other, non-rpm packs.
@end quotation
+@item appimage
+@cindex AppImage, create an AppImage file with @command{guix pack}
+This produces an AppImage file with the @samp{.AppImage} extension.
+AppImage is a SquashFS volume prefixed with a runtime that mounts the
+SquashFS file system and executes the binary provided with
+@option{--entry-point}. This results in a self-contained archive that
+bundles the software and all its requirements into a single file. When
+the file is made executable it runs the packaged software.
+
+@example
+guix pack -f appimage --entry-point=bin/vlc vlc
+@end example
+
+The runtime used by AppImages makes use of libfuse to mount the image
+quickly. If libfuse is not available, the AppImage can still be started
+using the @option{--appimage-extract-and-run} flag.
+
+@quotation Warning
+ When building an AppImage, always @emph{pass} the
+@option{--relocatable} option (or @option{-R}, or @option{-RR}) to make
+sure the image can be used on systems where Guix is not installed. A
+warning is printed when this option is not used.
+@end quotation
+
+@example
+guix pack -f appimage --entry-point=bin/hello --relocatable hello
+@end example
+
+@quotation Note
+The resulting AppImage does not conform to the complete standard as it
+currently does not contain a @file{.DirIcon} file. This does not impact
+functionality of the AppImage itself, but possibly that of software used
+to manage AppImages.
+@end quotation
+
+@quotation Note
+As the generated AppImage packages the complete dependency graph, it
+will be larger than comparable AppImage files found online, which depend
+on host system libraries.
+@end quotation
+
@end table
@cindex relocatable binaries
@@ -7155,7 +7208,7 @@ Invoking guix pack
@cindex entry point, for Docker and Singularity images
@item --entry-point=@var{command}
Use @var{command} as the @dfn{entry point} of the resulting pack, if the pack
-format supports it---currently @code{docker} and @code{squashfs} (Singularity)
+format supports it---currently @code{docker}, @code{appimage} and @code{squashfs} (Singularity)
support it. @var{command} must be relative to the profile contained in the
pack.
diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm
index 7c5fe76fe0..95b40a743b 100644
--- a/guix/scripts/pack.scm
+++ b/guix/scripts/pack.scm
@@ -10,6 +10,8 @@
;;; Copyright © 2022 Alex Griffin <a@ajgrf.com>
;;; Copyright © 2023 Graham James Addis <graham@addis.org.uk>
;;; Copyright © 2023 Oleg Pykhalov <go.wigust@gmail.com>
+;;; Copyright © 2024 Sebastian Dümcke <code@sam-d.com>
+;;; Copyright © 2024 Noé Lopez <noelopez@free.fr>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -56,6 +58,7 @@ (define-module (guix scripts pack)
#:use-module ((gnu packages compression) #:hide (zip))
#:use-module (gnu packages guile)
#:use-module (gnu packages base)
+ #:autoload (gnu packages appimage) (appimage-type2-runtime)
#:autoload (gnu packages gnupg) (guile-gcrypt)
#:autoload (gnu packages guile) (guile2.0-json guile-json)
#:use-module (srfi srfi-1)
@@ -64,6 +67,7 @@ (define-module (guix scripts pack)
#:use-module (srfi srfi-35)
#:use-module (srfi srfi-37)
#:use-module (ice-9 match)
+ #:use-module (ice-9 optargs)
#:export (symlink-spec-option-parser
self-contained-tarball
@@ -71,6 +75,7 @@ (define-module (guix scripts pack)
rpm-archive
docker-image
squashfs-image
+ self-contained-appimage
%formats
guix-pack))
@@ -974,8 +979,100 @@ (define* (rpm-archive name profile
(gexp->derivation (string-append name ".rpm") build
#:target target
#:references-graphs `(("profile" ,profile))))
+\f
+;;;
+;;; AppImage format
+;;;
+(define* (self-contained-appimage name profile
+ #:key target
+ (profile-name "guix-profile")
+ entry-point
+ (compressor (lookup-compressor "zstd"))
+ localstatedir?
+ (symlinks '())
+ (archiver tar)
+ (extra-options '()))
+ "Return a self-contained AppImage containing a store initialized with the
+closure of PROFILE, a derivation. The AppImage contains /gnu/store unless
+RELOCATABLE option is used; if LOCALSTATEDIR? is true, it also contains
+/var/guix, including /var/guix/db with a properly initialized store database.
+
+SYMLINKS must be a list of (SOURCE -> TARGET) tuples denoting symlinks to be
+added to the pack."
+ (unless entry-point
+ (leave (G_ "entry-point must be provided in the '~a' format~%")
+ 'appimage))
+ (let-keywords extra-options #f ((relocatable? #f))
+ (unless relocatable?
+ (warning (G_ "AppImages should be built with the --relocatable flag~%"))))
+
+ (define runtime-package appimage-type2-runtime)
+ (define runtime-path "bin/runtime-fuse3")
+ (define %valid-compressors '("gzip" "zstd"))
+
+ (let ((compressor-name (compressor-name compressor)))
+ (unless (member compressor-name %valid-compressors)
+ (leave (G_ "~a is not a valid squashfs archive compressor used in
+generating the AppImage. Valid compressors are: ~a~%")
+ compressor-name
+ %valid-compressors)))
- \f
+ (define builder
+ (with-extensions (list guile-gcrypt)
+ (with-imported-modules (source-module-closure
+ '((guix build store-copy)
+ (guix build utils))
+ #:select? not-config?)
+ #~(begin
+ (use-modules (guix build utils)
+ (guix build store-copy)
+ (rnrs io ports)
+ (srfi srfi-1)
+ (srfi srfi-26))
+
+ (define (concatenate-files result file1 file2)
+ "Creates a new file RESULT containing FILE1 followed by FILE2."
+ (call-with-output-file result
+ (lambda (output)
+ (call-with-input-file file1
+ (lambda (input)
+ (dump-port input output)))
+ (call-with-input-file file2
+ (lambda (input)
+ (dump-port input output))))))
+
+ (let* ((appdir "AppDir")
+ (squashfs "squashfs")
+ (profile-items (map store-info-item
+ (call-with-input-file "profile" read-reference-graph)))
+ (profile (find (lambda (item)
+ (string-suffix? "-profile" item))
+ profile-items)))
+ (mkdir-p appdir)
+ ;; copy all store items from the profile to the AppDir
+ (populate-store '("profile") appdir)
+ ;; symlink the provided entry-point to AppDir/AppRun
+ (symlink (string-append "." profile "/" #$entry-point)
+ (string-append appdir "/AppRun"))
+ ;; create .desktop file as required by the spec
+ (make-desktop-entry-file
+ (string-append appdir "/" #$name ".desktop")
+ #:name #$name
+ #:exec #$entry-point)
+ ;; compress the AppDir
+ (invoke #+(file-append squashfs-tools "/bin/mksquashfs") appdir
+ squashfs "-root-owned" "-noappend"
+ "-comp" #+(compressor-name compressor))
+ ;; append runtime and squashFS into file AppImage
+ (concatenate-files #$output
+ #$(file-append runtime-package "/" runtime-path)
+ squashfs)
+ ;; add execution permission
+ (chmod #$output #o555))))))
+ (gexp->derivation (string-append name ".AppImage") builder
+ #:target target
+ #:references-graphs `(("profile" ,profile))))
+\f
;;;
;;; Compiling C programs.
;;;
@@ -1311,6 +1408,7 @@ (define %formats
(squashfs . ,squashfs-image)
(docker . ,docker-image)
(deb . ,debian-archive)
+ (appimage . ,self-contained-appimage)
(rpm . ,rpm-archive)))
(define (show-formats)
@@ -1327,6 +1425,8 @@ (define (show-formats)
deb Debian archive installable via dpkg/apt"))
(display (G_ "
rpm RPM archive installable via rpm/yum"))
+ (display (G_ "
+ appimage AppImage self-contained and executable format"))
(newline))
(define (required-option symbol)
@@ -1694,6 +1794,8 @@ (define-command (guix-pack . args)
(process-file-arg opts 'preun-file)
#:postun-file
(process-file-arg opts 'postun-file)))
+ ('appimage
+ (list #:relocatable? relocatable?))
(_ '())))
(target (assoc-ref opts 'target))
(bootstrap? (assoc-ref opts 'bootstrap?))
diff --git a/tests/pack.scm b/tests/pack.scm
index f8a9e09c28..6ac9a966af 100644
--- a/tests/pack.scm
+++ b/tests/pack.scm
@@ -3,6 +3,7 @@
;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2021, 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2023 Oleg Pykhalov <go.wigust@gmail.com>
+;;; Copyright © 2024 Noé Lopez <noelopez@free.fr>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -32,7 +33,8 @@ (define-module (test-pack)
#:use-module (guix utils)
#:use-module ((guix build utils) #:select (%store-directory))
#:use-module (gnu packages)
- #:use-module ((gnu packages base) #:select (libc-utf8-locales-for-target))
+ #:use-module ((gnu packages base) #:select (libc-utf8-locales-for-target
+ hello))
#:use-module (gnu packages bootstrap)
#:use-module ((gnu packages package-management) #:select (rpm))
#:use-module ((gnu packages compression) #:select (squashfs-tools))
@@ -340,6 +342,43 @@ (define rpm-for-tests
(mkdir #$output))))))))
(built-derivations (list check))))
+ (unless store (test-skip 1))
+ (test-assertm "appimage"
+ (mlet* %store-monad
+ ((guile (set-guile-for-build (default-guile)))
+ (profile -> (profile
+ (content (packages->manifest (list %bootstrap-guile hello)))
+ (hooks '())
+ (locales? #f)))
+ (image (self-contained-appimage "hello-appimage" profile
+ #:entry-point "bin/hello"
+ #:extra-options
+ (list #:relocatable? #t)))
+ (check (gexp->derivation
+ "check-appimage"
+ #~(begin
+ (invoke #$image)))))
+ (built-derivations (list check))))
+
+ (unless store (test-skip 1))
+ (test-assertm "appimage + localstatedir"
+ (mlet* %store-monad
+ ((guile (set-guile-for-build (default-guile)))
+ (profile -> (profile
+ (content (packages->manifest (list %bootstrap-guile hello)))
+ (hooks '())
+ (locales? #f)))
+ (image (self-contained-appimage "hello-appimage" profile
+ #:entry-point "bin/hello"
+ #:localstatedir? #t
+ #:extra-options
+ (list #:relocatable? #t)))
+ (check (gexp->derivation
+ "check-appimage"
+ #~(begin
+ (invoke #$image)))))
+ (built-derivations (list check))))
+
(unless store (test-skip 1))
(test-assertm "deb archive with symlinks and control files"
(mlet* %store-monad
--
2.46.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v2 3/3] news: Add entry for guix pack’s AppImage format
2024-10-26 17:28 ` [bug#73842] [PATCH v2 0/3] " Noé Lopez
2024-10-26 17:28 ` [bug#73842] [PATCH v2 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez
2024-10-26 17:28 ` [bug#73842] [PATCH v2 2/3] pack: Add support for AppImage pack format Noé Lopez
@ 2024-10-26 17:28 ` Noé Lopez
2024-10-27 13:38 ` pelzflorian (Florian Pelz)
2024-11-01 13:27 ` Maxim Cournoyer
2 siblings, 2 replies; 24+ messages in thread
From: Noé Lopez @ 2024-10-26 17:28 UTC (permalink / raw)
To: 73842; +Cc: Sebastian Dümcke, Florian Pelz, Julien Lepiller
From: Sebastian Dümcke <code@sam-d.com>
* etc/news.scm: Add entry.
Change-Id: If37b3b578517c15c2868239998975f7718f7d689
---
etc/news.scm | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/etc/news.scm b/etc/news.scm
index 4929fa2a9a..59fdd94dd8 100644
--- a/etc/news.scm
+++ b/etc/news.scm
@@ -25,6 +25,7 @@
;; Copyright © 2024 Vivien Kraus <vivien@planete-kraus.eu>
;; Copyright © 2024 Guillaume Le Vaillant <glv@posteo.net>
;; Copyright © 2024 Zheng Junjie <873216071@qq.com>
+;; Copyright © 2024 Sebastian Dümcke <code@sam-d.com>
;;
;; Copying and distribution of this file, with or without modification, are
;; permitted in any medium without royalty provided the copyright notice and
@@ -32,6 +33,43 @@
(channel-news
(version 0)
+ (entry (commit "ea1fe6e106f2abc9fce5cf7e686227c0c1f9e9e1")
+ (title
+ (de "Neues Format @samp{AppImage} für den Befehl @command{guix pack}")
+ (en "New @samp{AppImage} format for the @command{guix pack} command")
+ (fr "Nouveau format @samp{AppImage} pour la commande @command{guix pack}"))
+ (body
+ (de "@command{guix pack} kann nun AppImage Dateien erstellen. Das
+AppImage Dateiformat erlaubt es in einer einzelnen Datei Software zu verteilen. Die
+AppImage Datei lässt sich ohne besondere Benutzerrechte ausführen. Hier ist
+ein Beispiel:
+
+@example
+guix pack --format=appimage --entry-point=bin/hello hello
+@end example
+
+Siehe @command{info \"(guix.de) Aufruf von guix pack\"} für mehr
+Informationen.")
+ (en "@command{guix pack} can now produce AppImage a single file,
+self-contained software archive. AppImage files are easily distributed and can
+be run with user privileges. Here is an example for the @code{hello} package:
+
+@example
+guix pack --format=appimage --entry-point=bin/hello hello
+@end example
+
+See @command{info \"(guix) Invoking guix pack\"} for more information.")
+ (fr "@command{guix pack} peut désormais produire un fichier
+AppImage. AppImage est une manière de distribuer les logiciels en un seul
+fichier, qui peut être executer avec des droits d’utilisateur. Voici un
+exemple pour le paquet @code{hello} :
+
+@example
+guix pack --format=appimage --entry-point=bin/hello hello
+@end example
+
+Consultez @command{info \"(guix.fr) Invoquer guix pack\"} pour plus
+d’informations.")))
(entry (commit "5966e0fdc78771c562e0f484a22f381a77908be0")
(title
--
2.46.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v2 3/3] news: Add entry for guix pack’s AppImage format
2024-10-26 17:28 ` [bug#73842] [PATCH v2 3/3] news: Add entry for guix pack’s AppImage format Noé Lopez
@ 2024-10-27 13:38 ` pelzflorian (Florian Pelz)
2024-11-01 13:27 ` Maxim Cournoyer
1 sibling, 0 replies; 24+ messages in thread
From: pelzflorian (Florian Pelz) @ 2024-10-27 13:38 UTC (permalink / raw)
To: Noé Lopez; +Cc: Julien Lepiller, 73842, Sebastian Dümcke
Thank you Noé and Sebastian for not only the command but also including
German news. Some minor suggestions:
Noé Lopez <noelopez@free.fr> writes:
> + (body
> + (de "@command{guix pack} kann nun AppImage Dateien erstellen. Das
> +AppImage Dateiformat erlaubt es in einer
comma: erlaubt es, in einer
To avoid <https://de.wikipedia.org/wiki/Leerzeichen_in_Komposita>,
please put in hyphens: AppImage-Dateien, AppImage-Dateiformat,
> einzelnen Datei Software zu verteilen. Die
> +AppImage Datei lässt sich ohne besondere Benutzerrechte ausführen. Hier ist
> +ein Beispiel:
AppImage-Datei
> +
> +@example
> +guix pack --format=appimage --entry-point=bin/hello hello
> +@end example
> +
> +Siehe @command{info \"(guix.de) Aufruf von guix pack\"} für mehr
> +Informationen.")
Regards,
Florian
^ permalink raw reply [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v2 2/3] pack: Add support for AppImage pack format.
2024-10-26 17:28 ` [bug#73842] [PATCH v2 2/3] pack: Add support for AppImage pack format Noé Lopez
@ 2024-11-01 13:19 ` Maxim Cournoyer
2024-11-01 15:22 ` Noé Lopez via Guix-patches via
0 siblings, 1 reply; 24+ messages in thread
From: Maxim Cournoyer @ 2024-11-01 13:19 UTC (permalink / raw)
To: Noé Lopez
Cc: Josselin Poiret, 73842, Simon Tournier, Mathieu Othacehe,
Ludovic Courtès, Tobias Geerinckx-Rice,
Sebastian Dümcke, Christopher Baines
Hi,
Noé Lopez <noelopez@free.fr> writes:
> From: Sebastian Dümcke <code@sam-d.com>
>
> * guix/scripts/pack.scm: Add Appimage format.
> * doc/guix.texi: Document AppImage pack.
>
> Co-authored-by: Noé Lopez <noelopez@free.fr>
Thanks for this great addition.
> Change-Id: I33ebfec623cff1cfcd6f029d2d3054c23ab1949a
> ---
> doc/guix.texi | 55 +++++++++++++++++++++-
> guix/scripts/pack.scm | 104 +++++++++++++++++++++++++++++++++++++++++-
> tests/pack.scm | 41 ++++++++++++++++-
> 3 files changed, 197 insertions(+), 3 deletions(-)
>
> diff --git a/doc/guix.texi b/doc/guix.texi
> index ac3a7adef0..18edf8e550 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -6949,6 +6949,18 @@ Invoking guix pack
> environment}, using commands like @command{singularity shell} or
> @command{singularity exec}.
>
> +@cindex AppImage, create an AppImage file with @command{guix pack}
> +Another format internally based on SquashFS is
> +@uref{https://appimage.org/, AppImage}. An AppImage file can be made
> +executable and run without any special privileges:
> +
> +@example
> +guix pack -f appimage --entry-point=bin/guile guile
> +cp @var{file} . && chmod u+x $(basename @var{file})
> +./$(basename @var{file}) --help
> +@end example
> +where @var{file} is the image returned by @command{guix pack}.
The chmod is no longer needed in this v2. Also, it could be nicer
perhaps to capture the output file in a real variable:
@example
file=$(guix pack -f appimage --entry-point=bin/guile guile)
$file
@end example
> +
> Several command-line options allow you to customize your pack:
>
> @table @code
> @@ -7065,6 +7077,47 @@ Invoking guix pack
> installation or other, non-rpm packs.
> @end quotation
>
> +@item appimage
> +@cindex AppImage, create an AppImage file with @command{guix pack}
> +This produces an AppImage file with the @samp{.AppImage} extension.
> +AppImage is a SquashFS volume prefixed with a runtime that mounts the
> +SquashFS file system and executes the binary provided with
> +@option{--entry-point}. This results in a self-contained archive that
> +bundles the software and all its requirements into a single file. When
> +the file is made executable it runs the packaged software.
> +
> +@example
> +guix pack -f appimage --entry-point=bin/vlc vlc
> +@end example
> +
> +The runtime used by AppImages makes use of libfuse to mount the image
> +quickly. If libfuse is not available, the AppImage can still be started
> +using the @option{--appimage-extract-and-run} flag.
> +
> +@quotation Warning
> + When building an AppImage, always @emph{pass} the
> +@option{--relocatable} option (or @option{-R}, or @option{-RR}) to make
> +sure the image can be used on systems where Guix is not installed. A
> +warning is printed when this option is not used.
Instead of a warning, could we just make it always -RR by default and
document that these are always relocatable, by design? The no
relocatable flags would be treated as an implicit -RR, and otherwise a
single -R would be treated as a single -R (and -RR as -RR, eh).
> +@end quotation
> +
> +@example
> +guix pack -f appimage --entry-point=bin/hello --relocatable hello
> +@end example
> +
> +@quotation Note
> +The resulting AppImage does not conform to the complete standard as it
> +currently does not contain a @file{.DirIcon} file. This does not impact
> +functionality of the AppImage itself, but possibly that of software used
> +to manage AppImages.
> +@end quotation
Are there plans to add support for .DirIcon in the future?
> +@quotation Note
> +As the generated AppImage packages the complete dependency graph, it
> +will be larger than comparable AppImage files found online, which depend
> +on host system libraries.
> +@end quotation
> +
> @end table
>
> @cindex relocatable binaries
> @@ -7155,7 +7208,7 @@ Invoking guix pack
> @cindex entry point, for Docker and Singularity images
> @item --entry-point=@var{command}
> Use @var{command} as the @dfn{entry point} of the resulting pack, if the pack
> -format supports it---currently @code{docker} and @code{squashfs} (Singularity)
> +format supports it---currently @code{docker}, @code{appimage} and @code{squashfs} (Singularity)
> support it. @var{command} must be relative to the profile contained in the
> pack.
>
> diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm
> index 7c5fe76fe0..95b40a743b 100644
> --- a/guix/scripts/pack.scm
> +++ b/guix/scripts/pack.scm
> @@ -10,6 +10,8 @@
> ;;; Copyright © 2022 Alex Griffin <a@ajgrf.com>
> ;;; Copyright © 2023 Graham James Addis <graham@addis.org.uk>
> ;;; Copyright © 2023 Oleg Pykhalov <go.wigust@gmail.com>
> +;;; Copyright © 2024 Sebastian Dümcke <code@sam-d.com>
> +;;; Copyright © 2024 Noé Lopez <noelopez@free.fr>
> ;;;
> ;;; This file is part of GNU Guix.
> ;;;
> @@ -56,6 +58,7 @@ (define-module (guix scripts pack)
> #:use-module ((gnu packages compression) #:hide (zip))
> #:use-module (gnu packages guile)
> #:use-module (gnu packages base)
> + #:autoload (gnu packages appimage) (appimage-type2-runtime)
> #:autoload (gnu packages gnupg) (guile-gcrypt)
> #:autoload (gnu packages guile) (guile2.0-json guile-json)
> #:use-module (srfi srfi-1)
> @@ -64,6 +67,7 @@ (define-module (guix scripts pack)
> #:use-module (srfi srfi-35)
> #:use-module (srfi srfi-37)
> #:use-module (ice-9 match)
> + #:use-module (ice-9 optargs)
> #:export (symlink-spec-option-parser
>
> self-contained-tarball
> @@ -71,6 +75,7 @@ (define-module (guix scripts pack)
> rpm-archive
> docker-image
> squashfs-image
> + self-contained-appimage
>
> %formats
> guix-pack))
> @@ -974,8 +979,100 @@ (define* (rpm-archive name profile
> (gexp->derivation (string-append name ".rpm") build
> #:target target
> #:references-graphs `(("profile" ,profile))))
> +\f
> +;;;
> +;;; AppImage format
> +;;;
> +(define* (self-contained-appimage name profile
> + #:key target
> + (profile-name "guix-profile")
> + entry-point
> + (compressor (lookup-compressor "zstd"))
> + localstatedir?
> + (symlinks '())
> + (archiver tar)
> + (extra-options '()))
> + "Return a self-contained AppImage containing a store initialized with the
> +closure of PROFILE, a derivation. The AppImage contains /gnu/store unless
> +RELOCATABLE option is used; if LOCALSTATEDIR? is true, it also contains
> +/var/guix, including /var/guix/db with a properly initialized store database.
> +
> +SYMLINKS must be a list of (SOURCE -> TARGET) tuples denoting symlinks to be
> +added to the pack."
> + (unless entry-point
> + (leave (G_ "entry-point must be provided in the '~a' format~%")
> + 'appimage))
> + (let-keywords extra-options #f ((relocatable? #f))
> + (unless relocatable?
> + (warning (G_ "AppImages should be built with the --relocatable flag~%"))))
> +
> + (define runtime-package appimage-type2-runtime)
> + (define runtime-path "bin/runtime-fuse3")
> + (define %valid-compressors '("gzip" "zstd"))
> +
> + (let ((compressor-name (compressor-name compressor)))
> + (unless (member compressor-name %valid-compressors)
> + (leave (G_ "~a is not a valid squashfs archive compressor used in
> +generating the AppImage. Valid compressors are: ~a~%")
> + compressor-name
> + %valid-compressors)))
>
> - \f
> + (define builder
> + (with-extensions (list guile-gcrypt)
> + (with-imported-modules (source-module-closure
> + '((guix build store-copy)
> + (guix build utils))
> + #:select? not-config?)
> + #~(begin
> + (use-modules (guix build utils)
> + (guix build store-copy)
> + (rnrs io ports)
> + (srfi srfi-1)
> + (srfi srfi-26))
> +
> + (define (concatenate-files result file1 file2)
> + "Creates a new file RESULT containing FILE1 followed by FILE2."
> + (call-with-output-file result
> + (lambda (output)
> + (call-with-input-file file1
> + (lambda (input)
> + (dump-port input output)))
> + (call-with-input-file file2
> + (lambda (input)
> + (dump-port input output))))))
> +
> + (let* ((appdir "AppDir")
> + (squashfs "squashfs")
> + (profile-items (map store-info-item
> + (call-with-input-file "profile" read-reference-graph)))
> + (profile (find (lambda (item)
> + (string-suffix? "-profile" item))
> + profile-items)))
> + (mkdir-p appdir)
> + ;; copy all store items from the profile to the AppDir
> + (populate-store '("profile") appdir)
> + ;; symlink the provided entry-point to AppDir/AppRun
> + (symlink (string-append "." profile "/" #$entry-point)
> + (string-append appdir "/AppRun"))
> + ;; create .desktop file as required by the spec
> + (make-desktop-entry-file
> + (string-append appdir "/" #$name ".desktop")
> + #:name #$name
> + #:exec #$entry-point)
> + ;; compress the AppDir
> + (invoke #+(file-append squashfs-tools "/bin/mksquashfs") appdir
> + squashfs "-root-owned" "-noappend"
> + "-comp" #+(compressor-name compressor))
> + ;; append runtime and squashFS into file AppImage
> + (concatenate-files #$output
> + #$(file-append runtime-package "/" runtime-path)
> + squashfs)
> + ;; add execution permission
Standalone comments (those starting on their own line with ;;) should be
fully punctuated (complete sentence), e.g.: "Add execution permission."
for the last one.
> + (chmod #$output #o555))))))
> + (gexp->derivation (string-append name ".AppImage") builder
> + #:target target
> + #:references-graphs `(("profile" ,profile))))
> +\f
> ;;;
> ;;; Compiling C programs.
> ;;;
> @@ -1311,6 +1408,7 @@ (define %formats
> (squashfs . ,squashfs-image)
> (docker . ,docker-image)
> (deb . ,debian-archive)
> + (appimage . ,self-contained-appimage)
> (rpm . ,rpm-archive)))
>
> (define (show-formats)
> @@ -1327,6 +1425,8 @@ (define (show-formats)
> deb Debian archive installable via dpkg/apt"))
> (display (G_ "
> rpm RPM archive installable via rpm/yum"))
> + (display (G_ "
> + appimage AppImage self-contained and executable format"))
> (newline))
>
> (define (required-option symbol)
> @@ -1694,6 +1794,8 @@ (define-command (guix-pack . args)
> (process-file-arg opts 'preun-file)
> #:postun-file
> (process-file-arg opts 'postun-file)))
> + ('appimage
> + (list #:relocatable? relocatable?))
> (_ '())))
> (target (assoc-ref opts 'target))
> (bootstrap? (assoc-ref opts 'bootstrap?))
> diff --git a/tests/pack.scm b/tests/pack.scm
> index f8a9e09c28..6ac9a966af 100644
> --- a/tests/pack.scm
> +++ b/tests/pack.scm
> @@ -3,6 +3,7 @@
> ;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
> ;;; Copyright © 2021, 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
> ;;; Copyright © 2023 Oleg Pykhalov <go.wigust@gmail.com>
> +;;; Copyright © 2024 Noé Lopez <noelopez@free.fr>
> ;;;
> ;;; This file is part of GNU Guix.
> ;;;
> @@ -32,7 +33,8 @@ (define-module (test-pack)
> #:use-module (guix utils)
> #:use-module ((guix build utils) #:select (%store-directory))
> #:use-module (gnu packages)
> - #:use-module ((gnu packages base) #:select (libc-utf8-locales-for-target))
> + #:use-module ((gnu packages base) #:select (libc-utf8-locales-for-target
> + hello))
> #:use-module (gnu packages bootstrap)
> #:use-module ((gnu packages package-management) #:select (rpm))
> #:use-module ((gnu packages compression) #:select (squashfs-tools))
> @@ -340,6 +342,43 @@ (define rpm-for-tests
> (mkdir #$output))))))))
> (built-derivations (list check))))
>
> + (unless store (test-skip 1))
> + (test-assertm "appimage"
> + (mlet* %store-monad
> + ((guile (set-guile-for-build (default-guile)))
> + (profile -> (profile
> + (content (packages->manifest (list %bootstrap-guile hello)))
> + (hooks '())
> + (locales? #f)))
> + (image (self-contained-appimage "hello-appimage" profile
> + #:entry-point "bin/hello"
> + #:extra-options
> + (list #:relocatable? #t)))
> + (check (gexp->derivation
> + "check-appimage"
> + #~(begin
> + (invoke #$image)))))
> + (built-derivations (list check))))
> +
> + (unless store (test-skip 1))
> + (test-assertm "appimage + localstatedir"
> + (mlet* %store-monad
> + ((guile (set-guile-for-build (default-guile)))
> + (profile -> (profile
> + (content (packages->manifest (list %bootstrap-guile hello)))
> + (hooks '())
> + (locales? #f)))
> + (image (self-contained-appimage "hello-appimage" profile
> + #:entry-point "bin/hello"
> + #:localstatedir? #t
> + #:extra-options
> + (list #:relocatable? #t)))
> + (check (gexp->derivation
> + "check-appimage"
> + #~(begin
> + (invoke #$image)))))
> + (built-derivations (list check))))
> +
> (unless store (test-skip 1))
> (test-assertm "deb archive with symlinks and control files"
> (mlet* %store-monad
The rest looks good to me, from a quick read. If you could send a v3,
I'll then give it a real try.
--
Thanks,
Maxim
^ permalink raw reply [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v2 1/3] gnu: appimage: New packages for the appimage runtime.
2024-10-26 17:28 ` [bug#73842] [PATCH v2 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez
@ 2024-11-01 13:24 ` Maxim Cournoyer
0 siblings, 0 replies; 24+ messages in thread
From: Maxim Cournoyer @ 2024-11-01 13:24 UTC (permalink / raw)
To: Noé Lopez; +Cc: Ludovic Courtès, 73842
Hi,
Noé Lopez <noelopez@free.fr> writes:
[...]
> +(define squashfuse-for-appimage
> + (package
> + (inherit squashfuse)
> + (arguments
> + (list
> + #:configure-flags #~'("CFLAGS=-ffunction-sections -fdata-sections -Os -no-pie"
> + "LDFLAGS=-static")
> + #:phases #~(modify-phases %standard-phases
> + (add-after 'install 'install-private-headers
> + (lambda _
> + (install-file "fuseprivate.h"
> + (string-append #$output
> + "/include/squashfuse/")))))))
> + (inputs (list fuse-for-appimage
> + `(,zstd "lib")
> + `(,zstd "static")
> + `(,zlib "out")
> + `(,zlib "static")))))
>
Some lines are a bit too long (our coding style says 80 columns max);
you could place the gexps starting with #~ on the line below to make
things a bit easier.
> +
> +(define-public appimage-type2-runtime
> + (let ((revision "0")
> + ;; No releases, just the latest commit.
> + (commit "47b665594856b4e8928f8932adcf6d13061d8c30"))
> + (package
> + (name "appimage-type2-runtime")
> + (version (git-version "continuous" revision commit))
> + (source
> + (origin
> + (method git-fetch)
> + (uri (git-reference
> + (url "https://github.com/AppImage/type2-runtime")
> + (commit commit)))
> + (file-name (git-file-name name version))
> + (sha256
> + (base32 "0954crhlbapxis96g1s0vfpf78ybr64zvjalak387ksxj560g44x"))))
> + (arguments
> + (list
> + #:make-flags #~(list "-Csrc/runtime" "runtime-fuse3"
> + (string-append "CFLAGS="
> + "-I"
> + #$fuse-2
> + "/include/fuse/"
> + " -DGIT_COMMIT='\""
> + "guix-"
> + #$version
> + "\"'"
> + " -D_FILE_OFFSET_BITS=64"
> + " -static"))
This feels cramped; start on a new line to give yourself a bit more
horizontal width.
> + #:modules
> + `((guix build gnu-build-system)
> + (guix build utils)
> + (ice-9 binary-ports))
> + #:phases #~(modify-phases %standard-phases
> + (delete 'configure)
> + (delete 'check) ; No tests.
> + (replace 'install
> + (lambda _
> + (install-file "src/runtime/runtime-fuse3"
> + (string-append #$output "/bin"))))
> + ;; must be after all elf reliant phases
> + (add-after 'make-dynamic-linker-cache 'set-magic-bytes
> + (lambda _
> + (let ((port (open (string-append #$output
> + "/bin/runtime-fuse3")
The indentation is off here. Try running it with 'guix style' or the
old Emacs-based indenter to see.
> + (logior O_WRONLY))))
> + (seek port 8 SEEK_SET)
> + (put-bytevector port #vu8(#x41 #x49 #x02))
> + (close-port port)))))
> + #:disallowed-references (list squashfuse-for-appimage
> + fuse-for-appimage zstd zlib)))
> + ;; only needed at build time
As mentioned earlier, please use complete sentences for standalone
comments.
> + (inputs (list squashfuse-for-appimage fuse-for-appimage
> + `(,zstd "static")
> + `(,zlib "static")))
> + (build-system gnu-build-system)
> + (home-page "https://github.com/AppImage/type2-runtime")
> + (synopsis "Runtime for executing AppImages")
> + (description "The runtime is the executable part of every AppImage, it mounts
> +the payload via FUSE and executes the entrypoint.")
> + (license license:expat))))
--
Thanks,
Maxim
^ permalink raw reply [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v2 3/3] news: Add entry for guix pack’s AppImage format
2024-10-26 17:28 ` [bug#73842] [PATCH v2 3/3] news: Add entry for guix pack’s AppImage format Noé Lopez
2024-10-27 13:38 ` pelzflorian (Florian Pelz)
@ 2024-11-01 13:27 ` Maxim Cournoyer
1 sibling, 0 replies; 24+ messages in thread
From: Maxim Cournoyer @ 2024-11-01 13:27 UTC (permalink / raw)
To: Noé Lopez
Cc: Julien Lepiller, 73842, Florian Pelz, Sebastian Dümcke
Hi,
Noé Lopez <noelopez@free.fr> writes:
> From: Sebastian Dümcke <code@sam-d.com>
>
> * etc/news.scm: Add entry.
>
> Change-Id: If37b3b578517c15c2868239998975f7718f7d689
> ---
> etc/news.scm | 38 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 38 insertions(+)
>
> diff --git a/etc/news.scm b/etc/news.scm
> index 4929fa2a9a..59fdd94dd8 100644
> --- a/etc/news.scm
> +++ b/etc/news.scm
> @@ -25,6 +25,7 @@
> ;; Copyright © 2024 Vivien Kraus <vivien@planete-kraus.eu>
> ;; Copyright © 2024 Guillaume Le Vaillant <glv@posteo.net>
> ;; Copyright © 2024 Zheng Junjie <873216071@qq.com>
> +;; Copyright © 2024 Sebastian Dümcke <code@sam-d.com>
> ;;
> ;; Copying and distribution of this file, with or without modification, are
> ;; permitted in any medium without royalty provided the copyright notice and
> @@ -32,6 +33,43 @@
>
> (channel-news
> (version 0)
> + (entry (commit "ea1fe6e106f2abc9fce5cf7e686227c0c1f9e9e1")
> + (title
> + (de "Neues Format @samp{AppImage} für den Befehl @command{guix pack}")
> + (en "New @samp{AppImage} format for the @command{guix pack} command")
> + (fr "Nouveau format @samp{AppImage} pour la commande @command{guix pack}"))
> + (body
> + (de "@command{guix pack} kann nun AppImage Dateien erstellen. Das
> +AppImage Dateiformat erlaubt es in einer einzelnen Datei Software zu verteilen. Die
> +AppImage Datei lässt sich ohne besondere Benutzerrechte ausführen. Hier ist
> +ein Beispiel:
> +
> +@example
> +guix pack --format=appimage --entry-point=bin/hello hello
> +@end example
> +
> +Siehe @command{info \"(guix.de) Aufruf von guix pack\"} für mehr
> +Informationen.")
> + (en "@command{guix pack} can now produce AppImage a single file,
> +self-contained software archive. AppImage files are easily distributed and can
> +be run with user privileges. Here is an example for the @code{hello} package:
> +
> +@example
> +guix pack --format=appimage --entry-point=bin/hello hello
> +@end example
> +
> +See @command{info \"(guix) Invoking guix pack\"} for more information.")
> + (fr "@command{guix pack} peut désormais produire un fichier
> +AppImage. AppImage est une manière de distribuer les logiciels en un seul
> +fichier, qui peut être executer avec des droits d’utilisateur. Voici un
s/executer/exécuté/
I believe double spacing should be used in this patch as well between
sentences.
--
Thanks,
Maxim
^ permalink raw reply [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v2 2/3] pack: Add support for AppImage pack format.
2024-11-01 13:19 ` Maxim Cournoyer
@ 2024-11-01 15:22 ` Noé Lopez via Guix-patches via
0 siblings, 0 replies; 24+ messages in thread
From: Noé Lopez via Guix-patches via @ 2024-11-01 15:22 UTC (permalink / raw)
To: Maxim Cournoyer
Cc: dev, 73842, zimon.toutoune, othacehe, noelopez, me, code, guix,
ludo
Maxim Cournoyer <maxim.cournoyer@gmail.com> writes:
> Instead of a warning, could we just make it always -RR by default and
> document that these are always relocatable, by design? The no
> relocatable flags would be treated as an implicit -RR, and otherwise a
> single -R would be treated as a single -R (and -RR as -RR, eh).
I think it would be confusing to have default options change between
pack formats, additionaly I’m not sure the -RR option has any effect
compared to -R as we already use a runtime that requires fuse.
The command will output a warning when the -R option is not used though:
« guix pack: warning: AppImages should be built with the --relocatable
flag »
> Are there plans to add support for .DirIcon in the future?
It was originally planned but with the added complexity it was kept for
a later version. Notably, you need a full XDG icon structure inside
your AppImage for the specification, that means multiple resolutions of
your image and other icon stuff I don’t know about. It’s worth retrying
though, as a single 256x256 png might work.
> The rest looks good to me, from a quick read. If you could send a v3,
> I'll then give it a real try.
I’ve applied the rest of your suggestions, sending the v3 just after
this.
Thanks for reviewing,
Noé
^ permalink raw reply [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v4 0/3] pack: Add support for AppImage pack format.
2024-10-16 21:51 [bug#73842] [PATCH] pack: Add support for AppImage pack format Noé Lopez
` (3 preceding siblings ...)
2024-10-26 17:28 ` [bug#73842] [PATCH v2 0/3] " Noé Lopez
@ 2024-11-03 22:37 ` Noé Lopez via Guix-patches via
2024-11-03 22:37 ` [bug#73842] [PATCH v4 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez via Guix-patches via
` (2 more replies)
2024-11-07 16:50 ` [bug#73842] [PATCH v5 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez via Guix-patches via
5 siblings, 3 replies; 24+ messages in thread
From: Noé Lopez via Guix-patches via @ 2024-11-03 22:37 UTC (permalink / raw)
To: 73842
Cc: Noé Lopez, Noé Lopez, Ludovic Courtès, pelzflorian,
Maxim Cournoyer, Noé Lopez, noe, Florian Pelz,
Julien Lepiller
From: Noé Lopez <noelopez@free.fr>
Hi,
I forgot to apply Sebastian’s patch for the german news entry following
Florian’s suggestions. Here is a new version.
Good evening,
Noé Lopez
Noé Lopez (1):
gnu: appimage: New packages for the appimage runtime.
Sebastian Dümcke (2):
pack: Add support for AppImage pack format.
news: Add entry for guix pack’s AppImage format
doc/guix.texi | 53 +++++++++++++++-
etc/news.scm | 38 ++++++++++++
gnu/packages/appimage.scm | 126 ++++++++++++++++++++++++++++++++++++++
guix/scripts/pack.scm | 104 ++++++++++++++++++++++++++++++-
tests/pack.scm | 41 ++++++++++++-
5 files changed, 359 insertions(+), 3 deletions(-)
create mode 100644 gnu/packages/appimage.scm
base-commit: 870b7d69b4b06d01cdf6bfca71bcc161c0b832bf
--
2.46.0
^ permalink raw reply [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v4 1/3] gnu: appimage: New packages for the appimage runtime.
2024-11-03 22:37 ` [bug#73842] [PATCH v4 0/3] pack: Add support for AppImage pack format Noé Lopez via Guix-patches via
@ 2024-11-03 22:37 ` Noé Lopez via Guix-patches via
2024-11-05 14:22 ` Ludovic Courtès
2024-11-03 22:37 ` [bug#73842] [PATCH v4 2/3] pack: Add support for AppImage pack format Noé Lopez via Guix-patches via
2024-11-03 22:37 ` [bug#73842] [PATCH v4 3/3] news: Add entry for guix pack’s AppImage format Noé Lopez via Guix-patches via
2 siblings, 1 reply; 24+ messages in thread
From: Noé Lopez via Guix-patches via @ 2024-11-03 22:37 UTC (permalink / raw)
To: 73842
Cc: Noé Lopez, Noé Lopez, Ludovic Courtès, pelzflorian,
Maxim Cournoyer, Noé Lopez, noe
From: Noé Lopez <noelopez@free.fr>
* gnu/packages/appimage.scm
(gnu packages appimage): New module.
(fuse-for-appimage, squashfuse-for-appimage)
(appimage-type2-runtime): New variables.
Change-Id: I857a8eb5399a6a493e52db70b6c8cf0c71360930
---
gnu/packages/appimage.scm | 126 ++++++++++++++++++++++++++++++++++++++
1 file changed, 126 insertions(+)
create mode 100644 gnu/packages/appimage.scm
diff --git a/gnu/packages/appimage.scm b/gnu/packages/appimage.scm
new file mode 100644
index 0000000000..df17be214e
--- /dev/null
+++ b/gnu/packages/appimage.scm
@@ -0,0 +1,126 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2024 Noé Lopez <noelopez@free.fr>
+;;;
+;;; 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/>.
+
+(define-module (gnu packages appimage)
+ #:use-module ((guix licenses) #:prefix license:)
+ #:use-module (gnu packages base)
+ #:use-module (gnu packages compression)
+ #:use-module (gnu packages file-systems)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages)
+ #:use-module (guix build-system gnu)
+ #:use-module (guix download)
+ #:use-module (guix gexp)
+ #:use-module (guix git-download)
+ #:use-module (guix packages)
+ #:use-module (guix utils))
+
+(define fuse-for-appimage
+ (package
+ (inherit fuse)
+ (name "fuse")
+ (version "3.16.2")
+ (source
+ (origin
+ (method url-fetch)
+ (uri (string-append "https://github.com/libfuse/libfuse/releases/"
+ "download/fuse-" version "/fuse-" version ".tar.gz"))
+ (sha256
+ (base32 "11yfl2w2a445hllyzlakq97n32g06972vxpmh7lpbclnj9fhb5zp"))))
+ (arguments
+ (substitute-keyword-arguments (package-arguments fuse)
+ ((#:configure-flags original-flags #~(list))
+ #~(append #$original-flags '("--default-library=static")))))))
+
+(define squashfuse-for-appimage
+ (package
+ (inherit squashfuse)
+ (arguments
+ (list
+ #:configure-flags
+ #~'("CFLAGS=-ffunction-sections -fdata-sections -Os -no-pie"
+ "LDFLAGS=-static")
+ #:phases
+ #~(modify-phases %standard-phases
+ (add-after 'install 'install-private-headers
+ (lambda _
+ (install-file "fuseprivate.h"
+ (string-append #$output
+ "/include/squashfuse/")))))))
+ (inputs (list fuse-for-appimage
+ `(,zstd "lib")
+ `(,zstd "static")
+ `(,zlib "out")
+ `(,zlib "static")))))
+
+(define-public appimage-type2-runtime
+ (let ((revision "0")
+ ;; No releases, just the latest commit.
+ (commit "47b665594856b4e8928f8932adcf6d13061d8c30"))
+ (package
+ (name "appimage-type2-runtime")
+ (version (git-version "continuous" revision commit))
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/AppImage/type2-runtime")
+ (commit commit)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32 "0954crhlbapxis96g1s0vfpf78ybr64zvjalak387ksxj560g44x"))))
+ (arguments
+ (list
+ #:make-flags
+ #~(list "-Csrc/runtime" "runtime-fuse3"
+ (string-append "CFLAGS=" "-I" #$fuse-2 "/include/fuse/"
+ " -DGIT_COMMIT='\"" "guix-" #$version "\"'"
+ " -D_FILE_OFFSET_BITS=64"
+ " -static"))
+ #:modules
+ `((guix build gnu-build-system)
+ (guix build utils)
+ (ice-9 binary-ports))
+ #:phases #~(modify-phases %standard-phases
+ (delete 'configure)
+ (delete 'check) ; No tests.
+ (replace 'install
+ (lambda _
+ (install-file "src/runtime/runtime-fuse3"
+ (string-append #$output "/bin"))))
+ ;; Must be after all elf reliant phases.
+ (add-after 'make-dynamic-linker-cache 'set-magic-bytes
+ (lambda _
+ (let ((port (open (string-append #$output
+ "/bin/runtime-fuse3")
+ (logior O_WRONLY))))
+ (seek port 8 SEEK_SET)
+ (put-bytevector port #vu8(#x41 #x49 #x02))
+ (close-port port)))))
+ #:disallowed-references (list squashfuse-for-appimage
+ fuse-for-appimage zstd zlib)))
+ ;; Only needed at build time.
+ (inputs (list squashfuse-for-appimage fuse-for-appimage
+ `(,zstd "static")
+ `(,zlib "static")))
+ (build-system gnu-build-system)
+ (home-page "https://github.com/AppImage/type2-runtime")
+ (synopsis "Runtime for executing AppImages")
+ (description "The runtime is the executable part of every AppImage, it
+mounts the payload via FUSE and executes the entrypoint.")
+ (license license:expat))))
--
2.46.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v4 2/3] pack: Add support for AppImage pack format.
2024-11-03 22:37 ` [bug#73842] [PATCH v4 0/3] pack: Add support for AppImage pack format Noé Lopez via Guix-patches via
2024-11-03 22:37 ` [bug#73842] [PATCH v4 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez via Guix-patches via
@ 2024-11-03 22:37 ` Noé Lopez via Guix-patches via
2024-11-05 14:27 ` Ludovic Courtès
2024-11-03 22:37 ` [bug#73842] [PATCH v4 3/3] news: Add entry for guix pack’s AppImage format Noé Lopez via Guix-patches via
2 siblings, 1 reply; 24+ messages in thread
From: Noé Lopez via Guix-patches via @ 2024-11-03 22:37 UTC (permalink / raw)
To: 73842
Cc: Noé Lopez, Sebastian Dümcke, Noé Lopez,
Ludovic Courtès, pelzflorian, Maxim Cournoyer,
Noé Lopez, noe, Christopher Baines, Josselin Poiret,
Mathieu Othacehe, Simon Tournier, Tobias Geerinckx-Rice
From: Sebastian Dümcke <code@sam-d.com>
* guix/scripts/pack.scm: Add Appimage format.
* doc/guix.texi: Document AppImage pack.
Co-authored-by: Noé Lopez <noelopez@free.fr>
Change-Id: I33ebfec623cff1cfcd6f029d2d3054c23ab1949a
---
doc/guix.texi | 53 ++++++++++++++++++++-
guix/scripts/pack.scm | 104 +++++++++++++++++++++++++++++++++++++++++-
tests/pack.scm | 41 ++++++++++++++++-
3 files changed, 195 insertions(+), 3 deletions(-)
diff --git a/doc/guix.texi b/doc/guix.texi
index 187bae6898..46108dc3f1 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -6949,6 +6949,16 @@ Invoking guix pack
environment}, using commands like @command{singularity shell} or
@command{singularity exec}.
+@cindex AppImage, create an AppImage file with @command{guix pack}
+Another format internally based on SquashFS is
+@uref{https://appimage.org/, AppImage}. An AppImage file can be created
+and executed without any special privileges:
+
+@example
+file=$(guix pack -f appimage --entry-point=bin/guile guile)
+$file --help
+@end example
+
Several command-line options allow you to customize your pack:
@table @code
@@ -7065,6 +7075,47 @@ Invoking guix pack
installation or other, non-rpm packs.
@end quotation
+@item appimage
+@cindex AppImage, create an AppImage file with @command{guix pack}
+This produces an AppImage file with the @samp{.AppImage} extension.
+AppImage is a SquashFS volume prefixed with a runtime that mounts the
+SquashFS file system and executes the binary provided with
+@option{--entry-point}. This results in a self-contained archive that
+bundles the software and all its requirements into a single file. When
+the file is made executable it runs the packaged software.
+
+@example
+guix pack -f appimage --entry-point=bin/vlc vlc
+@end example
+
+The runtime used by AppImages makes use of libfuse to mount the image
+quickly. If libfuse is not available, the AppImage can still be started
+using the @option{--appimage-extract-and-run} flag.
+
+@quotation Warning
+ When building an AppImage, always @emph{pass} the
+@option{--relocatable} option (or @option{-R}, or @option{-RR}) to make
+sure the image can be used on systems where Guix is not installed. A
+warning is printed when this option is not used.
+@end quotation
+
+@example
+guix pack -f appimage --entry-point=bin/hello --relocatable hello
+@end example
+
+@quotation Note
+The resulting AppImage does not conform to the complete standard as it
+currently does not contain a @file{.DirIcon} file. This does not impact
+functionality of the AppImage itself, but possibly that of software used
+to manage AppImages.
+@end quotation
+
+@quotation Note
+As the generated AppImage packages the complete dependency graph, it
+will be larger than comparable AppImage files found online, which depend
+on host system libraries.
+@end quotation
+
@end table
@cindex relocatable binaries
@@ -7155,7 +7206,7 @@ Invoking guix pack
@cindex entry point, for Docker and Singularity images
@item --entry-point=@var{command}
Use @var{command} as the @dfn{entry point} of the resulting pack, if the pack
-format supports it---currently @code{docker} and @code{squashfs} (Singularity)
+format supports it---currently @code{docker}, @code{appimage} and @code{squashfs} (Singularity)
support it. @var{command} must be relative to the profile contained in the
pack.
diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm
index 7c5fe76fe0..26ba80b80d 100644
--- a/guix/scripts/pack.scm
+++ b/guix/scripts/pack.scm
@@ -10,6 +10,8 @@
;;; Copyright © 2022 Alex Griffin <a@ajgrf.com>
;;; Copyright © 2023 Graham James Addis <graham@addis.org.uk>
;;; Copyright © 2023 Oleg Pykhalov <go.wigust@gmail.com>
+;;; Copyright © 2024 Sebastian Dümcke <code@sam-d.com>
+;;; Copyright © 2024 Noé Lopez <noelopez@free.fr>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -56,6 +58,7 @@ (define-module (guix scripts pack)
#:use-module ((gnu packages compression) #:hide (zip))
#:use-module (gnu packages guile)
#:use-module (gnu packages base)
+ #:autoload (gnu packages appimage) (appimage-type2-runtime)
#:autoload (gnu packages gnupg) (guile-gcrypt)
#:autoload (gnu packages guile) (guile2.0-json guile-json)
#:use-module (srfi srfi-1)
@@ -64,6 +67,7 @@ (define-module (guix scripts pack)
#:use-module (srfi srfi-35)
#:use-module (srfi srfi-37)
#:use-module (ice-9 match)
+ #:use-module (ice-9 optargs)
#:export (symlink-spec-option-parser
self-contained-tarball
@@ -71,6 +75,7 @@ (define-module (guix scripts pack)
rpm-archive
docker-image
squashfs-image
+ self-contained-appimage
%formats
guix-pack))
@@ -974,8 +979,100 @@ (define* (rpm-archive name profile
(gexp->derivation (string-append name ".rpm") build
#:target target
#:references-graphs `(("profile" ,profile))))
+\f
+;;;
+;;; AppImage format
+;;;
+(define* (self-contained-appimage name profile
+ #:key target
+ (profile-name "guix-profile")
+ entry-point
+ (compressor (lookup-compressor "zstd"))
+ localstatedir?
+ (symlinks '())
+ (archiver tar)
+ (extra-options '()))
+ "Return a self-contained AppImage containing a store initialized with the
+closure of PROFILE, a derivation. The AppImage contains /gnu/store unless
+RELOCATABLE option is used; if LOCALSTATEDIR? is true, it also contains
+/var/guix, including /var/guix/db with a properly initialized store database.
+
+SYMLINKS must be a list of (SOURCE -> TARGET) tuples denoting symlinks to be
+added to the pack."
+ (unless entry-point
+ (leave (G_ "entry-point must be provided in the '~a' format~%")
+ 'appimage))
+ (let-keywords extra-options #f ((relocatable? #f))
+ (unless relocatable?
+ (warning (G_ "AppImages should be built with the --relocatable flag~%"))))
+
+ (define runtime-package appimage-type2-runtime)
+ (define runtime-path "bin/runtime-fuse3")
+ (define %valid-compressors '("gzip" "zstd"))
+
+ (let ((compressor-name (compressor-name compressor)))
+ (unless (member compressor-name %valid-compressors)
+ (leave (G_ "~a is not a valid squashfs archive compressor used in
+generating the AppImage. Valid compressors are: ~a~%")
+ compressor-name
+ %valid-compressors)))
- \f
+ (define builder
+ (with-extensions (list guile-gcrypt)
+ (with-imported-modules (source-module-closure
+ '((guix build store-copy)
+ (guix build utils))
+ #:select? not-config?)
+ #~(begin
+ (use-modules (guix build utils)
+ (guix build store-copy)
+ (rnrs io ports)
+ (srfi srfi-1)
+ (srfi srfi-26))
+
+ (define (concatenate-files result file1 file2)
+ "Creates a new file RESULT containing FILE1 followed by FILE2."
+ (call-with-output-file result
+ (lambda (output)
+ (call-with-input-file file1
+ (lambda (input)
+ (dump-port input output)))
+ (call-with-input-file file2
+ (lambda (input)
+ (dump-port input output))))))
+
+ (let* ((appdir "AppDir")
+ (squashfs "squashfs")
+ (profile-items (map store-info-item
+ (call-with-input-file "profile" read-reference-graph)))
+ (profile (find (lambda (item)
+ (string-suffix? "-profile" item))
+ profile-items)))
+ (mkdir-p appdir)
+ ;; Copy all store items from the profile to the AppDir.
+ (populate-store '("profile") appdir)
+ ;; Symlink the provided entry-point to AppDir/AppRun.
+ (symlink (string-append "." profile "/" #$entry-point)
+ (string-append appdir "/AppRun"))
+ ;; Create .desktop file as required by the spec.
+ (make-desktop-entry-file
+ (string-append appdir "/" #$name ".desktop")
+ #:name #$name
+ #:exec #$entry-point)
+ ;; Compress the AppDir.
+ (invoke #+(file-append squashfs-tools "/bin/mksquashfs") appdir
+ squashfs "-root-owned" "-noappend"
+ "-comp" #+(compressor-name compressor))
+ ;; Append runtime and squashFS into file AppImage.
+ (concatenate-files #$output
+ #$(file-append runtime-package "/" runtime-path)
+ squashfs)
+ ;; Add execution permission.
+ (chmod #$output #o555))))))
+ (gexp->derivation (string-append name ".AppImage") builder
+ #:target target
+ #:references-graphs `(("profile" ,profile))))
+\f
;;;
;;; Compiling C programs.
;;;
@@ -1311,6 +1408,7 @@ (define %formats
(squashfs . ,squashfs-image)
(docker . ,docker-image)
(deb . ,debian-archive)
+ (appimage . ,self-contained-appimage)
(rpm . ,rpm-archive)))
(define (show-formats)
@@ -1327,6 +1425,8 @@ (define (show-formats)
deb Debian archive installable via dpkg/apt"))
(display (G_ "
rpm RPM archive installable via rpm/yum"))
+ (display (G_ "
+ appimage AppImage self-contained and executable format"))
(newline))
(define (required-option symbol)
@@ -1694,6 +1794,8 @@ (define-command (guix-pack . args)
(process-file-arg opts 'preun-file)
#:postun-file
(process-file-arg opts 'postun-file)))
+ ('appimage
+ (list #:relocatable? relocatable?))
(_ '())))
(target (assoc-ref opts 'target))
(bootstrap? (assoc-ref opts 'bootstrap?))
diff --git a/tests/pack.scm b/tests/pack.scm
index f8a9e09c28..6ac9a966af 100644
--- a/tests/pack.scm
+++ b/tests/pack.scm
@@ -3,6 +3,7 @@
;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2021, 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2023 Oleg Pykhalov <go.wigust@gmail.com>
+;;; Copyright © 2024 Noé Lopez <noelopez@free.fr>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -32,7 +33,8 @@ (define-module (test-pack)
#:use-module (guix utils)
#:use-module ((guix build utils) #:select (%store-directory))
#:use-module (gnu packages)
- #:use-module ((gnu packages base) #:select (libc-utf8-locales-for-target))
+ #:use-module ((gnu packages base) #:select (libc-utf8-locales-for-target
+ hello))
#:use-module (gnu packages bootstrap)
#:use-module ((gnu packages package-management) #:select (rpm))
#:use-module ((gnu packages compression) #:select (squashfs-tools))
@@ -340,6 +342,43 @@ (define rpm-for-tests
(mkdir #$output))))))))
(built-derivations (list check))))
+ (unless store (test-skip 1))
+ (test-assertm "appimage"
+ (mlet* %store-monad
+ ((guile (set-guile-for-build (default-guile)))
+ (profile -> (profile
+ (content (packages->manifest (list %bootstrap-guile hello)))
+ (hooks '())
+ (locales? #f)))
+ (image (self-contained-appimage "hello-appimage" profile
+ #:entry-point "bin/hello"
+ #:extra-options
+ (list #:relocatable? #t)))
+ (check (gexp->derivation
+ "check-appimage"
+ #~(begin
+ (invoke #$image)))))
+ (built-derivations (list check))))
+
+ (unless store (test-skip 1))
+ (test-assertm "appimage + localstatedir"
+ (mlet* %store-monad
+ ((guile (set-guile-for-build (default-guile)))
+ (profile -> (profile
+ (content (packages->manifest (list %bootstrap-guile hello)))
+ (hooks '())
+ (locales? #f)))
+ (image (self-contained-appimage "hello-appimage" profile
+ #:entry-point "bin/hello"
+ #:localstatedir? #t
+ #:extra-options
+ (list #:relocatable? #t)))
+ (check (gexp->derivation
+ "check-appimage"
+ #~(begin
+ (invoke #$image)))))
+ (built-derivations (list check))))
+
(unless store (test-skip 1))
(test-assertm "deb archive with symlinks and control files"
(mlet* %store-monad
--
2.46.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v4 3/3] news: Add entry for guix pack’s AppImage format
2024-11-03 22:37 ` [bug#73842] [PATCH v4 0/3] pack: Add support for AppImage pack format Noé Lopez via Guix-patches via
2024-11-03 22:37 ` [bug#73842] [PATCH v4 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez via Guix-patches via
2024-11-03 22:37 ` [bug#73842] [PATCH v4 2/3] pack: Add support for AppImage pack format Noé Lopez via Guix-patches via
@ 2024-11-03 22:37 ` Noé Lopez via Guix-patches via
2024-11-05 14:28 ` Ludovic Courtès
2 siblings, 1 reply; 24+ messages in thread
From: Noé Lopez via Guix-patches via @ 2024-11-03 22:37 UTC (permalink / raw)
To: 73842
Cc: Sebastian Dümcke, Noé Lopez, Ludovic Courtès,
pelzflorian, Maxim Cournoyer, Noé Lopez, noe, Florian Pelz,
Julien Lepiller
From: Sebastian Dümcke <code@sam-d.com>
* etc/news.scm: Add entry.
Change-Id: If37b3b578517c15c2868239998975f7718f7d689
---
etc/news.scm | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/etc/news.scm b/etc/news.scm
index 4929fa2a9a..30d907f2ed 100644
--- a/etc/news.scm
+++ b/etc/news.scm
@@ -25,6 +25,7 @@
;; Copyright © 2024 Vivien Kraus <vivien@planete-kraus.eu>
;; Copyright © 2024 Guillaume Le Vaillant <glv@posteo.net>
;; Copyright © 2024 Zheng Junjie <873216071@qq.com>
+;; Copyright © 2024 Sebastian Dümcke <code@sam-d.com>
;;
;; Copying and distribution of this file, with or without modification, are
;; permitted in any medium without royalty provided the copyright notice and
@@ -32,6 +33,43 @@
(channel-news
(version 0)
+ (entry (commit "e6534c6ba947d3edbdcb090ae4a410cd9b5ef1c1")
+ (title
+ (de "Neues Format @samp{appimage} für den Befehl @command{guix pack}")
+ (en "New @samp{AppImage} format for the @command{guix pack} command")
+ (fr "Nouveau format @samp{AppImage} pour la commande @command{guix pack}"))
+ (body
+ (de "@command{guix pack} kann nun AppImage-Dateien erstellen. Das
+AppImage-Dateiformat erlaubt es, in einer einzelnen Datei Software zu verteilen. Die
+AppImage-Datei lässt sich ohne besondere Benutzerrechte ausführen. Hier ist
+ein Beispiel:
+
+@example
+guix pack --format=appimage --entry-point=bin/hello hello
+@end example
+
+Siehe @command{info \"(guix.de) Aufruf von guix pack\"} für mehr
+Informationen.")
+ (en "@command{guix pack} can now produce AppImage a single file,
+self-contained software archive. AppImage files are easily distributed and can
+be run with user privileges. Here is an example for the @code{hello} package:
+
+@example
+guix pack --format=appimage --entry-point=bin/hello hello
+@end example
+
+See @command{info \"(guix) Invoking guix pack\"} for more information.")
+ (fr "@command{guix pack} peut désormais produire un fichier
+AppImage. AppImage est une manière de distribuer les logiciels en un seul
+fichier, qui peut être executé avec des droits d’utilisateur. Voici un
+exemple pour le paquet @code{hello} :
+
+@example
+guix pack --format=appimage --entry-point=bin/hello hello
+@end example
+
+Consultez @command{info \"(guix.fr) Invoquer guix pack\"} pour plus
+d’informations.")))
(entry (commit "5966e0fdc78771c562e0f484a22f381a77908be0")
(title
--
2.46.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v4 1/3] gnu: appimage: New packages for the appimage runtime.
2024-11-03 22:37 ` [bug#73842] [PATCH v4 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez via Guix-patches via
@ 2024-11-05 14:22 ` Ludovic Courtès
0 siblings, 0 replies; 24+ messages in thread
From: Ludovic Courtès @ 2024-11-05 14:22 UTC (permalink / raw)
To: Noé Lopez; +Cc: Noé Lopez, 73842, pelzflorian, Maxim Cournoyer
Hi!
Noé Lopez <noe@noé.eu> skribis:
> From: Noé Lopez <noelopez@free.fr>
>
> * gnu/packages/appimage.scm
> (gnu packages appimage): New module.
> (fuse-for-appimage, squashfuse-for-appimage)
> (appimage-type2-runtime): New variables.
>
> Change-Id: I857a8eb5399a6a493e52db70b6c8cf0c71360930
> ---
> gnu/packages/appimage.scm | 126 ++++++++++++++++++++++++++++++++++++++
Please add this file to ‘gnu/local.mk’.
> +(define fuse-for-appimage
> + (package
> + (inherit fuse)
Due to restrictions having to do with circular module dependencies, this
package must be defined in the same file as ‘fuse’ itself (apologies for
overlooking it!). You could add the ‘hidden?’ property if needed, but
IMO it perhaps not even necessary to hide it.
> +(define squashfuse-for-appimage
> + (package
> + (inherit squashfuse)
Likewise, this should be in the same file as ‘squashfuse’.
> + (arguments
> + (list
> + #:make-flags
> + #~(list "-Csrc/runtime" "runtime-fuse3"
> + (string-append "CFLAGS=" "-I" #$fuse-2 "/include/fuse/"
Rather: #$(this-package-input "fuse").
> + " -DGIT_COMMIT='\"" "guix-" #$version "\"'"
> + " -D_FILE_OFFSET_BITS=64"
> + " -static"))
You may need to add “-O2 -g” here, or the code might be compiled as with
“-O0 -g0”.
> + ;; Must be after all elf reliant phases.
> + (add-after 'make-dynamic-linker-cache 'set-magic-bytes
> + (lambda _
> + (let ((port (open (string-append #$output
> + "/bin/runtime-fuse3")
> + (logior O_WRONLY))))
> + (seek port 8 SEEK_SET)
> + (put-bytevector port #vu8(#x41 #x49 #x02))
> + (close-port port)))))
What’s the story with magic bytes here? :-)
Could you add a comment explaining what the phase does and why it’s
necessary?
> + #:disallowed-references (list squashfuse-for-appimage
> + fuse-for-appimage zstd zlib)))
> + ;; Only needed at build time.
> + (inputs (list squashfuse-for-appimage fuse-for-appimage
> + `(,zstd "static")
> + `(,zlib "static")))
It should probably be ‘native-inputs’, then.
Also, in #:disallowed-references, I think you need:
`(,zstd "static") `(,zlib "static")
> + (synopsis "Runtime for executing AppImages")
> + (description "The runtime is the executable part of every AppImage, it
> +mounts the payload via FUSE and executes the entrypoint.")
Please make that a full sentence, as per
<https://guix.gnu.org/manual/devel/en/html_node/Synopses-and-Descriptions.html>.
^ permalink raw reply [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v4 2/3] pack: Add support for AppImage pack format.
2024-11-03 22:37 ` [bug#73842] [PATCH v4 2/3] pack: Add support for AppImage pack format Noé Lopez via Guix-patches via
@ 2024-11-05 14:27 ` Ludovic Courtès
0 siblings, 0 replies; 24+ messages in thread
From: Ludovic Courtès @ 2024-11-05 14:27 UTC (permalink / raw)
To: Noé Lopez
Cc: Josselin Poiret, 73842, Maxim Cournoyer, Simon Tournier,
Mathieu Othacehe, Noé Lopez, Tobias Geerinckx-Rice,
pelzflorian, Sebastian Dümcke, Christopher Baines
Noé Lopez <noe@noé.eu> skribis:
> From: Sebastian Dümcke <code@sam-d.com>
>
> * guix/scripts/pack.scm: Add Appimage format.
> * doc/guix.texi: Document AppImage pack.
>
> Co-authored-by: Noé Lopez <noelopez@free.fr>
> Change-Id: I33ebfec623cff1cfcd6f029d2d3054c23ab1949a
Please mention ‘tests/pack.scm’ in the log.
> +@cindex AppImage, create an AppImage file with @command{guix pack}
> +This produces an AppImage file with the @samp{.AppImage} extension.
s/AppImage file/@uref{https://appimage.org/, AppImage file}/
> -format supports it---currently @code{docker} and @code{squashfs} (Singularity)
> +format supports it---currently @code{docker}, @code{appimage} and @code{squashfs} (Singularity)
Nitpick: s/ and/, and/
> + (check (gexp->derivation
> + "check-appimage"
> + #~(begin
> + (invoke #$image)))))
#~(invoke #$image)
^ permalink raw reply [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v4 3/3] news: Add entry for guix pack’s AppImage format
2024-11-03 22:37 ` [bug#73842] [PATCH v4 3/3] news: Add entry for guix pack’s AppImage format Noé Lopez via Guix-patches via
@ 2024-11-05 14:28 ` Ludovic Courtès
0 siblings, 0 replies; 24+ messages in thread
From: Ludovic Courtès @ 2024-11-05 14:28 UTC (permalink / raw)
To: Noé Lopez
Cc: Julien Lepiller, 73842, Maxim Cournoyer, Noé Lopez,
pelzflorian, Sebastian Dümcke
Noé Lopez <noe@noé.eu> skribis:
> From: Sebastian Dümcke <code@sam-d.com>
>
> * etc/news.scm: Add entry.
>
> Change-Id: If37b3b578517c15c2868239998975f7718f7d689
Perfect!
As you can see, these comments are mostly nitpicking, so hopefully v5
will be the final one.
Great job, thank you!
Ludo’.
^ permalink raw reply [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v5 1/3] gnu: appimage: New packages for the appimage runtime.
2024-10-16 21:51 [bug#73842] [PATCH] pack: Add support for AppImage pack format Noé Lopez
` (4 preceding siblings ...)
2024-11-03 22:37 ` [bug#73842] [PATCH v4 0/3] pack: Add support for AppImage pack format Noé Lopez via Guix-patches via
@ 2024-11-07 16:50 ` Noé Lopez via Guix-patches via
2024-11-07 16:50 ` [bug#73842] [PATCH v5 2/3] pack: Add support for AppImage pack format Noé Lopez via Guix-patches via
2024-11-07 16:50 ` [bug#73842] [PATCH v5 3/3] news: Add entry for guix pack’s AppImage format Noé Lopez via Guix-patches via
5 siblings, 2 replies; 24+ messages in thread
From: Noé Lopez via Guix-patches via @ 2024-11-07 16:50 UTC (permalink / raw)
To: 73842
Cc: Noé Lopez, Noé Lopez, Ludovic Courtès, pelzflorian,
Maxim Cournoyer, Noé Lopez, noe, Leo Famulari, Wilko Meyer
From: Noé Lopez <noelopez@free.fr>
* gnu/packages/appimage.scm
(gnu packages appimage): New module.
(appimage-type2-runtime): New variable.
* gnu/packages/file-systems.scm (squashfuse-for-appimage):
New variable.
* gnu/packages/linux.scm (fuse-for-appimage): New variable.
Change-Id: I857a8eb5399a6a493e52db70b6c8cf0c71360930
---
gnu/local.mk | 2 +
gnu/packages/appimage.scm | 97 +++++++++++++++++++++++++++++++++++
gnu/packages/file-systems.scm | 21 ++++++++
gnu/packages/linux.scm | 17 ++++++
4 files changed, 137 insertions(+)
create mode 100644 gnu/packages/appimage.scm
diff --git a/gnu/local.mk b/gnu/local.mk
index 945d89d550..0deab9065f 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -67,6 +67,7 @@
# Copyright © 2024 David Elsing <david.elsing@posteo.net>
# Copyright © 2024 Ashish SHUKLA <ashish.is@lostca.se>
# Copyright © 2024 Fabio Natali <me@fabionatali.com>
+# Copyright © 2024 Noé Lopez <noelopez@free.fr>
#
# This file is part of GNU Guix.
#
@@ -139,6 +140,7 @@ GNU_SYSTEM_MODULES = \
%D%/packages/apl.scm \
%D%/packages/apple.scm \
%D%/packages/apparmor.scm \
+ %D%/packages/appimage.scm \
%D%/packages/apr.scm \
%D%/packages/arcan.scm \
%D%/packages/aspell.scm \
diff --git a/gnu/packages/appimage.scm b/gnu/packages/appimage.scm
new file mode 100644
index 0000000000..1d0caada46
--- /dev/null
+++ b/gnu/packages/appimage.scm
@@ -0,0 +1,97 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2024 Noé Lopez <noelopez@free.fr>
+;;;
+;;; 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/>.
+
+(define-module (gnu packages appimage)
+ #:use-module ((guix licenses) #:prefix license:)
+ #:use-module (gnu packages base)
+ #:use-module (gnu packages compression)
+ #:use-module (gnu packages file-systems)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages)
+ #:use-module (guix build-system gnu)
+ #:use-module (guix gexp)
+ #:use-module (guix git-download)
+ #:use-module (guix packages)
+ #:use-module (guix utils))
+
+(define-public appimage-type2-runtime
+ (let ((revision "0")
+ ;; No releases, just the latest commit.
+ (commit "47b665594856b4e8928f8932adcf6d13061d8c30"))
+ (package
+ (name "appimage-type2-runtime")
+ (version (git-version "continuous" revision commit))
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/AppImage/type2-runtime")
+ (commit commit)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32 "0954crhlbapxis96g1s0vfpf78ybr64zvjalak387ksxj560g44x"))))
+ (arguments
+ (list
+ #:make-flags
+ #~(list "-Csrc/runtime" "runtime-fuse3"
+ (string-append
+ "CFLAGS=" "-I" #$(this-package-input "fuse") "/include/fuse/"
+ " -DGIT_COMMIT='\"" "guix-" #$version "\"'"
+ " -D_FILE_OFFSET_BITS=64"
+ " -static"))
+ #:modules
+ `((guix build gnu-build-system)
+ (guix build utils)
+ (ice-9 binary-ports))
+ #:phases #~(modify-phases %standard-phases
+ (delete 'configure)
+ (delete 'check) ; No tests.
+ (replace 'install
+ (lambda _
+ (install-file "src/runtime/runtime-fuse3"
+ (string-append #$output "/bin"))))
+ ;; Must be after all elf reliant phases. Used to identify the
+ ;; executable as an AppImage as per the specification.
+ (add-after 'make-dynamic-linker-cache 'set-magic-bytes
+ (lambda _
+ (let ((port (open (string-append #$output
+ "/bin/runtime-fuse3")
+ (logior O_WRONLY))))
+ (seek port 8 SEEK_SET)
+ (put-bytevector port #vu8(#x41 #x49 #x02))
+ (close-port port)))))
+ #:disallowed-references (list squashfuse-for-appimage
+ fuse-for-appimage
+ (gexp-input zstd "static")
+ (gexp-input zlib "static"))))
+ ;; Only needed at build time.
+ (inputs (list squashfuse-for-appimage
+ fuse-for-appimage
+ `(,zstd "static")
+ `(,zlib "static")))
+ (build-system gnu-build-system)
+ (home-page "https://github.com/AppImage/type2-runtime")
+ (synopsis "Runtime for executing AppImages")
+ (description "The runtime is the executable part of every AppImage. It mounts
+the payload via @acronym{FUSE} and executes the entrypoint, allowing users to run
+applications in a portable manner without the need for installation. This runtime
+ensures that the AppImage can access its bundled libraries and resources seamlessly,
+providing a consistent environment across different Linux distributions. In the
+absence of @acronym{FUSE}, the AppImage can still be started using the
+@option{--appimage-extract-and-run} flag.")
+ (license license:expat))))
diff --git a/gnu/packages/file-systems.scm b/gnu/packages/file-systems.scm
index 059bdf67a9..e36751e774 100644
--- a/gnu/packages/file-systems.scm
+++ b/gnu/packages/file-systems.scm
@@ -2059,6 +2059,27 @@ (define-public squashfuse
memory-efficient.")
(license license:bsd-2)))
+(define-public squashfuse-for-appimage
+ (package
+ (inherit squashfuse)
+ (arguments
+ (list
+ #:configure-flags
+ #~'("CFLAGS=-ffunction-sections -fdata-sections -Os -no-pie"
+ "LDFLAGS=-static")
+ #:phases
+ #~(modify-phases %standard-phases
+ (add-after 'install 'install-private-headers
+ (lambda _
+ (install-file "fuseprivate.h"
+ (string-append #$output
+ "/include/squashfuse/")))))))
+ (inputs (list fuse-for-appimage
+ `(,zstd "lib")
+ `(,zstd "static")
+ `(,zlib "out")
+ `(,zlib "static")))))
+
(define-public tmsu
(package
(name "tmsu")
diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 992790188a..58403c5b17 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -4100,6 +4100,23 @@ (define-public fuse-2
(("-DFUSERMOUNT_DIR=[[:graph:]]+")
"-DFUSERMOUNT_DIR=\\\"/var/empty\\\"")))))))))
+(define-public fuse-for-appimage
+ (package
+ (inherit fuse)
+ (name "fuse")
+ (version "3.16.2")
+ (source
+ (origin
+ (method url-fetch)
+ (uri (string-append "https://github.com/libfuse/libfuse/releases/"
+ "download/fuse-" version "/fuse-" version ".tar.gz"))
+ (sha256
+ (base32 "11yfl2w2a445hllyzlakq97n32g06972vxpmh7lpbclnj9fhb5zp"))))
+ (arguments
+ (substitute-keyword-arguments (package-arguments fuse)
+ ((#:configure-flags original-flags #~(list))
+ #~(append #$original-flags '("--default-library=static")))))))
+
(define-public unionfs-fuse
(package
(name "unionfs-fuse")
base-commit: ba9466481d10992d35f09d010166d616fdb6a637
--
2.46.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v5 2/3] pack: Add support for AppImage pack format.
2024-11-07 16:50 ` [bug#73842] [PATCH v5 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez via Guix-patches via
@ 2024-11-07 16:50 ` Noé Lopez via Guix-patches via
2024-11-15 17:02 ` Ludovic Courtès
2024-11-07 16:50 ` [bug#73842] [PATCH v5 3/3] news: Add entry for guix pack’s AppImage format Noé Lopez via Guix-patches via
1 sibling, 1 reply; 24+ messages in thread
From: Noé Lopez via Guix-patches via @ 2024-11-07 16:50 UTC (permalink / raw)
To: 73842
Cc: Noé Lopez, Sebastian Dümcke, Noé Lopez,
Ludovic Courtès, pelzflorian, Maxim Cournoyer,
Noé Lopez, noe, Christopher Baines, Josselin Poiret,
Mathieu Othacehe, Simon Tournier, Tobias Geerinckx-Rice
From: Sebastian Dümcke <code@sam-d.com>
* guix/scripts/pack.scm: Add Appimage format.
* doc/guix.texi: Document AppImage pack.
* tests/pack.scm: New AppImage tests.
Co-authored-by: Noé Lopez <noelopez@free.fr>
Change-Id: I33ebfec623cff1cfcd6f029d2d3054c23ab1949a
---
doc/guix.texi | 59 ++++++++++++++++++++++--
guix/scripts/pack.scm | 104 +++++++++++++++++++++++++++++++++++++++++-
tests/pack.scm | 40 +++++++++++++++-
3 files changed, 197 insertions(+), 6 deletions(-)
diff --git a/doc/guix.texi b/doc/guix.texi
index 151fcd89ac..a1435ceece 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -6949,6 +6949,16 @@ Invoking guix pack
environment}, using commands like @command{singularity shell} or
@command{singularity exec}.
+@cindex AppImage, create an AppImage file with @command{guix pack}
+Another format internally based on SquashFS is
+@uref{https://appimage.org/, AppImage}. An AppImage file can be created
+and executed without any special privileges:
+
+@example
+file=$(guix pack -f appimage --entry-point=bin/guile guile)
+$file --help
+@end example
+
Several command-line options allow you to customize your pack:
@table @code
@@ -7065,6 +7075,47 @@ Invoking guix pack
installation or other, non-rpm packs.
@end quotation
+@item appimage
+@cindex AppImage, create an AppImage file with @command{guix pack}
+This produces an @uref{https://appimage.org/, AppImage file} with the
+@samp{.AppImage} extension. AppImage is a SquashFS volume prefixed with
+a runtime that mounts the SquashFS file system and executes the binary
+provided with @option{--entry-point}. This results in a self-contained
+archive that bundles the software and all its requirements into a single
+file. When the file is made executable it runs the packaged software.
+
+@example
+guix pack -f appimage --entry-point=bin/vlc vlc
+@end example
+
+The runtime used by AppImages makes use of libfuse to mount the image
+quickly. If libfuse is not available, the AppImage can still be started
+using the @option{--appimage-extract-and-run} flag.
+
+@quotation Warning
+ When building an AppImage, always @emph{pass} the
+@option{--relocatable} option (or @option{-R}, or @option{-RR}) to make
+sure the image can be used on systems where Guix is not installed. A
+warning is printed when this option is not used.
+@end quotation
+
+@example
+guix pack -f appimage --entry-point=bin/hello --relocatable hello
+@end example
+
+@quotation Note
+The resulting AppImage does not conform to the complete standard as it
+currently does not contain a @file{.DirIcon} file. This does not impact
+functionality of the AppImage itself, but possibly that of software used
+to manage AppImages.
+@end quotation
+
+@quotation Note
+As the generated AppImage packages the complete dependency graph, it
+will be larger than comparable AppImage files found online, which depend
+on host system libraries.
+@end quotation
+
@end table
@cindex relocatable binaries
@@ -7154,10 +7205,10 @@ Invoking guix pack
@cindex entry point, for Docker and Singularity images
@item --entry-point=@var{command}
-Use @var{command} as the @dfn{entry point} of the resulting pack, if the pack
-format supports it---currently @code{docker} and @code{squashfs} (Singularity)
-support it. @var{command} must be relative to the profile contained in the
-pack.
+Use @var{command} as the @dfn{entry point} of the resulting pack, if the
+pack format supports it---currently @code{docker}, @code{appimage}, and
+@code{squashfs} (Singularity) support it. @var{command} must be
+relative to the profile contained in the pack.
The entry point specifies the command that tools like @code{docker run} or
@code{singularity run} automatically start by default. For example, you can
diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm
index 7c5fe76fe0..26ba80b80d 100644
--- a/guix/scripts/pack.scm
+++ b/guix/scripts/pack.scm
@@ -10,6 +10,8 @@
;;; Copyright © 2022 Alex Griffin <a@ajgrf.com>
;;; Copyright © 2023 Graham James Addis <graham@addis.org.uk>
;;; Copyright © 2023 Oleg Pykhalov <go.wigust@gmail.com>
+;;; Copyright © 2024 Sebastian Dümcke <code@sam-d.com>
+;;; Copyright © 2024 Noé Lopez <noelopez@free.fr>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -56,6 +58,7 @@ (define-module (guix scripts pack)
#:use-module ((gnu packages compression) #:hide (zip))
#:use-module (gnu packages guile)
#:use-module (gnu packages base)
+ #:autoload (gnu packages appimage) (appimage-type2-runtime)
#:autoload (gnu packages gnupg) (guile-gcrypt)
#:autoload (gnu packages guile) (guile2.0-json guile-json)
#:use-module (srfi srfi-1)
@@ -64,6 +67,7 @@ (define-module (guix scripts pack)
#:use-module (srfi srfi-35)
#:use-module (srfi srfi-37)
#:use-module (ice-9 match)
+ #:use-module (ice-9 optargs)
#:export (symlink-spec-option-parser
self-contained-tarball
@@ -71,6 +75,7 @@ (define-module (guix scripts pack)
rpm-archive
docker-image
squashfs-image
+ self-contained-appimage
%formats
guix-pack))
@@ -974,8 +979,100 @@ (define* (rpm-archive name profile
(gexp->derivation (string-append name ".rpm") build
#:target target
#:references-graphs `(("profile" ,profile))))
+\f
+;;;
+;;; AppImage format
+;;;
+(define* (self-contained-appimage name profile
+ #:key target
+ (profile-name "guix-profile")
+ entry-point
+ (compressor (lookup-compressor "zstd"))
+ localstatedir?
+ (symlinks '())
+ (archiver tar)
+ (extra-options '()))
+ "Return a self-contained AppImage containing a store initialized with the
+closure of PROFILE, a derivation. The AppImage contains /gnu/store unless
+RELOCATABLE option is used; if LOCALSTATEDIR? is true, it also contains
+/var/guix, including /var/guix/db with a properly initialized store database.
+
+SYMLINKS must be a list of (SOURCE -> TARGET) tuples denoting symlinks to be
+added to the pack."
+ (unless entry-point
+ (leave (G_ "entry-point must be provided in the '~a' format~%")
+ 'appimage))
+ (let-keywords extra-options #f ((relocatable? #f))
+ (unless relocatable?
+ (warning (G_ "AppImages should be built with the --relocatable flag~%"))))
+
+ (define runtime-package appimage-type2-runtime)
+ (define runtime-path "bin/runtime-fuse3")
+ (define %valid-compressors '("gzip" "zstd"))
+
+ (let ((compressor-name (compressor-name compressor)))
+ (unless (member compressor-name %valid-compressors)
+ (leave (G_ "~a is not a valid squashfs archive compressor used in
+generating the AppImage. Valid compressors are: ~a~%")
+ compressor-name
+ %valid-compressors)))
- \f
+ (define builder
+ (with-extensions (list guile-gcrypt)
+ (with-imported-modules (source-module-closure
+ '((guix build store-copy)
+ (guix build utils))
+ #:select? not-config?)
+ #~(begin
+ (use-modules (guix build utils)
+ (guix build store-copy)
+ (rnrs io ports)
+ (srfi srfi-1)
+ (srfi srfi-26))
+
+ (define (concatenate-files result file1 file2)
+ "Creates a new file RESULT containing FILE1 followed by FILE2."
+ (call-with-output-file result
+ (lambda (output)
+ (call-with-input-file file1
+ (lambda (input)
+ (dump-port input output)))
+ (call-with-input-file file2
+ (lambda (input)
+ (dump-port input output))))))
+
+ (let* ((appdir "AppDir")
+ (squashfs "squashfs")
+ (profile-items (map store-info-item
+ (call-with-input-file "profile" read-reference-graph)))
+ (profile (find (lambda (item)
+ (string-suffix? "-profile" item))
+ profile-items)))
+ (mkdir-p appdir)
+ ;; Copy all store items from the profile to the AppDir.
+ (populate-store '("profile") appdir)
+ ;; Symlink the provided entry-point to AppDir/AppRun.
+ (symlink (string-append "." profile "/" #$entry-point)
+ (string-append appdir "/AppRun"))
+ ;; Create .desktop file as required by the spec.
+ (make-desktop-entry-file
+ (string-append appdir "/" #$name ".desktop")
+ #:name #$name
+ #:exec #$entry-point)
+ ;; Compress the AppDir.
+ (invoke #+(file-append squashfs-tools "/bin/mksquashfs") appdir
+ squashfs "-root-owned" "-noappend"
+ "-comp" #+(compressor-name compressor))
+ ;; Append runtime and squashFS into file AppImage.
+ (concatenate-files #$output
+ #$(file-append runtime-package "/" runtime-path)
+ squashfs)
+ ;; Add execution permission.
+ (chmod #$output #o555))))))
+ (gexp->derivation (string-append name ".AppImage") builder
+ #:target target
+ #:references-graphs `(("profile" ,profile))))
+\f
;;;
;;; Compiling C programs.
;;;
@@ -1311,6 +1408,7 @@ (define %formats
(squashfs . ,squashfs-image)
(docker . ,docker-image)
(deb . ,debian-archive)
+ (appimage . ,self-contained-appimage)
(rpm . ,rpm-archive)))
(define (show-formats)
@@ -1327,6 +1425,8 @@ (define (show-formats)
deb Debian archive installable via dpkg/apt"))
(display (G_ "
rpm RPM archive installable via rpm/yum"))
+ (display (G_ "
+ appimage AppImage self-contained and executable format"))
(newline))
(define (required-option symbol)
@@ -1694,6 +1794,8 @@ (define-command (guix-pack . args)
(process-file-arg opts 'preun-file)
#:postun-file
(process-file-arg opts 'postun-file)))
+ ('appimage
+ (list #:relocatable? relocatable?))
(_ '())))
(target (assoc-ref opts 'target))
(bootstrap? (assoc-ref opts 'bootstrap?))
diff --git a/tests/pack.scm b/tests/pack.scm
index f8a9e09c28..1c1e312557 100644
--- a/tests/pack.scm
+++ b/tests/pack.scm
@@ -3,6 +3,7 @@
;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2021, 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2023 Oleg Pykhalov <go.wigust@gmail.com>
+;;; Copyright © 2024 Noé Lopez <noelopez@free.fr>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -32,7 +33,8 @@ (define-module (test-pack)
#:use-module (guix utils)
#:use-module ((guix build utils) #:select (%store-directory))
#:use-module (gnu packages)
- #:use-module ((gnu packages base) #:select (libc-utf8-locales-for-target))
+ #:use-module ((gnu packages base) #:select (libc-utf8-locales-for-target
+ hello))
#:use-module (gnu packages bootstrap)
#:use-module ((gnu packages package-management) #:select (rpm))
#:use-module ((gnu packages compression) #:select (squashfs-tools))
@@ -340,6 +342,42 @@ (define rpm-for-tests
(mkdir #$output))))))))
(built-derivations (list check))))
+ (unless store (test-skip 1))
+ (test-assertm "appimage"
+ (mlet* %store-monad
+ ((guile (set-guile-for-build (default-guile)))
+ (profile -> (profile
+ (content (packages->manifest (list %bootstrap-guile hello)))
+ (hooks '())
+ (locales? #f)))
+ (image (self-contained-appimage "hello-appimage" profile
+ #:entry-point "bin/hello"
+ #:extra-options
+ (list #:relocatable? #t)))
+ (check (gexp->derivation
+ "check-appimage"
+ #~(invoke #$image))))
+ (built-derivations (list check))))
+
+ (unless store (test-skip 1))
+ (test-assertm "appimage + localstatedir"
+ (mlet* %store-monad
+ ((guile (set-guile-for-build (default-guile)))
+ (profile -> (profile
+ (content (packages->manifest (list %bootstrap-guile hello)))
+ (hooks '())
+ (locales? #f)))
+ (image (self-contained-appimage "hello-appimage" profile
+ #:entry-point "bin/hello"
+ #:localstatedir? #t
+ #:extra-options
+ (list #:relocatable? #t)))
+ (check (gexp->derivation
+ "check-appimage"
+ #~(begin
+ (invoke #$image)))))
+ (built-derivations (list check))))
+
(unless store (test-skip 1))
(test-assertm "deb archive with symlinks and control files"
(mlet* %store-monad
--
2.46.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v5 3/3] news: Add entry for guix pack’s AppImage format
2024-11-07 16:50 ` [bug#73842] [PATCH v5 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez via Guix-patches via
2024-11-07 16:50 ` [bug#73842] [PATCH v5 2/3] pack: Add support for AppImage pack format Noé Lopez via Guix-patches via
@ 2024-11-07 16:50 ` Noé Lopez via Guix-patches via
1 sibling, 0 replies; 24+ messages in thread
From: Noé Lopez via Guix-patches via @ 2024-11-07 16:50 UTC (permalink / raw)
To: 73842
Cc: Sebastian Dümcke, Noé Lopez, Ludovic Courtès,
pelzflorian, Maxim Cournoyer, Noé Lopez, noe, Florian Pelz,
Julien Lepiller
From: Sebastian Dümcke <code@sam-d.com>
* etc/news.scm: Add entry.
Change-Id: If37b3b578517c15c2868239998975f7718f7d689
---
etc/news.scm | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/etc/news.scm b/etc/news.scm
index 4929fa2a9a..4911ee65ee 100644
--- a/etc/news.scm
+++ b/etc/news.scm
@@ -25,6 +25,7 @@
;; Copyright © 2024 Vivien Kraus <vivien@planete-kraus.eu>
;; Copyright © 2024 Guillaume Le Vaillant <glv@posteo.net>
;; Copyright © 2024 Zheng Junjie <873216071@qq.com>
+;; Copyright © 2024 Sebastian Dümcke <code@sam-d.com>
;;
;; Copying and distribution of this file, with or without modification, are
;; permitted in any medium without royalty provided the copyright notice and
@@ -32,6 +33,43 @@
(channel-news
(version 0)
+ (entry (commit "9e96056bf40591cc9439d60c4c5bae5aa0f0b2f8")
+ (title
+ (de "Neues Format @samp{appimage} für den Befehl @command{guix pack}")
+ (en "New @samp{AppImage} format for the @command{guix pack} command")
+ (fr "Nouveau format @samp{AppImage} pour la commande @command{guix pack}"))
+ (body
+ (de "@command{guix pack} kann nun AppImage-Dateien erstellen. Das
+AppImage-Dateiformat erlaubt es, in einer einzelnen Datei Software zu verteilen. Die
+AppImage-Datei lässt sich ohne besondere Benutzerrechte ausführen. Hier ist
+ein Beispiel:
+
+@example
+guix pack --format=appimage --entry-point=bin/hello hello
+@end example
+
+Siehe @command{info \"(guix.de) Aufruf von guix pack\"} für mehr
+Informationen.")
+ (en "@command{guix pack} can now produce AppImage a single file,
+self-contained software archive. AppImage files are easily distributed and can
+be run with user privileges. Here is an example for the @code{hello} package:
+
+@example
+guix pack --format=appimage --entry-point=bin/hello hello
+@end example
+
+See @command{info \"(guix) Invoking guix pack\"} for more information.")
+ (fr "@command{guix pack} peut désormais produire un fichier
+AppImage. AppImage est une manière de distribuer les logiciels en un seul
+fichier, qui peut être executé avec des droits d’utilisateur. Voici un
+exemple pour le paquet @code{hello} :
+
+@example
+guix pack --format=appimage --entry-point=bin/hello hello
+@end example
+
+Consultez @command{info \"(guix.fr) Invoquer guix pack\"} pour plus
+d’informations.")))
(entry (commit "5966e0fdc78771c562e0f484a22f381a77908be0")
(title
--
2.46.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [bug#73842] [PATCH v5 2/3] pack: Add support for AppImage pack format.
2024-11-07 16:50 ` [bug#73842] [PATCH v5 2/3] pack: Add support for AppImage pack format Noé Lopez via Guix-patches via
@ 2024-11-15 17:02 ` Ludovic Courtès
0 siblings, 0 replies; 24+ messages in thread
From: Ludovic Courtès @ 2024-11-15 17:02 UTC (permalink / raw)
To: Noé Lopez
Cc: Josselin Poiret, 73842, Maxim Cournoyer, Simon Tournier,
Mathieu Othacehe, Noé Lopez, Tobias Geerinckx-Rice,
pelzflorian, Sebastian Dümcke, Christopher Baines
Hello Noé,
The patch series LGTM, and tests pass: we’re all set!
But… one thing I noticed when trying it out is that the resulting
AppImage would fail to run on relatively bare-bones non-Guix systems:
--8<---------------cut here---------------start------------->8---
$ ./2i2l6irl2n8q24aimfmidvlglllc4s8z-hello-appimage-pack.AppImage
fuse: failed to exec fusermount3: No such file or directory
Cannot mount AppImage, please check your FUSE setup.
You might still be able to extract the contents of this AppImage
if you run it with the --appimage-extract option.
See https://github.com/AppImage/AppImageKit/wiki/FUSE
for more information
open dir error: No such file or directory
--8<---------------cut here---------------end--------------->8---
I wonder if there’s something that can be done on our side about it or
if it’s a limitation of the approach (I expect the latter: ‘fusermount’
has to be available and setuid root), in which case we could just add a
warning in the manual.
WDYT?
Interestingly, it works on my Guix System laptop, except if I strace it:
--8<---------------cut here---------------start------------->8---
$ /gnu/store/2i2l6irl2n8q24aimfmidvlglllc4s8z-hello-appimage-pack.AppImage
Hello, world!
$ strace -f -o /tmp/log.strace -s 500 /gnu/store/2i2l6irl2n8q24aimfmidvlglllc4s8z-hello-appimage-pack.AppImage
fusermount3: mount failed: Operation not permitted
Cannot mount AppImage, please check your FUSE setup.
You might still be able to extract the contents of this AppImage
if you run it with the --appimage-extract option.
See https://github.com/AppImage/AppImageKit/wiki/FUSE
for more information
open dir error: No such file or directory
$ grep 'mount(' /tmp/log.strace
17569 mount("2i2l6irl2n8q24aimfmidvlglllc4s8z-hello-appimage-pack.AppImage", "/tmp/.mount_2i2l6iLZ8WYZ", "fuse.2i2l6irl2n8q24aimfmidvlglllc4s8z-hello-appimage-pack.AppImage", MS_RDONLY|MS_NOSUID|MS_NODEV, "fd=5,rootmode=40000,user_id=1000,group_id=998") = -1 EPERM (Operation not permitted)
17570 mount("2i2l6irl2n8q24aimfmidvlglllc4s8z-hello-appimage-pack.AppImage", ".", "fuse.2i2l6irl2n8q24aimfmidvlglllc4s8z-hello-appimage-pack.AppImage", MS_RDONLY|MS_NOSUID|MS_NODEV, "fd=6,rootmode=40000,user_id=1000,group_id=998") = -1 EPERM (Operation not permitted)
17571 mount("/dev/fuse", ".", "fuse", MS_RDONLY|MS_NOSUID|MS_NODEV, "fd=6,rootmode=40000,user_id=1000,group_id=998") = -1 EPERM (Operation not permitted)
--8<---------------cut here---------------end--------------->8---
Ludo’.
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2024-11-15 17:03 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-16 21:51 [bug#73842] [PATCH] pack: Add support for AppImage pack format Noé Lopez
2024-10-18 12:20 ` Ludovic Courtès
2024-10-18 12:22 ` Ludovic Courtès
2024-10-18 20:34 ` Ludovic Courtès
2024-10-26 17:28 ` [bug#73842] [PATCH v2 0/3] " Noé Lopez
2024-10-26 17:28 ` [bug#73842] [PATCH v2 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez
2024-11-01 13:24 ` Maxim Cournoyer
2024-10-26 17:28 ` [bug#73842] [PATCH v2 2/3] pack: Add support for AppImage pack format Noé Lopez
2024-11-01 13:19 ` Maxim Cournoyer
2024-11-01 15:22 ` Noé Lopez via Guix-patches via
2024-10-26 17:28 ` [bug#73842] [PATCH v2 3/3] news: Add entry for guix pack’s AppImage format Noé Lopez
2024-10-27 13:38 ` pelzflorian (Florian Pelz)
2024-11-01 13:27 ` Maxim Cournoyer
2024-11-03 22:37 ` [bug#73842] [PATCH v4 0/3] pack: Add support for AppImage pack format Noé Lopez via Guix-patches via
2024-11-03 22:37 ` [bug#73842] [PATCH v4 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez via Guix-patches via
2024-11-05 14:22 ` Ludovic Courtès
2024-11-03 22:37 ` [bug#73842] [PATCH v4 2/3] pack: Add support for AppImage pack format Noé Lopez via Guix-patches via
2024-11-05 14:27 ` Ludovic Courtès
2024-11-03 22:37 ` [bug#73842] [PATCH v4 3/3] news: Add entry for guix pack’s AppImage format Noé Lopez via Guix-patches via
2024-11-05 14:28 ` Ludovic Courtès
2024-11-07 16:50 ` [bug#73842] [PATCH v5 1/3] gnu: appimage: New packages for the appimage runtime Noé Lopez via Guix-patches via
2024-11-07 16:50 ` [bug#73842] [PATCH v5 2/3] pack: Add support for AppImage pack format Noé Lopez via Guix-patches via
2024-11-15 17:02 ` Ludovic Courtès
2024-11-07 16:50 ` [bug#73842] [PATCH v5 3/3] news: Add entry for guix pack’s AppImage format Noé Lopez via Guix-patches via
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/guix.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).