Snapcraft GNOME Extension Update

This is an early PSA aimed at developers who publish snaps in the Snap Store. They can probably skip this preamble, but for anyone else here’s some backstory in case you’re bored interested.

Preamble

Snaps are confined software packages for Linux. They were originally designed / intended for IoT use cases so are optimised for size, bundling dependencies, are compressed on disk and auto update. They can also be used to package server software, like NextCloud, and desktop software like Signal Desktop. There’s millions of desktops, routers, servers and other interesting devices with snaps installed.

There’s a bunch of common components that snap publishers started bundling in their snaps which bloated them out a bit. Snaps have had (for some time) a concept of “shared content” such that one snap may consume assets from another snap. The reason we use the hand-wavy term “assets” and “content” is because while it could be binary programs and libraries which are shared between snaps, it’s not just limited to that. A theme or bundle of themes can be shared too.

A few content snaps were created which could be used by snap publishers, to offload re-usable common components to another well-maintained package. One example, the GNOME Calculator (gnome-calculator) snap connects to and consumes a bunch of libraries from the GNOME Platform (gnome-3-34-1804) snap. Note the name of the platform snap indicates the project, version and release of Ubuntu it was built on, so GNOME 3.34 on Ubuntu 18.04. As a result the GNOME Calculator is 2MB on disk.

These content snaps are very useful, and a bunch of publishers leveraged them to reduce their build time, snap size, security attack surface, startup time and up/download duration. While great, the downside is there’s a bunch of common boilerplate required in the snapcraft.yaml to make it all work. A simple typo or omission would break the build or resulting snap, which is frustrating.

So a while back the snapcraft developers worked with the Ubuntu Desktop Team and Snap Team to develop a concept of “extensions”. An extension is code in snapcraft which expresses all the necessary pieces to enable the above behaviour while removing the potential errors. Put simply, you add one line to your snapcraft.yaml rather than 20, and snapcraft does the rest.

Let’s look at an example snippet, GNOME Calculator. The full source is in this snapcraft.yaml on GitLab. Here we can see an extension listed - gnome-3-34, and the base set to core18.

confinement: strict
base: core18

apps:
  gnome-calculator:
    command: usr/bin/gnome-calculator
    extensions: [gnome-3-34]
    plugs:
      - gsettings
      - network
    desktop: usr/share/applications/org.gnome.Calculator.desktop
    common-id: org.gnome.Calculator.desktop
    environment:
      LD_LIBRARY_PATH: $LD_LIBRARY_PATH:$SNAP/lib/gnome-calculator

So once built, this snap will consume “content” (GNOME binaries and libraries) from a snap called gnome-3-34-1804. You can pull back the curtain and see what the extensions expands to with the snapcraft expand-extensions command. Let’s see what that one line adds in the background at build time:

$ diff -y <(cat snap/snapcraft.yaml) <(snapcraft expand-extensions) | wc -l
143

Ok, Lots. I’ve put it here if you want to see. In short, it plugs interfaces to common resources that GNOME applications need, connects the necessary paths in this snap to the content snap(s) and sets the environment up so the application feels at home.

Just like the rest of snapcraft the code that makes these extensions work is open source, and lives in the snapcraft github if you’re interested in seeing how all this works.

Back in the GNOME calculator snap, there’s also a bit of a kludge down the bottom of that yaml which does a “cleanup” to ensure there absolutely aren’t any duplicated files between the resulting gnome-calculator snap and the gnome-3-34-1804 snap. That’s wasteful, and can cause unexpected behaviour if the libraries get loaded from the “wrong” place.

  # Find files provided by the base and platform snap and ensure they aren't
  # duplicated in this snap
  cleanup:
    after: [gnome-calculator]
    plugin: nil
    build-snaps: [core18, gtk-common-themes, gnome-3-34-1804]
    override-prime: |
      set -eux
      for snap in "core18" "gtk-common-themes" "gnome-3-34-1804"; do
        cd "/snap/$snap/current" && find . -type f,l -name *.so.* -exec rm -f "$SNAPCRAFT_PRIME/{}" \;
      done

Get to the point

Ok, so far so groovy, so what’s the update Alan?

The point

Glad you asked! You’ll note above the references to core18 and Ubuntu 18.04 LTS. If you’re packaging an application which needs to be built against a newer LTS, this didn’t help. The extensions need to be updated for each LTS, and thus each base. There’s work going on between Ken from the Ubuntu Desktop Team and Sergio & Chris on the snapcraft side to update the extension.

It’s not completely ready yet, but you (snap publishers) can test drive it. As the extension is (as I write this) marked as experimental, you’ll need a very new build of snapcraft. Here’s what you need to do.

Update snapcraft

Get the latest snapcraft from the edge channel, I used revision 6002 for my tests.

snap refresh snapcraft --edge

Tweak your yaml

Update your snap to use core20 as the base, and gnome-3-38 as the extension name. If you’re using a cleanup section like the example above, make sure to update references there too, to core20 and gnome-3-38-2004.

Update any stage-packages which may have changed between one LTS and the next. You’ll soon know which ones have changed when you try and build the snap, and packages aren’t found. For example on one snap I had to update libcurl3 to libcurl4. Use something like apt search or https://packages.ubuntu.com/ to discover updated package names between releases.

Build and test

Rebuild your snap, using the super special --enable-experimental-extensions option. This will use an Ubuntu 20.04 LTS container or VM in which to build your snap. It’ll use the new extension which in turn will use the new GNOME 3.38 based content snap.

Examples

Here’s some examples I did this morning.

The diffs are mostly just as I outlined above:

Xonotic diff

Danger Will Robinson

Note: As this experimental feature is only in the edge builds of snapcraft, you can’t easily use this on the launchpad build system. I’m told it should land in a release soon though, and the more people who test it out the better. nudge nudge, hint hint

Try out the new extension, install your updated snap and test it out! Report any issues over on the snapcraft forum.