[snapcraft 3.x] Cross-compilation amd64 → armhf in Multipass VM

I’ve updated to snapcraft 3 to take advantage of the new base and multipass goodness – big thank you to the team for your work!

Using core18 as a base permits me to use stage-packages instead of the ruby plugin, which didn’t have cross-compilation support. My snap targets amd64 and armhf, and I’d like to cross-compile for armhf on my amd64 machine to speed up development.

What’s the best practice for cross-compiling a snap with snapcraft v3 and Multipass?

Gathered from other topics, I’ve modified my snapcraft.yaml to include:

# top level
architectures:
  - build-on: [amd64, armhf]
    run-on: [amd64, armhf]

# example part
parts:
  nginx:
    source: src/nginx
    stage-packages:
      - on amd64 to armhf:
        - "nginx:armhf"
        - "gettext-base:armhf"
        - "libatm1:armhf"
        - "libxtables12:armhf"
      - else:
        - nginx
        - gettext-base
        - libatm1
        - libxtables12
    plugin: dump

I also added the ubuntu-ports repository to the Multipass VM’s sources.list via apt edit-sources and ran apt update in the VM:

deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports bionic main universe
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports bionic-security main universe
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports bionic-updates main universe
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports bionic-backports main universe

Running snapcraft in my snap directory, snapcraft fetches the armhf repositories, but no actual package with _armhf.deb suffix. The resulting snap has the multi suffix, but attempting to install it on an ARM device results in Exec format error during the install hook (I’m invoking envsubst from the gettext-base package there).

Running snapcraft --target-arch=armhf prints Setting target machine to 'armhf', but doesn’t seem to do anything else.

/Edit
snapcraft version: snapcraft, version 3.1 (same result with snapcraft 3.0.1 on stable channel)

1 Like

Your architectures key is wrong, how you have it now specifies that the snap can be built on either armhf or amd64, and the resulting snap will run on both of those architectures (i.e. it’s a multi-arch snap).

What you want is to specify that the snap is built on armhf and runs on armhf and also built on amd64 and runs on armhf. The architectures key doesn’t convey any cross-compilation information, that’s handled through the --target-arch option. Try using

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

And then cross compiling with --target-arch>

I am having the same problem

I really should have re-read the Architectures doc page … thank you @ijohnson!

However: If I change architectures to your suggestion

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

and then run snapcraft --target-arch=armhf, Multipass states “target machine set to armhf” and then proceeds to build an amd64 snap anyway. I even tried to remove the amd64 build-on/run-on section, so that architectures only contains armhf, but even then the cross-compilation produces an amd64 snap.

2 Likes

I can’t say that I’ve tried using this architectures syntax with snapcraft 3.x, but this used to work with snapcraft 2.x. This might be a bug with snapcraft 3.x. @sergiusens may be of more help

1 Like

Yep, this is the identical problem I am having - and cross compiling worked with 2.x so I am fairly certain this is a bug.

1 Like

@sergiusens cleared that up over in @eberkund’s thread: