Architectures

By default, Snapcraft builds a snap to run on the same architecture as the build environment. This behaviour can be modified with the root keyword architectures in the snap’s snapcraft.yaml.

The architectures keyword is used to create a build plan. See build plans for an explanation of how build plans are created.

How to create a snap for a specific architecture

To create a snap that will be built on amd64 and built for amd64, use one of the snapcraft.yaml snippets below.

core22

architectures:
  - build-on: [amd64]
    build-for: [amd64]

Building on amd64 will produce one snap built for amd64. Snapcraft will raise an error when building on another architecture.

If build-for is omitted, then it will assume the value of build-on. The following snippet snippet will produce the same result:

architectures:
  - build-on: [amd64]

core20

architectures:
  - build-on: [amd64]
    run-on: [amd64]

Building on amd64 will produce one snap built for amd64. Snapcraft will not raise an error when building on another architecture. Instead, it will ignore the architectures keyword and build for the build-on architecture.

If run-on is omitted, then it will assume the value of build-on. The following snippet snippet will produce the same result:

architectures:
  - build-on: [amd64]

The shorthand format will also produce the same result:

architectures:
  - amd64

How to create a set of snaps for multiple architectures

core22

architectures:
  - build-on: [amd64]
    build-for: [amd64]
  - build-on: [arm64]
    build-for: [arm64]

Building on amd64 will produce one snap for amd64. Building on arm64 will produce one snap for arm64. Snapcraft will raise an error when building on another architecture.

If build-for is omitted, then it will assume the value of build-on. The following snippet snippet will produce the same result:

architectures:
  - build-on: [amd64]
  - build-on: [arm64]

core20

architectures:
  - build-on: [amd64]
    run-on: [amd64]
  - build-on: [arm64]
    run-on: [arm64]

Building on amd64 will produce one snap built for amd64. Building on arm64 will produce one snap built for arm64. Snapcraft will not raise an error when building on another architecture. Instead, it will ignore the architectures keyword and build for the build-on architecture.

If run-on is omitted, then it will assume the value of build-on. The following snippet snippet will produce the same result:

architectures:
  - build-on: amd64
  - build-on: arm64

The shorthand format will also produce the same result:

architectures: [amd64, arm64]

How to create an architecture independent snap

build-for: [all] is used for a snap that can run on all architectures, like a shell or python script snap. It cannot be combined with other architectures. Click here for more information on the all keyword.

core22

architectures:
  - build-on: [amd64]
    build-for: [all]

core20

architectures:
  - build-on: [amd64]
    run-on: [all]

How to build a snap for a different architecture

core22

architectures:
  - build-on: [amd64]
    build-for: [arm64]

Building on amd64 will produce one snap built for arm64. Snapcraft will raise an error when building on another architecture.

core22 can handle complex build plans. For example:

architectures:
  - build-on: [amd64]
    build-for: [amd64]
  - build-on: [amd64, arm64]
    build-for: [arm64]

Building on amd64 will produce two snaps, one built for amd64 and one built for arm64. Building on arm64 will produce one snap built for arm64. Snapcraft will raise an error when building on another architecture.

core20

architectures:
  - build-on: [amd64]
    run-on: [arm64]

Building on amd64 will produce one snap built for arm64. Snapcraft will not raise an error when building on another architecture. Instead, it will ignore the architectures keyword and build for the build-on architecture.

Complex build plans like the previous core22 example are not supported for core20.

How to stage packages from another architecture

To use an i386 package for an amd64 snap, use the following snapcraft.yaml snippets for core22:

architectures:
  - build-on: [amd64]
    build-for: [amd64]

package-repositories:
  - type: apt
    formats: [deb]
    architectures: [i386]
    components: [main]
    suites: [jammy]
    key-id: F23C5A6CF475977595C89F51BA6932366A755776
    url: https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu

parts:
  mypart:
    stage-packages:
      - libpython3.11-minimal:i386

This is supported for related architectures. A snap built for amd64 can stage i386 packages and a snap built for i386 can stage amd64 packages. Similarly, a snap built for arm64 can stage armhf packages and a snap built for armhf can stage amd64 packages.

