Snapcraft build-on hint for builders

It’s a fair remark here, and specifically in the case of 32-bit x86, it’s not really as much of an issue. It breaks down on ARM architectures mainly, and probably will also have the same issue with MIPS and RISC-V (though neither are supported in snapd today).

At least specifically with 32-bit x86, Debian did baseline i386 until recently. OpenSUSE and Mageia do i586 (meaning certain instructions aren’t used), and Fedora does i686. There are CPU incompatibilities for this, but in practice I don’t think we’ll encounter them much except with IoT and specialized computers like the OLPC XO laptops.

Can I have an option for CPUs without mmx? Sorry for the half joke, but part of the conversation here brought me back to the days when you had to look out for that :slight_smile:

Oh, I mean

$ grep architectures snap/snapcraft.yaml
architectures: [[armhf], [amd64, arm64]]

Would result in

$ grep architectures prime/meta/snap.yaml
architectures: [amd64, arm64]

or

$ grep architectures prime/meta/snap.yaml
architectures: [armhf]

Technically there is no issue here, my angle is from a documentation and support point of view.

Assuming the typo in the second example is an excessive bracket and not a missing one, +1.

This seems an odd conglomeration of build-on and run-on semantics. The [armhf] case says to me “build and run on armhf”. But I’m not sure what [amd64,i386] says to me. Knowing what architectures means today I think it means “run on amd64 and i386,” but where does it build? amd64, or i386? It’s only one snap, so it must be one or the other, right? How do we know which is appropriate?

The architectures field is already so confusing, its only saving grace is that it’s just as confusing in both snapd and snapcraft, since it means the same thing :stuck_out_tongue: . Changing its meaning in snapcraft makes it worse, at least to me.

Furthermore, making that syntax change in a backward-compatible way seems to lead toward something even more difficult to understand, document and use.

I would guess that the reason that you are confused is precisely because you’re trying to assign to it a meaning that you want to find in it based on prior conversations, but that it never had and that it should not have in my opinion.

The field describes the architectures the snap runs on. It always did, and that’s not very confusing to me at least.

We are on the same page wrt the meaning of architectures to figure out where it runs, specially when tied to meta/snap.yaml, the thing that makes it hard is tying architectures in snapcraft.yaml to something different, we have a 1:1 matching where it matters between both manifests, that of snapd and snapcraft, which makes support and documentation rather easy.

Can we live talk during the rally between @niemeyer, @cjwatson, @kyrofa and myself, and later write down the minutes from that conversation here.

1 Like

Sure; I’ve not been following this in very great detail, but feel free to book me for a meeting.

Can we get those? Or the pictures we took of the board, at least.

1 Like

Here’s the photo of the board

The summary and take away from this meeting is that, following that photo, if I were running snapcraft on amd64:

  • The first line will satisfy and we would produce a snap by building on amd64 and cross compiling to i386
  • The second item will satisfy as we are on `amd64, so we will produce two more snaps:
    • one cross compiled to arm64
    • another one cross compiled to amrhf and armel
  • The last item will not satisfy as amd64 != ppc.

Please correct me if I am wrong. That said, now that I am looking back on this, I think we need to reevaluate what was decided.

:+1:

That looks needlessly complex and difficult to understand. My opinion is that you specify the architectures as a single list without any on foo do bar nonsense. You’re telling snapcraft what architectures your snap can build on, not what to build on. So if your architectures contains:

architectures:
  - arm64
  - i386

… then, when you try to build locally on amd64, snapcraft will say “sorry, but I can’t do that, Dave.” To get past that you will tell snapcraft to build on a different host of the correct architecture or specify a cross-compile in which case if the cross-toolchain supports the architecture you’re golden, but you’ll still fail otherwise.

When the buildservice picks up the yaml it spins up a build system for each of the architectures listed unless the buildservice doesn’t support one or other of the specified architectures.

Yeah I didn’t remember any of the cross-compile magic that complicates this. I only remembered that build.snapcraft.io wanted hints about what to build on, and what architectures the resulting snap ran on. My memory turned it into this:

snapcraft.yaml architectures snap.yaml architectures build.snapcraft.io impression
(none) architectures: [<host>] “build everywhere”
architectures:
  - amd64
  - i386
architectures:
  - amd64
  - i386
“build everywhere”
architectures:
  - on i386: [amd64, i386]
When building on i386:
architectures: [amd64, i386]

When building elsewhere:
architectures: [<host>]
“build on i386 only”
# Not the best example
# since we have no armel,
# but you get the idea
architectures:
  - on i386: [amd64, i386]
  - on armel:
    - armhf
    - armel
When building on i386:
architectures: [amd64, i386]

When building on armel:
architectures:
  - armhf
  - armel

When building elsewhere:
architectures: [<host>]
“build on i386 and armel only”

Nice table, for

architectures:
  - on i386: [amd64, i386]

What would be done with amd64?

Haha, it took way too long, don’t look at the raw version.

In my understanding: nothing new. It would simply be placed into the snap.yaml, telling snapd “this snap runs on both amd64 and i386” just like it does today.

So how do we specify NOT to build on arm?! your table says that when we say [amd64, i386] then it will build on arm! This has got seriously complicated, see my previous post for an example of how simple it could be…

That’s actually how it works today, we don’t want to break existing semantics (see the rest of the thread).

If you don’t want it to build on arm you would have a few options:

Option 1: Specify architectures you CAN build on:

architectures:
  - on i386: [amd64, i386]

Then build.snapcraft.io will know not to build on arm, but if you try to run Snapcraft on non-i386 it’ll build for the host. If you also want that to fail you can use:

Option 2: Use the grammar to force failure

architectures:
  - on i386: [amd64, i386]
  - else fail

Then snapcraft will error out whenever one tries to build the snap on anything other than i386.

To be clear: I wasn’t actually trying to propose something new. I was trying to explain the PR I made that I thought implemented this, but apparently didn’t :smiley: .

I like to not overload a single stanza with too much information, so would prefer the cross-compile specifics moved elsewhere, e.g.:

architectures: # This is the architectures of systems we _will_ build _on_ (host arch)
  - amd64 # build on amd64, and produce an amd64 variant using native toolchain
  - arm64

cross-compile:
  - amd64:
      - i386 # when building on an amd64 host cross-compile an additional version for i386
  - arm64:
      - armhf # when building on an arm64 host cross-compile an additional version for armhf
      - armel # when building on an arm64 host cross-compile an additional version for armel
      - -arm64 # we don't want an arm64 build from an arm64 system so remove it (strange situation that will never occur, but for completeness)

It would be ok to change the cross-compile host arch to on amd64: etc. to be more explicit which is the host and which is the target, i.e.:

cross-compile:
  - on amd64:
      - i386

I think the big problem is trying to support a single snap package file targeting multiple architectures, and thus in snap.yaml we’re struggling to correlate the architectures: stanza in a 1:1 mapping with that in snapcraft.yaml. IMO there is very minimal net-gain in allowing multiple architectures for a single squashfs package file because the store supports serving the correct file to the client anyway. So IMO we should force snap.yaml to only allow a single architecture and force packagers to build each architecture separately even if ostensibly they’re the same set of files apart from the snap.yaml.

Using a CI system or the build service as we’re advising people to do, this would be simple to achieve, and by forcing packagers to build for each architecture they target separately we’re actually making their lives easier when they’re working on the crafting of the snapcraft.yaml.

I would all be in favour of killing the support for “fat” architectured snaps, with the exception of the all keyword.

1 Like