How to Snap your Awesome Haskell App

Lettier
5 min readFeb 12, 2018

--

There comes a time in most every app’s life when it needs distribution. If you can, it’s best to ship it in as many ways as possible. Still, if you’re targeting Ubuntu—or Linux in general — a decent solution is to create a snap.

What is a snap?

According to the Snapcraft website, “Snaps are universal Linux packages.” The end user goal is to provide a no-hassle way to download software and keep it up to date as new revisions come out. No building, compiling, transpiling, linking, making, make installing, and/or dependency downloading — just download the snap and you’re off to the races.

So how do I get started snapping my app?

I recommend firing up a virtual machine running Ubuntu 16.04 even if you use Ubuntu as your daily driver. This will give you a clean slate and you’ll have the most documentation/support at your disposal.

Before we continue, I’ll make this concrete by going over what it took to snap Movie Monad — a mildly-popular Haskell app. For another example, checkout Gifcurry, a great Haskell app that converts videos to GIFs.

With the virtual machine up, you’ll need to install snapcraft and everything needed to run its cleanbuild command. You could do away with the clean build approach but this will help you work out the kinks faster and keep your build nice and well…clean. I once failed the linting process because a stray Vim .swp file found its way into the final squashFS file system.

mkdir -p ~/my-snap-builds/my-app/snap/gui
sudo apt install snapcraft lxd lxd-client
sudo usermod -a -G lxd myusername
sudo lxd init
cd ~/my-snap-builds/my-app
snapcraft init

If everything went to plan, you should end up with a directory structure like this.

~/
my-snap-builds/
my-app/
snap/
gui/
snapcraft.yaml

If it is a GUI app, you’ll want to place a .desktop file and icon under gui/.

How do I fill out the snapcraft.yaml file?

The first entries of the file are the metadata for use in the snap store. I recommend a snappy summary since this is all they’ll have to go on when searching the snap store.

snap search movie-monad
# Name Version Developer Notes Summary
# movie-monad 0.0.4.0 lettier - A free and simple to use video player built with Haskell.

The grade must be stable to release the snap into the stable channel. Once you figure out what permissions or “plugs” your app will need, make sure to set the confinement to strict.

After the metadata, there are two major sections — the apps and the parts. For Movie Monad, there’s only one app. The command subsection contains a “desktop launcher” which is a convenience wrapper provided by the Snapcraft team. If your app is GTK or QT based, be sure to look into it.

The Movie Monad snapcraft.yaml file has two major parts. There is the Movie Monad build/install part and the desktop-gtk3 part which sets up the GTK+ desktop environment. The Snapcraft team provides the desktop-gtk3 part. I list it under after informing the Snapcraft build system to create that part after the Movie Monad part.

If your app has a standard build and install process (./configure, make, make install) then you can use a plugin. I’ve deviated from the norm, so instead of a plugin, I created my own scriplets.

Scriptlets are shell scripts sourced directly from your snapcraft.yaml, to change the behaviour of a plugin. — https://docs.snapcraft.io/build-snaps/scriptlets

The most elaborate scriptlet is the install one. In this scriplet, I take the output files from cabal and move them all over to the install directory. It is the install directory that the Snapcraft build system will squash into a snap file.

Backing up a bit, you’ll see a list of build-packages and stage-packages. The build packages are the software you’ll need to build your app’s executable file(s). The stage packages are more than likely the run-time dependencies your app needs. The build packages do not make it into the final snap file — so if you only need it to build — do not list it under stage packages.

Movie Monad uses the Haskell Stack build tool to make the build process as reproducible as possible. Unfortunately, the resulting executable is not all that relocatable or portable. Portable meaning you can move the build directory around and the app will still run. Snapcraft recommends that your app be relocatable.

The main concept to snap your software is that your application needs to be relocatable. It’s a good practice to not rely on hard coded paths like /etc and such, but to read your assets, configuration, hooks from subdirectories of your application. — https://docs.snapcraft.io/snaps/philosophy

Having the build be portable is important since Movie Monad relies on data files at run time. So to have both a reproducible and relocatable build, Movie Monad uses both Stack and Cabal. After the build scriptlet finishes, the .cabal-sandbox directory is created and its contents are relocated into the install scriptlet.

With your snapcraft.yaml file done, run the clean build command.

cd ~/my-snap-builds/my-app
snapcraft cleanbuild
ls
# my-app_version_arch.snap my-app_version_source.tar.bz2 snap/

How do I get my snap into the snap store?

With your snap built, you’ll need to setup an account if you haven’t already.

cd ~/my-snap-builds/my-app
snapcraft login
snap login myusername@myemailprovider.com
snapcraft register my-app
snapcraft push my-app_version_arch.snap
snapcraft release my-app 1 stable

And with that, you’ve snapped your awesome Haskell app!

What snags, if any, did you run into?

The snapping process came together well. I did run into a bug with the Snapcraft site when trying to undo a revoked name. I had deleted my yet unreleased snap which locked me out of the name — don’t do that. The moderator noise, from the forums, was very helpful and recovered the name for me.

The snap itself does have some issues that are not present in a regular build of Movie Monad. If you run the executable out of the sandbox, all the issues go away. Based on this, the sandboxing has some issues that need work.

Where can I find more information about Snapcraft?

For more information head over to the Snapcraft site and be sure to make a stop at the forums. The community there is very helpful.

How do you use snap? What apps have you snapped? Do you like Flatpak, Snapcraft, or AppImage better? What Haskell apps do you enjoy? Let me know in the responses below. Thanks!

--

--