Specifying architecture on cross-compilations

Then that means snapcraft needs to pre-process the entire package set directives so that they can be handled in a backend independent manner. I currently don’t know how I’m going to handle a mix of these with the soon-to-be made RPM backend…

In case it’s not clear from the above: while the :native suffix happens to have the same name as Debian’s, :target is entirely new. And both can be implemented as literal replacements to whatever the backend’s syntax is for a package from a specific architecture.

The PR resolving these items is here.

2 Likes

I proposed a PR implementing :target.

I have PRs for the following parts of the proposal:

#1639

#1800

One question came up last week: there will be two ways to use the new “to” statement, given the above proposal, which wasn’t specifically discussed - or at least not recorded anywhere that I’m aware of.

on i386:
  - to armhf:
    - hello

on i386 to armhf:
  - hello

If on..to is implemented, like I did in my branch, we still get the nested style for free given the way the grammar works. Do we want to make it an error so only on ie86 to armhf is allowed?

Please no, that’s a redesign-- it breaks the recursive nature of the grammar.

The fact that you can write the same thing two ways is more insidious than it first appears. Note that the two examples given above look like they’re writing the same thing, but they’re not.

Say you have a part definition like this:

my-part:
  plugin: nil
  stage-packages:
    - on i386 to i386: [hello]

Odd, I know, but bear with me. If you’re on an amd64 machine, this rule should be impossible to match. And indeed, hello is never fetched, regardless of whether you run snapcraft or snapcraft --target-arch=i386.

However, if that same part were written this way:

my-part:
  plugin: nil
  stage-packages:
    - on i386:
      - to i386: [hello]

You get the same behavior when running snapcraft, but when you run snapcraft --target-arch=i386 it actually fetches hello:i386. This is because the standalone on statement uses the target arch for its selectors, not the host (similar to the to command). So these look the same, but they’re not. The new “on X to Y” is actually an entirely new “on” statement that works differently. This inconsistency is a problem, in my opinion, because they intuitively look like they should be doing the same thing.

If we fix the inconsistency by changing how the standalone “on” statement behaves to match, then why do we have an “on X to Y” statement at all? Why not just support the nested structure that we get for free with the addition of the to statement?

1 Like

Yes, the nested and non-nested statements should definitely work the same way, otherwise it’ll be very arbitrary and confusing.

Thanks for catching that, Kyle.

If we change the on statement, then, do we still need a new on X to Y statement? Or can we just introduce the to statement and have people write the nested version? Seems more succinct to not have two ways of writing the same thing.

The reason why these two statements should obviously do the same thing is also the reason why it seems fine to have the two of them: they express exactly the same idea, with the same terms and almost the same syntax. Forcing people to use the nested style for trivial cases doesn’t feel like a relevant win, and it’s definitely not more succinct.

I meant “succinct” as in clarity, not brevity, but yeah, point taken. If the on statements behave the same way, we should be able to re-use one to make the other so the code side makes me happier. @kalikiana does that sound like a good path?

From the original comment from Gustavo it seems that this is what we want:

parts:
    plugin: nil
    stage-packages:
        - on <host-arch> to <target-arch>: [hello]

And

parts:
    plugin: nil
    stage-packages:
        - on <host-arch>:
            - to <target-arch>: [hello]

Meaning the standalone on statement should use <host> for its selectors. This expresses the intent of the snapcraft.yaml author that cross compilation is supported, but only when running from <host>.

I installed the snapcraft 2.38 edge channel on my ubuntu 16.04 x86 host to try out the “to” keyword in my stage-packages parts section. When I ran snapcraft --target-arch=armhf, the command failed with the following summary (I’ve excluded the line-by-line python error messages):

