Recently, we published several blog posts, aimed at helping developers enjoy a smoother, faster, more streamlined experience creating snaps. We discussed the tools and tricks you can employ in snapcraft to accelerate the speed at which you iterate on your builds.
We want to continue the work presented in the Make your snap development faster tutorial, by giving you some fresh pointers and practical tips that will make the journey even brisker and snappier than before.
You shall not … multipass
Multipass is a cross-platform tool used to launch and manage virtual machines on Windows, Mac and Linux. Behind the scenes, snapcraft uses multipass to setup a clean, isolated build environment inside which your snaps will be created. Multipass leverages KVM (qemu) to create virtual machine instances. While this is handy when running natively on a host, this approach is not reliable for nested virtual machines or systems with limited KVM support.
Indeed, if you are running snapcraft inside a VM that does not support hardware acceleration passthrough, you’re running on a host with a CPU that does not support hardware acceleration, hardware acceleration is disabled in BIOS, or KVM modules are not loaded into memory, you will most likely see the following error:
failed to launch: Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
If you encounter this problem – which can happen if you’re using Linux as a virtual machine, a setup that is quite popular with a large number of developers, this means that you cannot use multipass for your builds. However, snapcraft supports several other clever methods that will let you successfully create your snaps in a safe, isolated manner.
You can run snapcraft with the LXD backend. This requires that you have the LXD software installed and configured on your system. Start by installing and configuring the tool:
snap install lxd
To verify that LXD has been set up correctly, you can start an Ubuntu 18.04 container instance and open a shell inside it:
lxc launch ubuntu:18.04 test-instance
lxc exec test-instance -- /bin/bash
You will now have a minimal Ubuntu installation. You can exit and destroy the container, or continue working inside it. For instance, you can use it now to setup snapcraft, installation additional software you may need, as well as copy any assets, like your project files and source code, into the container.
Outside the container environment, if you want to invoke snapcraft with LXD, you can run snapcraft with the –use-lxd flag:
Destructive mode & manual container setup
By default, snapcraft uses multipass to start virtual machine instances and run the build inside them. This mode will not work when snapcraft is invoked inside the container environment. To that end, snapcraft needs to be invoked with the –destructive-mode argument. Please note that this feature is intended for short-lived CI systems, as the build will install packages on the (virtual) host, may include existing files from the host and could thus be unclean.
In this case, the full sequence of a manual container setup would include the following steps:
- Manually start a container (lxc launch).
- Copy your snapcraft.yaml into the container (lxc file push).
- Open an interactive shell (lxc exec).
- Inside the container, run snapcraft –destructive-mode flag. Please be extra careful and make sure that you run this command in the right shell, so you don’t accidentally do this on your host system. You may end up retrieving various packages and libraries that could potentially conflict with your setup.
- Once you have successfully completed the build, you can retrieve the snap from inside the container (lxc pull).
- Stop and/or destroy the container instance (lxc stop).
In the tutorial linked above, we talked about the debug flag, which lets you step into the build environment on failure, allowing you to examine the system and understand better what might have gone wrong. Similarly, you can step into the virtual machine or container upon successful build using the –shell-after flag.
You also have the option to run your snaps with the –shell flag. This can be useful in troubleshooting runtime issues, like missing libraries, permissions – or other errors that you have encountered while reviewing your snap before pushing to the store. Alongside the try and pack commands, which we examined last week, you get a great deal of flexibility in nailing down issues and bugs during the development phase.
If you’ve ever raced a car, you know the best lap times aren’t decided by straight line dashes, they are decided by how fast you go through corners. Slow in, fast out. This article comes with a handful of useful, advanced tricks – the ability to use different provisioning backends, the destructive mode and the after-build shell. These should help you enjoy higher, faster productivity creating snaps. If you have any feedback or questions on this topic, please join our forum for a discussion.
No iconic Lord of the Rings phrases were harmed in the writing of this article.