Skip to content

[Linux] runtimes/<rid>/native/ not probed on Ubuntu — _linuxRiDs fallback list missing "ubuntu" (regression of #652) #2571

@EJTP

Description

@EJTP

Summary

On Ubuntu / Ubuntu-derived distros, Silk.NET 2.22.0's native loader does not probe runtimes/<rid>/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 <RuntimeIdentifier> 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:

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/<libname> (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("<exe-dir>/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("<exe-dir>/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("<exe-dir>/libglfw.so", ...)                    = ENOENT

The bundled lib is on disk and works:

$ ls <exe-dir>/runtimes/linux-x64/native/libglfw.so.3
<exe-dir>/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/<config>/<tfm>/ build output (no dotnet publish, no <RuntimeIdentifier>)

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 <RuntimeIdentifier>linux-x64</RuntimeIdentifier> 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions