A snap build consists of the processing one or more software parts. Each part follows an ordered series of five steps, which forms the lifecycle, ensuring a coherent and reproducible build process.
This page aims to help anyone who seeks to build a snap and understand the inner workings of parts – including their steps, commands, directories, and dependencies.
Lifecycle
A part goes through five steps:
-
Pull. Downloads or otherwise retrieves the components needed to build the part.
You can use the
source-*
keys of a part to specify which components to retrieve. For instance, ifsource
points to a Git repository, the pull step will clone that repository. -
Build. Constructs the part from the previously-pulled components.
The
plugin
of a part specifies how it’s constructed. Themeson
plugin, for example, executesmeson
andninja
to compile source code.Each part is built in a separate directory, but it can use the contents of the staging area if it specifies a dependency on other parts using the
after
key. See Processing order and dependencies for more information.To rename or move files, you can use the
organize
key. -
Stage. Copies the built components into the staging area.
This is the first time all the different parts that make up the snap are actually placed in the same directory. If multiple parts provide the same file with differing contents, you will get a conflict. You can avoid these conflicts by using the
stage
key to enable or block files coming from the part. You can also use this key to filter out files that aren’t required in the snap itself, for example build files specific to a single part. -
Prime. Copies the staged components into the priming area.
This is very similar to the stage step, but files go into the priming area instead of the staging area. The prime step exists because the staging area might still contain files that are required for the build but not for the snap. For example, if you have a part that downloads and installs a compiler, then you stage this part so other parts can use the compiler during building. You can then use the
prime
filter key to make sure that it doesn’t get copied to the priming area, so it doesn’t take up space in the snap.To apply specific permissions to files, you can use the
permissions
key.Some extra checks are also run during this step to ensure that all dependencies are satisfied for a proper run time. If the snap is classically-confined, then files will be scanned and, if needed, patched to work with this confinement mode.
-
Pack. Takes the entire contents of the
/prime
directory and packs it into a snap file.
Commands
Each of the lifecycle steps can be run from the command line, and the command can be part-specific or applied to all parts in a project.
snapcraft pull [<part-name>]
snapcraft build [<part-name>]
snapcraft stage [<part-name>]
snapcraft prime [<part-name>]
snapcraft pack
Each command also executes the previous lifecycle steps, therefore snapcraft pack
executes all the lifecycle steps chained together.
It’s possible to access the part environment at any stage by running one of the lifecycle commands with the --shell
argument. For example, snapcraft prime --shell
processes the parts up to the prime step, then opens a shell. See Iterating over a build for more details.
Part directories
When running through its lifecycle steps, a part will use different working directories inside the snap. The directory names closely follow the step names.
Environment variable | Directory | Purpose |
---|---|---|
CRAFT_PART_SRC |
/parts/<part-name>/src |
The location of the source after the pull step |
CRAFT_PART_BUILD |
/parts/<part-name>/build |
The working directory during the build step |
CRAFT_PART_INSTALL |
/parts/<part-name>/install |
Contains the results of the build step and the stage packages. It’s also the directory where the organize event renames the built files |
CRAFT_STAGE |
/stage |
Shared by all parts, this directory contains the contents of each part’s CRAFT_PART_INSTALL after the stage step. It can contain development libraries, headers, and other components (e.g. pkgconfig files) that need to be accessible from other parts |
CRAFT_PRIME |
/prime |
Shared by all parts, this directory holds the final components after the prime step |
CRAFT_PROJECT_DIR |
Path to the current project’s subtree in the filesystem | Used to access resources from the project’s subtree, such as an icon or version file |
Overriding a step
Each plugin defines the default actions that happen during a step. This behavior can be changed in two ways:
- By using
override-<step-name>
in the project file. See Overriding steps to see how. - By using a local plugin. This can inherit the parent plugin or scaffolding from the original. See Local plugins for a practical guide. Using a local plugin was deprecated in core20 and removed in core22.
Processing order and dependencies
By default, snapcraft pack
runs the same lifecycle step of all parts before moving to the next step. However, you can change this behavior using the after
key in the definition of a part in the project file. This creates a dependency chain from one part to another.
The ordering rules are as follows:
- Parts are ordered alphabetically by name.
- When a part requires another part (using the
after
key), the required part will go through the build and stage steps before the initial part can run its build step.
Note that each lifecycle step depends on the completion of the previous step for that part, so to reach a desired step, all prior steps need to have successfully run. Renaming or adding parts and modifying or removing after
keys can change that order.
Example of default ordering
parts:
A:
plugin: go
C:
plugin: go
B:
plugin: go
Pulling A
Pulling B
Pulling C
Building A
Building B
Building C
Staging A
Staging B
Staging C
...
Example of dependent ordering
parts:
A:
plugin: go
after:
- C
C:
plugin: go
B:
plugin: go
Pulling C
Pulling A
Pulling B
Building C
Skipping pull for C (already ran)
Skipping build for C (already ran)
Staging C (required to build 'A')
Building A
Building B
Skipping stage for C (already ran)
Staging A
Staging B
...
In the above example, part A is built after part C is successfully built and staged.
Lifecycle processing diagram
Further reading
If you want to learn more about the Snapcraft ecosystem, see the following resources:
- Snapcraft for an overview of Snapcraft.
- Adding parts to understand what parts are and how to use them.
- Parts environment variables for a list of part-specific environment variables that can be accessed to help build a part.
- Snapcraft plugins to learn more about this essential component of any part.
- Scriptlets for more details on how to override steps.