Dotnet 7 cannot built on architectures arm64, s390x, ppc64 and elarmhf on Core22

On those architectures package with .Net 7 SDK is not found


While .Net states that it supports more than amd64 architecture including x86 and arm.

Consider adding at least arm64 architecture support.

We currently only build .NET .deb packages for amd64 (aka x64) and arm64. Therefor it is expected behavior that you can not find s390x, ppc64el, armhf, i386 (aka x86).

Regarding s390x and the Power platform, we are considering on adding support for these architectures, but we haven’t committed to a particular release cycle when this will be done.

Regarding armhf and i386, there are no plans to add support for these architectures. We currently do not see the demand to justify the maintenance cost.

That you can not find arm64 is unexpected to me. Do you use the .NET SDK snap? If yes, this snap currently is maintained by Microsoft and they only build for amd64 (aka x64). See:

We are currently working on taking over the snap until the release of Ubuntu 24.04 LTS (Noble Numbat). When this happens we will also add builds for arm64.

If you don’t use the .NET SDK snap, please reply and we look into what is going on.

Thanks for raising this Issue!

  1. .Net SDK snap

During preparing I found out that .Net SDK snap does not work for building/staging and running app spending a day on it. So I’m using the package this way

      - dotnet-sdk-7.0
  1. Platform support

Sorry. I rechecked .NET and Ubuntu overview - .NET | Microsoft Learn and they write that on Ubuntu 23.04 they support only X64 and ARM64. But indeed I’m kind of stupid to expect X86 supported by default. Probably linter check for snapcraft.yaml would be good to avoid the issues with platforms. When I saw missing package messages, I was thinking that its kind of bug in Core22 images for those platforms, then trying to find hard coded platform inside my code etc.

I wrote a simple .NET 7 demo (hello world) app that gets packaged with snapcraft ( Using dotnet-sdk-7.0 works on my system.

Can you share details of your application (e.g. snapcraft.yaml file and overall directory structure)?

EDIT: I noticed that you shared the details here.

We also have this how-to that demonstrates how to build a .NET snap step by step:

1 Like

I used this how to try make build. I’m happy that for some people it will help to package console.

The problem is that most applications on .Net are GUI apps. Very few people will want to package simple do-nothing console applications.

What is a non-doing-nothing console? Application that might want spawn other apps either part of system or bundle, redirect output, have settings.

However, in .Net world the only way to create UI cross platform applications are Avalonia UI application. Ordinary application has settings, which it wants to store somewhere like theme. Ordinary application can have dialogs. Ordinary application will want to able to save results of its work to user folder of choice (because if does not produce output, then probably there’s a website for that, right). Ordinary application might want to spawn console worker app to do something and redirect input, output, error output. Ordinary app contains multiple executables, including console apps.

If your guide would cover this ordinary UI case scenario, it would be nice.

Why would you expect this to be any different from any other gui app you package as a snap? All you describe above are things all GUI apps have in common and there are plenty tutorials you could derive from…

Shipping multiple apps is a general snap feature , you simply have to add multiple apps entries in your snapcraft.yaml…

All snapped qt, gnome, gtk apps store their settings in their desired configuration location and have to ship required fonts or themes, why would .net be any different in that regard ?

The one thing that is not common about them is the .net plugin and the how-to explains exactly this particular piece…

Like @ogra already mentioned. There already exists the general snapcraft documentation that covers most (if not all) of the topics you seem interested in. We didn’t wanted to duplicate already existing documentation for every use case.

With that said, I see your point that it is hard to put all the pieces together (especially with the current dotnet plugin). I will put a work item for writing a tutorial how to package an Avalonia UI application on our roadmap for the current 24.04 cycle.

In the meantime you could use this demo application (written by a colleague of mine) as a reference for snap packaging an Avalonia UI application. Note that it uses .NET 6, but it should also work with .NET 7. I hope that you find it useful :slight_smile:

I agree that there are a lot of .NET GUI applications, but I think you underestimate the amount of non-GUI .NET applications.

Just to spread the word for other awesome open source .NET cross platform GUI frameworks, there also exists

1 Like

Hi @ogra

Thanks for commenting about fonts. Currently for snaps for child dialogs in AvaloniaUI windows have for english texts ??? chars. As I remember it happens in strict confinement only. I never expected that for GUI app I need for Ubuntu override default fonts, embed them inside application.

I will investigate are there normal unicode to handle all chars and without fees, but in general its kind of disappointing. I’m starting to think that your vision of snap as a separate linux distro with installed application with some joint points to host OS withing allowed slots, i.e. Docker with GUI capabilities.

My vision was that font support for Ubuntu and having it as collection is OS responsibility. When font cannot be found, fallback font should be used automatically, like lit’s done for PDF for in Firefox: when you didn’t embed fonts in PDF, OS fonts are used.

For .Net WinForms, WPF applications general practice is not to override default fonts. Default font comes from the OS itself. Also in former times user could adjust default fonts for Windows and its sizes. After that it it was replaced with DPI awareness. And default font is defined by desktop manager theme until its overriden.

For .Net apps commonly used practice for storing settings is to combine application data folder with name of company, application and its version like this

     "app name",

This code is supposed to be cross-platform, accepted way to store settings. When application is snapped in strict confinement - Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) - returns empty. So applications stores settings in directory of launch. And it’s like snap but its not limited to access to current directory.

