Igor Ljubuncic
on 23 May 2019
Last week, we published Introduction to snapcraft, a tutorial that provided a detailed overview of the snap build process. We touched on the concepts like snap ecosystem components, snapcraft command line, snapcraft.yaml syntax, and more. We’d like to expand on the first lesson, and today, we are going to talk about parts and plugins, used in the build process of snaps.
What are we going to do?
Our tasks for today include:
- Overview of parts.
- Overview of plugins.
- Basic examples.
Parts
As their name implies, parts are the raw building blocks of a snap, used to collect and build binaries and their dependencies. Each part defines a source needed to assemble your application into a snap. Parts can be anything – programs, libraries, or other needed assets.
Parts support a large number of keys and values to describe the build process. However, before we demonstrate, let’s discuss plugins too, as the two are tightly coupled.
Plugins
If you work with complex projects, having to manually define every part can be tedious. Snapcraft uses plugins, which help simplify the build process. They are declared within parts to better integrate projects using existing programming languages and frameworks.
In the background, plugins will perform various language-specific commands. For example, the nodejs plugin create parts that use Node.js and/or the JavaScript packages manager npm or yarn. Snapcraft supports many languages. To see the full list, in a command-line window, type:
snapcraft list-plugins
You can also check specific details for each plugin, like:
snapcraft help ruby
Each plugin comes with its own capabilities and language-specific keywords. To illustrate the power and flexibility of plugins, let’s examine a real snap use case.
Python example
This is a section of code from a simple snapcraft.yaml file:
parts:
tqdm:
plugin: python
python-version: python2
source: https://github.com/tqdm/tqdm.git
What do we have here?
- plugin: python declares the use of the Python plugin. It can be used for Python projects where you would want to do import Python modules with a requirements.txt, build a Python project that has a setup.py, or install packages straight from pip.
- The python-version keyword has two valid options: python2 and python3. The selected version of Python will also be included in your snap, so it will run on systems that don’t have Python installed. You can examine this by expanding the built snap with the unsquashfs command. As we’ve seen in the first guide, relative to the snap directory, you will find directories like bin, lib, usr. In the tqdm example, python2.7 will be included under usr/bin inside the snap.
- The source keyword points to the root of your Python project and can be a local directory or a remote Git repository.
Go example
Now, let’s examine a Go plugin example:
parts:
caire:
plugin: go
source: https://github.com/esimov/caire.git
go-importpath: github.com/esimov/caire
build-packages:
- build-essential
What do we have here?
- Much like what we’ve seen with the Python plugin, we declare the use of the plugin and the root of the project containing the Go code.
- Furthermore, the Go plugin will build using the version of Go available in the system’s traditional package achive. However, if you require a different version, you can use additional Go-specific keywords available in the plugin to override the defaults. Specifically, you can do this with the go-channel keyword (e.g. “1.8/stable”).
- Also, we can see another difference from the Python example. We’re also using the go-importpath keyword. When using local sources, snapcraft needs to construct a suitable GOPATH. For this it uses go-importpath to know where the sources should live within GOPATH/src.
- There’s another declaration (build-packages), which we will examine in greater detail below.
Additional parts keys
In the Go example, you can also see the use of another keyword: build-packages. This is one of the important keys available in the parts section of the snapcraft.yaml file. Specifically, build-packages defines the list of packages required to build a snap.
If you have compiled code on Ubuntu-based systems, you may be familiar with the build-essential package. This is a meta package that defines a large number of compilation tools and dependencies, like gcc, make, headers, and more.
You can also list specific packages that your project needs. For instance: libnetfilter-queue-dev or portaudio19-dev.
These packages are installed using the package manager inside the snapcraft build instance. Some other examples of parts keywords include:
- stage-packages – A list of packages required at runtime by a snap, e.g. python-bcrypt.
- prepare – This key runs a script before the plugin’s build step.
- organize – A map of files to rename.
And there are many other keys, available in the snapcraft documentation.
Conclusion
This brings us to the end of this tutorial. Today, we learned about parts and plugins, used in the build process of snaps. We also saw several language-specific examples and examined the differences between them. In the next episode, we will talk more about snap confinement.
If you have any questions or feedback, please join our forum for a discussion.
Photo by Tory Bishop on Unsplash.