summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGraham Christensen <graham@grahamc.com>2019-06-18 18:51:58 +0200
committerGraham Christensen <graham@grahamc.com>2019-06-18 18:51:58 +0200
commita82901fb5e7f244d2db6b1e6a90e9a7a23ca588a (patch)
tree66b4e9a0ef69c439117e370ee885b980812e9527
parentb5cf5ff20f92d790b703db00d202a72231943845 (diff)
snapTools.makeSnap: init
-rw-r--r--doc/functions.xml1
-rw-r--r--doc/functions/snaptools.xml74
-rw-r--r--pkgs/build-support/snap/default.nix4
-rw-r--r--pkgs/build-support/snap/example-firefox.nix28
-rw-r--r--pkgs/build-support/snap/example-hello.nix12
-rw-r--r--pkgs/build-support/snap/make-snap.nix84
-rw-r--r--pkgs/top-level/all-packages.nix2
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 {};