How Snapcraft builds snaps

The Snapcraft tool can perform a variety of operations, including:

  • Snap creation operations like build, stage, prime, pack, etc.
  • Store management operations like login, register, sign-build, etc.
  • Extensions-specific operations like expand-extensions and list-extensions.

These operations translate into practical tasks like:

  • It can build snaps locally or send remote tasks to Launchpad.
  • It allows the developer to register and log into the Snap Store.
  • It can upload snaps to the Snap Store.
  • It can promote snaps to different channels.

The list of available global options and commands can be checked with one of:

snapcraft help
snapcraft help --all

snapcraft.yaml

Snaps are created using a build recipe defined in a file called snapcraft.yaml.

When the snapcraft tool is executed on the command line, it will look for the file in the current project work directory, either in the top-level folder or a snap subdirectory. If the file is found, snapcraft will then parse its contents and progress the build toward completion.

snapcraft.yaml is a configuration file written in the YAML language, with stanzas defining the application structure and behavior. When snapcraft runs and parses this file, it will use the declared information to build the snap. For developers more familiar with the traditional Linux build systems, the process is somewhat similar to the use of a Makefile or an RPM spec file.

You can create the snapcraft.yaml file manually, or you can run the snapcraft init command to create a template file in the snap subdirectory.

snapcraft init

A generated template file contains just enough data to build, split across three stanzas:

  • Metadata.
  • Confinement level.
  • Build definition.

Main definitions inside snapcraft.yaml

There is no one way for how a snap ought to be assembled. However, most snapcraft.yaml files have the same common elements, including a number of mandatory declarations. Below is a short list of these keys, which will be further explained in the Examples sections later in the tutorial.

  • Metadata - describes the snap functionality and provides identifiers by which the snap can be cataloged and searched in the Snap Store.
  • Security confinement - describes the level of security of the snap.
  • Base - describes which set of libraries the snap will use for its functionality. The base also defines the operating system version for the snap build instance in the virtual machine or container launched by Snapcraft. For instance, base: core18 means that Snapcraft will launch an Ubuntu 18.04 virtual machine or container, the set of tools and libraries used inside the snap will originate from the Ubuntu 18.04 repository archives, and the snap applications will “think” they are running on top of an Ubuntu 18.04 system, regardless of what the actual underlying Linux distribution is.
  • Parts - describes the components that will be used to assemble the snap.
  • Apps - describes the applications and their commands that can be run in an installed snap.

It is important to note several additional details:

  • A snap may contain one or more parts.
  • A snap may contain one or more applications
  • Parts can be pre-assembled binaries or they may be compiled as part of the build process.
  • The parts section of the snapcraft.yaml file uses Snapcraft build system or language-specific plugins to simplify the build process.
  • The parts section may also include a list of build packages (build-packages) that will be used to create the snap applications but will not be included in the final snap. For instance, gcc or make.

The parts section may also include a list of stage packages (stage-packages) that will be used by the snap’s applications at runtime, e.g.: python-bcrypt. These will be obtained from the repository archives in the build instance.

Snapcraft build lifecycle

Snaps are built in several steps, collectively known as the “lifecycle”:

  • Pull - At this step of the snap build process, Snapcraft downloads or retrieves the components needed to build the relevant part. For instance, if source points to a Git repository, the pull step will clone that repository.
  • Build - Snapcraft constructs the part from the previously pulled components. Since the snap ecosystem supports multiple types of applications (C, Java, Go, Rust, Python, etc.), the build definition also needs to include a specification on how to construct the part. This is done by declaring a Snapcraft plugin. Parts are processed linearly, unless there is a dependency order declared.
  • Stage - Snapcraft copies the built parts into the staging area. Parts are not ordered at this point, and there might be an additional level of processing to ensure the snap contains the required files, and that there are no conflicts between parts. This is an advanced topic beyond the scope of this tutorial.
  • Prime - Snapcraft copies the staged components into the priming area, where the files will be placed in their final locations (folder and files path hierarchy) for the resulting snap. The prime step is similar to the stage step, but it may exclude certain components from the stage step.
  • Pack - Snapcraft packs the assembled components in the prime directory into a single archive.

