From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0.migadu.com ([2001:41d0:303:e224::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms13.migadu.com with LMTPS id 4K/nClVBEGcLDwEAqHPOHw:P1 (envelope-from ) for ; Wed, 16 Oct 2024 22:42:29 +0000 Received: from aspmx1.migadu.com ([2001:41d0:303:e224::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0.migadu.com with LMTPS id 4K/nClVBEGcLDwEAqHPOHw (envelope-from ) for ; Thu, 17 Oct 2024 00:42:29 +0200 X-Envelope-To: larch@yhetil.org Authentication-Results: aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=debbugs.gnu.org header.s=debbugs-gnu-org header.b=Xs82izzT; dmarc=fail reason="SPF not aligned (relaxed)" header.from=free.fr (policy=none); spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" ARC-Seal: i=1; s=key1; d=yhetil.org; t=1729118549; a=rsa-sha256; cv=none; b=p7IT3L/Kk0z35J6zqfr1Gj796I2jSkAy5L/ncgDYUN3PGYdsNQu+vl3HvfARFkdIY85+OL oIcY5/HPzW844qmWzqQIVPKd5eGT695c+8zZYPRs+4OOh7Bd97sIjHiXn3ZOH9B3sgsgaN p10FtsOxFn+DgkF+3iuaL4L+wjwchD9kJyLTnx8qZU3Q/x/t5P9dP8Qo05UYT0eI3USEVU dJp4ak9nBwQ0NkCHUnbUmkvlTSF8Zrsm4RsjewYxN55Y5blhLQtHqVvM3/xduTByRn+e19 Cy8CpgIhEZJjRKCfqAVWIH169mzuQ5VyE2yqHhH6Vp3EjRoBH7JKWIKb6urd+Q== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=debbugs.gnu.org header.s=debbugs-gnu-org header.b=Xs82izzT; dmarc=fail reason="SPF not aligned (relaxed)" header.from=free.fr (policy=none); spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1729118549; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:resent-cc: resent-from:resent-sender:resent-message-id:list-id:list-help: list-unsubscribe:list-subscribe:list-post:dkim-signature; bh=7ecldrLmBXwkHZ/TlwbFqiuTZjwPvaqJtzIjNYnDA5E=; b=uL9/BX3jIkOkjR2vXx8LFdmSf3f0ZVSJC+wr34ux1zQYcc/Qj/8tpGpvx3NCGUyh1uc0p9 l59X/KC90nNHcdFC8vE7ckHUnTxDhcekZ/2BIPyJXtCikxfQz/L4zkX8tQ5/o55C4L68Oy GTkexeNUPSH4+hy4U5oB3D2W92AdFlic0kTVWjYID4q19dIkHslvJgxGkl0bHDPrduaL9D pqq7GTnPmSoLIF5306bAyt2waXD2N47nwTY6KGhwNCJuLP+KTQ4j9abhzxRI48oMqq+Ldp 9OGwQA85JWsTHjVHB7tjzwPa/1PLdpp3aIzGXGesxQDn0lmHfq6NCfdDaOisow== Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 516CF1F78C for ; Thu, 17 Oct 2024 00:42:28 +0200 (CEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t1Bvu-0002p5-32; Wed, 16 Oct 2024 17:51:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t1Bvs-0002os-Th for guix-patches@gnu.org; Wed, 16 Oct 2024 17:51:52 -0400 Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t1Bvq-0004RP-Cj; Wed, 16 Oct 2024 17:51:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=MIME-Version:Date:From:To:Subject; bh=AZz1HAfCWj/jHbq6Ej1MmuIR1NuaFXivqCJtbDMZRfE=; b=Xs82izzTBLz9vxBxU2uvM0BQdkVp5HLw7OTE27h9QEWZMS0IhfkpQAhPYuLxY/903hv6cV+8g7RZeVF4MamfErI88edOReTWObmwmEGInYfoU5PiFn+2fyujp4XnRhxb25mvKsL1XirBUwhAQPjkLlxt/ZO3Vj4WmJVtPJmypKm85688Wk5nnNQcEWwa2UVzi5Rxm9h1P/TTxdBpUNf+zLp6wJYBaEXoPxeJAJk0xOt2Bq73KagNQPeFN8lBdBd866tOLSFh6mE6P8GgFJAqgBSiLxc6+QPTegG9lyCr3qaMfkfCm/SnqLIK8RI6rBPc1n8RT8uqqBHC91PbJiuH3Q==; Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1t1Bw2-0007Oh-2m; Wed, 16 Oct 2024 17:52:02 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#73842] [PATCH] pack: Add support for AppImage pack format. Resent-From: =?UTF-8?Q?No=C3=A9?= Lopez Original-Sender: "Debbugs-submit" Resent-CC: guix@cbaines.net, dev@jpoiret.xyz, ludo@gnu.org, othacehe@gnu.org, maxim.cournoyer@gmail.com, zimon.toutoune@gmail.com, me@tobias.gr, guix-patches@gnu.org Resent-Date: Wed, 16 Oct 2024 21:52:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 73842 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 73842@debbugs.gnu.org Cc: =?UTF-8?Q?No=C3=A9?= Lopez , Sebastian =?UTF-8?Q?D=C3=BCmcke?= , Christopher Baines , Josselin Poiret , Ludovic =?UTF-8?Q?Court=C3=A8s?= , Mathieu Othacehe , Maxim Cournoyer , Simon Tournier , Tobias Geerinckx-Rice X-Debbugs-Original-To: guix-patches@gnu.org X-Debbugs-Original-Xcc: Christopher Baines , Josselin Poiret , Ludovic =?UTF-8?Q?Court=C3=A8s?= , Mathieu Othacehe , Maxim Cournoyer , Simon Tournier , Tobias Geerinckx-Rice Received: via spool by submit@debbugs.gnu.org id=B.172911547928367 (code B ref -1); Wed, 16 Oct 2024 21:52:01 +0000 Received: (at submit) by debbugs.gnu.org; 16 Oct 2024 21:51:19 +0000 Received: from localhost ([127.0.0.1]:60741 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1t1BvJ-0007NQ-J6 for submit@debbugs.gnu.org; Wed, 16 Oct 2024 17:51:18 -0400 Received: from lists.gnu.org ([209.51.188.17]:38528) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1t1BvG-0007NG-MU for submit@debbugs.gnu.org; Wed, 16 Oct 2024 17:51:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t1Buw-0002lh-56 for guix-patches@gnu.org; Wed, 16 Oct 2024 17:50:54 -0400 Received: from smtp1-g21.free.fr ([212.27.42.1]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t1But-0004LA-5H for guix-patches@gnu.org; Wed, 16 Oct 2024 17:50:53 -0400 Received: from localhost.localdomain (unknown [IPv6:2a01:e0a:990:a960:b4f3:8f44:ec4:5af5]) by smtp1-g21.free.fr (Postfix) with ESMTP id BE2B4B0053E; Wed, 16 Oct 2024 23:50:43 +0200 (CEST) From: =?UTF-8?Q?No=C3=A9?= Lopez Date: Wed, 16 Oct 2024 23:51:30 +0200 Message-ID: X-Mailer: git-send-email 2.46.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Received-SPF: pass client-ip=212.27.42.1; envelope-from=noelopez@free.fr; helo=smtp1-g21.free.fr X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: guix-patches-bounces+larch=yhetil.org@gnu.org X-Migadu-Flow: FLOW_IN X-Migadu-Country: US X-Migadu-Spam-Score: 4.08 X-Spam-Score: 4.08 X-Migadu-Queue-Id: 516CF1F78C X-Migadu-Scanner: mx12.migadu.com X-TUID: iu73Oh/r8h0g From: Sebastian Dümcke * 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 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 +;;; +;;; 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 . + +(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 ;;; Copyright © 2023 Graham James Addis ;;; Copyright © 2023 Oleg Pykhalov +;;; Copyright © 2024 Sebastian Dümcke +;;; Copyright © 2024 Noé Lopez ;;; ;;; 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)))) + +;;; +;;; 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))) - + (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)))) + ;;; ;;; 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