Multiple architectures in store

I seem to be able to create a snap with multiple architectures: armhf and arm64, but if i publish to the store I get the following error:

The store was unable to accept this snap.
architectures: Invalid architecture specified in the manifest: armhf, arm64.

my snapcraft yaml has the following:

architectures:
- armhf, arm64

If i specify only 1 of them it works. Is there a limitation with the store? How is one supposed to create a snap for multiple architectures?

Try…

architectures:
- armhf
- arm64

As that is the yaml format for a list.

Hope that helps, if not post the full snapcraft.yaml and someone can take a closer look.

alternatively,

architectures: [armhf, arm64]

thanks… that worked

Shouldn’t the parser reject invalid tokens? I was able to build the snap without any indication that I had specified an invalid architecture … it certainly would help figuring out problems

@sergiusens @abbot does have a point I think: snapcraft should at least check architectures – it changes slowly enough that carrying a whitelist shouldn’t be too onerous.

It should, in any case, we are migrating away from this architecture specification to the new one we defined during the Ubuntu Rally.

This will move us away from this confusing format of what to set the snap to to a more approachable one from a builders point of view of what to build snaps for

FYI - currently, if you don’t specify architectures then build.snapcraft.io will build for all available architectures.

This is not what this field does. It sets the architecture of the snap for all the builds that occurred to the architecture set in the architectures field. We don’t even document this field for that reason.

Are you saying not to use that field?

right now if i set this field I get a “multi” architecture snap… which seems to be exactly what I want. I tried specifying --target-arch, but that never seemed to work. I am never going to be building my snap on an actual Arm. I will only be cross-building, so i can’t rely on my default / native architecture for packages

can you explain the “correct” way? And/or future way? Is there a real world example / tutorial of the following:

cross package/build on an amd64 for multiple target architectures (non-amd64).

This should be the exact use case for Unbuntu Core, no?

The tricky part is how to properly pull in different compiled libraries for each architecture and setup the snap accordingly. (ie lib search path)

I really get broken behavior when I attempted to do this since I need to have completely different apt sources (ubuntu-ports) in order to stage/package which doesnt seem to be documented anywhere.

Has anyone in snap/snapcraft ever even done this?

There are lots features related to architecture but its not clear when or how these are used in relation to cross package/building for multiple targets

1 –target-arch=ARCH (snapcraft command line argument)

snapcraft.yaml:
2. architectures: [ARCH,ARCH] (hidden feature?)

stage-packages:
3. - libcurl3 :ARCH (architecture specifier for package)
4. on ARCH Selector (I am am only going to stage, so do i even need this?)

And to top it all off, nothing seems to work without the proper apt sources.list setup.(ie a whole bunch of different
deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ xenial universe) or else you get the dbkpg add architecture message which doesn’t even work!

