Parts, together with plugins, are one of the key components to any snapcraft project, what follows intends to explore what parts can do after a quick recap on some concepts.
bases
A base
in snapcraft defines where the building of a snap should take place and once it is built, where it should run.
As an example, two prominent bases are core
and core18
.When building, these use a stack based out Ubuntu 16.04LTS for the former and Ubuntu 18.04LTS for the latter. This information is encoded in the project’s snapcraft.yaml
as a top level keyword base
. Invoking snapcraft
will trigger the correct behaviour.
Read more about bases here
lifecycle
A part is the basic building block for a snapcraft project, it defines the recipe to build a specific source, a basic example of a part can be:
parts:
hello-part:
source: gnu-hello.tar.gz
plugin: autotools
The plugins defined in a part have the knowledge on how to build that specific source, to get a list of the available plugins run snapcraft list-plugins
.
Find more about using the different language specific plugin guides here
All parts, by means of the logic encoded in the plugins, go through a lifecycle. These are the lifecycle steps each part goes through irrespective of the chosen plugin:
- pull
- build
- stage
- prime
Each of these lifecycle steps is exposed through the command line and can be part specific or apply to all parts in a project:
snapcraft pull [<part-name>]
snapcraft build [<part-name>]
snapcraft stage [<part-name>]
snapcraft prime [<part-name>]
For completion, the resulting snap is generated by calling snapcraft snap
which is also the implicit command, so usually this is invoked as just snapcraft
.
Each lifecycle step depend on the previous, so to reach the desired lifecycle step, all prior lifecycle steps need to have run.
Parts can also depend on each other, this is usually exposed through the after
keyword in snapcraft.yaml
. This adds a new dependency to the lifecycle in that all dependant parts must be staged prior for the depending parts’ lifecycle can run.
part directories
Each part when run through its lifecycle (the lifecycle itself depends on the selected plugin) will have different working directories:
parts/<part-name>/src
used to pull the source during the pull step.parts/<part-name>/build
used to build the pulled sources during the build step.parts/<part-name>/install
a location to privately install built artifacts during the build stepstage
a shared place where parts can expose artifacts to other parts such as development libraries, headers or others (e.g.; pkgconfig files).prime
a shared place where the final artifacts are to be placed, this directory is the reflection of the resulting snap.
overriding the lifecycle
Sometimes the default behaviour of a plugin is not enough or not desired, for this purpose there are two methods:
- Using the
override-<step-name>
keyword (read more on overriding steps) - Using a local plugin, by inheriting from the parent or scaffolding from the original (read more on local plugins)
part environment
When a part is run, snapcraft sets the following environment variables so they can be accessed through overrides or build specific logic for a project that contemplates snapcraft in its code path (e.g.; a Makefile
that has an install target that transparently contemplate SNAPCRAFT_PART_INSTALL
)
directories
These are the exposed directory related environment variables, cosideration on how the lifecycle works should be taken when using some of these:
- SNAPCRAFT_PROJECT_DIR: the absolute path to the root of the snapcraft project
- SNAPCRAFT_PART_SRC: absolute path to where a part’s sources are pulled, it is also the part’s working directory for the pull step
- SNAPCRAFT_PART_BUILD: absolute path to where a part’s sources are built, it is also the part’s working directory for the build step
- SNAPCRAFT_PART_INSTALL: absolute path to where a part’s is to install artifacts to be staged.
- SNAPCRAFT_STAGE: absolute path to where files are staged.
- SNAPCRAFT_PRIME: absolute path to where files are primed.
facilities
Certain facilitating environment variables are also set:
- SNAPCRAFT_ARCH_TRIPLET: the architecture triplet used for the selected base.
- SNAPCRAFT_PARALLEL_BUILD_COUNT: the preferred amount of jobs the project is to be built with
- SNAPCRAFT_PROJECT_NAME: the snapcraft project name (i.e.;
name
fromsnapcraft.yaml
) - SNAPCRAFT_PROJECT_VERSION: the snapcraft project version as set in
snapcraft.yaml
- SNAPCRAFT_PROJECT_GRADE: the snapcraft project grade as set in
snapcraft.yaml
build flags
And lastly, specific build flags are also set:
- CFLAGS: empty unless
after
is used in the part and headers are staged in the common include paths for which they will be included (i.e.; paths added with-I
) - CPPFLAGS: same behavior as CFLAGS
- CXXFLAGS: same behavior as CFLAGS
- LDFLAGS: empty unless
after
is used in the part and headers are staged in the common library paths (i.e.; paths added with-L
) - PKG_CONFIG_PATH: empty unless
after
is used in the part and .pc files are staged in the common pkgconfig paths.
A plugin can also add its own set of environment variables or expand on these existing build related ones.
It is sometimes useful to override or expand on the defaults, for that, the build-environment
keyword can be used, here’s a basic example:
parts:
hello-part:
source: gnu-hello.tar.gz
plugin: autotools
build-environment:
- CFLAGS: "$CFLAGS -O3" # add -O3 to the existing flags
- LDFLAG: "-L$SNAPCRAFT_STAGE/non-standard/lib" # override default flags and search for libraries in a non-standard path
hardening
When considering the GNU build tools, the same applies and when using different bases, different build flags could be applied depending on the selected base.
On Ubuntu based bases you can verify which hardening flag has been applied to your built artifacts by running hardening-check
against your built binaries in the priming area.
As an example:
hardening-check prime/usr/bin/indicator-sensors
prime/usr/bin/indicator-sensors:
Position Independent Executable: yes
Stack protected: yes
Fortify Source functions: yes
Read-only relocations: yes
Immediate binding: yes