Snapcraft build-on hint for builders

@Conan_Kudo We don’t actually rely on Debian logic for anything architecture-related. We’re simply reusing the architecture names as we needed to pick a set of names and didn’t feel like inventing new names unnecessarily, and assumed that some good thinking went into defining the existing names (that’s true for rpm too, but we couldn’t pick both).

If we need to introduce new names, we just need some good rationale for it, but we’re not strictly tied to the logic of anything else but snapd itself.

If we could be relatively assured that architectures would always match the assumptions the base arch names give, then I think it’d be fine. However, with snapd needing to be able to run across a wide array of distributions and CPUs, this falls apart. I think we probably need to at least consider moving to using machine architecture names used in platform triples.

For example:

  • i586 / i686 instead of i386 (this relieves ambiguity with 32-bit x86, and CPUs/distros do choose different levels)
  • armv6hl, armv7hl, etc. instead of armhf (removes invalid assumption of compatibility)
  • armv4tl, armv5tl, etc. instead of armel (removes invalid assumption of compatibility)

For these cases, enforcing the correct architecture can matter, as it can mean the computer can or cannot run the snap.

Some cases, there’s not much of an issue:

  • x86_64 / amd64 are consistent on what they mean, and I’d be comfortable with both being supported as labels for the same architecture
  • aarch64 / arm64 are in the same boat as x86_64
  • ppc64le / ppc64el / powerpc64le are in the same boat as x86_64 and aarch64 are
  • s390x is the only label for that particular architecture

In the cases above, I’d prefer if all those markers actually worked and internally resolved to their correct designation (x86_64, aarch64, powerpc64le, etc.).

It sounds good, I am even ok with one list as long as we understand that there is a syntax change in what architectures mean (how to parse it) in snap.yaml and snapcraft.yaml.

But this new syntax also allows us to think about backwards compatibility. We already have --target-arch for cross compilation.

Let me think about the workflow here and get back to this.

You mean handling “architectures: [a, b]” the same as “architectures: [[a, b]]” per the proposal, while still allowing the latter? We probably cannot do that in a compatible way. Or is that not what you mean?

We need to keep some pragmatism while considering those ideas. Distributions don’t have dozens of different alternatives for every minor change in CPU compatibility, and we should be careful not to break down excessivel5y either. For example, what’s the real benefit of transforming i386 into i586 and i686?

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…