···11+<section xmlns="http://docbook.org/ns/docbook"
22+ xmlns:xlink="http://www.w3.org/1999/xlink"
33+ xmlns:xi="http://www.w3.org/2001/XInclude"
44+ xml:id="sec-pkgs-snapTools">
55+ <title>pkgs.snapTools</title>
66+77+ <para>
88+ <varname>pkgs.snapTools</varname> is a set of functions for creating
99+ Snapcraft images. Snap and Snapcraft is not used to perform these operations.
1010+ </para>
1111+1212+ <section xml:id="ssec-pkgs-snapTools-makeSnap-signature">
1313+ <title>The makeSnap Function</title>
1414+1515+ <para>
1616+ <function>makeSnap</function> takes a single named argument,
1717+ <parameter>meta</parameter>. This argument mirrors
1818+ <link xlink:href="https://docs.snapcraft.io/snap-format">the upstream
1919+ <filename>snap.yaml</filename> format</link> exactly.
2020+ </para>
2121+2222+ <para>
2323+ The <parameter>base</parameter> should not be be specified, as
2424+ <function>makeSnap</function> will force set it.
2525+ </para>
2626+2727+ <para>
2828+ Currently, <function>makeSnap</function> does not support creating GUI
2929+ stubs.
3030+ </para>
3131+ </section>
3232+3333+ <section xml:id="ssec-pkgs-snapTools-build-a-snap-hello">
3434+ <title>Build a Hello World Snap</title>
3535+3636+ <example xml:id="ex-snapTools-buildSnap-hello">
3737+ <title>Making a Hello World Snap</title>
3838+ <para>
3939+ The following expression packages GNU Hello as a Snapcraft snap.
4040+ </para>
4141+<programlisting><xi:include href="../../pkgs/build-support/snap/example-hello.nix" parse="text" /></programlisting>
4242+ <para>
4343+ <command>nix-build</command> this expression and install it with
4444+ <command>snap install ./result --dangerous</command>.
4545+ <command>hello</command> will now be the Snapcraft version of the package.
4646+ </para>
4747+ </example>
4848+ </section>
4949+5050+ <section xml:id="ssec-pkgs-snapTools-build-a-snap-firefox">
5151+ <title>Build a Hello World Snap</title>
5252+5353+ <example xml:id="ex-snapTools-buildSnap-firefox">
5454+ <title>Making a Graphical Snap</title>
5555+ <para>
5656+ Graphical programs require many more integrations with the host. This
5757+ example uses Firefox as an example, because it is one of the most
5858+ complicated programs we could package.
5959+ </para>
6060+<programlisting><xi:include href="../../pkgs/build-support/snap/example-firefox.nix" parse="text" /></programlisting>
6161+ <para>
6262+ <command>nix-build</command> this expression and install it with
6363+ <command>snap install ./result --dangerous</command>.
6464+ <command>nix-example-firefox</command> will now be the Snapcraft version of
6565+ the Firefox package.
6666+ </para>
6767+ <para>
6868+ The specific meaning behind plugs can be looked up in the
6969+ <link xlink:href="https://docs.snapcraft.io/supported-interfaces">Snapcraft
7070+ interface documentation</link>.
7171+ </para>
7272+ </example>
7373+ </section>
7474+</section>
···11+{
22+ runCommand, squashfsTools, closureInfo, lib, jq, writeText
33+}:
44+55+{
66+ # The meta parameter is the contents of the `snap.yaml`, NOT the
77+ # `snapcraft.yaml`.
88+ #
99+ # - `snap.yaml` is what is inside of the final Snap,
1010+ # - `snapcraft.yaml` is used by `snapcraft` to build snaps
1111+ #
1212+ # Since we skip the `snapcraft` tool, we skip the `snapcraft.yaml`
1313+ # file. For more information:
1414+ #
1515+ # https://docs.snapcraft.io/snap-format
1616+ #
1717+ # Note: unsquashfs'ing an existing snap from the store can be helpful
1818+ # for determining what you you're missing.
1919+ #
2020+ meta
2121+}: let
2222+ snap_yaml = let
2323+ # Validate the snap's meta contains a name.
2424+ # Also: automatically set the `base` parameter and the layout for
2525+ # the `/nix` bind.
2626+ validate = { name, ... } @ args:
2727+ args // {
2828+ # Combine the provided arguments with the required options.
2929+3030+ # base: built from https://github.com/NixOS/snapd-nix-base
3131+ # and published as The NixOS Foundation on the Snapcraft store.
3232+ base = "nix-base";
3333+ layout = (args.layout or {}) // {
3434+ # Bind mount the Snap's root nix directory to `/nix` in the
3535+ # execution environment's filesystem namespace.
3636+ "/nix".bind = "$SNAP/nix";
3737+ };
3838+ };
3939+ in writeText "snap.yaml"
4040+ (builtins.toJSON (validate meta));
4141+4242+ # These are specifically required by snapd, so don't change them
4343+ # unless you've verified snapcraft / snapd can handle them. Best bet
4444+ # is to just mirror this list against how snapcraft creates images.
4545+ # from: https://github.com/snapcore/snapcraft/blob/b88e378148134383ffecf3658e3a940b67c9bcc9/snapcraft/internal/lifecycle/_packer.py#L96-L98
4646+ mksquashfs_args = [
4747+ "-noappend" "-comp" "xz" "-no-xattrs" "-no-fragments"
4848+4949+ # Note: We want -all-root every time, since all the files are
5050+ # owned by root anyway. This is true for Nix, but not true for
5151+ # other builds.
5252+ # from: https://github.com/snapcore/snapcraft/blob/b88e378148134383ffecf3658e3a940b67c9bcc9/snapcraft/internal/lifecycle/_packer.py#L100
5353+ "-all-root"
5454+ ];
5555+5656+in runCommand "squashfs.img" {
5757+ nativeBuildInputs = [ squashfsTools jq ];
5858+5959+ closureInfo = closureInfo {
6060+ rootPaths = [ snap_yaml ];
6161+ };
6262+} ''
6363+ root=$PWD/root
6464+ mkdir $root
6565+6666+ (
6767+ # Put the snap.yaml in to `/meta/snap.yaml`, setting the version
6868+ # to the hash part of the store path
6969+ mkdir $root/meta
7070+ version=$(echo $out | cut -d/ -f4 | cut -d- -f1)
7171+ cat ${snap_yaml} | jq ". + { version: \"$version\" }" \
7272+ > $root/meta/snap.yaml
7373+ )
7474+7575+ (
7676+ # Copy the store closure in to the root
7777+ mkdir -p $root/nix/store
7878+ cat $closureInfo/store-paths | xargs -I{} cp -r {} $root/nix/store/
7979+ )
8080+8181+ # Generate the squashfs image.
8282+ mksquashfs $root $out \
8383+ ${lib.concatStringsSep " " mksquashfs_args}
8484+''