Common use case is to create SNAP for GUI application, not console. For GUI applications currently the most popular framework is Avalonia.

Guide states that it takes 20 minute to snap .Net application. The reallity for me was different. It took several weeks on weekends to make application be cross-platform - I was ok with that since also WinForms could be dropped which are dead since 2010. Then I found snap thing. 8 days (3 weeks) I was trying it to compile and be possible to be launched.

There’re lots of problems with dotnet plugin, I posted them for devs of this staff to rise their awareness, that for newcomers it will take months to snap dot net for linux because this and that. So devs will be aware and somehow make experience better. You cannot use it as it is for ordinary app. You have to override build. Even your colleagure did it

    override-build: |
      dotnet publish -o ./dist -c Release -r linux-x64 -p:PublishSingleFile=true --self-contained true
      cp ./dist/* $SNAPCRAFT_PART_INSTALL

I had to do it

    override-build: |     
      cd ./sources
      app_version=`git describe --tags --abbrev=0`
      dotnet publish /p:Version=$app_version /p:AssemblyVersion=$app_version -r linux-x64 -c Release --self-contained true -o $SNAPCRAFT_PART_INSTALL/bin/
      chmod 0755 $SNAPCRAFT_PART_INSTALL/bin/butil-ui.Desktop
      chmod 0755 $SNAPCRAFT_PART_INSTALL/bin/butilc

And by default in documentation example you see that it can handle normally without doing it. So ordinary documentation sample should have this code for overriding build (its nothing wrong with it, build command easily understandable). The same documentation for ordinary use case should state that you cannot run any dot net executable via dotnet. That you should use --self-contained true and other topics that were already mentioned.

I’ve created those topics because as a newcomer I spent 3 weeks and for me it was a bad experience because of time spent (basically it was interest, that is converted to rage at some point). If I was a student, or something without work, it would be interesting to dig here and there for months. If i was an employee doing this - probably it would be fine too. But for hobby it’s a lot for nothing.

The same with .Net MS package itself. .Net 7 invalidly resolves user folders Videos, Pictures. Those folks fixed it for Ubuntu since .Net 8 to not break existing apps. In strict confinement things go worther when I request path to those folders in .Net 7 - empty strings are returned. Normally people uses culture but if I don’t specify package libicu70 then it will be impossible to start even console application. The same for other libraries:

      - libicu70
      - libx11-6
      - libstdc++5
      - libice6
      - libsm6

If they are required for app to run in strict confinement, they should be part of .Net package dependencies, not of mine directly. And in strict confinement some paths are resolved incorrectly probably because .Net cannot see environment variables required to do so. Or simply they did not test it.

Those other frameworks you mentioned they are quite new, so I think after couple of years they will have community and more or less good cross-platform experience.

I finally gave up on creating strict confinement snap - its not possible to do it for .Net world - and created classic one. Then I saw it fails builds for no reason, because in new version of web-site releases page errors are hidden by default and not obvious that they can be expanded. Then I found out that manual approval is required for that. I created a topic about that. What I see that I was proposed to investigate more how to make app be in strict confinement. And I understand that it’s for monthes of future work. So I just publish snap with classic confinement on github with instruction how to install it from console.

But it is, here’s a .NET snap with a GUI in strict confinement, it doesn’t bundle libstdc++, libICE, etc; just .NET, and it uses system/user fonts. Give it a go, sudo snap install pinta. It’ll access your files and use your fonts just fine.

I can understand frustration with the documentation, but you seem to be coming to the conclusion that these things just aren’t possible. They are.

The community can try to help, but if you spend the entire time struggling and only ask for help after already burning yourself out on it, with the the conclusion that half the features we have don’t exist; now cementing the idea in your head that classic is the only option, it’s difficult to start over on better footing.

Classic confinement didn’t even exist in Snaps for the first few years of its design. And amongst the community we generally consider the strict snaps the easier of the two. A classic snap might look like it runs fine, but they have completely different problems of their own to deal with, beyond any concerns of security.

That snap doesn’t use AOT compilation. The .NET Runtime (not SDK) is shipped with it and the code JIT’d for the exact machine it’s on. It’s not just theoretically possible, there’s full examples already.

Yes, it’s annoying that even for the example above override-build was used rather than the dotnet plugin, but the 3 lines to override are just building on the make files the project already has, I wouldn’t consider the override build eggregious at all.

If you were to still go ahead, I think you’d find it a lot easier to work from the example above, in strict confinement, using the Gnome extensions; where significant amounts of the work are offloaded as an implementation detail for the extension to deal with.