I’m the author of lxi-tools (see http://lxi-tools.github.io) and I’ve just set up build.snapcraft.io to build lxi-tools for the 3 supported architectures: armhf, i386, amd64

This is my snapcraft configuration: https://github.com/lxi-tools/lxi-tools.snapcraft/blob/master/snap/snapcraft.yaml

Every time I push changes to git repositories lxi-tools.snapcraft, lxi-tools, or liblxi a build for all architectures is triggered and pushed to the edge channel of the global store (see https://dashboard.snapcraft.io/dev/snaps/8744) where I can go promote it to release if I need - it’s very flexible and I’m liking it.

What I did here is probably what is considered minimum configuration and is possible because all involved components (app and library) fully supports standard autotools configuration which makes it work well with the snap autotools plugin which abstracts away the architecture specific details.

I’m very happy with the setup. The only thing that was tricky is setting up github so that push changes in the non-snapcraft repositories (lxi-tools and liblxi) triggers build.snapcraft.io to build the lxi-tools snap pulled from lxi-tools.snapcraft. However, it does create a minor artifact in the build.snapcraft.io UI interface (the incorrect trigger git sha is shown when pushing trigger changes from the non-snapcraft enabled repositories).

thanks, but are you producing 3 snaps? or 1 snap with 3 architectures?

I can’t see your dashboard / snap since that link is used by your login.

I wasnt planning to use build.snapcraft.io

I’m only producing a snap for ‘lxi-tools’, well technically its 3 snap files, one for each architecture.

To me build.snapcraft.io seems to be the easier option compared to e.g. launchpad or building manually.

https://uappexplorer.com/snap/ubuntu/lxi-tools

@abbot What @sergiusens is saying, in an arguably obtuse way :slight_smile:, is that the “architectures:” field in snapcraft.yaml today defines exactly what goes into the respective field in snap.yaml inside the snap.

So if a single snap is built with, say, “architectures: [amd64, armhf]”, that will produce as an outcome a single snap that will be happily installed in both of those architectures. Unless the snap is indeed capable of running on both of these architectures (is independent, or has binaries for both), this is not what you want.

This is indeed a bit confusing and unexpected, which is why we’re changing that field to allow defining multiple architecture sets, one for each produced snap.

There are further conversations on this topic if you are curious.

@sergiusens Do you have more details on the schedule frame for this to land?

Making the architectures change is planned for 2.37

the original topic of this post was how to properly setup multi-architecture support. Not the specific syntax of the architecture field.

All i care about is having a single snap that runs on multiple architectures! I have the binaries built fine, but creating the package and its dependencies seem to be a nightmare.

To be clear, my issue was solved, but i still feel like i’ve just hacked everything together.

in my case, I am shipping binaries which feels like a secondary feature of snap. (since I have to deal with setting lib search paths manually)

A specific example / how-to guide on setting this up is what is needed given the state of the documentation and inconsistent functionality of snapcraft. For it to have any value to anyone it needs demonstration staging packages (libraries) used by the different architectures. I would also recommend showing arm based package staging since out of the box arm packages don’t seem to stage correctly on an amd64…

if you are changing the specification, please include the above/below scenario as a it seems like a typical use case for any multi-arch platform snap of moderate complexity

lets say we create a snap: “SnapPans”

I see 2 generalized cases for artifacts that are deployed with snap:
platform agnostic (content, source files, man pages, etc )
platform specific ( compiled binaries, shared libraries, packages)

I would structure it as follows:

SnapPans\armhf\bin
SnapPans\armhf\lib
SnapPans\arm64\bin
SnapPans\arm64\lib
SnapPans\i386\bin
SnapPans\i386\lib
SnapPans\common\man

anyone would just install it using: “snap install SnapPans”

Depending on the host architecture, it would run the binaries and use the lib search path for that architecture.

it could download everything, or just the binaries tagged common and specific to that architecture. The latter is just an optimization to be implemented at some point.

The other option is: I could create multiple snaps: SnapPans-arm64, SnapPans-armhf, SnapPans-i386

This is obviously feels like a hack, but given the current state of snapcraft, it is something I know would work.

I think you’re misunderstanding how multiple architectures usually work in the store:

You would normally build an amd64 snap called SnapPans and upload to the store which labels it build 1. Then you would build another snap called SnapPans for i386 again uploading to the store, this time the build will be 2. Finally you build a third snap called SnapPans for armhf which will take the build number of 3. In each case you only include the binaries and common files relevant for the single architecture it’s building: amd64, i386, or armhf. You would then release each of the three builds in the store separately. They will all be called SnapPans and installable via snap install SnapPans where the system will select the appropriate architecture automatically.

The architectures field in the snapcraft.yaml is telling the builder that it should label the built snap with specific, maybe multiple, architectures. This is usually not what you want as compilation will only occur once targeting the architecture of the build machine.

The build service at build.snapcraft.io handles the building of multiple architectures individually and automatically out-of-the-box without you specifying the architectures field. It will build on systems of each of the three architectures and upload each of the resultant snaps into the same name in the store.

@daniel I personally agree with you that this is the best way to go about delivering a snap but creating a fat package is somewhat supported given the legacy of the snap format (I am not entirely sure it would be something we’d say we supported if starting out today).

Now on to snapcraft, stage-packages for multiple architectures does work, but there are numerous gotchas in the way given how the archive is constructed, these gotchas should be properly managed when doing container builds but are not when using a regular host as it has potential to break the system or just make it really slow to update (ports.ubuntu.com is not mirrored).

Additionally to the architectures entry work there is work to expand the language for defining stage-packages which can be tracked on 1869

If this was the original topic, I’d suggest changing the title which at the time of this writing has not been edited and is Syntax for the architectures field. Anyone reading the text presented here might be skewed by the title no matter what the intention was.

If you have set confinement: classic or the libraries do not fall under the conventional place to put libraries in Ubuntu, then yes, today it would be a manual process. Conventional library paths for multiple architecures in mind, in Ubuntu, are those of the form [usr/]/lib/$(gcc -print-multiarch) If you dump your binaries in there it should be sorted. There is work to make this an automatic process and crawl the tree to be primed so this convention becomes just that a convention and not a form of function.

Now for “binary” paths, snapcraft can work something out using the currently runtime exposed SNAP_ARCH but to further implement this cleanly with eyes to the future we’d actually want the architecture triplet so that you could do

apps:
    my-app:
        command: bin/$SNAP_ARCH_TRIPLET/my-command

and this would just work.

@daniel if I am misunderstanding anything, its because its not documented (or not clearly). Basically what you are saying is I need to produce 3 snaps (or is package the term) and ship them.

That feels counter intuitive since each architecture will actually be on a different snap “revision”. if you have 5 or 6 architectures (along with channels for each), its going to be very hard to track and manage since snap seems to be centered around revision (its even in the file system), not version.

But, In the end I really don’t care how its implemented, I just want something that works using my own CI build environment, not build.snapcraft. Perhaps this is not the general use case, but it does seem like a standard use case.

@sergiusens the original topic name was “Multiple architectures in store” my question was: " Is there a limitation with the store? How is one supposed to create a snap for multiple architectures?"

I am using strict confinement, the only way i got things to work was to put this:

    environment:
      LD_LIBRARY_PATH: $LD_LIBRARY_PATH:$SNAP/usr/lib/arm-linux-gnueabihf/

Based on your post though, that sounds redundant and I should not need this? (It was my first snap, so perhaps the problem was something else, and I thought this is what fixed it)

FYI: I don’t know who changed the topic It wasn’t me.

I see the issue now and it is related to my comment before. There is a multiarch LD_LIBRARY_PATH exported, but only valid for the arch where it was build on; if the runtime environment were to export something like SNAP_ARCH_TRIPLET we would be able to make this a lot smarter.

@abbot The topic of the original message, and all responses that followed it, were related to the syntax and the meaning of the architectures field, specifically. That’s why I renamed the topic, so people reading it would read what they expect.