Packaging and Deploying Ubuntu Frame Snaps on the Desktop

Packaging your application as a Snap for IoT graphics

For use with Ubuntu Core, your application needs to be packaged as a snap. This will also allow you to leverage Over The Air updates, automatic rollbacks, delta updates, update semantic channels, and more. If you don’t use Ubuntu Core, but instead another form of Linux, we recommend you use snaps to get many of these advantages.

There’s a lot of information about packaging snaps online, and the purpose here is not to teach about the snapcraft packaging tool or the Snap Store. We will, instead, focus on the things that are special to IoT graphics.

Much of what you find online about packaging GUI applications as a snap refers to packaging for desktop. Some of that doesn’t apply to IoT as Ubuntu Core and Ubuntu Server do not include everything a desktop installation does and the snaps need to run as daemons (background services) instead of being launched in a user session. In particular, you should ignore various Snapcraft extensions that help writing snap recipes that integrate with the desktop environment (e.g. using the correct theme).

Writing snap recipes without these extensions is not difficult as we’ll illustrate for each of the example programs used in the previous section.

First, you will clone a repository containing a generic Snapcraft recipe for IoT graphics.

In the same terminal window you opened at the start of the last section, type:

git clone https://github.com/MirServer/iot-example-graphical-snap.git
cd iot-example-graphical-snap

If you look in snap/snapcraft.yaml, you’ll see a generic “snapcraft recipe” for an IoT graphics snap. This is where you will insert instructions for packaging your application. This is how the .yaml file looks like:

The customised snapcraft recipe for each example described in this guide (i.e. GTK, Qt and SDL2) is on a corresponding branch in this repository:

$ git branch -a
* master
  remotes/origin/GTK3-mastermind
  remotes/origin/HEAD -> origin/master
  remotes/origin/Qt5-bomber
  remotes/origin/SDL2-neverputt
  remotes/origin/master

Once you have the customised snapcraft recipe you can snap your example applications.

Example Applications

GTK Example: Mastermind

GTK Example: Mastermind

Switch to the GTK example branch. Then use snapcraft to build the snap:

git checkout GTK3-mastermind
snapcraft

Snapcraft is the packaging tool used to create snaps. We are not going to explore all its options here but, to avoid confusion, note that when you first run snapcraft, you will be asked “Support for ‘multipass’ needs to be set up. Would you like to do it now? [y/N]:”, answer “yes”.

After a few minutes, the snap will be built with a message like:

Snapped iot-example-graphical-snap_0+git.7c73b6a_amd64.snap

You can then install and run the snap:

sudo snap install --dangerous *.snap
snap run iot-example-graphical-snap

The first time you run your snap with Ubuntu Frame installed, you are likely to see a warning:

WARNING: wayland interface not connected! Please run: /snap/iot-example-graphical-snap/current/bin/setup.sh

(gnome-mastermind:814838): Gtk-WARNING **: 14:13:26.644: Locale not supported by C library.

    Using the fallback 'C' locale.

Unable to init server: Could not connect: Connection refused

(gnome-mastermind:814838): Gtk-WARNING **: 14:13:26.649: cannot open display:

The first WARNING is the key to the problem and comes from one of the scripts in the generic recipe. While developing your snap (that is, until your snap is uploaded to the store and any necessary “store assertions” granted), connecting any “interfaces” your snap uses needs to be done manually. As the message suggests, there’s a helper script for this. Run it and try again:

/snap/iot-example-graphical-snap/current/bin/setup.sh
snap run iot-example-graphical-snap

Now Frame’s “Mir on X” window should contain the “Mastermind” game.

Close that (Ctrl-C) and try the next example:

Qt Example: Bomber

Qt Example: Bomber

If you followed the GTK example, delete the .snap file that was created to avoid confusion:

rm *.snap

Now switch to the Qt first-try example branch. Then build, install, and run the snap:

git checkout Qt5-bomber-first-try
snapcraft
sudo snap install --dangerous *.snap
snap run iot-example-graphical-snap

If you’ve been paying attention, you’ll notice that the branch name Qt5-bomber-first-try is not what you might expect. This is to show you the sort of problem you might encounter:

Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.


QSocketNotifier: Can only be used with threads started with QThread


"Session bus not found\nTo circumvent this problem try the following command (with Linux and bash)\nexport $(dbus-launch)"

This didn’t work as the bomber application requires a DBus “session bus”. To solve this issue, you can provide one within the snap using dbus-run-session. You can see exactly how this is done by comparing branches:

git diff Qt5-bomber-first-try Qt5-bomber

Now switch to the Qt example branch. Then build, install and run the snap:

git checkout Qt5-bomber
snapcraft
sudo snap install --dangerous *.snap
snap run iot-example-graphical-snap

Now Frame’s “Mir on X” should contain the “Bomber” game.

Close that (Ctrl-C) and try the next example:

SDL2 Example: Neverputt

SDL2 Example: Neverputt

If you followed the Qt example, delete the .snap file that was created to avoid confusion:

rm *.snap

Now switch to the SDL2 example branch. Then build, install, and run the snap:

git checkout SDL2-neverputt
snapcraft
sudo snap install --dangerous *.snap
snap run iot-example-graphical-snap

Now Frame’s “Mir on X” window should contain the “Neverputt” game.

But you are likely to see a warning as Neverputt uses additional plugs that have not been connected:

WARNING: hardware-observe interface not connected! Please run: /snap/iot-example-graphical-snap/current/bin/setup.sh

WARNING: joystick interface not connected! Please run: /snap/iot-example-graphical-snap/current/bin/setup.sh

ALSA lib conf.c:4120:(snd_config_update_r) Cannot access file /usr/share/alsa/alsa.conf

Failure to initialize SDL (Could not initialize UDEV)

You have warnings requesting that the setup script is run. This is because the Neverputt snap needs some interfaces that you haven’t connected yet, and this could be the case with other applications that you build. Identifying the interfaces needed by your application and adding them to the snapcraft.yaml recipe is one of the things you need to do at this stage.

Run the setup script to connect the missing interfaces, and try again:

/snap/iot-example-graphical-snap/current/bin/setup.sh
snap run iot-example-graphical-snap

Close that (Ctrl-C) and close the Ubuntu Frame window. Your application has been successfully snapped.

Further Reading

To learn how to package Ubuntu Frame applications for embedded devices, follow this how-to.

1 Like