6 Likes

What about cross compilation? Shouldn’t there also be a build-for keyword?

well, the combination fo build-on and run-on is essentially that …

if you cross build for armhf you’d use “build-on: amd64” and “run-on: armhf” like here:

https://github.com/ogra1/pi-kiosk-gadget/blob/master/snapcraft.yaml#L11

@kyrofa it would be very helpful if this doc could have some cross reference to the architecture specific bits in stage-packages: (and/or build-packages) often you use the more exotic build-on/run-on combinations together with arch specific entries in build/stage-packages entries.

1 Like

Thanks @ogra I am still a bit confused though. What is the relationship between the root keyword architectures and the command line --target-arch flag?

For example snapcraft --target-arch=armhf and also how about snaps which are “cross platform” (say Bash scripts or interpretted programs) versus programs which need to be compiled separately and linked to platform specific dynamic libraries?

Once you have the proper build-on and run-on lines, there is no need for --target-architecture anymore since you defined it in your snapcraft.yaml already.

if you read the first post carefully you will see “run-on: all” … that is for bash scripts and friends :wink:

3 Likes

This is work in progress, and documents behavior that does not yet exist in its entirety. The snapcraft CLI gained support for this in v2.42, but it’s not yet fully integrated with build.snapcraft.io.

This is now supported by build.snapcraft.io: that is, builds will be dispatched for the set of architectures requested in snapcraft.yaml, provided that they’re supported by BSI. (In most cases, I expect that the main use case for this will be to disable builds for architectures that you know can’t work, although it will later be a useful building block for build sets.)

This will allow us to enable builds for ppc64el and s390x on BSI (the remaining Ubuntu architectures that we don’t yet support there), but we’ll do that early next week rather than making a significant change like that just before the weekend.

4 Likes

This will allow us to enable builds for ppc64el and s390x on BSI (the remaining Ubuntu architectures that we don’t yet support there), but we’ll do that early next week rather than making a significant change like that just before the weekend.

Now done.

2 Likes

Is it possible to specify an architecture that we want it not build on? Enumerating all other arches doesn’t seem to be desirable.

For example I know a certain snap won’t build on armhf architecture, is there a way to disable it without enumerating all other architectures in the build-on key?

What are all the supported architectures?

This should also more explicitly explain What is the proper way to build and support multi-architecture snap in store (year 2018)? and the $SNAP_ARCH_TRIPLET variable.

The ‘Architectures’ page isn’t visible in the ‘contents’ down the page’s left-hand column. Is that deliberate?

1 Like

It hasn’t been deliberately left off, and adding it is certainly something we should do if it’s considered important enough (it is linked to from the snapcraft yaml reference pages).

I think it probably is important enough, but needs a little work (I can do this).

1 Like

Hi, what’s the recommended way to cross-compile (e.g. Go) from amd64 to all other archs?

Could this work? Also with CI like GH Actions? Would I need any command like option to produce that?

base: core20

architectures:
  - build-on: amd64
    run on: [amd64, armhf, arm64]

What you’ve listed says that a single build on amd64 will produce a snap that can be used on the three architectures amd64, armhf, and arm64. You probably want something more like:

architectures:
  - build-on: amd64
    run on: amd64
  - build-on: amd64
    run on: armhf
  - build-on: amd64
    run on: arm64

The snapcore/action-build@v1 action does not currently do anything with this information in the snapcraft.yaml. But if you are set up to do cross builds, then you could probably drive it with:

    steps:
      ...
      - uses: snapcore/action-build@v1
        with:
         snapcraft-args: --target-arch arm64

You could either repeat the action three times to perform the three builds in series from a single job, or use the matrix feature to create three parallel jobs.

Whoops, sorry for the spurious edit! I accidentally saved while updating this post for changes in core22. I think I reverted my changes.

This page should also link to https://snapcraft.io/docs/snapcraft-advanced-grammar

Examples 1-4 could easily be condensed into a single example.