Cross-building issues

Our buildsystem outputs distro-independent tarballs which are then used as input for a packaging build that create distro-specific packages (deb, rpm, etc.). Our tarballs (apart from libc6) are self-contained, i.e. all SOs are shipped and RPATHs are set correctly. We are adding snap creation to this setup but I’m running into problems while creating the armhf and arm64 packages.

We are running snapcraft in a 16.04-based docker container and building the x86 and amd64 snaps works fine. However, during both armhf and arm64 building we get the following error:

Could not find a required package in 'build-packages': libc6-dev-armhf-cross

Then I try to add it:

parts:
  mypart:
    stage-packages: [libc6]
    build-packages:
      - to armhf: [libc6-dev-armhf-cross]

Now the error becomes:

Could not find a required package in 'build-packages': libc6-dev-armhf-cross:armhf

We are calling snapcraft as snapcraft --target-arch=armhf. I was under the impression that this package would be automatically added to build-packages, but even adding it explicitly fails in a weird way. What’s the solution here? Can we avoid dev packages completely? We don’t use snapcraft to “build” the application (nor want to), we are just using the dump plugin, so we shouldn’t need these (unless I’m missing something). Thanks for any input.

Can you post your full snapcraft.yaml file? If you are using the dump plugin you’re right that you shouldn’t need anything else.

name: mypkg
version: {version}
summary: foo.
description: |
  foo bar
  .
type: app
confinement: strict
icon: meta/gui/mypkg.png
grade: stable
architectures: [{arch}]

plugs:
  home-all:
    interface: home
    read: all

apps:
  mypkg:
    command: wrapper.sh
    daemon: simple
    restart-condition: always
    plugs:
      - home-all
      - network
      - network-bind
      - opengl
      - raw-usb
      - removable-media
      - system-observe

parts:
  myypart:
    stage-packages: [libc6]
    source: bin/
    plugin: dump
    override-build: |
      chmod +x wrapper.sh
      snapcraftctl build

{version} and {arch} are replaced by the appropriate values during the build. So in one case it is, say, amd64, in another case it is armhf.

Try this,

    stage-packages:
      - on amd64 to armhf: ["libc6:armhf"]
      - else: ["libc6"]

FYI you shouldn’t need to specify libc6 at all, it should come in from the core snap. However I know there has been some issues with this in the past.

The error now becomes gcc-aarch64-linux-gnu. I tried things like this, always staging what it complained about but eventually ran into the first error again. But all around it’s weird that it requires a compiler.

Hi there,

You probably do not want to add libc6 to stage-packages as that is provided by the core snap.

Thanks. I tried that again but I’m getting the same error (Could not find a required package in 'build-packages': gcc-aarch64-linux-gnu). I verified that I’m building the right commit, just to be sure. There is no stage-packages section.

I wonder if the clue here is Could not find a required package in 'build-packages': libc6-dev-armhf-cross:armhf the fact that it’s mentioning :armhf which is probably not a supported architecture inside your docker image. So it can’t find armhf packages in the container .

Does the error go away if you:

dpkg --add-architecture armhf
apt-get update

Inside the docker container?

1 Like

Thanks for the suggestion, I’m trying it right now (though I find it weird that when I remove all the stage-packages, gcc becomes required as a build-package).

OK, interesting. We are mirroring archive.ubuntu.com and we’re using our mirror in the source.list. I’ve added the armhf and arm64 architectures as you suggested, but now I’m getting this:

E: Failed to fetch https://<our server>/cache-ubuntu-archive/dists/xenial/main/binary-armhf/Packages  404  Not Found
E: Failed to fetch https://<our server>/cache-ubuntu-archive/dists/xenial-updates/main/binary-armhf/Packages  404  Not Found
E: Failed to fetch https://<our server>/cache-ubuntu-archive/dists/xenial-backports/main/binary-armhf/Packages  404  Not Found
E: Failed to fetch https://<our server>/cache-ubuntu-security/dists/xenial-security/main/binary-armhf/Packages  404  Not Found
E: Some index files failed to download. They have been ignored, or old ones used instead.

Looking at http://archive.ubuntu.com/ubuntu/dists/xenial/main/ is seems those are not there. Where are they supposed to come from? Some debian source?

The armhf and arm64 repository is at: http://ports.ubuntu.com/ (also there is s390x, powerpc, and ppc64el :slight_smile:)

1 Like

Well that explains it! :slight_smile: Good to know - adding a mirror now and trying again.

Still fails with: Could not find a required package in 'build-packages': libc6-dev-arm64-cross (again, nothing staged nor added to build-packages explicitly).

I also tried the commit where we added to & on statements failed the same way:

-    stage-packages: [libc6]
-    # build-packages:
-    #   - to armhf: [libc6-dev-armhf-cross, gcc-arm-linux-gnueabihf]
-    #   - to amd64: [libc6-dev-amd64-cross]
+    stage-packages:
+      - on amd64:
+        - to armhf: ["libc6:armhf"]
+        - to arm64: ["libc6:arm64"]
+      - else: ["libc6"]

For my cross compiling setup there were two things I found necessary for it to work.

  1. Make sure you add the repository where the libs for your architecture. For me I do this in my CI script (not in my snapcraft file, although maybe you can find a way to do that).
cat sources.txt > /etc/apt/sources.list
dpkg --add-architecture armhf
apt-get update
  1. Using the advanced grammar on amd64 to armhf: [...] to specifiy build and stage packages.

Although again, I am not sure why any of this is necessary if you are just using the dump plugin.

As far as I can tell we have both down at this point but it still doesn’t work. Could it be that this part triggers the attempted installation of gcc?

    override-build: |
      chmod +x wrapper.sh
      snapcraftctl build

I can probably get rid of that wrapper because it only sets a couple of environment variables which should be possible to express in the yaml.

How do you replace {version} and {arch} in your build? Ansible or something like that?

In core22 the target arch is available in step override scriptlets as $CRAFT_TARGET_ARCH ($SNAPCRAFT_TARGET_ARCH also works for backwards compatibility). The current version can be recovered by invoking craftctl get version (or using $SNAPCRAFT_PROJECT_VERSION).

Ah so writing {arch} somewhere in the snapcraft.yaml file doesn’t actually cause some kind of substitution, right?

Not that I’m aware of. $CRAFT_TARGET_ARCH is the variable that craft-parts understands, and Snapcraft also sets $SNAPCRAFT_TARGET_ARCH on top of that, but mostly for compatibility reasons. For new projects, $CRAFT_TARGET_ARCH is the preferred variable to use.