AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
25.17k stars 2.18k forks source link

Cannot start Avalonia under FreeBSD #6990

Open CyberBotX opened 2 years ago

CyberBotX commented 2 years ago

Describe the bug When trying to use Avalonia under FreeBSD, it cannot start at all. After creating project via the dotnet cli using the MVVM template, the unedited code cannot run because FreeBSD isn't one of the platforms being detected by UsePlatformDetect(). When I change that to UseX11() and add a call to UseSkia(), I instead get an exception because FreeBSD's libc does not have epoll functions in it:

Unhandled exception. System.EntryPointNotFoundException: Unable to find an entry point named 'epoll_create1' in shared library 'libc'.
   at Avalonia.X11.X11PlatformThreading.epoll_create1(Int32 size)
   at Avalonia.X11.X11PlatformThreading..ctor(AvaloniaX11Platform platform) in /_/src/Avalonia.X11/X11PlatformThreading.cs:line 121
   at Avalonia.X11.AvaloniaX11Platform.Initialize(X11PlatformOptions options) in /_/src/Avalonia.X11/X11Platform.cs:line 71
   at Avalonia.AvaloniaX11PlatformExtensions.<>c__0`1.<UseX11>b__0_0() in /_/src/Avalonia.X11/X11Platform.cs:line 266
   at Avalonia.Controls.AppBuilderBase`1.Setup() in /_/src/Avalonia.Controls/AppBuilderBase.cs:line 303
   at Avalonia.Controls.AppBuilderBase`1.SetupWithLifetime(IApplicationLifetime lifetime) in /_/src/Avalonia.Controls/AppBuilderBase.cs:line 179
   at Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime[T](T builder, String[] args, ShutdownMode shutdownMode) in /_/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs:line 174
   at MyProject.Program.Main(String[] args) in /MyProject/Program.cs:line 21

I cannot get around this currently because I do not see any way with C#'s P/Invoke to override libraries on a per-method basis (I only know of how to use NativeLibrary.SetDllImportResolver for doing so on a per-library basis, which won't work here).

FreeBSD does have epoll functions in the form of a shim over its kqueue functions, namely the port devel/libepoll-shim from https://github.com/jiixyj/epoll-shim, so Avalonia is either going to need a way to specify a way to use kqueue instead of epoll or a way to use libepoll-shim.

To Reproduce Steps to reproduce the behavior:

  1. Create a new application using the MVVM template.
  2. Change UsePlatformDetect() to UseX11() and add call to UseSkia().
  3. Try to run, get the exception.

Expected behavior Being able to run even a sample Avalonia application under FreeBSD.

Desktop (please complete the following information):

Additional context I am using the build of .NET 6 for FreeBSD from https://github.com/Servarr/dotnet-bsd/releases as there is no version of .NET 6 from Microsoft themselves for FreeBSD.

kekekeks commented 2 years ago

The only workaround I can think of is overriding dlsym via LD_PRELOAD library but that seems a bit excessive.

I don't quite remember why do we use epoll instead of select since we are only waiting on two descriptors (X11 socket and a pipe) and using timeouts for timers. Need to investigate that.

What does one need to run .NET SDK on FreeBSD in a VM?

CyberBotX commented 2 years ago

From that repo I mentioned at the end of the report, I downloaded the runtime (not the one that says internal or composite) and the sdk. I then extracted both to the same folder. Then you can run dotnet from that folder just like you would run it on any other platform. If you wanted to be able to run the command without prefixing the folder, you'd have to add that folder to your path.

kekekeks commented 2 years ago

Try with the build from this PR once it finishes https://github.com/AvaloniaUI/Avalonia/pull/6998

CyberBotX commented 2 years ago

Sorry for not replying to this sooner. I didn't know how to get the builds created from that PR until the recent update to the PR a couple days ago.

I downloaded the NuGetOSX artifacts (for some reason, the NuGet one is missing Avalonia.Native and my system was wanting it for some reason despite not being OSX) and set it up for I could use them locally.

I can confirm that running does get farther now, the problem now being not having libSkiaSharp.so, but that is another issue entirely and not relevant for this issue.

sjsepan3 commented 1 month ago

What does one need to run .NET SDK on FreeBSD in a VM?

You've probably long since run across the answer (regarding setting up the SDK), but for reference, I've been using the SDKs built here... https://github.com/sec/dotnet-core-freebsd-source-build ...to try Avalonia on GhostBSD

CyberBotX commented 1 month ago

With how long it has been since this issue was opened, and with the Avalonia devs having never imported anything to change those epolls to selects (and that PR above was closed without import), and with the issue I had with SkiaSharp not working at all (which was not related to Avalonia at all), I gave up and have not bothered to try Avalonia again for my projects.

sjsepan3 commented 1 month ago

With how long it has been since this issue was opened, and with the Avalonia devs having never imported anything to change those epolls to selects (and that PR above was closed without import), and with the issue I had with SkiaSharp not working at all (which was not related to Avalonia at all), I gave up and have not bothered to try Avalonia again for my projects.

Understandable. BTW, I updated my comment to be more clear and indicate that it was in reference to setting up the SDK. The SkiaSharp issue is probably related to GTK# also not working on GhostBSD(/FreeBSD), as I had tried that too and got a type initializer exception.

yurivict commented 1 month ago

@CyberBotX

Does it run with LD_PRELOAD=/usr/local/lib/libepoll-shim.so ?

CyberBotX commented 1 month ago

It doesn't run with or without that, since Avalonia throws an InvalidOperationException of "No runtime platform services configured." (This was after making a completely run project using dotnet new avalonia.mvvm -o GetStartedApp like the Test Drive portion of the docs shows.)

But even if I edit Program.cs like I explained in my first post, it won't run because I don't have libSkiaSharp. Adding the SkiaSharp NuGet package doesn't fix this either. And the last time I tried to build my own copy of SkiaSharp, with it having been nearly 2.5 years now, I was unable to get a working copy of SkiaSharp for FreeBSD.

And just to note, I'm doing this now with .NET 8 (8.0.6 with 8.0.106 SDK), built for FreeBSD from the FreeBSD ports tree, which while unofficial, is also the best way to get .NET under FreeBSD these days.

kekekeks commented 1 month ago

"No runtime platform services configured."

If Linux platform check fails in UsePlatformDetect you need to specifically add UseX11() to your AppBuilder.

As of epoll-shim, note that .NET uses dlopen/dlsym to resolve DllImport, so you'll likely need to patch Avalonia.X11 code to use different DllImport's for FreeBSD.

sjsepan3 commented 1 month ago

Just to see what happens, when I swap UseX11 for UsePlatformDetect...

                    .UseX11()// .UsePlatformDetect()

...the error message changes to "No rendering system configured."

CyberBotX commented 1 month ago

I already mentioned that I did use .UseX11() and .UseSkia() in the sample code in place of .UsePlatformDetect(), so really the only issue with using .UsePlatformDetect() is it not detecting FreeBSD. The real issue right now is the lack of SkiaSharp for FreeBSD, which isn't really an Avalonia issue but it does prevent FreeBSD users from using Avalonia.

kekekeks commented 1 month ago

https://doc-1dng-3s2g-issuetracker.googleusercontent.com/attachments/kc7eu567pksi0u9a1bnf6bomkfbp1d7c/8q74c1ra4vig9j4ir8emgcs0na1inecv/1722499200000/1363359/*/40045542::45868240::1363359?q=AN9yeQKxWRN99I7K3PKqJbTjeoUW9sD7FiHiFsfw4Jnx-ycC1Rw21qxNO9zN70C_T23XC-1klUs8R5gX4nbVMpIRB-8&download=false

This patch doesn't look that complex. And given that SkGetExecutablePath isn't really used by SkiaSharp, I think it could be compiled for freebsd by simply passing current_os=linux to gn.

I think the main problem would be getting FreeBSD builds to run on SkiaSharp CI that uses Azure Pipelines. There are no built-in FreeBSD agents. Is it somehow possible to pack cross-toolchain for FreeBSD into a Linux Docker container?

kekekeks commented 1 month ago

https://gist.github.com/bijanebrahimi/62596745808f8667c40ff91b07d9e7b8 maybe something like this could be dockerized?

CyberBotX commented 1 month ago

You can already create Linux jails with FreeBSD, it has a Linux Emulation Layer (not perfect but it works for the most part), and you can either use CentOS 7.9.2009 or Rocky Linux 9.4 from the FreeBSD ports tree, or you can install debbootstrap and install a flavor of Debian or Ubuntu or whatnot (I've opted for the latter myself, using Ubuntu).

I haven't tested that for using Avalonia, but while it might work, I'd prefer being able to use Avalonia natively within FreeBSD, not within a Linux jail. But I haven't looked into using Avalonia again since my initial issue with doing so back in 2021.

kekekeks commented 1 month ago

The idea was to not use a Linux emulator, but to build SkiaSharp for FreeBSD by packaging a FreeBSD cross-toolchain into a Docker image, so it could be run on SkiaSharp CI. Azure Pipelines don't support FreeBSD VMs, so it's the only way to get official support.