Snapcraft build output

The artifact of a successful Snapcraft build run is a snap file, which is itself a compressed Squashfs archive distinguished by the .snap suffix.

A snap may contain one or more files that allow the applications to run without reliance on the underlying host system’s libraries. A snap will contain one or more applications, daemons, configuration files, assets like icons, and other objects.

Typically, the content of a snap will resemble a Linux filesystem layout:

drwxr-xr-x 10 igor igor  4096 Jun 10  2020 ./
drwxrwxrwx 14 igor igor 16384 Oct 17 16:40 ../
drwxr-xr-x  2 igor igor  4096 Jun 10  2020 bin/
drwxr-xr-x 10 igor igor  4096 Jun 10  2020 etc/
-rw-r--r--  1 igor igor	14 Jun 10  2020 flavor-select
drwxr-xr-x  3 igor igor  4096 Jun 10  2020 lib/
drwxr-xr-x  2 igor igor  4096 Jun 10  2020 lib64/
drwxr-xr-x  3 igor igor  4096 Jun 10  2020 meta/
drwxr-xr-x  3 igor igor  4096 Jun 10  2020 snap/
drwxr-xr-x  7 igor igor  4096 Jun 10  2020 usr/
drwxr-xr-x  3 igor igor  4096 Feb 26  2018 var/

The end user can examine the contents of a snap by either looking through the ‘prime’ directory of the build environment, or by extracting the snap archive:

unsquashfs <file>.snap
1 Like

It might be worth mentioning the “squashfuse” package and command, which allows mounting a snap file read-only if all you want to do is examine its contents. This avoids having to unpack the entire snap if you just want to peruse and have no interest in changing anything.

This is a duplication of already existing documentation and isn’t adding anything. See here: https://snapcraft.io/docs/parts-lifecycle

I lack:

  • good examples.
  • best practices
  • complete reference with examples.
  • un-scattered documentation (like this)
  • better explanation of what is “automatic” vs “the snap-authors responsibility”. I am always left in fear that I don’t know if snapcraft will do things autmatically or if I should.

Look, snaps are great. But its a MASSIVE time-consumer to produce even simple snaps.

READ THIS as to get a very good insight in why people do not go for snap: https://github.com/ipfs/kubo/issues/8688

TL:DR: It is way to complicated and swallows valuable developer time.

I totally resonate with this above comment. I’ve spent WAY TO MUCH time trying to produce even small examples and have never been able to understand the build process - at all. I’m going guess-work mostly when snapping. I’ve really tried.

The success/failure of snap has its root cause in this: “Producing/debugging snaps swallows too much of my time - with little payback.”

The constructive thing here should likely be to try to explain alot better how the snapping process works - what plugins do and don’t - what is automatic and not etc. etc. etc.

Hello, and thanks so much for the considered feedback.

This document in particular is intended to exist in relative isolation within the Snapcraft How-to Quickstart section, which isn’t always apparent from the forum but easier to see in the navigation (https://snapcraft.io/docs/how-snapcraft-builds).

However, I do think you’re right about what we’re lacking, and we are aware of a lot of these problems, especially when it comes to fragmentation and duplication. I also totally agree about providing good, simple examples.

It won’t be visible immediately, but we do genuinely have a plan to rationalise, revise and restructure our Snapcraft docs which we have already started working on. We’ll hopefully announce this on the forum (more formally) when we have something objective to share.

1 Like

Thanx for getting back on this. I have worked with the Juju community - that used to suffer from the same problem.

But it was addressed and the project took of and is taking off much more after sorting out docs and truly focusing on users ability to learn and train with “complete, focused, clear” documentation.

The work done there by the people at Canonical on this has been monumental.

1 Like

What’s with that early reference to the “f sub-folder”?

No idea where that came from (mae culpa). It probably should have been a reference to also looking in the snap directory for snapcraft.yaml. This is fixed now.

Re: the last paragraph, if the reader is the one building the snap, she can just examine the generated prime/ directory to see the contents of the snap.

Good suggestion, thanks!