···1+<section xmlns="http://docbook.org/ns/docbook"
2+ xmlns:xlink="http://www.w3.org/1999/xlink"
3+ xmlns:xi="http://www.w3.org/2001/XInclude"
4+ xml:id="sec-pkgs-snapTools">
5+ <title>pkgs.snapTools</title>
6+7+ <para>
8+ <varname>pkgs.snapTools</varname> is a set of functions for creating
9+ Snapcraft images. Snap and Snapcraft is not used to perform these operations.
10+ </para>
11+12+ <section xml:id="ssec-pkgs-snapTools-makeSnap-signature">
13+ <title>The makeSnap Function</title>
14+15+ <para>
16+ <function>makeSnap</function> takes a single named argument,
17+ <parameter>meta</parameter>. This argument mirrors
18+ <link xlink:href="https://docs.snapcraft.io/snap-format">the upstream
19+ <filename>snap.yaml</filename> format</link> exactly.
20+ </para>
21+22+ <para>
23+ The <parameter>base</parameter> should not be be specified, as
24+ <function>makeSnap</function> will force set it.
25+ </para>
26+27+ <para>
28+ Currently, <function>makeSnap</function> does not support creating GUI
29+ stubs.
30+ </para>
31+ </section>
32+33+ <section xml:id="ssec-pkgs-snapTools-build-a-snap-hello">
34+ <title>Build a Hello World Snap</title>
35+36+ <example xml:id="ex-snapTools-buildSnap-hello">
37+ <title>Making a Hello World Snap</title>
38+ <para>
39+ The following expression packages GNU Hello as a Snapcraft snap.
40+ </para>
41+<programlisting><xi:include href="../../pkgs/build-support/snap/example-hello.nix" parse="text" /></programlisting>
42+ <para>
43+ <command>nix-build</command> this expression and install it with
44+ <command>snap install ./result --dangerous</command>.
45+ <command>hello</command> will now be the Snapcraft version of the package.
46+ </para>
47+ </example>
48+ </section>
49+50+ <section xml:id="ssec-pkgs-snapTools-build-a-snap-firefox">
51+ <title>Build a Hello World Snap</title>
52+53+ <example xml:id="ex-snapTools-buildSnap-firefox">
54+ <title>Making a Graphical Snap</title>
55+ <para>
56+ Graphical programs require many more integrations with the host. This
57+ example uses Firefox as an example, because it is one of the most
58+ complicated programs we could package.
59+ </para>
60+<programlisting><xi:include href="../../pkgs/build-support/snap/example-firefox.nix" parse="text" /></programlisting>
61+ <para>
62+ <command>nix-build</command> this expression and install it with
63+ <command>snap install ./result --dangerous</command>.
64+ <command>nix-example-firefox</command> will now be the Snapcraft version of
65+ the Firefox package.
66+ </para>
67+ <para>
68+ The specific meaning behind plugs can be looked up in the
69+ <link xlink:href="https://docs.snapcraft.io/supported-interfaces">Snapcraft
70+ interface documentation</link>.
71+ </para>
72+ </example>
73+ </section>
74+</section>
···1+{
2+ runCommand, squashfsTools, closureInfo, lib, jq, writeText
3+}:
4+5+{
6+ # The meta parameter is the contents of the `snap.yaml`, NOT the
7+ # `snapcraft.yaml`.
8+ #
9+ # - `snap.yaml` is what is inside of the final Snap,
10+ # - `snapcraft.yaml` is used by `snapcraft` to build snaps
11+ #
12+ # Since we skip the `snapcraft` tool, we skip the `snapcraft.yaml`
13+ # file. For more information:
14+ #
15+ # https://docs.snapcraft.io/snap-format
16+ #
17+ # Note: unsquashfs'ing an existing snap from the store can be helpful
18+ # for determining what you you're missing.
19+ #
20+ meta
21+}: let
22+ snap_yaml = let
23+ # Validate the snap's meta contains a name.
24+ # Also: automatically set the `base` parameter and the layout for
25+ # the `/nix` bind.
26+ validate = { name, ... } @ args:
27+ args // {
28+ # Combine the provided arguments with the required options.
29+30+ # base: built from https://github.com/NixOS/snapd-nix-base
31+ # and published as The NixOS Foundation on the Snapcraft store.
32+ base = "nix-base";
33+ layout = (args.layout or {}) // {
34+ # Bind mount the Snap's root nix directory to `/nix` in the
35+ # execution environment's filesystem namespace.
36+ "/nix".bind = "$SNAP/nix";
37+ };
38+ };
39+ in writeText "snap.yaml"
40+ (builtins.toJSON (validate meta));
41+42+ # These are specifically required by snapd, so don't change them
43+ # unless you've verified snapcraft / snapd can handle them. Best bet
44+ # is to just mirror this list against how snapcraft creates images.
45+ # from: https://github.com/snapcore/snapcraft/blob/b88e378148134383ffecf3658e3a940b67c9bcc9/snapcraft/internal/lifecycle/_packer.py#L96-L98
46+ mksquashfs_args = [
47+ "-noappend" "-comp" "xz" "-no-xattrs" "-no-fragments"
48+49+ # Note: We want -all-root every time, since all the files are
50+ # owned by root anyway. This is true for Nix, but not true for
51+ # other builds.
52+ # from: https://github.com/snapcore/snapcraft/blob/b88e378148134383ffecf3658e3a940b67c9bcc9/snapcraft/internal/lifecycle/_packer.py#L100
53+ "-all-root"
54+ ];
55+56+in runCommand "squashfs.img" {
57+ nativeBuildInputs = [ squashfsTools jq ];
58+59+ closureInfo = closureInfo {
60+ rootPaths = [ snap_yaml ];
61+ };
62+} ''
63+ root=$PWD/root
64+ mkdir $root
65+66+ (
67+ # Put the snap.yaml in to `/meta/snap.yaml`, setting the version
68+ # to the hash part of the store path
69+ mkdir $root/meta
70+ version=$(echo $out | cut -d/ -f4 | cut -d- -f1)
71+ cat ${snap_yaml} | jq ". + { version: \"$version\" }" \
72+ > $root/meta/snap.yaml
73+ )
74+75+ (
76+ # Copy the store closure in to the root
77+ mkdir -p $root/nix/store
78+ cat $closureInfo/store-paths | xargs -I{} cp -r {} $root/nix/store/
79+ )
80+81+ # Generate the squashfs image.
82+ mksquashfs $root $out \
83+ ${lib.concatStringsSep " " mksquashfs_args}
84+''