all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* [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
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ 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] 9+ 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
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ 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] 9+ 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
  3 siblings, 0 replies; 9+ 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] 9+ 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
  3 siblings, 0 replies; 9+ 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] 9+ 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)
  3 siblings, 3 replies; 9+ 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] 9+ 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-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, 0 replies; 9+ 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] 9+ 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-10-26 17:28   ` [bug#73842] [PATCH v2 3/3] news: Add entry for guix pack’s AppImage format Noé Lopez
  2 siblings, 0 replies; 9+ 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] 9+ 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)
  2 siblings, 1 reply; 9+ 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] 9+ 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)
  0 siblings, 0 replies; 9+ 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] 9+ messages in thread

end of thread, other threads:[~2024-10-27 13:38 UTC | newest]

Thread overview: 9+ 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-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
2024-10-27 13:38     ` pelzflorian (Florian Pelz)

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.