Example cross-compiled app

Projects built using the Autotools plugin can be cross-compiled, allowing software to be developed on one architecture and built for a number of target architectures.

Example project file for example-curl

The following code comprises the project file for a project that uses libcurl. The complete code can be found in this repository.

hello-curl project
snapcraft.yaml
name: hello-curl
version: "1.0"
summary: cross-compiled app that uses curl
description: |
  A cross-compiled snap that uses libcurl. This exercises installing
  libcurl-dev as a build package and staging libcurl, both from ubuntu-ports.
grade: devel
base: core24
confinement: strict

platforms:
  armhf:
    build-on: [amd64]
    build-for: [armhf]
  arm64:
    build-on: [amd64]
    build-for: [arm64]
  riscv64:
    build-on: [amd64]
    build-for: [riscv64]

lint:
  ignore:
    - library

apps:
  hello-curl:
    command: usr/bin/hello-curl

package-repositories:
  - type: apt
    architectures: [$CRAFT_ARCH_BUILD_FOR]
    formats: [deb, deb-src]
    components: [main]
    suites: [noble, noble-updates, noble-backports]
    key-id: F6ECB3762474EDA9D21B7022871920D1991BC93C
    url: http://ports.ubuntu.com/ubuntu-ports

parts:
  hello-curl:
    plugin: autotools
    source: src
    build-environment:
      - PKG_CONFIG_PATH: "/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/pkgconfig"
    build-packages:
      - pkg-config
      - libcurl4-openssl-dev:$CRAFT_ARCH_BUILD_FOR
      - gcc-$CRAFT_ARCH_TRIPLET_BUILD_FOR
      - libc6-dev-$CRAFT_ARCH_BUILD_FOR-cross
    stage-packages:
      - libcurl4t64:$CRAFT_ARCH_BUILD_FOR
    autotools-configure-parameters:
      - --prefix=/usr
      - --host=$CRAFT_ARCH_TRIPLET_BUILD_FOR

Enable cross-compilation

The platforms key specifies which architectures should be used when building a snap. The platforms key can also be used to specify sets of architectures with the build-on and build-for keys. In the simplest case, this can be used to cross-compile on one architecture for a single, different architecture:

snapcraft.yaml
platforms:
  - build-on: amd64
    build-for: armhf

In this example, Snapcraft will only build the project on the AMD64 architecture, and it will only build it for the armhf architecture.

In the hello-curl project, the platforms key to lists several cross-compilation targets:

snapcraft.yaml of hello-curl
platforms:
  armhf:
    build-on: [amd64]
    build-for: [armhf]
  arm64:
    build-on: [amd64]
    build-for: [arm64]
  riscv64:
    build-on: [amd64]
    build-for: [riscv64]

Adjust the Autotools configuration

When building for a particular architecture, Snapcraft will initialise the CRAFT_ARCH_TRIPLET_BUILD_FOR environment variable in the build environment. This variable describes the platform and architecture that Autotools uses to configure cross-compilation. For more information on environment variables, see environment variables.

A project building with the Autotools plugin can adjust the options passed to the configure script for a given part with the plugin’s autotools-configure-parameters key.

snapcraft.yaml of hello-curl
    autotools-configure-parameters:
      - --prefix=/usr
      - --host=$CRAFT_ARCH_TRIPLET_BUILD_FOR

Satisfy the dependencies

The build-packages key specifies which packages will supply the toolchain and libraries necessary for cross-compilation.

snapcraft.yaml of hello-curl
    build-packages:
      - pkg-config
      - libcurl4-openssl-dev:$CRAFT_ARCH_BUILD_FOR
      - gcc-$CRAFT_ARCH_TRIPLET_BUILD_FOR
      - libc6-dev-$CRAFT_ARCH_BUILD_FOR-cross

Package repositories can also be specified for the target platform using the package-repositories key and the CRAFT_ARCH_BUILD_FOR environment variable.

snapcraft.yaml of hello-curl
package-repositories:
  - type: apt
    architectures: [$CRAFT_ARCH_BUILD_FOR]
    formats: [deb, deb-src]
    components: [main]
    suites: [noble, noble-updates, noble-backports]
    key-id: F6ECB3762474EDA9D21B7022871920D1991BC93C
    url: http://ports.ubuntu.com/ubuntu-ports

To select the correct library for the target platform, include these packages in the stage-packages key with the package:repo syntax.

snapcraft.yaml of hello-curl
    stage-packages:
      - libcurl4t64:$CRAFT_ARCH_BUILD_FOR

The build-packages and stage-packages keys additionally support the advanced grammar keys, which allow further customisation of packages installed per-platform.

Build the snap

To build the snap, navigate to the project directory and run:

snapcraft

Because linters are enabled by default for core24 snaps, this will produce warnings like the following:

user@host:~$ snapcraft
not a dynamic executablearm-binfmt-P: Could not open '/lib/ld-linux-armhf.so.3': No such file or directoryUnable to determine library dependencies for '/root/prime/usr/bin/autotools-cross-compile-example'

This is because snapcraft is unable to resolve the dependencies for the target architecture using the library linter.

Since the /lib/ld-linux-armhf.so.3 library will be present in the base of the target system, these warnings can be suppressed for this case by including a lint section in the project file:

snapcraft.yaml of hello-curl
lint:
  ignore:
    - library

Rebuild the snap, and this time it should finish without warnings. A .snap file for each target architecture is deposited at the root of the project directory. Each snap is distinguished by the architecture name at the end of its name. The hello-curl project should’ve created three files, ending in _armhf.snap, _arm64.snap, and _riscv.snap.