[Linux] runtimes/<rid>/native/ not probed on Ubuntu — _linuxRiDs fallback list missing "ubuntu" (regression of #652)
- Dominant language
- C#
- Stars
- 5.2k
- Forks
- 477
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 2
Description
## Summary
On Ubuntu / Ubuntu-derived distros, Silk.NET 2.22.0's native loader does not probe `runtimes//native/` for bundled native libraries because the hardcoded `_linuxRiDs` fallback list in `DefaultPathResolver.cs` is missing `"ubuntu"`.
The bundled `libglfw.so.3` shipped by the `Silk.NET` NuGet package is therefore unreachable, and `Silk.NET.Windowing.Window.Create(...)` throws:
```
System.PlatformNotSupportedException: Couldn't find a suitable window platform.
(GlfwPlatform - not applicable)
at Silk.NET.Windowing.Window.Create(WindowOptions options)
```
This is the same symptom as #652 (which #661 was supposed to fix). The `RuntimesFolderResolver` / `NativePackageResolver` machinery added in #661 is still there in 2.22.0, but it can't reach `linux-x64` from `ubuntu.24.04-x64` on a modern .NET SDK because of the missing fallback entry.
## Environment
- **Silk.NET**: 2.22.0
- **OS**: Pop!_OS 24.04 LTS (Ubuntu-based), kernel 6.18.7, x86_64
- **.NET SDK**: 10.0.107
- **Session**: Wayland (with XWayland; `DISPLAY=:1`)
- **Build**: framework-dependent `dotnet build` (no `` set, no `dotnet publish`)
- **`RuntimeEnvironment.GetRuntimeIdentifier()` reports**: `ubuntu.24.04-x64`
## Root cause (traced through the v2.22.0 source)
In [`src/Core/Silk.NET.Core/Loader/DefaultPathResolver.cs`](https://github.com/dotnet/Silk.NET/blob/v2.22.0/src/Core/Silk.NET.Core/Loader/DefaultPathResolver.cs):
```csharp
private static readonly string[] _linuxRiDs =
{
"alpine", "android", "arch", "centos", "debian", "exherbo", "fedora", "freebsd", "gentoo", "linux",
"opensuse", "rhel", "sles", "tizen"
};
```
`GuessFallbackRid("ubuntu.24.04-x64")` splits on `-` giving `split[0] = "ubuntu.24.04"`, then runs `_linuxRiDs.Any(x => split[0].StartsWith(x))`. `"ubuntu.24.04"` does not start with any of those prefixes (`"ubuntu"` is missing), so the function returns `null`.
In `GetAllRuntimeIds`, that means:
1. `currentRid = "ubuntu.24.04-x64"` is added.
2. `AddFallbacks` walks `ctx.RuntimeGraph` for an entry whose `Runtime == "ubuntu.24.04-x64"`. On modern .NET (8+), framework-dependent deps.json files have an empty or minimal `runtimes` section (RID graphs were largely retired in favor of portable RIDs), so this lookup misses.
3. `GuessFallbackRid` is called as the last-resort path → returns null → `linux-x64` is never added.
So `TryLocateNativeAssetInRuntimesFolder` only ever tests `runtimes/ubuntu.24.04-x64/native/` (which doesn't exist — NuGet places the assets under the portable RID `linux-x64`) and `TryLocateNativeAssetFromDeps` never matches a runtime asset either.
## strace evidence
`strace -f -e openat` of the failing run, filtered to glfw probes, showing zero `runtimes/linux-x64/native/` lookups:
```
openat("/lib/x86_64-linux-gnu/libglfw.so.3.3", ...) = ENOENT
openat("/usr/lib/x86_64-linux-gnu/libglfw.so.3.3", ...) = ENOENT
openat("/lib/libglfw.so.3.3", ...) = ENOENT
openat("/usr/lib/libglfw.so.3.3", ...) = ENOENT
openat("/libglfw.so.3.3", ...) = ENOENT
openat("/lib/x86_64-linux-gnu/libglfw.so.3", ...) = ENOENT
openat("/usr/lib/x86_64-linux-gnu/libglfw.so.3", ...) = ENOENT
openat("/lib/libglfw.so.3", ...) = ENOENT
openat("/usr/lib/libglfw.so.3", ...) = ENOENT
openat("/libglfw.so.3", ...) = ENOENT
openat("/lib/x86_64-linux-gnu/libglfw.so", ...) = ENOENT
openat("/usr/lib/x86_64-linux-gnu/libglfw.so", ...) = ENOENT
openat("/lib/libglfw.so", ...) = ENOENT
openat("/usr/lib/libglfw.so", ...) = ENOENT
openat("/libglfw.so", ...) = ENOENT
```
The bundled lib is on disk and works:
```bash
$ ls /runtimes/linux-x64/native/libglfw.so.3
/runtimes/linux-x64/native/libglfw.so.3
$ # dlopen + glfwInit on it returns 1, GLFW 3.4.0 with Wayland + X11 + EGL
```
## Repro
Any project that:
1. References `Silk.NET` 2.22.0
2. Calls `Silk.NET.Windowing.Window.Create(WindowOptions.Default)` on Ubuntu / Ubuntu-derived
3. Is run from a normal `bin///` build output (no `dotnet publish`, no ``)
## Workarounds (confirmed)
Any of these makes it succeed:
- `LD_LIBRARY_PATH="$PWD/runtimes/linux-x64/native" ./MyApp`
- Symlinking/copying `runtimes/linux-x64/native/libglfw.so.3` next to the exe
- `apt install libglfw3` (so it's found in `/usr/lib/x86_64-linux-gnu/`)
- Setting `linux-x64` in the csproj
## Suggested fix
Minimal, low-risk: add `"ubuntu"` (and probably `"pop"`, `"linuxmint"`) to `_linuxRiDs` in `DefaultPathResolver.cs`. That alone unblocks the most common case.
Better fix: when the SDK reports a distro-specific RID like `ubuntu.24.04-x64`, walk it down to the portable RID `linux-x64` directly rather than relying on a hand-maintained distro-prefix list. Modern .NET has been moving toward portable-RID-only for years, so SDK output drifting away from the legacy graph is going to keep happening.
## Cross-reference
- #652 — original report, same symptom on Linux
- #661 — landed the resolver chain that *should* handle this, but the fallback list it depends on hasn't been kept up to date with what `Microsoft.DotNet.PlatformAbstractions` actually returns on newer SDKs
Contributor guide
Assessment
This issue has not been assessed yet.