-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(Snapcraft): move parts lifecycle into a reference #163
base: main
Are you sure you want to change the base?
Changes from all commits
d8ae70b
e99432f
fc2c9c5
9fc34e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# Parts lifecycle | ||
|
||
Parts, alongside [plugins](/t/snapcraft-plugins/4284), are a key component in any [Snapcraft](/t/snapcraft-overview/8940) project. | ||
|
||
See [Adding parts](/t/adding-parts/11473) for a general overview of what parts are and how to use them, [Scriptlets](https://forum.snapcraft.io/t/scriptlets/4892) for details on how they can be scripted outside of _snapcraft.yaml_, and <!--TO DO: Path to be added when the page is created--> [Parts lifecycle]() reference for the summarised information of this page. | ||
|
||
All parts within a project, by means of the logic encoded the plugins they're using, all go through the same series of steps. Knowing these steps, and which directories are used for each step, can help when creating more advanced snaps, and when troubleshooting build issues. | ||
|
||
- [Lifecycle steps](#heading--steps) | ||
- [Steps commands](#heading--steps-commands) | ||
- [Steps dependencies](#heading--steps-dependencies) | ||
- [Overriding a step](#heading--overriding-steps) | ||
- [Parts directories](#heading--parts-directories) | ||
|
||
--- | ||
|
||
<h3 id='heading--steps'>Lifecycle steps<sup><a href=#heading--steps>⚓</a></sup></h3> | ||
|
||
The steps of a part goes through are as follows: | ||
|
||
1. **pull**: downloads or otherwise retrieves the components needed to build the part. You can use the [`source-*` keywords](/t/snapcraft-parts-metadata/8336#heading--source) of a part to specify which components to retrieve. If `source` points to a git repository, for example, the pull step will clone that repository. | ||
1. **build**: constructs the part from the previously pulled components. The [`plugin`](/t/snapcraft-plugins/4284) of a part specifies how it is constructed. The [`meson` plugin](/t/the-meson-plugin/8623), for example, executes `meson` and `ninja` 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` keyword. See [Step dependencies](#heading--step-dependencies) for more information. | ||
1. **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` keyword](/t/snapcraft-parts-metadata/8336#heading--stage) to enable or block files coming from the part. You can also use this keyword to filter out files that are not required in the snap itself, for example build files specific to a single part. | ||
1. **prime**: copies the staged components into the priming area, to their final locations for the resulting snap. 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 keyword to make sure that it doesn't get copied to the priming area, so it's not taking up space in the snap. Some extra checks are also run during this step to ensure that all dependencies are satisfied for a proper run time. If confinement was set to `classic`, then files will be scanned and, if needed, patched to work with this confinement mode. | ||
1. **pack**: takes the entire contents of the `prime` directory and packs it into [a snap](/t/the-snap-format/698). | ||
|
||
<h3 id='#heading--steps-commands'>Steps commands<sup><a href=##heading--steps-commands>⚓</a></sup></h3> | ||
|
||
Each of these lifecycle steps can be run from the command line, and the command can be part specific or apply to all parts in a project. | ||
|
||
1. `snapcraft pull [<part-name>]` | ||
1. `snapcraft build [<part-name>]` | ||
1. `snapcraft stage [<part-name>]` | ||
1. `snapcraft prime [<part-name>]` | ||
1. `snapcraft pack` or `snapcraft` | ||
|
||
Note that each command also executes the previous lifecycle steps, so `snapcraft` executes all the lifecycle steps chained together. | ||
|
||
To access the part environment at any stage, add the `--shell` argument. For example, `snapcraft prime --shell` will run up to the *prime* step and open a shell. See [Iterating over a build](/t/iterating-over-a-build/12143) for more details. | ||
|
||
<h3 id='heading--steps-dependencies'>Steps dependencies<sup><a href=#heading--steps-dependencies>⚓</a></sup></h3> | ||
|
||
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. By default, `snapcraft` runs the same lifecycle step of all parts before moving to the next step. However, you can change this behavior using the `after` keyword in the definition of a part in `snapcraft.yaml`. This creates a dependency chain from one part to another. | ||
|
||
```yaml | ||
grv: | ||
plugin: go | ||
go-channel: 1.11/stable | ||
after: | ||
- libgit2 | ||
``` | ||
|
||
In the above example, the part named `grv` will be built after the part named `libgit2` has been successfully built _and_ staged. | ||
|
||
<h3 id='heading--overriding-steps'>Overriding a step<sup><a href=#heading--overriding-steps>⚓</a></sup></h3> | ||
|
||
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 `snapcraft.yaml`. See [Overriding steps](/t/scriptlets/4892) for more details. | ||
- By using a local plugin. This can inherit the parent plugin or scaffolding from the original. See [Local plugins](/t/writing-local-plugins/5125) for more details. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be prudent to mention that this hasn't been supported for recent bases in snaps for several years -- I believe the cut-off is core20? |
||
|
||
See [Parts environment variables](/t/parts-environment-variables/12271) for a list of part-specific environment variables that can be accessed to help build a part. | ||
|
||
<h3 id='heading--parts-directories'>Parts directories<sup><a href=#heading--parts-directories>⚓</a></sup></h3> | ||
|
||
When running through its build steps, a part will use different working directories. These closely follow the step names for the lifecycle. | ||
|
||
The directories are specified by their environment variables: | ||
- **Snapcraft 7+**: environment variables start with `CRAFT_` | ||
- **Snapcraft 6, and earlier**: variables start with `SNAPCRAFT_` but are otherwise identical | ||
|
||
See [Parts environment variables](/t/parts-environment-variables/12271) for more details. | ||
|
||
| Environment variable | Directory | Purpose | | ||
|--|--|--| | ||
| `CRAFT_PART_SRC` | **`parts/<part-name>/src`** | the location of the source during 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. | | ||
| `CRAFT_STAGE` | **`stage`** | shared by all parts, this directory contains the development libraries, headers, and other components (e.g.; pkgconfig files) that need to be accessible from other parts | | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "This directory can contain" -- it isn't necessary that they do so (depends on the plugin, |
||
| `CRAFT_PRIME` | **`prime`** | shared by all parts, this directory holds the final components for the resulting snap. | | ||
|
||
<!-- | ||
| Step | Explanation | Source directory | Result directory | | ||
|--|--|--|--| | ||
| **pull** | downloads and retrieves the sources | *as specified by [`source`](https://forum.snapcraft.io/t/snapcraft-parts-metadata/8336#heading--source) key* | CRAFT_PART_**SRC** | | ||
| **build** <br> *organise* | builds the part <br> renames built files | CRAFT_PART_**BUILD** <br> CRAFT_PART_**INSTALL** | CRAFT_PART_**INSTALL** <br> CRAFT_PART_**INSTALL** | | ||
| **stage** | copies built files to shared stage directory | CRAFT_PART_**INSTALL** | CRAFT_**STAGE** | | ||
| **prime** | copies staged files to shared prime directory | CRAFT_PART_**INSTALL*** | SNAPCRAFT_**PRIME** | | ||
| **snap** | packs contents of prime directory into a snap | CRAFT_**PRIME** | CRAFT_PROJECT_DIR | | ||
--> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# 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. | ||
Comment on lines
+10
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would remove the "It" from these lines; it's well established we're talking about Snapcraft, and it better mirrors the previous lines (4-6). |
||
|
||
The list of available global options and commands can be checked with one of: | ||
|
||
```bash | ||
snapcraft help | ||
snapcraft help --all | ||
``` | ||
|
||
<h2 id='heading--snapcraft'>snapcraft.yaml</h2> | ||
|
||
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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @medubelko does snapcraft (plan to continue to) support |
||
|
||
`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. | ||
|
||
```bash | ||
snapcraft init | ||
``` | ||
|
||
A generated template file contains just enough data to build, split across three stanzas: | ||
|
||
* Metadata. | ||
* Confinement level. | ||
* Build definition. | ||
|
||
<h3 id='heading--definitions'>Main definitions inside snapcraft.yaml</h3> | ||
|
||
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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As we call out that only some keys are mandatory, should we specify in 46-50 which of them are mandatory? Parts and Apps are both optional, for instance - but one wouldn't know it from reading this. |
||
|
||
* **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 | ||
Comment on lines
+54
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "None or more", especially for apps -- snaps like |
||
* 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](/t/build-and-staging-dependencies/11451) (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](/t/build-and-staging-dependencies/11451) (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. | ||
Comment on lines
+58
to
+60
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we give a link to adding package repositories after these lines? |
||
|
||
<h2 id='heading--output'>Snapcraft build output</h2> | ||
|
||
See <!--TO DO: Path to be added when the page is created--> [Parts lifecycle]() to consult the Parts lifecycle steps. | ||
|
||
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: | ||
|
||
```no-highlight | ||
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: | ||
|
||
```bash | ||
unsquashfs <file>.snap | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Parts lifecycle | ||
|
||
Each part is composed of five steps, known as the "lifecycle". | ||
|
||
See [Part lifecycle](/t/parts-lifecycle/12231) and [Parts environment variables](/t/parts-environment-variables/12271) to learn more about the Parts lifeycle and its environment variables. | ||
|
||
| Step | Command | Purpose | Directory | Path | ||
| ----------- | ----------- | ----------- | ----------- | ----------- | | ||
| **Pull** | `snapcraft pull [<part-name>]` | Downloads or retrieve the components' sources and external dependencies needed to build the part. | Components' sources and external dependencies are put in CRAFT_PART_**SRC** or CRAFT_PART_SRC_**WORK** if the source subdirectory is overridden. | **`parts/<part-name>/src`** or **`parts/<part-name>/src/<subdirectory>`** | | ||
| **Build** | `snapcraft build [<part-name>]` | Builds the components from the previously pulled sources. | Build the sources in CRAFT_PART_**BUILD** and places the result in CRAFT_PART_**INSTALL**. | **`parts/<part-name>/build`** and **`parts/<part-name>/install`** | | ||
| **Stage** | `snapcraft stage [<part-name>]` | Copies the built components into the staging area. | The built components are put in CRAFT_**STAGE**. | **`stage`** | | ||
| **Prime** | `snapcraft prime [<part-name>]` | Copies the staged components into the priming area. | The staged components are put in CRAFT_**PRIME**. | **`prime`** | | ||
| **Pack** | `snapcraft pack or snapcraft` | Takes the contents of the prime directory and packs it into a snap. | The snap is put in CRAFT_PROJECT_**DIR**. | The path to the current project’s subtree in the filesystem. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will note that
organize
is missing -- considering its importance and relationship to thestage
andprime
keywords, it should be included here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a problem in the existing docs where they imply that
organize
it itself a step, rather than a before/after events.organize
belongs to Stage, not Build, so I think we should be careful about where we lodge the keys and how we organise the lifecycle.One way we could model and present the timeline is with – to use an idea from music – on beat events for steps (one and two and) and off beat events for the in-between procedures (one and two and). Shown as a tree:
after
overlay-script
(to borrow a case from Rockcraft)build-packages
build-snaps
For absolute correctness, it would probably need to be presented as a table that resembles a gantt-like schedule.
If we did this, whether we include all the keys remains a question. There are many. I think Sophie is already on the right track by including the most important in-between events and providing examples.
Do you think this could be a helpful way to map the steps?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not familiar with such a style, but it's potentially a helpful way of organizing this information -- at the very least, I wouldn't see any harm in attempting adding a structure like this!
Is it not the case that
organize
belongs to the build step? I believeorganize
d bits will end up modified in the part's$CRAFT_PART_INSTALL
, which then carries over into$CRAFT_STAGE
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be misled.
organize
is described as both part of the stage step and the build step.@mr-cal Which is correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
organize
is the last event in the build step. It moves files within$CRAFT_PART_INSTALL
.@dilyn-corner is correct here.