diff options
-rw-r--r-- | doc/functions.xml | 1 | ||||
-rw-r--r-- | doc/functions/snaptools.xml | 74 | ||||
-rw-r--r-- | pkgs/build-support/snap/default.nix | 4 | ||||
-rw-r--r-- | pkgs/build-support/snap/example-firefox.nix | 28 | ||||
-rw-r--r-- | pkgs/build-support/snap/example-hello.nix | 12 | ||||
-rw-r--r-- | pkgs/build-support/snap/make-snap.nix | 84 | ||||
-rw-r--r-- | pkgs/top-level/all-packages.nix | 2 |
7 files changed, 205 insertions, 0 deletions
diff --git a/doc/functions.xml b/doc/functions.xml index 1f2d00b9e1af..3b60f46d81da 100644 --- a/doc/functions.xml +++ b/doc/functions.xml @@ -16,6 +16,7 @@ <xi:include href="functions/fhs-environments.xml" /> <xi:include href="functions/shell.xml" /> <xi:include href="functions/dockertools.xml" /> + <xi:include href="functions/snaptools.xml" /> <xi:include href="functions/appimagetools.xml" /> <xi:include href="functions/prefer-remote-fetch.xml" /> <xi:include href="functions/nix-gitignore.xml" /> diff --git a/doc/functions/snaptools.xml b/doc/functions/snaptools.xml new file mode 100644 index 000000000000..a951c36730d3 --- /dev/null +++ b/doc/functions/snaptools.xml @@ -0,0 +1,74 @@ +<section xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xi="http://www.w3.org/2001/XInclude" + xml:id="sec-pkgs-snapTools"> + <title>pkgs.snapTools</title> + + <para> + <varname>pkgs.snapTools</varname> is a set of functions for creating + Snapcraft images. Snap and Snapcraft is not used to perform these operations. + </para> + + <section xml:id="ssec-pkgs-snapTools-makeSnap-signature"> + <title>The makeSnap Function</title> + + <para> + <function>makeSnap</function> takes a single named argument, + <parameter>meta</parameter>. This argument mirrors + <link xlink:href="https://docs.snapcraft.io/snap-format">the upstream + <filename>snap.yaml</filename> format</link> exactly. + </para> + + <para> + The <parameter>base</parameter> should not be be specified, as + <function>makeSnap</function> will force set it. + </para> + + <para> + Currently, <function>makeSnap</function> does not support creating GUI + stubs. + </para> + </section> + + <section xml:id="ssec-pkgs-snapTools-build-a-snap-hello"> + <title>Build a Hello World Snap</title> + + <example xml:id="ex-snapTools-buildSnap-hello"> + <title>Making a Hello World Snap</title> + <para> + The following expression packages GNU Hello as a Snapcraft snap. + </para> +<programlisting><xi:include href="../../pkgs/build-support/snap/example-hello.nix" parse="text" /></programlisting> + <para> + <command>nix-build</command> this expression and install it with + <command>snap install ./result --dangerous</command>. + <command>hello</command> will now be the Snapcraft version of the package. + </para> + </example> + </section> + + <section xml:id="ssec-pkgs-snapTools-build-a-snap-firefox"> + <title>Build a Hello World Snap</title> + + <example xml:id="ex-snapTools-buildSnap-firefox"> + <title>Making a Graphical Snap</title> + <para> + Graphical programs require many more integrations with the host. This + example uses Firefox as an example, because it is one of the most + complicated programs we could package. + </para> +<programlisting><xi:include href="../../pkgs/build-support/snap/example-firefox.nix" parse="text" /></programlisting> + <para> + <command>nix-build</command> this expression and install it with + <command>snap install ./result --dangerous</command>. + <command>nix-example-firefox</command> will now be the Snapcraft version of + the Firefox package. + </para> + <para> + The specific meaning behind plugs can be looked up in the + <link xlink:href="https://docs.snapcraft.io/supported-interfaces">Snapcraft + interface documentation</link>. + </para> + </example> + </section> +</section> diff --git a/pkgs/build-support/snap/default.nix b/pkgs/build-support/snap/default.nix new file mode 100644 index 000000000000..ba5271868911 --- /dev/null +++ b/pkgs/build-support/snap/default.nix @@ -0,0 +1,4 @@ +{ callPackage, hello }: +{ + makeSnap = callPackage ./make-snap.nix { }; +} diff --git a/pkgs/build-support/snap/example-firefox.nix b/pkgs/build-support/snap/example-firefox.nix new file mode 100644 index 000000000000..d58c98a65a2e --- /dev/null +++ b/pkgs/build-support/snap/example-firefox.nix @@ -0,0 +1,28 @@ +let + inherit (import <nixpkgs> { }) snapTools firefox; +in snapTools.makeSnap { + meta = { + name = "nix-example-firefox"; + summary = firefox.meta.description; + architectures = [ "amd64" ]; + apps.nix-example-firefox = { + command = "${firefox}/bin/firefox"; + plugs = [ + "pulseaudio" + "camera" + "browser-support" + "avahi-observe" + "cups-control" + "desktop" + "desktop-legacy" + "gsettings" + "home" + "network" + "mount-observe" + "removable-media" + "x11" + ]; + }; + confinement = "strict"; + }; +} diff --git a/pkgs/build-support/snap/example-hello.nix b/pkgs/build-support/snap/example-hello.nix new file mode 100644 index 000000000000..123da80c5477 --- /dev/null +++ b/pkgs/build-support/snap/example-hello.nix @@ -0,0 +1,12 @@ +let + inherit (import <nixpkgs> { }) snapTools hello; +in snapTools.makeSnap { + meta = { + name = "hello"; + summary = hello.meta.description; + description = hello.meta.longDescription; + architectures = [ "amd64" ]; + confinement = "strict"; + apps.hello.command = "${hello}/bin/hello"; + }; +} diff --git a/pkgs/build-support/snap/make-snap.nix b/pkgs/build-support/snap/make-snap.nix new file mode 100644 index 000000000000..cef7500bcbaf --- /dev/null +++ b/pkgs/build-support/snap/make-snap.nix @@ -0,0 +1,84 @@ +{ + runCommand, squashfsTools, closureInfo, lib, jq, writeText +}: + +{ + # The meta parameter is the contents of the `snap.yaml`, NOT the + # `snapcraft.yaml`. + # + # - `snap.yaml` is what is inside of the final Snap, + # - `snapcraft.yaml` is used by `snapcraft` to build snaps + # + # Since we skip the `snapcraft` tool, we skip the `snapcraft.yaml` + # file. For more information: + # + # https://docs.snapcraft.io/snap-format + # + # Note: unsquashfs'ing an existing snap from the store can be helpful + # for determining what you you're missing. + # + meta +}: let + snap_yaml = let + # Validate the snap's meta contains a name. + # Also: automatically set the `base` parameter and the layout for + # the `/nix` bind. + validate = { name, ... } @ args: + args // { + # Combine the provided arguments with the required options. + + # base: built from https://github.com/NixOS/snapd-nix-base + # and published as The NixOS Foundation on the Snapcraft store. + base = "nix-base"; + layout = (args.layout or {}) // { + # Bind mount the Snap's root nix directory to `/nix` in the + # execution environment's filesystem namespace. + "/nix".bind = "$SNAP/nix"; + }; + }; + in writeText "snap.yaml" + (builtins.toJSON (validate meta)); + + # These are specifically required by snapd, so don't change them + # unless you've verified snapcraft / snapd can handle them. Best bet + # is to just mirror this list against how snapcraft creates images. + # from: https://github.com/snapcore/snapcraft/blob/b88e378148134383ffecf3658e3a940b67c9bcc9/snapcraft/internal/lifecycle/_packer.py#L96-L98 + mksquashfs_args = [ + "-noappend" "-comp" "xz" "-no-xattrs" "-no-fragments" + + # Note: We want -all-root every time, since all the files are + # owned by root anyway. This is true for Nix, but not true for + # other builds. + # from: https://github.com/snapcore/snapcraft/blob/b88e378148134383ffecf3658e3a940b67c9bcc9/snapcraft/internal/lifecycle/_packer.py#L100 + "-all-root" + ]; + +in runCommand "squashfs.img" { + nativeBuildInputs = [ squashfsTools jq ]; + + closureInfo = closureInfo { + rootPaths = [ snap_yaml ]; + }; +} '' + root=$PWD/root + mkdir $root + + ( + # Put the snap.yaml in to `/meta/snap.yaml`, setting the version + # to the hash part of the store path + mkdir $root/meta + version=$(echo $out | cut -d/ -f4 | cut -d- -f1) + cat ${snap_yaml} | jq ". + { version: \"$version\" }" \ + > $root/meta/snap.yaml + ) + + ( + # Copy the store closure in to the root + mkdir -p $root/nix/store + cat $closureInfo/store-paths | xargs -I{} cp -r {} $root/nix/store/ + ) + + # Generate the squashfs image. + mksquashfs $root $out \ + ${lib.concatStringsSep " " mksquashfs_args} +'' diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 09a2f6c391db..8cbe329d2e9b 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -175,6 +175,8 @@ in dockerTools = callPackage ../build-support/docker { }; + snapTools = callPackage ../build-support/snap { }; + nix-prefetch-docker = callPackage ../build-support/docker/nix-prefetch-docker.nix { }; docker-compose = python3Packages.callPackage ../applications/virtualization/docker-compose {}; |