[GSOC 2023] .NET Port

Thank you so much for all your support! This project has been accepted into GSoC 2023!


Behold, the first .NET 8.0 binary running on Haiku.

(The first binary ever was for .NET 7.0 in last year’s effort).

At this stage, it is theoretically possible to run many computation-heavy .NET apps such as the Roslyn C# compiler given enough effort to set up a correct environment.

The source code for this year’s CoreCLR porting effort looks much cleaner, but there are still a few final issues that have to be resolved. I’ve talked about these problems on the IRC channel, but if you’re interested, I can write a blog update this weekend.


A blog update would be nice for those of us that don’t frequent the IRC channel. Though not if it takes a lot of time from your main efforts.


Blog posts are important for long term archival and tracking of the work done. It’s not very convenient to have to find informations about things on the IRC channels after a few years have passed, whereas blog posts can more easily be found and reused.


The .NET CLI is (somewhat) working. I’ll just have to find a way to install the SDK.


dotnet(1) tool working on Haiku.

The helloworld.dll is scped from Linux, I don’t know how to obtain an SDK tarball (yet) so I cannot test dotnet build and other functions.


It’s been a while, but here is the current status of the port:

As said in a blog that should have been merged last week, I am working on the SDK and the managed libraries simultaneously.

After fixing a few Haiku memory bugs, one of which crashes the kernel, this is where I got.

The exception message is due to .NET complaining about a lack of epoll. So today this port officially joins the list of projects affected by epoll.


After applying some hacks to the .NET SDK, dotnet passed the Restore phase and got to the Build phase (where it invokes Roslyn).

Sadly, this phase raises yet another Haiku virtual memory bug and crashes the kernel. Before dotnet could even reach this phase at all, two patches (#6392 and #6394) need to be applied, both of which fix some kind of VM-related Haiku bug.


With a few more hacks, the .NET SDK is working and successfully builds and runs a binary.

Specifically, there are two hacks involved:


Despite defining all the standard constants in compile-time, Haiku does not have full IPv6 support. Some operations that .NET requires (setsockopt with IPV6_V6ONLY) is currently stubbed. I do not have much experience with the internet protocol so for now I will just disable IPv6 altogether.

Disabling the double mapper (COMPlus_EnableWriteXorExecute=0)

.NET has a strange feature that allows mapping the same physical pages once with read-write and another time with read-exec called the “double mapper”. On macOS, it is cleanly implemented using vm_remap. On other UNIXes, a workaround using a shared memory file is used instead.

The implementation for Haiku currently follows the shared memory file path, but this causes problems on fork and also somehow makes the system unstable after multiple usage. Haiku has a method to clone virtual address pages (clone_area), but this function only allows cloning one area at a time, while .NET needs to atomically clone arbitrary ranges of pages.

In my opinion the ideal fix is a new syscall, _kern_remap_memory, that I have mentioned in my previous blog. For a while I thought I could make an attempt to implement this, but I was stuck on the problem of potentially having to merge two VMCaches.

For now, I will just disable this feature to focus on the main goal of this project.


I wonder if there are any interests in binary downloads of the .NET runtime and SDKs for Haiku.

If there is significant community interest in testing my WIP branch, now that it can handle the basic restore, build, and run workflow, I can set up weekly binary releases on a GitHub repo as well as a NuGet feed providing the latest packages.


I once has an internship where my assigned task was to make a SOAP request by downloading a NuGet package and using that for the task.
Naturally I thought the assignment was to make the request myself.
Also SOAP is terrible.

Anyhow I decided against IT as a Job because of that! : D

1 Like

downloading a NuGet package and using that for the task.

There’s a NuGet package for almost programming task you can think of. There’s even one for reading Haiku HPKG files.

We would like to try to support other languages in Genio with the full spectrum of features: build and run, syntax highlighting and LSP support (via omnisharp maybe?).
.NET and C# and Python would be our first choices.
So yes, please make the binaries available so we can experiment a bit.


For anyone interested, I will release my binary builds here.

The .NET runtime is already released as a build artifact. I will set up build scripts for the .NET SDK as well as the NuGet feeds later today. After that I will provide further installation instructions.

HaikuPorts releases are currently impossible because:

  • The current branch is using a prerelease version of .NET 8.
  • Many PRs are waiting to get merged upstream.
  • No official documentation (at least, not among the ones I know) on how to create packages that have themselves as a build prerequisite. Probably creating an initial dummy package that downloads pre-built binaries and then use that one to bootstrap another “revision” of the recipe might work?
  • Unconventional installation layout. All of .NET lives in one directory, and it should be writable so that additional workloads or other optional components can be installed through NuGet, instead of being divided into /bin, /lib, etc. like other UNIX applications.

You can look at hos this is done for Rust and Haskell.

For Rust, haikuports does not currently builds from source, but just repackages existing binaries.

For Haskell, the first version was cross compiled, and then that version was used to build the next one, and so on.

That will not really fit with the way haiku packages work. Living in one directory is no problem (just put it in system/develop/tools/dotnet for example), but you’ll probably need some things to be in a packaged directory and some to be in a non-packaged one.

According to the documentation, NuGet has “user” and “computer” levels, just like other package managers. Usually in Haiku, the “computer” level is read-only and managed by packages, and the “user” level will be in a non-packaged directory (at least I think that’s what we do for Python and Perl).

This is actually solvable, as .NET provides a way to install workloads using the native installation method of the platform. For example, on Windows, workloads are installed as .msi files.

When workloads are actually needed, we can make .hpkg files for each workload and write some kind of provider backend for Haiku packages.

1 Like

Detailed installation instructions have been provided here:

The instructions assume an audience with some familiarity to both the .NET and Haiku ecosystems.

A blog with the technical details behind this will come soon.


I have provided a dotnet-install.sh-like script that installs the latest .NET builds on Haiku.
The script currently installs Debug builds, not Release builds as the latter might have some mysterious hidden bugs.

Make sure you install .NET dependencies first:

pkgman install -y gmp krb5 libiconv llvm12_libunwind mpfr
pkgman install -y jq # Required for the dotnet-install script.

Then run the installer script:

bash -c "$(curl -fsSL https://raw.githubusercontent.com/trungnt2910/dotnet-builds/HEAD/dotnet-install.sh)" -- --install-dir=/path/to/where/you/want/to/install/dotnet

For veteran users of .NET, no, this script does not work like the Microsoft’s official script and currently still lacks many options.



This is my HpkgReader.Gtk, a demo application for my personal HPKG reader implementation written 100% in C#.

The application runs on Haiku using GtkSharp bindings for Gtk3.


It seems like .NET uses edge-triggered polling with EPOLLET, or the equivalent EV_CLEAR for platforms with kqueue.

This means after an event has been read by the user, it will not be returned by the polling function a second time, even when there is more data to be read from/more data can be write to the file descriptor. The event will only be re-triggered when another write/read actually occurs on the other end.

This property cannot be satisfied by the current poll workaround. For poll, it is not possible to distinguish between two different events in two calls and the same unchanged event in two calls. Therefore, .NET tries to loop again and again and handles the same event over and over, starving CPU resources and preventing other threads from running.

1 Like