Cross-compiling rust and go apps for multi-platform snap builds

Rust and Go natively support cross-compilation.

We can combine several snapcraft directives to build snaps for multiple platforms, on the same host.

Plarforms

With the platforms (or architectures) directive, we can tell snapcraft to build a snap for a platform different from the host platform, for example:

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

This obviously will work only if the build product itself is in fact dedicated to the target (build-for) platform. With rust, go or scripts, this is very handy.

Build details

With the on directive, we can tell snapcraft to do different things per platform. This is quite convenient. Without it, we would need to map from arm64 to aarch64-unknown-linux-gnu etc. in an override-build script ourselves.

For example:

    build-packages:
      - on amd64 to arm64:
        - gcc-aarch64-linux-gnu
        - linux-libc-dev-arm64-cross
        - libc6-dev-arm64-cross

    build-environment:
      - to amd64:
        - target: x86_64-unknown-linux-gnu
      - on amd64 to arm64:
        - CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
        - target: aarch64-unknown-linux-gnu

or, for golang:

    build-environment:
      - to arm64:
        - GOOS: linux
        - GOARCH: arm64
        - CC: /usr/bin/aarch64-linux-gnu-gcc

Override build

Next, we just pass the target to the compiler:

cargo build --release --target=$target

CI

Using a platform matrix, because:

  • Packing amd64 and arm64 snaps without snapcraft clean in between fills up github runner’s disk space.
  • The snapcore/action-publish action takes only one snap at a time anyway.
jobs:
  release:
    name: Release
    runs-on: ubuntu-24.04
    strategy:
      matrix:
        platform:
          - amd64
          - arm64

The main thing is to filter the snapcraft build, because that github workflow’s matrix directive already takes care of that:

    - name: Build snap
      uses: snapcore/action-build@v1
      id: build
      env:
        CRAFT_BUILD_FOR: ${{ matrix.platform }}

If you’re using snapcraft directly, then

snapcraft pack --build-for=${{ matrix.platform }}

Examples

See also