Background
Although Snapcraft supports many build systems through its multitude of plugins, there are times that one’s build process falls outside of the norm, and none of the plugins quite do exactly what is needed. For example, maybe some of the source code of the part needs to be patched before it’s built. Maybe one must do some setup work before the autotools
plugin’s build step is run.
Today, Snapcraft supports these use-cases in a pretty limited manner by way of three scriptlets: prepare
, build
, and install
. These can be specified in the YAML and they surround the plugin’s build
step, where, if specified:
-
prepare
runs before the plugin’sbuild
step -
build
replaces the plugin’sbuild
step -
install
runs after the plugin’sbuild
step
There are a few reasons why this approach was incomplete. First of all, these are named somewhat confusingly. Second, they don’t cover all use-cases, such as patching, as well as a larger one discovered more recently: needing to build e.g. gsettings schemas for the entire snap after it has been primed.
Proposal
New Scriptlets
The Snapcraft part lifecycle consists of several steps, in order:
- pull
- build
- stage
- prime
The proposal is that Snapcraft adds scriptlets that can replace each of these steps, named override-<step>
. prepare
, build
, and install
will be deprecated in favor of override-build
. In order to get similar functionality, see the “Examples” section at the end.
This covers nearly all use-cases, except for one important one: building gsettings schemas. This type of thing needs to happen over the entire priming area after each part in the snap has been primed. Importantly, this needs to happen at the tail end of the overarching prime step so it works for snaps being installed with snap try
. The proposal is to add a new global scriptlet (i.e. one that does not belong to a part, but is in the root of the snapcraft.yaml
) called pre-pack
. This scriptlet will be run only after every part in the snapcraft.yaml
has been primed (when the snap.yaml
and associated data is being generated).
Communicating with Snapcraft from within scriptlets
The proposal is to include a new command-line utility solely for use within scriptlets, called snapcraftctl
. The purpose of this utility is for scriptlets to request some action or some tidbit of information from Snapcraft. To begin with, four subcommands will be supported:
-
snapcraftctl pull
Run the pull step of the lifecycle for this part. -
snapcraftctl build
Run the build step of the lifecycle for this part. -
snapcraftctl stage
Run the stage step of the lifecycle for this part. -
snapcraftctl prime
Run the prime step of the lifecycle for this part.
Examples
One could achieve functionality equivalent to today’s prepare
scriptlet by adding an override-build
scriptlet that looks like:
override-build: |
echo "I'm preparing to build..."
echo "I'm doing MORE stuff to prepare..."
# Now actually build like normal
snapcraftctl build
Similarly, to get functionality equivalent to today’s install
scriptlet:
override-build: |
# Build like normal
snapcraftctl build
echo "I'm doing more stuff after the build completes"
To patch source code after pulling:
override-pull: |
# Pull like normal
snapcraftctl pull
# Patch the code
patch -p1 < my.patch