If you haven’t heard, snaps are a new, modern packaging format made by the guys at Ubuntu. Snaps give every app a confined environment to live in, making desktops more secure and dependencies less of a hassle. One common way to create a snap is to simply use existing packages from the Ubuntu archives.
Let’s try to create a snap for the game pingus. pingus
is a great little Lemmings clone that we can easily convert to a snap. We’ll start by installing the necessary dependencies for snap building (see the snapcraft website for more):
1
|
|
Now we can initialize a project directory with snapcraft:
1 2 |
|
snapcraft init
creates the following sample file to give us an idea of what we’ll need to provide.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Most of these values for our pingus
snap should be obvious. The interesting markup here is in parts
, which is where we’ll describe how to build our snap. We’ll start by taking advantage of the nil
plugin to simply unpack the pingus
deb from the archive. We define our list of debs to install in a list called stage-packages
. We’ll also define another section, apps
, to tell snapcraft
what binaries we want to be able to execute. In our case, this will just be the pingus
command. Here’s what my first draft looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Nice, right? Building and installing our snap is easy:
1 2 3 |
|
We used devmode
here because our app will be running unconfined (a topic for another blog post). Now, for the moment of truth! The snap tools automatically put our new app in PATH
, so we can just run pingus
:
1 2 |
|
¡Ay, caramba! We’ve run into a fairly common issue while snapping legacy software: hardcoded paths. Fortunately, the corresponding pingus
executable is very simple. It’s trying to execute a command living in /usr/lib/games/pingus
, which is not in our snap’s PATH
. The easiest way to fix this is to fix the pingus
executable. Since we don’t want to spend time modifying the upstream to use a relative path, we can create our own version of the pingus
wrapper locally and copy it into our snap. The only change to this new wrapper will be prepending the snap’s install path $SNAP
to the absolute paths:
1 2 |
|
Now we can update our yaml file with a new part called env
which will use the dump
plugin to copy our wrapper file into the snap. We’ll also update our command to call the wrapper:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
When you run snapcraft
this time, the env
part will be built. After performing another install, you can run pingus
, and you should be greeted with one of the best Lemmings clones available! Because we’re running unconfined in devmode, this all just works without any issues. I intend to write another blog post in the near future with the details on confining pingus
, so look out for that soon. I may also go into detail on building more complex cases, such as building snaps from source and building custom plugins, or reviewing a case study such as the libertine
snap.
For much, much more on snaps, be sure to visit snapcraft.io. If you’re looking for a published version of pingus as a snap, you can try sudo snap install --devmode --beta pingus-game
, and you can run the game with pingus-game.pingus
.
Source code available at https://github.com/larryprice/pingus-snap.