apt.cache.FetchFailedException: E:Failed to fetch http://security.ubuntu.com/ubuntu/dists/xenial-security/main/binary-armhf/Packages 404 Not Found [IP: 91.189.88.161 80], E:Failed to fetch http://us.archive.ubuntu.com/ubuntu/dists/xenial/main/binary-armhf/Packages 404 Not Found [IP: 91.189.91.26 80], E:Failed to fetch http://us.archive.ubuntu.com/ubuntu/dists/xenial-updates/main/binary-armhf/Packages 404 Not Found [IP: 91.189.91.26 80], E:Failed to fetch http://us.archive.ubuntu.com/ubuntu/dists/xenial-backports/main/binary-armhf/Packages 404 Not Found [IP: 91.189.91.26 80], E:Some index files failed to download. They have been ignored, or old ones used instead.

Any ideas what I’m doing wrong? My snapcraft.yaml file is as follows:

name: netdata # you probably want to 'snapcraft register ’
version: ‘0.1’ # just for humans, typically ‘1.2+git’ or ‘1.3.2’
summary: netdata in snap form # 79 char long summary
description: |
Attempt to build a snap for the netdata applicaiton
grade: devel # must be ‘stable’ to release into candidate/stable channels
confinement: devmode # use ‘strict’ once you have the right plugs and slots

apps:
netdata:
command: netdata
plugs: [network-bind, hardware-observer]

parts:
my-part:
plugin: autotools
source-type: git
source: https://github.com/firehol/netdata
build-packages:
[zlib1g-dev,
uuid-dev,
libmnl-dev,
pkg-config,
curl]
stage-packages:
- to armhf:
[libghc-zlib-dev, uuid-runtime]

snapcraft uses the host machines sources.list by default … there are no armhf binaries on the “archive.ubuntu.com” machine (or its various mirrors like us.archive.ubuntu.com) … i bet if you temporary replace the sources.list with one from an armhf machine that error will go away …

Here is an example one …

deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted universe
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe

One general note on YAML in the forum: you need to indent by 4 spaces to render it as “preformatted text”, or use the button above the text field while selecting it. So this is what I tested with:

name: netdata
version: 0.1
summary: netdata in snap form
description: |
  Attempt to build a snap for the netdata applicaiton
grade: devel
confinement: devmode

apps:
  netdata:
    command: netdata
    plugs: [network-bind, hardware-observer]

parts:
  my-part:
    plugin: autotools
    source-type: git
    source: https://github.com/firehol/netdata
    build-packages: [zlib1g-dev, uuid-dev, libmnl-dev, pkg-config, curl]
    stage-packages:
      - to armhf: [libghc-zlib-dev, uuid-runtime]

From the looks of your error, it seems like your sources.list for armhf is wrong. It should look like this (note ports.ubuntu.com is slightly different to the standard archive mirrors):

deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ xenial universe
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ xenial-updates universe
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ xenial multiverse
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ xenial-updates multiverse
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports xenial-security main restricted
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports xenial-security universe
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports xenial-security multiverse

Now, building the snap, this is what I get:

> snap info snapcraft | grep -E 'tracking|installed'
tracking:    edge
installed:   2.38+git28.4c7edab (1033) 53MB classic
> snapcraft --target-arch=armhf
[...]
configure: error: C compiler cannot 
create executables
See `config.log' for more details

Said config.log contains this:

/home/rumo/dev/netdata/parts/my-part/install/usr/bin/ld: cannot find /usr/lib/arm-linux-gnueabihf/libc_nonshared.a

Adding libc6-dev-armhf-cross to build-packages didn’t seem to suffice as a quick build fix as it’s still hard-coding the path. But I hope this will get you a bit further.

Edit: Seems like @ogra was responding as I was still drafting my response :smiley: My sources.list is slightly more complete but both should do the trick.

well, libc6-armhf-cross (which the -dev pulls in) puts everything into /usr/arm-linux-gnueabihf/lib … snapcraft would have to teach the linker to actually look there i think …

even better is to use backticks and specify that it’s yaml. that way you don’t have to edit every… single… line…:

```yaml
parts:
    foo:
```